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

Asynchronous Oracle #1738

Merged
merged 90 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
fcc1fc4
Asynchronous Oracle
erikzhang Jun 30, 2020
a44f8d9
Fix TransactionAttributeType.cs
erikzhang Jun 30, 2020
d3ef125
SetOracleNodes
erikzhang Jul 1, 2020
ef23b29
format
erikzhang Jul 1, 2020
3379d1e
Check sender and oracle nodes
erikzhang Jul 1, 2020
a8656ed
Copy the witnesses from the request tx to the response tx.
erikzhang Jul 1, 2020
7ab62a2
Limitations on the requests
erikzhang Jul 1, 2020
2e94813
Set the price
erikzhang Jul 1, 2020
918ff94
Check Transaction.Script
erikzhang Jul 1, 2020
5df3f17
Add TODOs
erikzhang Jul 1, 2020
4252abf
Setup manifest
erikzhang Jul 1, 2020
d6cfaba
Consider the failure
erikzhang Jul 1, 2020
5fe1161
Merge branch 'master' into asynchronous-oracle
vncoelho Jul 2, 2020
e305899
Add UserData to OracleRequest
erikzhang Jul 2, 2020
c013d0a
Add filter
erikzhang Jul 2, 2020
e0a4bd0
Allow filter to be null
erikzhang Jul 2, 2020
7f1ea32
Add incentivize()
erikzhang Jul 2, 2020
337c3d9
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 2, 2020
d4471e3
Modify the incentive mode
erikzhang Jul 2, 2020
7f88364
Merge branch 'master' into asynchronous-oracle
shargon Jul 2, 2020
9fc6e23
Update src/neo/SmartContract/ApplicationEngine.Runtime.cs
shargon Jul 2, 2020
6d58ce9
Revert the change of Nep5Token
erikzhang Jul 3, 2020
c121370
Update Transaction.cs and ApplicationEngine.Runtime.cs
erikzhang Jul 3, 2020
8f2fb4d
Update OracleContract.Lists.cs
erikzhang Jul 3, 2020
63b3a75
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 3, 2020
30ed817
Rename
erikzhang Jul 6, 2020
3ca5e0b
Update OracleContract.cs
erikzhang Jul 6, 2020
03f5966
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 6, 2020
b2a2b52
Fix
erikzhang Jul 6, 2020
f8d3362
Add PostPersist()
erikzhang Jul 6, 2020
7685815
Merge branch 'master' into asynchronous-oracle
shargon Jul 6, 2020
3b8c586
Support creating new requests in callback
erikzhang Jul 7, 2020
1609b0f
Fix Transaction
erikzhang Jul 7, 2020
cad6853
Update Transaction.cs
erikzhang Jul 8, 2020
27a845a
Update OracleContract.cs
erikzhang Jul 9, 2020
6f47395
Better fee mechanism
erikzhang Jul 9, 2020
c744abb
Reorder
erikzhang Jul 9, 2020
cb491e6
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 10, 2020
7e3030e
Remove cosigners from response tx
erikzhang Jul 10, 2020
16ab182
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 11, 2020
b0615ef
Fix
erikzhang Jul 11, 2020
a682ff8
Update Transaction.cs
erikzhang Jul 11, 2020
f3a0605
Remove Transaction.IsOracleResponse
erikzhang Jul 11, 2020
9c0735b
Move the fixed script to OracleResponse.cs
erikzhang Jul 11, 2020
fd99ee3
Add TransactionAttribute.Verify()
erikzhang Jul 11, 2020
f2b9c0a
Move all check to OracleResponse.cs
erikzhang Jul 11, 2020
8685898
Merge branch 'master' into asynchronous-oracle
shargon Jul 12, 2020
dd8dca6
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 14, 2020
6147a3f
Merge branch 'master' into asynchronous-oracle
shargon Jul 15, 2020
afe905e
Check calling contract in Request()
erikzhang Jul 16, 2020
a04d758
Merge branch 'master' into asynchronous-oracle
shargon Jul 16, 2020
47044ad
Fix DivideByZeroException
erikzhang Jul 17, 2020
9b4ba50
Optimize mint
erikzhang Jul 17, 2020
6294404
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 17, 2020
4cfa41c
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 18, 2020
2638d9f
Use Transaction.GetAttribute<T>()
erikzhang Jul 18, 2020
c9bb097
Add GasFreeForOracle
erikzhang Jul 18, 2020
5c1ba7e
Allow FeeOnly for cosigners
erikzhang Jul 18, 2020
5786d9c
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 18, 2020
5ffbc09
Move some checks from OracleContract.Verify() to OracleResponse.Verify()
erikzhang Jul 20, 2020
bd02062
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 24, 2020
6c6cfff
Revert "Add GasFreeForOracle"
erikzhang Jul 24, 2020
3ad9f28
gasForRepsonse should be greater then 0.1 GAS
erikzhang Jul 24, 2020
7476b54
Merge branch 'master' into asynchronous-oracle
erikzhang Jul 29, 2020
c938ac6
Merge branch 'master' into asynchronous-oracle
erikzhang Aug 6, 2020
d307bca
Fix
erikzhang Aug 6, 2020
87422de
Merge branch 'master' into asynchronous-oracle
erikzhang Aug 11, 2020
f5bbf30
Add id to GetRequests()
erikzhang Aug 12, 2020
60856f6
Typo
shargon Aug 12, 2020
dfe8904
Merge branch 'master' into asynchronous-oracle
erikzhang Aug 19, 2020
cb7a327
Merge branch 'master' into asynchronous-oracle
erikzhang Aug 21, 2020
9b8801c
Merge branch 'master' into asynchronous-oracle
erikzhang Aug 28, 2020
c108af4
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
erikzhang Aug 28, 2020
5d28cd6
Optimize PostPersist when no oracleTx
shargon Aug 28, 2020
5363b6a
Merge branch 'master' into asynchronous-oracle
shargon Aug 28, 2020
708b1d8
Apply #1880
shargon Aug 28, 2020
51a6b86
Simplify
erikzhang Aug 28, 2020
b7ded27
Check for SetOracleNodes
erikzhang Aug 28, 2020
cb4f355
Remove check
shargon Aug 28, 2020
a4b5b4d
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
shargon Aug 31, 2020
cee850e
Merge branch 'master' into asynchronous-oracle
shargon Aug 31, 2020
cfc604c
Add OracleResponseCode
erikzhang Aug 31, 2020
3aae3f7
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
shargon Sep 1, 2020
d04709b
Merge branch 'master' into asynchronous-oracle
shargon Sep 1, 2020
2d356a0
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
erikzhang Sep 2, 2020
8937f49
Update src/neo/Network/P2P/Payloads/OracleResponse.cs
erikzhang Sep 2, 2020
1ffa850
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
shargon Sep 2, 2020
b58ef07
Merge branch 'master' into asynchronous-oracle
shargon Sep 2, 2020
93899b2
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
shargon Sep 2, 2020
7deeb06
fix format
shargon Sep 2, 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
48 changes: 48 additions & 0 deletions src/neo/Network/P2P/Payloads/OracleResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Neo.IO;
using Neo.IO.Json;
using System;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
public class OracleResponse : TransactionAttribute
{
private const int MaxResultSize = 1024;
shargon marked this conversation as resolved.
Show resolved Hide resolved

public ulong Id;
public bool Success;
public byte[] Result;

public override TransactionAttributeType Type => TransactionAttributeType.OracleResponse;
public override bool AllowMultiple => false;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

public override int Size => base.Size +
sizeof(ulong) + //Id
sizeof(bool) + //Success
Result.GetVarSize(); //Result

protected override void DeserializeWithoutType(BinaryReader reader)
{
Id = reader.ReadUInt64();
Success = reader.ReadBoolean();
Result = reader.ReadVarBytes(MaxResultSize);
shargon marked this conversation as resolved.
Show resolved Hide resolved
if (!Success && Result.Length > 0) throw new FormatException();
}

protected override void SerializeWithoutType(BinaryWriter writer)
{
writer.Write(Id);
writer.Write(Success);
writer.WriteVarBytes(Result);
}

public override JObject ToJson()
{
JObject json = base.ToJson();
json["id"] = Id;
json["success"] = Success;
json["result"] = Convert.ToBase64String(Result);
return json;
}
}
}
40 changes: 36 additions & 4 deletions src/neo/Network/P2P/Payloads/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Neo.Persistence;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.SmartContract.Native.Oracle;
using Neo.VM;
using Neo.VM.Types;
using Neo.Wallets;
Expand All @@ -26,6 +27,8 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable
/// </summary>
public const int MaxTransactionAttributes = 16;

