Skip to content

Commit

Permalink
Merge branch 'master' into change_consensus_timespan_strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Qiao-Jin authored May 9, 2020
2 parents 475e49f + a995e02 commit 3b2b4ef
Show file tree
Hide file tree
Showing 29 changed files with 184 additions and 222 deletions.
26 changes: 15 additions & 11 deletions src/neo/IO/Caching/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class Trackable
}

private readonly Dictionary<TKey, Trackable> dictionary = new Dictionary<TKey, Trackable>();
private readonly HashSet<TKey> changeSet = new HashSet<TKey>();

public TValue this[TKey key]
{
Expand Down Expand Up @@ -65,6 +66,7 @@ public void Add(TKey key, TValue value)
Item = value,
State = trackable == null ? TrackState.Added : TrackState.Changed
};
changeSet.Add(key);
}
}

Expand Down Expand Up @@ -96,6 +98,7 @@ public void Commit()
{
dictionary.Remove(key);
}
changeSet.Clear();
}

public DataCache<TKey, TValue> CreateSnapshot()
Expand All @@ -114,9 +117,15 @@ public void Delete(TKey key)
if (dictionary.TryGetValue(key, out Trackable trackable))
{
if (trackable.State == TrackState.Added)
{
dictionary.Remove(key);
changeSet.Remove(key);
}
else
{
trackable.State = TrackState.Deleted;
changeSet.Add(key);
}
}
else
{
Expand All @@ -128,21 +137,13 @@ public void Delete(TKey key)
Item = item,
State = TrackState.Deleted
});
changeSet.Add(key);
}
}
}

protected abstract void DeleteInternal(TKey key);

public void DeleteWhere(Func<TKey, TValue, bool> predicate)
{
lock (dictionary)
{
foreach (Trackable trackable in dictionary.Where(p => p.Value.State != TrackState.Deleted && predicate(p.Key, p.Value.Item)).Select(p => p.Value))
trackable.State = TrackState.Deleted;
}
}

/// <summary>
/// Find the entries that start with the `key_prefix`
/// </summary>
Expand Down Expand Up @@ -204,8 +205,8 @@ public IEnumerable<Trackable> GetChangeSet()
{
lock (dictionary)
{
foreach (Trackable trackable in dictionary.Values.Where(p => p.State != TrackState.None))
yield return trackable;
foreach (TKey key in changeSet)
yield return dictionary[key];
}
}

