diff --git a/neo/Core/StorageKey.cs b/neo/Core/StorageKey.cs index 3babef23c3..bb569a656c 100644 --- a/neo/Core/StorageKey.cs +++ b/neo/Core/StorageKey.cs @@ -11,12 +11,12 @@ public class StorageKey : IEquatable, ISerializable public UInt160 ScriptHash; public byte[] Key; - int ISerializable.Size => ScriptHash.Size + Key.GetVarSize(); + int ISerializable.Size => ScriptHash.Size + (Key.Length / 16 + 1) * 17; void ISerializable.Deserialize(BinaryReader reader) { ScriptHash = reader.ReadSerializable(); - Key = reader.ReadVarBytes(); + Key = reader.ReadBytesWithGrouping(); } public bool Equals(StorageKey other) @@ -43,7 +43,7 @@ public override int GetHashCode() void ISerializable.Serialize(BinaryWriter writer) { writer.Write(ScriptHash); - writer.WriteVarBytes(Key); + writer.WriteBytesWithGrouping(Key); } } } diff --git a/neo/IO/Helper.cs b/neo/IO/Helper.cs index 323db921d8..e264e443df 100644 --- a/neo/IO/Helper.cs +++ b/neo/IO/Helper.cs @@ -85,6 +85,26 @@ internal static int GetVarSize(this string value) return GetVarSize(size) + size; } + public static byte[] ReadBytesWithGrouping(this BinaryReader reader) + { + const int GROUP_SIZE = 16; + using (MemoryStream ms = new MemoryStream()) + { + int padding = 0; + do + { + byte[] group = reader.ReadBytes(GROUP_SIZE); + padding = reader.ReadByte(); + if (padding > GROUP_SIZE) + throw new FormatException(); + int count = GROUP_SIZE - padding; + if (count > 0) + ms.Write(group, 0, count); + } while (padding == 0); + return ms.ToArray(); + } + } + public static string ReadFixedString(this BinaryReader reader, int length) { byte[] data = reader.ReadBytes(length); @@ -171,6 +191,26 @@ public static void Write(this BinaryWriter writer, T[] value) where T : ISeri } } + public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value) + { + const int GROUP_SIZE = 16; + int index = 0; + int remain = value.Length; + while (remain >= GROUP_SIZE) + { + writer.Write(value, index, GROUP_SIZE); + writer.Write((byte)0); + index += GROUP_SIZE; + remain -= GROUP_SIZE; + } + if (remain > 0) + writer.Write(value, index, remain); + int padding = GROUP_SIZE - remain; + for (int i = 0; i < padding; i++) + writer.Write((byte)0); + writer.Write((byte)padding); + } + public static void WriteFixedString(this BinaryWriter writer, string value, int length) { if (value == null) diff --git a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.cs b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.cs index fc19773a37..0d356588aa 100644 --- a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.cs +++ b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.cs @@ -46,7 +46,7 @@ public LevelDBBlockchain(string path) Version version; Slice value; db = DB.Open(path, new Options { CreateIfMissing = true }); - if (db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.SYS_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("2.6.0")) + if (db.TryGet(ReadOptions.Default, SliceBuilder.Begin(DataEntryPrefix.SYS_Version), out value) && Version.TryParse(value.ToString(), out version) && version >= Version.Parse("2.7.4")) { ReadOptions options = new ReadOptions { FillCache = false }; value = db.Get(options, SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock)); diff --git a/neo/SmartContract/StateReader.cs b/neo/SmartContract/StateReader.cs index 5ae79fc227..9eb99e26f2 100644 --- a/neo/SmartContract/StateReader.cs +++ b/neo/SmartContract/StateReader.cs @@ -948,8 +948,23 @@ protected virtual bool Storage_Find(ExecutionEngine engine) StorageContext context = _interface.GetInterface(); if (!CheckStorageContext(context)) return false; byte[] prefix = engine.EvaluationStack.Pop().GetByteArray(); - prefix = context.ScriptHash.ToArray().Concat(prefix).ToArray(); - StorageIterator iterator = new StorageIterator(Storages.Find(prefix).GetEnumerator()); + byte[] prefix_key; + using (MemoryStream ms = new MemoryStream()) + { + int index = 0; + int remain = prefix.Length; + while (remain >= 16) + { + ms.Write(prefix, index, 16); + ms.WriteByte(0); + index += 16; + remain -= 16; + } + if (remain > 0) + ms.Write(prefix, index, remain); + prefix_key = context.ScriptHash.ToArray().Concat(ms.ToArray()).ToArray(); + } + StorageIterator iterator = new StorageIterator(Storages.Find(prefix_key).Where(p => p.Key.Key.Take(prefix.Length).SequenceEqual(prefix)).GetEnumerator()); engine.EvaluationStack.Push(StackItem.FromInterface(iterator)); disposables.Add(iterator); return true; diff --git a/neo/neo.csproj b/neo/neo.csproj index e286042071..b73763d434 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -3,7 +3,7 @@ 2015-2017 The Neo Project Neo - 2.7.3 + 2.7.4 The Neo Project netstandard2.0;net47 true