private static readonly byte[] oracleResponseScript;

private byte version;
private uint nonce;
private UInt160 sender;
Expand Down Expand Up @@ -53,6 +56,8 @@ public TransactionAttribute[] Attributes
private Dictionary<UInt160, Cosigner> _cosigners;
public IReadOnlyDictionary<UInt160, Cosigner> Cosigners => _cosigners ??= attributes.OfType<Cosigner>().ToDictionary(p => p.Account);

public bool IsOracleResponse => Attributes.Any(p => p is OracleResponse);

/// <summary>
/// The <c>NetworkFee</c> for the transaction divided by its <c>Size</c>.
/// <para>Note that this property must be used with care. Getting the value of this property multiple times will return the same result. The value of this property can only be obtained after the transaction has been completely built (no longer modified).</para>
Expand Down Expand Up @@ -144,6 +149,22 @@ public Witness[] Witnesses
set { witnesses = value; _size = 0; }
}

static Transaction()
{
using ScriptBuilder sb = new ScriptBuilder();
sb.EmitAppCall(NativeContract.Oracle.Hash, "finish");
oracleResponseScript = sb.ToArray();
}

private bool CheckOracleResponse(StoreView snapshot)
{
OracleResponse response = Attributes.OfType<OracleResponse>().FirstOrDefault();
if (response is null) return true;
OracleRequest request = NativeContract.Oracle.GetRequest(snapshot, response.Id);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
Transaction request_tx = snapshot.GetTransaction(request.Txid);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
return Sender.Equals(request_tx.Sender);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

void ISerializable.Deserialize(BinaryReader reader)
{
int startPosition = -1;
Expand Down Expand Up @@ -191,6 +212,12 @@ public void DeserializeUnsigned(BinaryReader reader)
}
Script = reader.ReadVarBytes(ushort.MaxValue);
if (Script.Length == 0) throw new FormatException();
if (IsOracleResponse)
{
if (Cosigners.Count > 0) throw new FormatException();
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
if (!Script.AsSpan().SequenceEqual(oracleResponseScript))
throw new FormatException();
}
}