Expand Down Expand Up @@ -234,6 +235,7 @@ public TValue GetAndChange(TKey key, Func<TValue> factory = null)
else if (trackable.State == TrackState.None)
{
trackable.State = TrackState.Changed;
changeSet.Add(key);
}
}
else
Expand All @@ -254,6 +256,7 @@ public TValue GetAndChange(TKey key, Func<TValue> factory = null)
trackable.State = TrackState.Changed;
}
dictionary.Add(key, trackable);
changeSet.Add(key);
}
return trackable.Item;
}
Expand Down Expand Up @@ -282,6 +285,7 @@ public TValue GetOrAdd(TKey key, Func<TValue> factory)
{
trackable.Item = factory();
trackable.State = TrackState.Added;
changeSet.Add(key);
}
else
{
Expand Down
3 changes: 1 addition & 2 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ private static Transaction DeployNativeContracts()
Script = script,
Sender = (new[] { (byte)OpCode.PUSH1 }).ToScriptHash(),
SystemFee = 0,
Attributes = new TransactionAttribute[0],
Cosigners = new Cosigner[0],
Attributes = Array.Empty<TransactionAttribute>(),
Witnesses = new[]
{
new Witness
Expand Down
20 changes: 11 additions & 9 deletions src/neo/Network/P2P/Payloads/Cosigner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,30 @@

namespace Neo.Network.P2P.Payloads
{
public class Cosigner : ISerializable
public class Cosigner : TransactionAttribute
{
// This limits maximum number of AllowedContracts or AllowedGroups here
private const int MaxSubitems = 16;

public UInt160 Account;
public WitnessScope Scopes;
public UInt160[] AllowedContracts;
public ECPoint[] AllowedGroups;

public override TransactionAttributeType Type => TransactionAttributeType.Cosigner;

public Cosigner()
{
this.Scopes = WitnessScope.Global;
}

// This limits maximum number of AllowedContracts or AllowedGroups here
private int MaxSubitems = 16;

public int Size =>
public override int Size => base.Size +
/*Account*/ UInt160.Length +
/*Scopes*/ sizeof(WitnessScope) +
/*AllowedContracts*/ (Scopes.HasFlag(WitnessScope.CustomContracts) ? AllowedContracts.GetVarSize() : 0) +
/*AllowedGroups*/ (Scopes.HasFlag(WitnessScope.CustomGroups) ? AllowedGroups.GetVarSize() : 0);

void ISerializable.Deserialize(BinaryReader reader)
protected override void DeserializeWithoutType(BinaryReader reader)
{
Account = reader.ReadSerializable<UInt160>();
Scopes = (WitnessScope)reader.ReadByte();
Expand All @@ -39,7 +41,7 @@ void ISerializable.Deserialize(BinaryReader reader)
: new ECPoint[0];
}

void ISerializable.Serialize(BinaryWriter writer)
protected override void SerializeWithoutType(BinaryWriter writer)
{
writer.Write(Account);
writer.Write((byte)Scopes);
Expand All @@ -49,9 +51,9 @@ void ISerializable.Serialize(BinaryWriter writer)
writer.Write(AllowedGroups);
}

public JObject ToJson()
public override JObject ToJson()
{
JObject json = new JObject();
JObject json = base.ToJson();
json["account"] = Account.ToString();
json["scopes"] = Scopes;
if (Scopes.HasFlag(WitnessScope.CustomContracts))
Expand Down
30 changes: 10 additions & 20 deletions src/neo/Network/P2P/Payloads/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable
/// <summary>
/// Maximum number of attributes that can be contained within a transaction
/// </summary>
private const int MaxTransactionAttributes = 16;
/// <summary>
/// Maximum number of cosigners that can be contained within a transaction
/// </summary>
private const int MaxCosigners = 16;
public const int MaxTransactionAttributes = 16;

private byte version;
private uint nonce;
Expand All @@ -37,7 +33,6 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable
private long netfee;
private uint validUntilBlock;
private TransactionAttribute[] attributes;
private Cosigner[] cosigners;
private byte[] script;
private Witness[] witnesses;

Expand All @@ -52,14 +47,11 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable
public TransactionAttribute[] Attributes
{
get => attributes;
set { attributes = value; _hash = null; _size = 0; }
set { attributes = value; _cosigners = null; _hash = null; _size = 0; }
}

public Cosigner[] Cosigners
{
get => cosigners;
set { cosigners = value; _hash = null; _size = 0; }
}
private Cosigner[] _cosigners;
public Cosigner[] Cosigners => _cosigners ??= attributes.OfType<Cosigner>().ToArray();

/// <summary>
/// The <c>NetworkFee</c> for the transaction divided by its <c>Size</c>.
Expand Down Expand Up @@ -117,10 +109,9 @@ public int Size
if (_size == 0)
{
_size = HeaderSize +
Attributes.GetVarSize() + //Attributes
Cosigners.GetVarSize() + //Cosigners
Script.GetVarSize() + //Script
Witnesses.GetVarSize(); //Witnesses
Attributes.GetVarSize() + // Attributes
Script.GetVarSize() + // Script
Witnesses.GetVarSize(); // Witnesses
}
return _size;
}
Expand Down Expand Up @@ -176,8 +167,9 @@ public void DeserializeUnsigned(BinaryReader reader)
if (NetworkFee < 0) throw new FormatException();
if (SystemFee + NetworkFee < SystemFee) throw new FormatException();
ValidUntilBlock = reader.ReadUInt32();
Attributes = reader.ReadSerializableArray<TransactionAttribute>(MaxTransactionAttributes);
Cosigners = reader.ReadSerializableArray<Cosigner>(MaxCosigners);
Attributes = new TransactionAttribute[reader.ReadVarInt(MaxTransactionAttributes)];
for (int i = 0; i < Attributes.Length; i++)
Attributes[i] = TransactionAttribute.DeserializeFrom(reader);
if (Cosigners.Select(u => u.Account).Distinct().Count() != Cosigners.Length) throw new FormatException();
Script = reader.ReadVarBytes(ushort.MaxValue);
if (Script.Length == 0) throw new FormatException();
Expand Down Expand Up @@ -227,7 +219,6 @@ void IVerifiable.SerializeUnsigned(BinaryWriter writer)
writer.Write(NetworkFee);
writer.Write(ValidUntilBlock);
writer.Write(Attributes);
writer.Write(Cosigners);
writer.WriteVarBytes(Script);
}

Expand All @@ -243,7 +234,6 @@ public JObject ToJson()
json["net_fee"] = NetworkFee.ToString();
json["valid_until_block"] = ValidUntilBlock;
json["attributes"] = Attributes.Select(p => p.ToJson()).ToArray();
json["cosigners"] = Cosigners.Select(p => p.ToJson()).ToArray();
json["script"] = Convert.ToBase64String(Script);
json["witnesses"] = Witnesses.Select(p => p.ToJson()).ToArray();
return json;
Expand Down
43 changes: 27 additions & 16 deletions src/neo/Network/P2P/Payloads/TransactionAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
using Neo.IO;
using Neo.IO.Caching;
using Neo.IO.Json;
using System;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
public class TransactionAttribute : ISerializable
public abstract class TransactionAttribute : ISerializable
{
public TransactionAttributeUsage Usage;
public byte[] Data;
public abstract TransactionAttributeType Type { get; }
public virtual int Size => sizeof(TransactionAttributeType);

public int Size => sizeof(TransactionAttributeUsage) + Data.GetVarSize();
public void Deserialize(BinaryReader reader)
{
if (reader.ReadByte() != (byte)Type)
throw new FormatException();
DeserializeWithoutType(reader);
}

void ISerializable.Deserialize(BinaryReader reader)
public static TransactionAttribute DeserializeFrom(BinaryReader reader)
{
Usage = (TransactionAttributeUsage)reader.ReadByte();
if (!Enum.IsDefined(typeof(TransactionAttributeUsage), Usage))
TransactionAttributeType type = (TransactionAttributeType)reader.ReadByte();
if (!(ReflectionCache<TransactionAttributeType>.CreateInstance(type) is TransactionAttribute attribute))
throw new FormatException();
Data = reader.ReadVarBytes(252);
attribute.DeserializeWithoutType(reader);
return attribute;
}

void ISerializable.Serialize(BinaryWriter writer)
protected abstract void DeserializeWithoutType(BinaryReader reader);

public virtual JObject ToJson()
{
writer.Write((byte)Usage);
writer.WriteVarBytes(Data);
return new JObject
{
["type"] = Type
};
}

public JObject ToJson()
public void Serialize(BinaryWriter writer)
{
JObject json = new JObject();
json["usage"] = Usage;
json["data"] = Convert.ToBase64String(Data);
return json;
writer.Write((byte)Type);
SerializeWithoutType(writer);
}

protected abstract void SerializeWithoutType(BinaryWriter writer);
}
}
10 changes: 10 additions & 0 deletions src/neo/Network/P2P/Payloads/TransactionAttributeType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Neo.IO.Caching;

namespace Neo.Network.P2P.Payloads
{
public enum TransactionAttributeType : byte
{
[ReflectionCache(typeof(Cosigner))]
Cosigner = 0x01
}
}
7 changes: 0 additions & 7 deletions src/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs

This file was deleted.

1 change: 1 addition & 0 deletions src/neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap
engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None);
if (engine.Execute() == VMState.FAULT) return false;
if (!engine.ResultStack.TryPop(out StackItem result) || !result.ToBoolean()) return false;
gas -= engine.GasConsumed;
}
}
return true;
Expand Down
16 changes: 8 additions & 8 deletions src/neo/SmartContract/InteropService.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,24 @@ internal static bool CheckWitnessInternal(ApplicationEngine engine, UInt160 hash
{
if (engine.ScriptContainer is Transaction tx)
{
Cosigner usage = tx.Cosigners.FirstOrDefault(p => p.Account.Equals(hash));
if (usage is null) return false;
if (usage.Scopes == WitnessScope.Global) return true;
if (usage.Scopes.HasFlag(WitnessScope.CalledByEntry))
Cosigner cosigner = tx.Cosigners.FirstOrDefault(p => p.Account.Equals(hash));
if (cosigner is null) return false;
if (cosigner.Scopes == WitnessScope.Global) return true;
if (cosigner.Scopes.HasFlag(WitnessScope.CalledByEntry))
{
if (engine.CallingScriptHash == engine.EntryScriptHash)
return true;
}
if (usage.Scopes.HasFlag(WitnessScope.CustomContracts))
if (cosigner.Scopes.HasFlag(WitnessScope.CustomContracts))
{
if (usage.AllowedContracts.Contains(engine.CurrentScriptHash))
if (cosigner.AllowedContracts.Contains(engine.CurrentScriptHash))
return true;
}
if (usage.Scopes.HasFlag(WitnessScope.CustomGroups))
if (cosigner.Scopes.HasFlag(WitnessScope.CustomGroups))
{
var contract = engine.Snapshot.Contracts[engine.CallingScriptHash];
// check if current group is the required one
if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(usage.AllowedGroups).Any())
if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(cosigner.AllowedGroups).Any())
return true;
}
return false;
Expand Down
Loading

0 comments on commit 3b2b4ef

Please sign in to comment.