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 81 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
40 changes: 27 additions & 13 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class RelayResult { public IInventory Inventory; public VerifyResult Resu
Transactions = new[] { DeployNativeContracts() }
};

private readonly static Script onPersistNativeContractScript;
private readonly static Script onPersistScript, postPersistScript;
private const int MaxTxToReverifyPerIdle = 10;
private static readonly object lockObj = new object();
private readonly NeoSystem system;
Expand Down Expand Up @@ -87,16 +87,23 @@ static Blockchain()
{
GenesisBlock.RebuildMerkleRoot();

NativeContract[] contracts = { NativeContract.GAS, NativeContract.NEO };
using (ScriptBuilder sb = new ScriptBuilder())
{
foreach (NativeContract contract in contracts)
foreach (NativeContract contract in new NativeContract[] { NativeContract.GAS, NativeContract.NEO })
{
sb.EmitAppCall(contract.Hash, "onPersist");
sb.Emit(OpCode.DROP);
}

onPersistNativeContractScript = sb.ToArray();
onPersistScript = sb.ToArray();
}
using (ScriptBuilder sb = new ScriptBuilder())
{
foreach (NativeContract contract in new NativeContract[] { NativeContract.Oracle })
{
sb.EmitAppCall(contract.Hash, "postPersist");
shargon marked this conversation as resolved.
Show resolved Hide resolved
sb.Emit(OpCode.DROP);
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
postPersistScript = sb.ToArray();
}
}

Expand Down Expand Up @@ -418,14 +425,12 @@ private void Persist(Block block)
snapshot.PersistingBlock = block;
if (block.Index > 0)
{
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.System, null, snapshot))
{
engine.LoadScript(onPersistNativeContractScript);
if (engine.Execute() != VMState.HALT) throw new InvalidOperationException();
ApplicationExecuted application_executed = new ApplicationExecuted(engine);
Context.System.EventStream.Publish(application_executed);
all_application_executed.Add(application_executed);
}
using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.System, null, snapshot);
engine.LoadScript(onPersistScript);
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
if (engine.Execute() != VMState.HALT) throw new InvalidOperationException();
ApplicationExecuted application_executed = new ApplicationExecuted(engine);
Context.System.EventStream.Publish(application_executed);
all_application_executed.Add(application_executed);
}
snapshot.Blocks.Add(block.Hash, block.Trim());
StoreView clonedSnapshot = snapshot.Clone();
Expand Down Expand Up @@ -459,6 +464,15 @@ private void Persist(Block block)
}
}
snapshot.BlockHashIndex.GetAndChange().Set(block);
if (block.Index > 0)
{
using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.System, null, snapshot);
engine.LoadScript(postPersistScript);
if (engine.Execute() != VMState.HALT) throw new InvalidOperationException();
ApplicationExecuted application_executed = new ApplicationExecuted(engine);
Context.System.EventStream.Publish(application_executed);
all_application_executed.Add(application_executed);
}
foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins)
plugin.OnPersist(snapshot, all_application_executed);
snapshot.Commit();
Expand Down
74 changes: 74 additions & 0 deletions src/neo/Network/P2P/Payloads/OracleResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Neo.IO;
using Neo.IO.Json;
using Neo.Ledger;
using Neo.Persistence;
using Neo.SmartContract.Native;
using Neo.SmartContract.Native.Oracle;
using Neo.VM;
using System;
using System.IO;
using System.Linq;

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 static readonly byte[] FixedScript;

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

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

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;
}

public override bool Verify(StoreView snapshot, Transaction tx)
{
if (tx.Signers.Any(p => p.Scopes != WitnessScope.None)) return false;
if (!tx.Script.AsSpan().SequenceEqual(FixedScript)) return false;
shargon marked this conversation as resolved.
Show resolved Hide resolved
OracleRequest request = NativeContract.Oracle.GetRequest(snapshot, Id);
if (request is null) return false;
if (tx.NetworkFee + tx.SystemFee > request.GasForResponse) return false;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
UInt160 oracleAccount = Blockchain.GetConsensusAddress(NativeContract.Oracle.GetOracleNodes(snapshot));
return tx.Signers.Any(p => p.Account.Equals(oracleAccount));
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
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(HighPriorityAttribute))]
HighPriority = 1
HighPriority = 0x01,
[ReflectionCache(typeof(OracleResponse))]
OracleResponse = 0x11
}
}
15 changes: 14 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,18 @@ protected internal bool CheckWitnessInternal(UInt160 hash)
{
if (ScriptContainer is Transaction tx)
{
Signer signer = tx.Signers.FirstOrDefault(p => p.Account.Equals(hash));
Signer[] signers;
OracleResponse response = tx.GetAttribute<OracleResponse>();
if (response is null)
{
signers = tx.Signers;
}
else
{
OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id);
signers = Snapshot.GetTransaction(request.OriginalTxid).Signers;
}
Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash));
if (signer is null) return false;
if (signer.Scopes == WitnessScope.Global) return true;
if (signer.Scopes.HasFlag(WitnessScope.CalledByEntry))
Expand Down
9 changes: 9 additions & 0 deletions src/neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Neo.IO;
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();

[ContractMethod(0, CallFlags.None)]
public abstract string Name { get; }
Expand Down Expand Up @@ -140,6 +142,13 @@ protected virtual void OnPersist(ApplicationEngine engine)
throw new InvalidOperationException();
}

[ContractMethod(0, CallFlags.AllowModifyStates)]
protected virtual void PostPersist(ApplicationEngine engine)
{
if (engine.Trigger != TriggerType.System)
throw new InvalidOperationException();
}

public ApplicationEngine TestCall(string operation, params object[] args)
{
using (ScriptBuilder sb = new ScriptBuilder())
Expand Down
40 changes: 40 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OracleContract.Lists.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.VM;
using Neo.VM.Types;
using System.Collections.Generic;
using System.Linq;

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((ulong)item.GetInteger());
}

public StackItem ToStackItem(ReferenceCounter referenceCounter)
{
return new Array(referenceCounter, this.Select(p => (Integer)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()));
}
}
}
}
Loading