public bool Equals(Transaction other)
Expand All @@ -217,7 +244,12 @@ public override int GetHashCode()

public UInt160[] GetScriptHashesForVerifying(StoreView snapshot)
{
var hashes = new HashSet<UInt160>(Cosigners.Keys) { Sender };
var hashes = new HashSet<UInt160>(Cosigners.Keys)
{
IsOracleResponse
? Blockchain.GetConsensusAddress(NativeContract.Oracle.GetOracleNodes(snapshot))
: Sender
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
};
return hashes.OrderBy(p => p).ToArray();
}

Expand Down Expand Up @@ -286,9 +318,9 @@ public virtual VerifyResult Verify(StoreView snapshot, BigInteger totalSenderFee
{
VerifyResult result = VerifyForEachBlock(snapshot, totalSenderFeeFromPool);
if (result != VerifyResult.Succeed) return result;
int size = Size;
if (size > MaxTransactionSize) return VerifyResult.Invalid;
long net_fee = NetworkFee - size * NativeContract.Policy.GetFeePerByte(snapshot);
if (!CheckOracleResponse(snapshot)) return VerifyResult.Invalid;
if (Size > MaxTransactionSize) return VerifyResult.Invalid;
long net_fee = NetworkFee - Size * NativeContract.Policy.GetFeePerByte(snapshot);
if (net_fee < 0) return VerifyResult.InsufficientFunds;
if (!this.VerifyWitnesses(snapshot, net_fee)) return VerifyResult.Invalid;
return VerifyResult.Succeed;
Expand Down
4 changes: 3 additions & 1 deletion src/neo/Network/P2P/Payloads/TransactionAttributeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace Neo.Network.P2P.Payloads
public enum TransactionAttributeType : byte
{
[ReflectionCache(typeof(Cosigner))]
Cosigner = 0x01
Cosigner = 0x01,
[ReflectionCache(typeof(OracleResponse))]
OracleResponse = 0x11
}
}
16 changes: 15 additions & 1 deletion src/neo/SmartContract/ApplicationEngine.Runtime.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.Network.P2P.Payloads;
using Neo.SmartContract.Native;
using Neo.SmartContract.Native.Oracle;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -104,7 +106,19 @@ internal bool CheckWitnessInternal(UInt160 hash)
{
if (ScriptContainer is Transaction tx)
{
if (!tx.Cosigners.TryGetValue(hash, out Cosigner cosigner)) return false;
IReadOnlyDictionary<UInt160, Cosigner> cosigners;
OracleResponse response = tx.Attributes.OfType<OracleResponse>().FirstOrDefault();
if (response is null)
{
cosigners = tx.Cosigners;
}
else
{
OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id);
Transaction request_tx = Snapshot.GetTransaction(request.Txid);
shargon marked this conversation as resolved.
Show resolved Hide resolved
cosigners = request_tx.Cosigners;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}
if (!cosigners.TryGetValue(hash, out Cosigner cosigner)) return false;
if (cosigner.Scopes == WitnessScope.Global) return true;
if (cosigner.Scopes.HasFlag(WitnessScope.CalledByEntry))
{
Expand Down
8 changes: 8 additions & 0 deletions src/neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,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 @@ -24,6 +25,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();

[ContractMethod(0, CallFlags.None)]
public abstract string Name { get; }
Expand Down Expand Up @@ -79,6 +81,12 @@ protected NativeContract()
contractsHashDictionary.Add(Hash, this);
}

protected bool CheckCommittees(ApplicationEngine engine)
vncoelho marked this conversation as resolved.
Show resolved Hide resolved
{
UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.Snapshot);
return engine.CheckWitnessInternal(committeeMultiSigAddr);
}

protected StorageKey CreateStorageKey(byte prefix, byte[] key = null)
{
StorageKey storageKey = new StorageKey
Expand Down
43 changes: 43 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OracleContract.Lists.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Linq;
using Array = Neo.VM.Types.Array;

namespace Neo.SmartContract.Native.Oracle
{
partial class OracleContract
{
private class IdList : List<ulong>, IInteroperable
{
public void FromStackItem(StackItem stackItem)
{
foreach (StackItem item in (Array)stackItem)
Add(BinaryPrimitives.ReadUInt64LittleEndian(item.GetSpan()));
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

public StackItem ToStackItem(ReferenceCounter referenceCounter)
{
return new Array(referenceCounter, this.Select(p => (StackItem)BitConverter.GetBytes(p)));
}
}

private class NodeList : List<ECPoint>, IInteroperable
{
public void FromStackItem(StackItem stackItem)
{
foreach (StackItem item in (Array)stackItem)
Add(ECPoint.DecodePoint(item.GetSpan(), ECCurve.Secp256r1));
}

public StackItem ToStackItem(ReferenceCounter referenceCounter)
{
return new Array(referenceCounter, this.Select(p => (StackItem)p.ToArray()));
}
}
}
}
135 changes: 135 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OracleContract.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#pragma warning disable IDE0051

using Neo.Cryptography;
using Neo.Cryptography.ECC;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract.Manifest;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace Neo.SmartContract.Native.Oracle
{
public sealed partial class OracleContract : NativeContract
vncoelho marked this conversation as resolved.
Show resolved Hide resolved
{
private const int MaxUrlLength = 256;
private const int MaxFilterLength = 128;
private const int MaxCallbackLength = 32;
private const int MaxUserDataLength = 512;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

private const byte Prefix_NodeList = 8;
private const byte Prefix_RequestId = 9;
private const byte Prefix_Request = 7;
private const byte Prefix_IdList = 6;

private const long OracleRequestPrice = 0_50000000;

public override int Id => -4;
public override string Name => "Oracle";

internal OracleContract()
{
Manifest.Features = ContractFeatures.HasStorage | ContractFeatures.Payable;
}

[ContractMethod(0, CallFlags.AllowModifyStates)]
private void Finish(ApplicationEngine engine)
{
Transaction tx = (Transaction)engine.ScriptContainer;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
OracleResponse response = tx.Attributes.OfType<OracleResponse>().First();
StorageKey key = CreateStorageKey(Prefix_Request, BitConverter.GetBytes(response.Id));
OracleRequest request = engine.Snapshot.Storages[key].GetInteroperable<OracleRequest>();
engine.Snapshot.Storages.Delete(key);
key = CreateStorageKey(Prefix_IdList, GetUrlHash(request.Url));
IdList list = engine.Snapshot.Storages.GetAndChange(key).GetInteroperable<IdList>();
if (!list.Remove(response.Id)) throw new InvalidOperationException();
if (list.Count == 0) engine.Snapshot.Storages.Delete(key);
GAS.Mint(engine, Hash, OracleRequestPrice);
StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.MaxStackSize, engine.MaxItemSize, engine.ReferenceCounter);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
engine.CallFromNativeContract(null, request.CallbackContract, request.CallbackMethod, request.Url, userData, response.Success, response.Result);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public ECPoint[] GetOracleNodes(StoreView snapshot)
{
return snapshot.Storages[CreateStorageKey(Prefix_NodeList)].GetInteroperable<NodeList>().ToArray();
}

public OracleRequest GetRequest(StoreView snapshot, ulong id)
{
return snapshot.Storages.TryGet(CreateStorageKey(Prefix_Request, BitConverter.GetBytes(id)))?.GetInteroperable<OracleRequest>();
}

public IEnumerable<OracleRequest> GetRequests(StoreView snapshot)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
return snapshot.Storages.Find(new byte[] { Prefix_Request }).Select(p => p.Value.GetInteroperable<OracleRequest>());
}

public IEnumerable<OracleRequest> GetRequestsByUrl(StoreView snapshot, string url)
{
IdList list = snapshot.Storages.TryGet(CreateStorageKey(Prefix_IdList, GetUrlHash(url)))?.GetInteroperable<IdList>();
if (list is null) yield break;
foreach (ulong id in list)
yield return snapshot.Storages[CreateStorageKey(Prefix_Request, BitConverter.GetBytes(id))].GetInteroperable<OracleRequest>();
}

private static byte[] GetUrlHash(string url)
{
return Crypto.Hash160(Utility.StrictUTF8.GetBytes(url));
}

[ContractMethod(1_00000000, CallFlags.AllowModifyStates)]
private void Incentivize(ApplicationEngine engine)
{
ECPoint[] nodes = GetOracleNodes(engine.Snapshot);
BigInteger gas = GAS.BalanceOf(engine.Snapshot, Hash) / nodes.Length;
if (gas.IsZero) return;
foreach (ECPoint node in nodes)
{
UInt160 to = Contract.CreateSignatureRedeemScript(node).ToScriptHash();
GAS.TransferInternal(engine, Hash, to, gas);
}
}

internal override void Initialize(ApplicationEngine engine)
{
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_NodeList), new StorageItem(new NodeList()));
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_RequestId), new StorageItem(BitConverter.GetBytes(0ul)));
}

