Skip to content

Commit

Permalink
Contract Guid by counter (#1405)
Browse files Browse the repository at this point in the history
  • Loading branch information
doubiliu authored and erikzhang committed Jan 17, 2020
1 parent a2544c1 commit 9a272e1
Show file tree
Hide file tree
Showing 30 changed files with 167 additions and 165 deletions.
42 changes: 42 additions & 0 deletions src/neo/Ledger/ContractIdState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Neo.IO;
using System;
using System.IO;

namespace Neo.Ledger
{
public class ContractIdState : ICloneable<ContractIdState>, ISerializable
{
public int Id;

int ISerializable.Size => sizeof(int);

ContractIdState ICloneable<ContractIdState>.Clone()
{
return new ContractIdState
{
Id = Id
};
}

void ISerializable.Deserialize(BinaryReader reader)
{
Id = reader.ReadInt32();
if (Id < 0) throw new FormatException();
}

void ICloneable<ContractIdState>.FromReplica(ContractIdState replica)
{
Id = replica.Id;
}

void ISerializable.Serialize(BinaryWriter writer)
{
writer.Write(Id);
}

internal void Set(int value)
{
Id = value;
}
}
}
13 changes: 7 additions & 6 deletions src/neo/Ledger/ContractState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Neo.Ledger
{
public class ContractState : ICloneable<ContractState>, ISerializable, IInteroperable
{
public Guid Guid;
public int Id;
public byte[] Script;
public ContractManifest Manifest;

Expand All @@ -32,42 +32,43 @@ public UInt160 ScriptHash
}
}

int ISerializable.Size => 16 + Script.GetVarSize() + Manifest.ToJson().ToString().GetVarSize();
int ISerializable.Size => sizeof(uint) + Script.GetVarSize() + Manifest.ToJson().ToString().GetVarSize();

ContractState ICloneable<ContractState>.Clone()
{
return new ContractState
{
Guid = Guid,
Id = Id,
Script = Script,
Manifest = Manifest.Clone()
};
}

void ISerializable.Deserialize(BinaryReader reader)
{
Guid = new Guid(reader.ReadBytes(16));
Id = reader.ReadInt32();
Script = reader.ReadVarBytes();
Manifest = reader.ReadSerializable<ContractManifest>();
}

void ICloneable<ContractState>.FromReplica(ContractState replica)
{
Guid = replica.Guid;
Id = replica.Id;
Script = replica.Script;
Manifest = replica.Manifest.Clone();
}

void ISerializable.Serialize(BinaryWriter writer)
{
writer.Write(Guid.ToByteArray());
writer.Write(Id);
writer.WriteVarBytes(Script);
writer.Write(Manifest);
}

public JObject ToJson()
{
JObject json = new JObject();
json["id"] = Id;
json["hash"] = ScriptHash.ToString();
json["script"] = Convert.ToBase64String(Script);
json["manifest"] = Manifest.ToJson();
Expand Down
16 changes: 8 additions & 8 deletions src/neo/Ledger/StorageKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ namespace Neo.Ledger
{
public class StorageKey : IEquatable<StorageKey>, ISerializable
{
public Guid Guid;
public int Id;
public byte[] Key;

int ISerializable.Size => 16 + (Key.Length / 16 + 1) * 17;
int ISerializable.Size => sizeof(int) + (Key.Length / 16 + 1) * 17;

internal static byte[] CreateSearchPrefix(Guid guid, byte[] prefix)
internal static byte[] CreateSearchPrefix(int id, byte[] prefix)
{
using (MemoryStream ms = new MemoryStream())
{
Expand All @@ -27,13 +27,13 @@ internal static byte[] CreateSearchPrefix(Guid guid, byte[] prefix)
}
if (remain > 0)
ms.Write(prefix, index, remain);
return Helper.Concat(guid.ToByteArray(), ms.ToArray());
return Helper.Concat(BitConverter.GetBytes(id), ms.ToArray());
}
}

void ISerializable.Deserialize(BinaryReader reader)
{
Guid = new Guid(reader.ReadBytes(16));
Id = reader.ReadInt32();
Key = reader.ReadBytesWithGrouping();
}

Expand All @@ -43,7 +43,7 @@ public bool Equals(StorageKey other)
return false;
if (ReferenceEquals(this, other))
return true;
return Guid.Equals(other.Guid) && MemoryExtensions.SequenceEqual<byte>(Key, other.Key);
return Id == other.Id && MemoryExtensions.SequenceEqual<byte>(Key, other.Key);
}

public override bool Equals(object obj)
Expand All @@ -54,12 +54,12 @@ public override bool Equals(object obj)

public override int GetHashCode()
{
return Guid.GetHashCode() + (int)Key.Murmur32(0);
return Id.GetHashCode() + (int)Key.Murmur32(0);
}

void ISerializable.Serialize(BinaryWriter writer)
{
writer.Write(Guid.ToByteArray());
writer.Write(Id);
writer.WriteBytesWithGrouping(Key);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/neo/Persistence/ClonedView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal class ClonedView : StoreView
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public override MetaDataCache<HashIndexState> BlockHashIndex { get; }
public override MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public override MetaDataCache<ContractIdState> ContractId { get; }

public ClonedView(StoreView view)
{
Expand All @@ -24,6 +25,7 @@ public ClonedView(StoreView view)
this.HeaderHashList = view.HeaderHashList.CreateSnapshot();
this.BlockHashIndex = view.BlockHashIndex.CreateSnapshot();
this.HeaderHashIndex = view.HeaderHashIndex.CreateSnapshot();
this.ContractId = view.ContractId.CreateSnapshot();
}
}
}
1 change: 1 addition & 0 deletions src/neo/Persistence/Prefixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal static class Prefixes
public const byte IX_HeaderHashList = 0x80;
public const byte IX_CurrentBlock = 0xc0;
public const byte IX_CurrentHeader = 0xc1;
public const byte IX_CurrentContractId = 0xc2;

/* Prefixes 0xf0 to 0xff are reserved for external use.
*
Expand Down
1 change: 1 addition & 0 deletions src/neo/Persistence/ReadOnlyView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class ReadOnlyView : StoreView
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList => new StoreDataCache<SerializableWrapper<uint>, HeaderHashList>(store, Prefixes.IX_HeaderHashList);
public override MetaDataCache<HashIndexState> BlockHashIndex => new StoreMetaDataCache<HashIndexState>(store, Prefixes.IX_CurrentBlock);
public override MetaDataCache<HashIndexState> HeaderHashIndex => new StoreMetaDataCache<HashIndexState>(store, Prefixes.IX_CurrentHeader);
public override MetaDataCache<ContractIdState> ContractId => new StoreMetaDataCache<ContractIdState>(store, Prefixes.IX_CurrentContractId);

public ReadOnlyView(IReadOnlyStore store)
{
Expand Down
2 changes: 2 additions & 0 deletions src/neo/Persistence/SnapshotView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class SnapshotView : StoreView, IDisposable
public override DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public override MetaDataCache<HashIndexState> BlockHashIndex { get; }
public override MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public override MetaDataCache<ContractIdState> ContractId { get; }

public SnapshotView(IStore store)
{
Expand All @@ -30,6 +31,7 @@ public SnapshotView(IStore store)
HeaderHashList = new StoreDataCache<SerializableWrapper<uint>, HeaderHashList>(snapshot, Prefixes.IX_HeaderHashList);
BlockHashIndex = new StoreMetaDataCache<HashIndexState>(snapshot, Prefixes.IX_CurrentBlock);
HeaderHashIndex = new StoreMetaDataCache<HashIndexState>(snapshot, Prefixes.IX_CurrentHeader);
ContractId = new StoreMetaDataCache<ContractIdState>(snapshot, Prefixes.IX_CurrentContractId);
}

public override void Commit()
Expand Down
3 changes: 3 additions & 0 deletions src/neo/Persistence/StoreView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ public abstract class StoreView
public abstract DataCache<SerializableWrapper<uint>, HeaderHashList> HeaderHashList { get; }
public abstract MetaDataCache<HashIndexState> BlockHashIndex { get; }
public abstract MetaDataCache<HashIndexState> HeaderHashIndex { get; }
public abstract MetaDataCache<ContractIdState> ContractId { get; }

public uint Height => BlockHashIndex.Get().Index;
public uint HeaderHeight => HeaderHashIndex.Get().Index;
public UInt256 CurrentBlockHash => BlockHashIndex.Get().Hash;
public UInt256 CurrentHeaderHash => HeaderHashIndex.Get().Hash;
public int CurrentContractId => ContractId.Get().Id;

public StoreView Clone()
{
Expand All @@ -38,6 +40,7 @@ public virtual void Commit()
HeaderHashList.Commit();
BlockHashIndex.Commit();
HeaderHashIndex.Commit();
ContractId.Commit();
}

public bool ContainsBlock(UInt256 hash)
Expand Down
2 changes: 0 additions & 2 deletions src/neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public partial class ApplicationEngine : ExecutionEngine
public UInt160 EntryScriptHash => EntryContext?.GetState<ExecutionContextState>().ScriptHash;
public IReadOnlyList<NotifyEventArgs> Notifications => notifications;
internal Dictionary<UInt160, int> InvocationCounter { get; } = new Dictionary<UInt160, int>();
internal uint SyscallCounter { get; private set; }

public ApplicationEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false)
{
Expand Down Expand Up @@ -81,7 +80,6 @@ protected override bool OnSysCall(uint method)
{
if (!AddGas(InteropService.GetPrice(method, CurrentContext.EvaluationStack)))
return false;
SyscallCounter++;
return InteropService.Invoke(this, method);
}

Expand Down
9 changes: 2 additions & 7 deletions src/neo/SmartContract/InteropService.Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ private static long GetDeploymentPrice(EvaluationStack stack)
return Storage.GasPerByte * size;
}

internal static Guid GetDeterministicGuid(Transaction tx, uint nonce)
{
return new Guid(Concat(tx.Hash.ToArray(), BitConverter.GetBytes(nonce)).Sha256().AsSpan(0, 16));
}

private static bool Contract_Create(ApplicationEngine engine)
{
byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray();
Expand All @@ -46,7 +41,7 @@ private static bool Contract_Create(ApplicationEngine engine)
if (contract != null) return false;
contract = new ContractState
{
Guid = GetDeterministicGuid((Transaction)engine.ScriptContainer, engine.SyscallCounter),
Id = engine.Snapshot.ContractId.GetAndChange().Id++,
Script = script,
Manifest = ContractManifest.Parse(manifest)
};
Expand Down Expand Up @@ -75,7 +70,7 @@ private static bool Contract_Update(ApplicationEngine engine)
if (engine.Snapshot.Contracts.TryGet(hash_new) != null) return false;
contract = new ContractState
{
Guid = contract.Guid,
Id = contract.Id,
Script = script,
Manifest = contract.Manifest
};
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/InteropService.Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ private static bool Native_Deploy(ApplicationEngine engine)
{
engine.Snapshot.Contracts.Add(contract.Hash, new ContractState
{
Guid = contract.Guid,
Id = contract.Id,
Script = contract.Script,
Manifest = contract.Manifest
});
Expand Down
14 changes: 7 additions & 7 deletions src/neo/SmartContract/InteropService.Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private static bool PutExInternal(ApplicationEngine engine, StorageContext conte

StorageKey skey = new StorageKey
{
Guid = context.Guid,
Id = context.Id,
Key = key
};

Expand All @@ -64,7 +64,7 @@ private static bool Storage_GetContext(ApplicationEngine engine)
if (!contract.HasStorage) return false;
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext
{
Guid = contract.Guid,
Id = contract.Id,
IsReadOnly = false
}));
return true;
Expand All @@ -77,7 +77,7 @@ private static bool Storage_GetReadOnlyContext(ApplicationEngine engine)
if (!contract.HasStorage) return false;
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext
{
Guid = contract.Guid,
Id = contract.Id,
IsReadOnly = true
}));
return true;
Expand All @@ -91,7 +91,7 @@ private static bool Storage_AsReadOnly(ApplicationEngine engine)
if (!context.IsReadOnly)
context = new StorageContext
{
Guid = context.Guid,
Id = context.Id,
IsReadOnly = true
};
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(context));
Expand All @@ -108,7 +108,7 @@ private static bool Storage_Get(ApplicationEngine engine)
byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray();
StorageItem item = engine.Snapshot.Storages.TryGet(new StorageKey
{
Guid = context.Guid,
Id = context.Id,
Key = key
});
engine.CurrentContext.EvaluationStack.Push(item?.Value ?? StackItem.Null);
Expand All @@ -123,7 +123,7 @@ private static bool Storage_Find(ApplicationEngine engine)
{
StorageContext context = _interface.GetInterface<StorageContext>();
byte[] prefix = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray();
byte[] prefix_key = StorageKey.CreateSearchPrefix(context.Guid, prefix);
byte[] prefix_key = StorageKey.CreateSearchPrefix(context.Id, prefix);
StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.AsSpan().StartsWith(prefix)).GetEnumerator()));
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator));
return true;
Expand Down Expand Up @@ -160,7 +160,7 @@ private static bool Storage_Delete(ApplicationEngine engine)
if (context.IsReadOnly) return false;
StorageKey key = new StorageKey
{
Guid = context.Guid,
Id = context.Id,
Key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray()
};
if (engine.Snapshot.Storages.TryGet(key)?.IsConstant == true) return false;
Expand Down
5 changes: 2 additions & 3 deletions src/neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public abstract class NativeContract
public uint ServiceHash { get; }
public byte[] Script { get; }
public UInt160 Hash { get; }
public Guid Guid { get; }
public abstract int Id { get; }
public ContractManifest Manifest { get; }
public virtual string[] SupportedStandards { get; } = { "NEP-10" };

Expand All @@ -41,7 +41,6 @@ protected NativeContract()
this.Script = sb.ToArray();
}
this.Hash = Script.ToScriptHash();
this.Guid = InteropService.Contract.GetDeterministicGuid(Blockchain.GenesisBlock.Transactions[0], ServiceHash);
this.Manifest = ContractManifest.CreateDefault(this.Hash);
List<ContractMethodDescriptor> descriptors = new List<ContractMethodDescriptor>();
List<string> safeMethods = new List<string>();
Expand Down Expand Up @@ -73,7 +72,7 @@ protected StorageKey CreateStorageKey(byte prefix, byte[] key = null)
{
StorageKey storageKey = new StorageKey
{
Guid = Guid,
Id = Id,
Key = new byte[sizeof(byte) + (key?.Length ?? 0)]
};
storageKey.Key[0] = prefix;
Expand Down
1 change: 1 addition & 0 deletions src/neo/SmartContract/Native/PolicyContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public sealed class PolicyContract : NativeContract
private const byte Prefix_FeePerByte = 10;
private const byte Prefix_BlockedAccounts = 15;
private const byte Prefix_MaxBlockSize = 16;
public override int Id => -1;

public PolicyContract()
{
Expand Down
2 changes: 2 additions & 0 deletions src/neo/SmartContract/Native/Tokens/GasToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public sealed class GasToken : Nep5Token<Nep5AccountState>
public override string Symbol => "gas";
public override byte Decimals => 8;

public override int Id => -3;

private const byte Prefix_SystemFeeAmount = 15;

internal GasToken()
Expand Down
Loading

0 comments on commit 9a272e1

Please sign in to comment.