Skip to content

Commit

Permalink
Oracle: P2P Response Signature Message (neo-project#1553)
Browse files Browse the repository at this point in the history
* Oracle Response Signature P2P

* caches

* rename private fields

* remove comments

* remove more comments and fix size

* Clean code

Co-authored-by: Shargon <shargon@gmail.com>
  • Loading branch information
belane and shargon committed Apr 17, 2020
1 parent 3177b80 commit da828e4
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/neo/Network/P2P/MessageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public enum MessageCommand : byte
Block = 0x2c,
[ReflectionCache(typeof(ConsensusPayload))]
Consensus = 0x2d,
[ReflectionCache(typeof(OraclePayload))]
Oracle = 0x2e,
Reject = 0x2f,

//SPV protocol
Expand All @@ -52,6 +54,6 @@ public enum MessageCommand : byte
MerkleBlock = 0x38,

//others
Alert = 0x40,
Alert = 0x40
}
}
134 changes: 134 additions & 0 deletions src/neo/Network/P2P/Payloads/OraclePayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Neo.IO;
using System.IO;
using Neo.Cryptography;
using Neo.Cryptography.ECC;
using Neo.Persistence;
using System;
using System.Linq;
using Neo.SmartContract;
using Neo.SmartContract.Native;

namespace Neo.Network.P2P.Payloads
{
public class OraclePayload : IVerifiable
{
private byte[] _data;
public byte[] Data
{
get => _data;
set { _data = value; _hash = null; _size = 0; }
}

private ECPoint _oraclePub;
public ECPoint OraclePub
{
get => _oraclePub;
set { _oraclePub = value; _hash = null; _size = 0; }
}

private Witness _witness;
public Witness Witness
{
get => _witness;
set { _witness = value; _hash = null; _size = 0; }
}

private int _size;
public int Size
{
get
{
if (_size == 0)
{
_size = Data.GetVarSize() + //Data
OraclePub.Size + //Oracle Public key
Witness.Size; //Witness
}
return _size;
}
}

private UInt256 _hash = null;
public UInt256 Hash
{
get
{
if (_hash == null)
{
_hash = new UInt256(Crypto.Hash256(this.GetHashData()));
}
return _hash;
}
}

public Witness[] Witnesses
{
get => new[] { Witness };
set
{
if (value.Length != 1) throw new ArgumentException();
Witness = value[0];
}
}

private OracleResponseSignature _deserializedOracleSignature = null;
public OracleResponseSignature OracleSignature
{
get
{
if (_deserializedOracleSignature is null)
_deserializedOracleSignature = OracleResponseSignature.DeserializeFrom(Data);
return _deserializedOracleSignature;
}
internal set
{
if (!ReferenceEquals(_deserializedOracleSignature, value))
{
_deserializedOracleSignature = value;
Data = value?.ToArray();
}
}
}

public OracleResponseSignature GetDeserializedOracleSignature()
{
return OracleSignature;
}

void ISerializable.Deserialize(BinaryReader reader)
{
((IVerifiable)this).DeserializeUnsigned(reader);
Witness = reader.ReadSerializable<Witness>();
}
void IVerifiable.DeserializeUnsigned(BinaryReader reader)
{
Data = reader.ReadVarBytes(Transaction.MaxTransactionSize);
OraclePub = reader.ReadSerializable<ECPoint>();
}

public virtual void Serialize(BinaryWriter writer)
{
((IVerifiable)this).SerializeUnsigned(writer);
writer.Write(new Witness[] { Witness });
}

void IVerifiable.SerializeUnsigned(BinaryWriter writer)
{
writer.Write(Data);
writer.Write(OraclePub);
}

UInt160[] IVerifiable.GetScriptHashesForVerifying(StoreView snapshot)
{
return new[] { Contract.CreateSignatureRedeemScript(OraclePub).ToScriptHash() };
}

public bool Verify(StoreView snapshot)
{
ECPoint[] validators = NativeContract.Oracle.GetOracleValidators(snapshot);
if (!validators.Any(u => u.Equals(OraclePub)))
return false;
return this.VerifyWitnesses(snapshot, 0_02000000);
}
}
}
110 changes: 110 additions & 0 deletions src/neo/Network/P2P/Payloads/OracleResponseSignature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using Neo.Cryptography;
using Neo.IO;
using System;
using System.IO;
using System.Linq;
using System.Text;

namespace Neo.Network.P2P.Payloads
{
public class OracleResponseSignature : ISerializable
{
private const byte ResponseSignatureType = 0x01;

private UInt256 _transactionRequestHash;
public UInt256 TransactionRequestHash
{
get => _transactionRequestHash;
set { _transactionRequestHash = value; _hash = null; _size = 0; }
}

private UInt256 _oracleExecutionCacheHash;
public UInt256 OracleExecutionCacheHash
{
get => _oracleExecutionCacheHash;
set { _oracleExecutionCacheHash = value; _hash = null; _size = 0; }
}

/// <summary>
/// Signature for the oracle response tx for this public key
/// </summary>
private byte[] _signature;
public byte[] Signature
{
get => _signature;
set
{
if (value.Length != 64) throw new ArgumentException();
_signature = value;
_hash = null;
_size = 0;
}
}

private int _size;
public int Size
{
get
{
if (_size == 0)
{
_size = sizeof(byte) + //Type
UInt256.Length + //Transaction Hash
UInt256.Length + //OracleExecutionCache Hash
Signature.Length; //Oracle Validator Signature
}
return _size;
}
}

private UInt256 _hash = null;
public UInt256 Hash
{
get
{
if (_hash == null)
{
_hash = new UInt256(Crypto.Hash256(this.ToArray()));
}
return _hash;
}
}

public virtual void Deserialize(BinaryReader reader)
{
if (reader.ReadByte() != ResponseSignatureType) throw new FormatException();
DeserializeWithoutType(reader);
}

private void DeserializeWithoutType(BinaryReader reader)
{
TransactionRequestHash = reader.ReadSerializable<UInt256>();
OracleExecutionCacheHash = reader.ReadSerializable<UInt256>();
Signature = reader.ReadFixedBytes(64);
}

public static OracleResponseSignature DeserializeFrom(byte[] data)
{
switch (data[0])
{
case ResponseSignatureType:
{
using BinaryReader reader = new BinaryReader(new MemoryStream(data, 1, data.Length - 1), Encoding.UTF8, false);

var ret = new OracleResponseSignature();
ret.DeserializeWithoutType(reader);
return ret;
}
default: throw new FormatException();
}
}

public virtual void Serialize(BinaryWriter writer)
{
writer.Write(ResponseSignatureType);
writer.Write(TransactionRequestHash);
writer.Write(OracleExecutionCacheHash);
writer.Write(Signature);
}
}
}

0 comments on commit da828e4

Please sign in to comment.