[ContractMethod(OracleRequestPrice, CallFlags.AllowModifyStates)]
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
private void Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData)
{
if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength
|| (filter != null && Utility.StrictUTF8.GetByteCount(filter) > MaxFilterLength)
|| Utility.StrictUTF8.GetByteCount(callback) > MaxCallbackLength)
throw new ArgumentException();
StorageItem item_id = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_RequestId));
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
ulong id = BitConverter.ToUInt64(item_id.Value) + 1;
Copy link
Member

Choose a reason for hiding this comment

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

The request Id it's predictable and it's used for reward a specific Oracle Node, if the owner of a exchange (or someone who produce a lot of tx) own a Oracle node can send transactions only if this node will be rewarded.

Copy link
Member Author

Choose a reason for hiding this comment

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

This will not cause uneven distribution.

Copy link
Member

Choose a reason for hiding this comment

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

If we make a hash, it could be uneven, but statistically should be fair.

item_id.Value = BitConverter.GetBytes(id);
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Request, item_id.Value), new StorageItem(new OracleRequest
{
Txid = ((Transaction)engine.ScriptContainer).Hash,
Url = url,
Filter = filter,
CallbackContract = engine.CallingScriptHash,
CallbackMethod = callback,
UserData = BinarySerializer.Serialize(userData, MaxUserDataLength)
}));
engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_IdList, GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable<IdList>().Add(id);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

[ContractMethod(0, CallFlags.AllowModifyStates)]
private void SetOracleNodes(ApplicationEngine engine, ECPoint[] nodes)
{
if (!CheckCommittees(engine)) throw new InvalidOperationException();
NodeList list = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_NodeList)).GetInteroperable<NodeList>();
list.Clear();
list.AddRange(nodes);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Loading