Skip to content

Commit

Permalink
Fix storage encoding (#3130)
Browse files Browse the repository at this point in the history
* Fix storage encoding

* Remove unsafe methods

* Revert BigEndian change

* Fix ut

* Revert change
  • Loading branch information
shargon authored Feb 10, 2024
1 parent 95708b5 commit b4dadcb
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 21 deletions.
68 changes: 55 additions & 13 deletions src/Neo/SmartContract/KeyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using Neo.IO;
using System;
using System.Buffers.Binary;
using System.IO;

namespace Neo.SmartContract
Expand All @@ -29,8 +30,22 @@ public class KeyBuilder
/// <param name="prefix">The prefix of the key.</param>
public KeyBuilder(int id, byte prefix)
{
Add(id);
this.stream.WriteByte(prefix);
var data = new byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(data, id);

stream.Write(data);
stream.WriteByte(prefix);
}

/// <summary>
/// Adds part of the key to the builder.
/// </summary>
/// <param name="key">Part of the key.</param>
/// <returns>A reference to this instance after the add operation has completed.</returns>
public KeyBuilder Add(byte key)
{
stream.WriteByte(key);
return this;
}

/// <summary>
Expand Down Expand Up @@ -60,28 +75,55 @@ public KeyBuilder Add(ISerializable key)
}

/// <summary>
/// Adds part of the key to the builder.
/// Adds part of the key to the builder in BigEndian.
/// </summary>
/// <typeparam name="T">The type of the <paramref name="key"/> parameter.</typeparam>
/// <param name="key">Part of the key.</param>
/// <returns>A reference to this instance after the add operation has completed.</returns>
unsafe public KeyBuilder Add<T>(T key) where T : unmanaged
public KeyBuilder AddBigEndian(int key)
{
return Add(new ReadOnlySpan<byte>(&key, sizeof(T)));
var data = new byte[sizeof(int)];
BinaryPrimitives.WriteInt32BigEndian(data, key);

return Add(data);
}

/// <summary>
/// Adds part of the key to the builder with big-endian.
/// Adds part of the key to the builder in BigEndian.
/// </summary>
/// <typeparam name="T">The type of the <paramref name="key"/> parameter.</typeparam>
/// <param name="key">Part of the key.</param>
/// <returns>A reference to this instance after the add operation has completed.</returns>
unsafe public KeyBuilder AddBigEndian<T>(T key) where T : unmanaged
public KeyBuilder AddBigEndian(uint key)
{
ReadOnlySpan<byte> buffer = new(&key, sizeof(T));
for (int i = buffer.Length - 1; i >= 0; i--)
stream.WriteByte(buffer[i]);
return this;
var data = new byte[sizeof(uint)];
BinaryPrimitives.WriteUInt32BigEndian(data, key);

return Add(data);
}

/// <summary>
/// Adds part of the key to the builder in BigEndian.
/// </summary>
/// <param name="key">Part of the key.</param>
/// <returns>A reference to this instance after the add operation has completed.</returns>
public KeyBuilder AddBigEndian(long key)
{
var data = new byte[sizeof(long)];
BinaryPrimitives.WriteInt64BigEndian(data, key);

return Add(data);
}

/// <summary>
/// Adds part of the key to the builder in BigEndian.
/// </summary>
/// <param name="key">Part of the key.</param>
/// <returns>A reference to this instance after the add operation has completed.</returns>
public KeyBuilder AddBigEndian(ulong key)
{
var data = new byte[sizeof(ulong)];
BinaryPrimitives.WriteUInt64BigEndian(data, key);

return Add(data);
}

/// <summary>
Expand Down
11 changes: 3 additions & 8 deletions tests/Neo.UnitTests/SmartContract/UT_KeyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ namespace Neo.UnitTests.SmartContract
[TestClass]
public class UT_KeyBuilder
{
private struct TestKey
{
public int Value;
}

[TestMethod]
public void Test()
{
Expand All @@ -39,11 +34,11 @@ public void Test()
Assert.AreEqual("010000000203040000000000000000000000000000000000000000", key.ToArray().ToHexString());

key = new KeyBuilder(1, 2);
key = key.Add(new TestKey { Value = 123 });
Assert.AreEqual("01000000027b000000", key.ToArray().ToHexString());
key = key.AddBigEndian(123);
Assert.AreEqual("01000000020000007b", key.ToArray().ToHexString());

key = new KeyBuilder(1, 0);
key = key.AddBigEndian(new TestKey { Value = 1 });
key = key.AddBigEndian(1);
Assert.AreEqual("010000000000000001", key.ToArray().ToHexString());
}
}
Expand Down

0 comments on commit b4dadcb

Please sign in to comment.