From 4cdb78ec70cff85cd06e705e8cada9def8ae385a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:15:01 +0200 Subject: [PATCH 01/22] Update TargetFramework to `netstandard2.0`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Casper.Network.SDK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index ce4c526..5b95a1d 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -1,7 +1,7 @@ - net7.0 + netstandard2.0 2.0.0.0 2.0.0 2.0.0 From fc6f1d153e6a7e5e82c713214fc4f0a791e1b15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:16:46 +0200 Subject: [PATCH 02/22] Update LangVersion to `9.0` to enable patterns. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS8370. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Casper.Network.SDK.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index 5b95a1d..726ad90 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -2,6 +2,7 @@ netstandard2.0 + 9.0 2.0.0.0 2.0.0 2.0.0 From bb2c363bbc050c17450af7c46a8d90aff59d7571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:20:24 +0200 Subject: [PATCH 03/22] Install `System.Text.Json` package. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0234. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Casper.Network.SDK.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index 726ad90..85147b3 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -22,6 +22,7 @@ + From 091e3fb141a4fd7372c61a0240ed1b59b69d0b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:29:04 +0200 Subject: [PATCH 04/22] Workaround for missing `IsExternalInit`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0518. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/IsExternalInit.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Casper.Network.SDK/Compat/IsExternalInit.cs diff --git a/Casper.Network.SDK/Compat/IsExternalInit.cs b/Casper.Network.SDK/Compat/IsExternalInit.cs new file mode 100644 index 0000000..3147b6c --- /dev/null +++ b/Casper.Network.SDK/Compat/IsExternalInit.cs @@ -0,0 +1,18 @@ +#if NETSTANDARD2_0 + +using System.ComponentModel; + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} + +#endif From 3918160e32e81f71624d755d790f3779c47ada52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:30:08 +0200 Subject: [PATCH 05/22] Install `System.Net.Http.Json` package. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0234. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Casper.Network.SDK.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index 85147b3..f8e033f 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -22,6 +22,7 @@ + From cbf2beec92b20c4e8dca12eb7ca5877ec82e3242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:38:12 +0200 Subject: [PATCH 06/22] Workaround for missing `ITuple`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0246. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/Tuple.cs | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Casper.Network.SDK/Compat/Tuple.cs diff --git a/Casper.Network.SDK/Compat/Tuple.cs b/Casper.Network.SDK/Compat/Tuple.cs new file mode 100644 index 0000000..7089a64 --- /dev/null +++ b/Casper.Network.SDK/Compat/Tuple.cs @@ -0,0 +1,92 @@ +#if NETSTANDARD2_0 + +using System; + +public partial interface ITuple +{ + object this[int index] { get; } + int Length { get; } +} + +public class Tuple : ITuple +{ + public T1 Item1 { get; } + + public Tuple(T1 item1) + { + Item1 = item1; + } + + public int Length => 1; + + public object this[int index] + { + get + { + switch (index) + { + case 0: return Item1; + default: throw new IndexOutOfRangeException(); + } + } + } +} + +public class Tuple : ITuple +{ + public T1 Item1 { get; } + public T2 Item2 { get; } + + public Tuple(T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + + public int Length => 2; + + public object this[int index] + { + get + { + switch (index) + { + case 0: return Item1; + case 1: return Item2; + default: throw new IndexOutOfRangeException(); + } + } + } +} + +public class Tuple : ITuple +{ + public T1 Item1 { get; } + public T2 Item2 { get; } + public T3 Item3 { get; } + + public Tuple(T1 item1, T2 item2, T3 item3) + { + Item1 = item1; + Item2 = item2; + Item3 = item3; + } + + public int Length => 3; + + public object this[int index] + { + get + { + switch (index) + { + case 0: return Item1; + case 1: return Item2; + case 2: return Item3; + default: throw new IndexOutOfRangeException(); + } + } + } +} + +#endif From 0df852495f13985a8f9900c31bbc3525ac787dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:47:30 +0200 Subject: [PATCH 07/22] Workaround for missing ranges/indexes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0518. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/BytesExtensions.cs | 25 +++++++++++++++++ Casper.Network.SDK/Types/CLValue.cs | 17 ++++++------ Casper.Network.SDK/Types/CLValueException.cs | 2 +- Casper.Network.SDK/Types/GlobalStateKey.cs | 28 ++++++++++---------- Casper.Network.SDK/Types/Signature.cs | 2 +- Casper.Network.SDK/Types/URef.cs | 2 +- 6 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 Casper.Network.SDK/Compat/BytesExtensions.cs diff --git a/Casper.Network.SDK/Compat/BytesExtensions.cs b/Casper.Network.SDK/Compat/BytesExtensions.cs new file mode 100644 index 0000000..a6db9c4 --- /dev/null +++ b/Casper.Network.SDK/Compat/BytesExtensions.cs @@ -0,0 +1,25 @@ +#if NETSTANDARD2_0 + +using System; + +public static class BytesExtensions +{ + public static byte[] Slice(this byte[] bytes, int from, int? to = null) + { + int actualTo = to ?? bytes.Length; // if to is not provided, use the last index + + if (from < 0 || actualTo > bytes.Length || from > actualTo) + { + throw new IndexOutOfRangeException(); + } + + int length = actualTo - from; + byte[] result = new byte[length]; + + Array.Copy(bytes, from, result, 0, length); + + return result; + } +} + +#endif diff --git a/Casper.Network.SDK/Types/CLValue.cs b/Casper.Network.SDK/Types/CLValue.cs index 99b373e..ee1abf7 100644 --- a/Casper.Network.SDK/Types/CLValue.cs +++ b/Casper.Network.SDK/Types/CLValue.cs @@ -536,7 +536,7 @@ public static CLValue Key(GlobalStateKey key) private void ParseResultError(byte[] Bytes, CLResultTypeInfo resultTypeInfo) { - var reader = new BinaryReader(new MemoryStream(Bytes[1..])); + var reader = new BinaryReader(new MemoryStream(Bytes.Slice(1))); var item = reader.ReadCLItem(resultTypeInfo.Err, null); if (item == null) @@ -554,7 +554,7 @@ private byte[] GetOkInnerTypeOrFail(ref CLTypeInfo typeInfo) ParseResultError(Bytes, resultTypeInfo); typeInfo = resultTypeInfo.Ok; - return Bytes[1..]; + return Bytes.Slice(1); } /// @@ -786,8 +786,9 @@ public URef ToURef() if (typeInfo.Type == CLType.URef) return new URef(bytes); - if (typeInfo.Type == CLType.Key && ((CLKeyTypeInfo) typeInfo).KeyIdentifier == KeyIdentifier.URef) - return new URef(bytes[1..]); + if (typeInfo.Type == CLType.Key && ((CLKeyTypeInfo) typeInfo).KeyIdentifier == KeyIdentifier.URef) { + return new URef(bytes.Slice(1)); + } throw new FormatException($"Cannot convert '{typeInfo.Type}' to 'URef'."); } @@ -1029,13 +1030,13 @@ public Result ToResult() if (Bytes[0] == 0x01) { - var reader = new BinaryReader(new MemoryStream(Bytes[1..])); + var reader = new BinaryReader(new MemoryStream(Bytes.Slice(1))); var v = reader.ReadCLItem(resultTypeInfo.Ok, typeof(TOk)); return Result.Ok((TOk) v); } else { - var reader = new BinaryReader(new MemoryStream(Bytes[1..])); + var reader = new BinaryReader(new MemoryStream(Bytes.Slice(1))); var v = reader.ReadCLItem(resultTypeInfo.Err, typeof(TErr)); return Result.Fail((TErr)v); } @@ -1076,7 +1077,7 @@ public bool Some(out object value) if(typeInfo==null) throw new ArgumentException(nameof(value), $"value is not an 'Option' CLValue."); - var reader = new BinaryReader(new MemoryStream(Bytes[1..])); + var reader = new BinaryReader(new MemoryStream(Bytes.Slice(1))); value = reader.ReadCLItem(typeInfo.OptionType, null); } @@ -1098,7 +1099,7 @@ public bool Some(out T value) if(typeInfo==null) throw new ArgumentException(nameof(value), $"value is not an 'Option' CLValue."); - var reader = new BinaryReader(new MemoryStream(Bytes[1..])); + var reader = new BinaryReader(new MemoryStream(Bytes.Slice(1))); value = (T) reader.ReadCLItem(typeInfo.OptionType, typeof(T)); return true; diff --git a/Casper.Network.SDK/Types/CLValueException.cs b/Casper.Network.SDK/Types/CLValueException.cs index 7999f09..2905b1f 100644 --- a/Casper.Network.SDK/Types/CLValueException.cs +++ b/Casper.Network.SDK/Types/CLValueException.cs @@ -20,7 +20,7 @@ public CLValueException(byte[] bytes, object err, CLTypeInfo okType, CLTypeInfo } public CLValueException(byte[] bytes, CLTypeInfo okType, CLTypeInfo errType) - : base($"Cannot convert {Hex.ToHexString(bytes[1..])}' to '{errType}'.") + : base($"Cannot convert {Hex.ToHexString(bytes.Slice(1))}' to '{errType}'.") { Bytes = bytes; ErrorValue = null; diff --git a/Casper.Network.SDK/Types/GlobalStateKey.cs b/Casper.Network.SDK/Types/GlobalStateKey.cs index 6c036c5..aef55ce 100644 --- a/Casper.Network.SDK/Types/GlobalStateKey.cs +++ b/Casper.Network.SDK/Types/GlobalStateKey.cs @@ -171,21 +171,21 @@ public static GlobalStateKey FromBytes(byte[] bytes) { return bytes[0] switch { - 0x00 => new AccountHashKey("account-hash-" + CEP57Checksum.Encode(bytes[1..])), - 0x01 => new HashKey("hash-" + CEP57Checksum.Encode(bytes[1..])), - 0x02 => new URef(bytes[1..]), - 0x03 => new TransferKey("transfer-" + CEP57Checksum.Encode(bytes[1..])), - 0x04 => new DeployInfoKey("deploy-" + CEP57Checksum.Encode(bytes[1..])), + 0x00 => new AccountHashKey("account-hash-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x01 => new HashKey("hash-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x02 => new URef(bytes.Slice(1)), + 0x03 => new TransferKey("transfer-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x04 => new DeployInfoKey("deploy-" + CEP57Checksum.Encode(bytes.Slice(1))), 0x05 => new EraInfoKey("era-" + BitConverter.ToInt64(bytes, 1)), - 0x06 => new BalanceKey("balance-" + CEP57Checksum.Encode(bytes[1..])), - 0x07 => new BidKey("bid-" + CEP57Checksum.Encode(bytes[1..])), - 0x08 => new WithdrawKey("withdraw-" + CEP57Checksum.Encode(bytes[1..])), - 0x09 => new DictionaryKey("dictionary-" + CEP57Checksum.Encode(bytes[1..])), - 0x0a => new SystemContractRegistryKey("system-contract-registry-" + CEP57Checksum.Encode(bytes[1..])), - 0x0b => new EraSummaryKey("era-summary-" + CEP57Checksum.Encode(bytes[1..])), - 0x0c => new UnbondKey("unbond-" + CEP57Checksum.Encode(bytes[1..])), - 0x0d => new ChainspecRegistryKey("chainspec-registry-" + CEP57Checksum.Encode(bytes[1..])), - 0x0e => new ChecksumRegistryKey("checksum-registry-" + CEP57Checksum.Encode(bytes[1..])), + 0x06 => new BalanceKey("balance-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x07 => new BidKey("bid-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x08 => new WithdrawKey("withdraw-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x09 => new DictionaryKey("dictionary-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x0a => new SystemContractRegistryKey("system-contract-registry-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x0b => new EraSummaryKey("era-summary-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x0c => new UnbondKey("unbond-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x0d => new ChainspecRegistryKey("chainspec-registry-" + CEP57Checksum.Encode(bytes.Slice(1))), + 0x0e => new ChecksumRegistryKey("checksum-registry-" + CEP57Checksum.Encode(bytes.Slice(1))), _ => throw new ArgumentException($"Unknown key identifier '{bytes[0]}'") }; } diff --git a/Casper.Network.SDK/Types/Signature.cs b/Casper.Network.SDK/Types/Signature.cs index d837b49..a28b27d 100644 --- a/Casper.Network.SDK/Types/Signature.cs +++ b/Casper.Network.SDK/Types/Signature.cs @@ -58,7 +58,7 @@ public static Signature FromBytes(byte[] bytes) _ => throw new ArgumentOutOfRangeException(nameof(bytes), "Wrong signature algorithm identifier") }; - return new Signature(bytes[1..], algoIdent); + return new Signature(bytes.Slice(1), algoIdent); } /// diff --git a/Casper.Network.SDK/Types/URef.cs b/Casper.Network.SDK/Types/URef.cs index aff2b64..e69ddc6 100644 --- a/Casper.Network.SDK/Types/URef.cs +++ b/Casper.Network.SDK/Types/URef.cs @@ -45,7 +45,7 @@ public URef(string value) : base(value) /// Creates an URef from a 33 bytes array. Last byte corresponds to the access rights. /// public URef(byte[] bytes) - : this($"{KEYPREFIX}{Hex.ToHexString(bytes[..32])}-{(int)bytes[32]:000}") + : this($"{KEYPREFIX}{Hex.ToHexString(bytes.Slice(0,32))}-{(int)bytes[32]:000}") { } From 19d6e9382654b5352ca4867f86ca38cbb04b2671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 13:58:49 +0200 Subject: [PATCH 08/22] Workaround for `MemoryStream.Write` with less args. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS7036. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/MemoryStreamExtensions.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Casper.Network.SDK/Compat/MemoryStreamExtensions.cs diff --git a/Casper.Network.SDK/Compat/MemoryStreamExtensions.cs b/Casper.Network.SDK/Compat/MemoryStreamExtensions.cs new file mode 100644 index 0000000..5fcc3bf --- /dev/null +++ b/Casper.Network.SDK/Compat/MemoryStreamExtensions.cs @@ -0,0 +1,13 @@ +#if NETSTANDARD2_0 + +using System.IO; + +public static class MemoryStreamExtensions +{ + public static void Write(this MemoryStream stream, byte[] buffer) + { + stream.Write(buffer, 0, buffer.Length); + } +} + +#endif From 79845b2585a6649156a2b5a703c323701cea430a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:12:50 +0200 Subject: [PATCH 09/22] Workaround for `BigInteger.ToByteArray` with arg. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS7036. Signed-off-by: Andrzej Broński --- .../Compat/BigIntegerExtensions.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Casper.Network.SDK/Compat/BigIntegerExtensions.cs diff --git a/Casper.Network.SDK/Compat/BigIntegerExtensions.cs b/Casper.Network.SDK/Compat/BigIntegerExtensions.cs new file mode 100644 index 0000000..cc2d2a9 --- /dev/null +++ b/Casper.Network.SDK/Compat/BigIntegerExtensions.cs @@ -0,0 +1,32 @@ +#if NETSTANDARD2_0 + +using System; +using System.Numerics; + +public static class BigIntegerExtensions +{ + public static byte[] ToByteArray(this BigInteger value, bool isUnsigned = false) + { + byte[] bytes = value.ToByteArray(); + + if (isUnsigned) + { + if (value < 0) + { + throw new InvalidOperationException("Cannot retrieve an unsigned byte array representation of a negative BigInteger."); + } + + // If the BigInteger is positive and the highest byte is 0x80 or higher, + // an additional byte is added to indicate a positive number when using two's complement notation. + // For the unsigned representation, this additional byte is not necessary. + if (bytes.Length > 1 && bytes[bytes.Length - 1] == 0) + { + Array.Resize(ref bytes, bytes.Length - 1); + } + } + + return bytes; + } +} + +#endif From 5f22e95a830c0670123e35ecbcea36a592b653ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:13:47 +0200 Subject: [PATCH 10/22] Workaround for `BitConverter.To*` without arg. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS1501. Signed-off-by: Andrzej Broński --- .../Compat/BitConverterExtensions.cs | 28 +++++++++++++++++++ .../Utils/BinaryReaderExtensions.cs | 8 +++--- 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Casper.Network.SDK/Compat/BitConverterExtensions.cs diff --git a/Casper.Network.SDK/Compat/BitConverterExtensions.cs b/Casper.Network.SDK/Compat/BitConverterExtensions.cs new file mode 100644 index 0000000..50fbcf1 --- /dev/null +++ b/Casper.Network.SDK/Compat/BitConverterExtensions.cs @@ -0,0 +1,28 @@ +#if NETSTANDARD2_0 + +using System; + +public static class BitConverterExtensions +{ + public static Int64 ToInt64(byte[] value, int startIndex = 0) + { + return BitConverter.ToInt64(value, startIndex); + } + + public static Int32 ToInt32(byte[] value, int startIndex = 0) + { + return BitConverter.ToInt32(value, startIndex); + } + + public static UInt64 ToUInt64(byte[] value, int startIndex = 0) + { + return BitConverter.ToUInt64(value, startIndex); + } + + public static UInt32 ToUInt32(byte[] value, int startIndex = 0) + { + return BitConverter.ToUInt32(value, startIndex); + } +} + +#endif diff --git a/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs b/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs index 558cd18..c016db3 100644 --- a/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs +++ b/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs @@ -15,7 +15,7 @@ public static int ReadCLI32(this BinaryReader reader) var bytes = reader.ReadBytes(4); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); - return BitConverter.ToInt32(bytes); + return BitConverterExtensions.ToInt32(bytes); } public static long ReadCLI64(this BinaryReader reader) @@ -23,7 +23,7 @@ public static long ReadCLI64(this BinaryReader reader) var bytes = reader.ReadBytes(8); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); - return BitConverter.ToInt64(bytes); + return BitConverterExtensions.ToInt64(bytes); } public static byte ReadCLU8(this BinaryReader reader) @@ -36,7 +36,7 @@ public static uint ReadCLU32(this BinaryReader reader) var bytes = reader.ReadBytes(4); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); - return BitConverter.ToUInt32(bytes); + return BitConverterExtensions.ToUInt32(bytes); } public static ulong ReadCLU64(this BinaryReader reader) @@ -44,7 +44,7 @@ public static ulong ReadCLU64(this BinaryReader reader) var bytes = reader.ReadBytes(8); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); - return BitConverter.ToUInt64(bytes); + return BitConverterExtensions.ToUInt64(bytes); } public static BigInteger ReadCLBigInteger(this BinaryReader reader) From 9ca4ca6f30c97b031045e3858d8a1a3e5653a0b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:18:53 +0200 Subject: [PATCH 11/22] Workaround for `HttpClient.GetStreamAsync` with 2 args. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS1501. Signed-off-by: Andrzej Broński --- .../Compat/HttpClientExtensions.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Casper.Network.SDK/Compat/HttpClientExtensions.cs diff --git a/Casper.Network.SDK/Compat/HttpClientExtensions.cs b/Casper.Network.SDK/Compat/HttpClientExtensions.cs new file mode 100644 index 0000000..507a929 --- /dev/null +++ b/Casper.Network.SDK/Compat/HttpClientExtensions.cs @@ -0,0 +1,22 @@ +#if NETSTANDARD2_0 + +using System; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +public static class HttpClientExtensions +{ + public static async Task GetStreamAsync(this HttpClient client, Uri uri, CancellationToken cancelToken) + { + var response = await client.GetAsync(uri, cancelToken); + if (!response.IsSuccessStatusCode) + { + throw new HttpRequestException($"Request to {uri} returned with HTTP status code {response.StatusCode}"); + } + return await response.Content.ReadAsStreamAsync(); + } +} + +#endif From 55728135c31031f466679e3b312d937b413b35c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:21:48 +0200 Subject: [PATCH 12/22] Workaround for `BigInteger` constructor with 2 args. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/BigIntegerCompat.cs | 34 +++++++++++++++++++ .../Utils/BinaryReaderExtensions.cs | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 Casper.Network.SDK/Compat/BigIntegerCompat.cs diff --git a/Casper.Network.SDK/Compat/BigIntegerCompat.cs b/Casper.Network.SDK/Compat/BigIntegerCompat.cs new file mode 100644 index 0000000..ee52d0a --- /dev/null +++ b/Casper.Network.SDK/Compat/BigIntegerCompat.cs @@ -0,0 +1,34 @@ +#if NETSTANDARD2_0 + +using System; +using System.Numerics; + +public class BigIntegerCompat +{ + public static BigInteger Create(byte[] value, bool isUnsigned = false, bool isBigEndian = false) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (isBigEndian) + { + Array.Reverse(value); + } + + if (isUnsigned) + { + // Ensure that the resulting BigInteger is treated as an unsigned value by appending a 0 byte if necessary + if (value[value.Length - 1] >= 0x80) + { + Array.Resize(ref value, value.Length + 1); + value[value.Length - 1] = 0; + } + } + + return new BigInteger(value); + } +} + +#endif diff --git a/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs b/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs index c016db3..31e4033 100644 --- a/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs +++ b/Casper.Network.SDK/Utils/BinaryReaderExtensions.cs @@ -51,7 +51,7 @@ public static BigInteger ReadCLBigInteger(this BinaryReader reader) { var length = (int) reader.ReadByte(); var bytes = reader.ReadBytes(length); - return new BigInteger(bytes, true, false); + return BigIntegerCompat.Create(bytes, true, false); } public static string ReadCLString(this BinaryReader reader) From 45b7fa16b20c113558281b422b375f19c47b9022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:25:26 +0200 Subject: [PATCH 13/22] Workaround for `Enum.Parse`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/EnumCompat.cs | 13 +++++++++++++ Casper.Network.SDK/Types/Transform.cs | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Casper.Network.SDK/Compat/EnumCompat.cs diff --git a/Casper.Network.SDK/Compat/EnumCompat.cs b/Casper.Network.SDK/Compat/EnumCompat.cs new file mode 100644 index 0000000..2a7d51f --- /dev/null +++ b/Casper.Network.SDK/Compat/EnumCompat.cs @@ -0,0 +1,13 @@ +#if NETSTANDARD2_0 + +using System; + +public static class EnumCompat +{ + public static TEnum Parse(this String value) where TEnum : struct + { + return (TEnum)Enum.Parse(typeof(TEnum), value); + } +} + +#endif diff --git a/Casper.Network.SDK/Types/Transform.cs b/Casper.Network.SDK/Types/Transform.cs index 6b424ab..e9ee8e9 100644 --- a/Casper.Network.SDK/Types/Transform.cs +++ b/Casper.Network.SDK/Types/Transform.cs @@ -84,7 +84,7 @@ public override Transform Read( { var stype = reader.GetString(); if (stype != null) - type = Enum.Parse(stype); + type = EnumCompat.Parse(stype); reader.Read(); } else if (reader.TokenType == JsonTokenType.StartObject) @@ -92,7 +92,7 @@ public override Transform Read( reader.Read(); var stype = reader.GetString(); if (stype != null) - type = Enum.Parse(stype); + type = EnumCompat.Parse(stype); reader.Read(); switch (type) { From 1610ff9f80a6961e8d924c5abcc117447236fee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 14:26:59 +0200 Subject: [PATCH 14/22] Workaround for `Enum.GetName` with less args. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS7036. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/EnumCompat.cs | 6 ++++++ Casper.Network.SDK/Types/PublicKey.cs | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Casper.Network.SDK/Compat/EnumCompat.cs b/Casper.Network.SDK/Compat/EnumCompat.cs index 2a7d51f..c2c8734 100644 --- a/Casper.Network.SDK/Compat/EnumCompat.cs +++ b/Casper.Network.SDK/Compat/EnumCompat.cs @@ -1,6 +1,7 @@ #if NETSTANDARD2_0 using System; +using System.Linq; public static class EnumCompat { @@ -8,6 +9,11 @@ public static TEnum Parse(this String value) where TEnum : struct { return (TEnum)Enum.Parse(typeof(TEnum), value); } + + public static string GetName(TEnum value) where TEnum : Enum + { + return Enum.GetName(typeof(TEnum), value); + } } #endif diff --git a/Casper.Network.SDK/Types/PublicKey.cs b/Casper.Network.SDK/Types/PublicKey.cs index ac0665f..3243aed 100644 --- a/Casper.Network.SDK/Types/PublicKey.cs +++ b/Casper.Network.SDK/Types/PublicKey.cs @@ -93,8 +93,8 @@ public static PublicKey FromBytes(byte[] bytes) (int expectedPublicKeySize, string algo) = algoIdent switch { - 0x01 => (KeyAlgo.ED25519.GetKeySizeInBytes(), Enum.GetName(KeyAlgo.ED25519)), - 0x02 => (KeyAlgo.SECP256K1.GetKeySizeInBytes(), Enum.GetName(KeyAlgo.SECP256K1)), + 0x01 => (KeyAlgo.ED25519.GetKeySizeInBytes(), EnumCompat.GetName(KeyAlgo.ED25519)), + 0x02 => (KeyAlgo.SECP256K1.GetKeySizeInBytes(), EnumCompat.GetName(KeyAlgo.SECP256K1)), _ => throw new ArgumentException("Wrong public key algorithm identifier", nameof(bytes)) }; From 9607b0f872e30e4a1b1f2fa4cad94003400cf6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 23:29:04 +0200 Subject: [PATCH 15/22] Workaround for missing `DateTime.UnixEpoch`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It solves CS0117. Signed-off-by: Andrzej Broński --- Casper.Network.SDK/Compat/DateTimeCompat.cs | 11 +++++++++++ Casper.Network.SDK/Utils/DateUtils.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Casper.Network.SDK/Compat/DateTimeCompat.cs diff --git a/Casper.Network.SDK/Compat/DateTimeCompat.cs b/Casper.Network.SDK/Compat/DateTimeCompat.cs new file mode 100644 index 0000000..ef13228 --- /dev/null +++ b/Casper.Network.SDK/Compat/DateTimeCompat.cs @@ -0,0 +1,11 @@ +#if NETSTANDARD2_0 + +using System; +using System.Globalization; + +public static class DateTimeCompat +{ + public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); +} + +#endif diff --git a/Casper.Network.SDK/Utils/DateUtils.cs b/Casper.Network.SDK/Utils/DateUtils.cs index af22654..c7cf09f 100644 --- a/Casper.Network.SDK/Utils/DateUtils.cs +++ b/Casper.Network.SDK/Utils/DateUtils.cs @@ -30,7 +30,7 @@ public static ulong ToEpochTime(DateTime datetime) /// public static string ToISOString(ulong epochTimeInMillis) { - return DateTime.UnixEpoch + return DateTimeCompat.UnixEpoch .AddMilliseconds(epochTimeInMillis) .ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture); } From d81a28ed64b4df741f2f0cabd9caec9e6a40e2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 29 Aug 2023 23:32:31 +0200 Subject: [PATCH 16/22] Define CI/CD for Unity branch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrzej Broński --- .github/workflows/unity-compat.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/unity-compat.yml diff --git a/.github/workflows/unity-compat.yml b/.github/workflows/unity-compat.yml new file mode 100644 index 0000000..629dec4 --- /dev/null +++ b/.github/workflows/unity-compat.yml @@ -0,0 +1,24 @@ +name: Unity Compat - Build and Test + +on: + push: + branches: [feature/unity-compat] + pull_request: + branches: [feature/unity-compat] + +jobs: + buildntest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 7.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal --filter "TestCategory!~NCTL" From e5344e49d8aca5c195aa998f612ccb78083b31e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Wed, 30 Aug 2023 16:52:36 +0200 Subject: [PATCH 17/22] Fix invalid `Content-Type` - remove empty charset. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before it was `Content-Type: application/json; charset`, which caused error "415 Unsupported Media Type". Signed-off-by: Andrzej Broński --- Casper.Network.SDK/JsonRpc/RpcClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Casper.Network.SDK/JsonRpc/RpcClient.cs b/Casper.Network.SDK/JsonRpc/RpcClient.cs index a6ef724..1f72e74 100644 --- a/Casper.Network.SDK/JsonRpc/RpcClient.cs +++ b/Casper.Network.SDK/JsonRpc/RpcClient.cs @@ -65,8 +65,8 @@ protected async Task> SendAsync(RpcMethod me strMethod, System.Text.Encoding.UTF8, "application/json"); //CONTENT-TYPE header - if(request.Content.Headers.ContentType != null) - request.Content.Headers.ContentType.CharSet = ""; + request.Content.Headers.Remove("Content-Type"); // "{application/json; charset=utf-8}" + request.Content.Headers.Add("Content-Type", "application/json"); try { From 978ea1b27e49eac136b7450c9640428d440999dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Wed, 30 Aug 2023 17:56:48 +0200 Subject: [PATCH 18/22] Update `unity-compat.yml` workflow with new branch name. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrzej Broński --- .github/workflows/unity-compat.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unity-compat.yml b/.github/workflows/unity-compat.yml index 629dec4..4e64782 100644 --- a/.github/workflows/unity-compat.yml +++ b/.github/workflows/unity-compat.yml @@ -2,9 +2,9 @@ name: Unity Compat - Build and Test on: push: - branches: [feature/unity-compat] + branches: [netstandard-2-0-target] pull_request: - branches: [feature/unity-compat] + branches: [netstandard-2-0-target] jobs: buildntest: From a955ef7cf3655a9abee5dcc79c9625a220a48431 Mon Sep 17 00:00:00 2001 From: David Hernando Date: Fri, 12 Apr 2024 13:04:49 +0200 Subject: [PATCH 19/22] run tests on net7.0 netstandard2.0 Signed-off-by: David Hernando --- .github/workflows/build-and-test.yml | 11 +++++- .../CLValueJsonDeserializerTest.cs | 5 +-- Casper.Network.SDK.Test/CLValueToTypeTest.cs | 2 +- .../Casper.Network.SDK.Test.csproj | 18 ++++++--- Casper.Network.SDK.Test/KeysTest.cs | 18 ++++----- Casper.Network.SDK.Test/NctlContractTest.cs | 2 +- .../NctlMyDictContractTest.cs | 2 +- .../NctlSpeculativeExecutionTest.cs | 2 +- Casper.Network.SDK.sln.DotSettings.user | 4 +- Casper.Network.SDK/Casper.Network.SDK.csproj | 3 +- Casper.Network.SDK/Compat/BigIntegerCompat.cs | 7 ++-- .../Compat/BigIntegerExtensions.cs | 30 +++++++++++++++ .../Compat/BitConverterExtensions.cs | 2 - Casper.Network.SDK/Compat/BytesExtensions.cs | 2 - Casper.Network.SDK/Compat/DateTimeCompat.cs | 7 ++-- Casper.Network.SDK/Compat/EnumCompat.cs | 4 -- Casper.Network.SDK/Compat/FileExtensions.cs | 38 +++++++++++++++++++ Casper.Network.SDK/Types/CLValue.cs | 8 ++-- README.md | 12 ++++++ 19 files changed, 134 insertions(+), 43 deletions(-) create mode 100644 Casper.Network.SDK/Compat/FileExtensions.cs diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 18de892..93d1b01 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -2,7 +2,7 @@ name: Build and Test on: push: - branches: [ master ] + branches: [ master, netstandard-2-0-target ] pull_request: branches: [ master ] @@ -11,6 +11,13 @@ jobs: runs-on: ubuntu-latest + strategy: + matrix: + include: + - name: net7.0 + framework: net7.0 + - name: netstandard2.0 + framework: netstandard2.0 steps: - uses: actions/checkout@v2 - name: Setup .NET @@ -22,4 +29,4 @@ jobs: - name: Build run: dotnet build --no-restore - name: Test - run: dotnet test --no-build --verbosity normal --filter "TestCategory!~NCTL" + run: TEST_FRAMEWORK ${{ matrix.framework }} dotnet test --no-build --verbosity normal --filter "TestCategory!~NCTL" diff --git a/Casper.Network.SDK.Test/CLValueJsonDeserializerTest.cs b/Casper.Network.SDK.Test/CLValueJsonDeserializerTest.cs index abccc0f..4862944 100644 --- a/Casper.Network.SDK.Test/CLValueJsonDeserializerTest.cs +++ b/Casper.Network.SDK.Test/CLValueJsonDeserializerTest.cs @@ -7,7 +7,6 @@ using System.Text.Json.Serialization; using Casper.Network.SDK.Converters; using Casper.Network.SDK.Types; -using Newtonsoft.Json.Linq; using NUnit.Framework; using Org.BouncyCastle.Utilities.Encoders; @@ -148,7 +147,7 @@ public void DeserializeI32CLValue() var json = @"{""cl_type"":""I32"",""bytes"":""00000080"",""parsed"":-2147483648}"; var clValue = JsonSerializer.Deserialize(json); Assert.IsNotNull(clValue); - Assert.AreEqual(int.MinValue, BitConverter.ToInt32(clValue.Bytes)); + Assert.AreEqual(int.MinValue, BitConverterExtensions.ToInt32(clValue.Bytes)); Assert.AreEqual(int.MinValue, clValue.Parsed); } @@ -168,7 +167,7 @@ public void DeserializeU64CLValue() var clValue = JsonSerializer.Deserialize(json); Assert.IsNotNull(clValue); Assert.AreEqual(CLType.U64, clValue.TypeInfo.Type); - Assert.AreEqual(ulong.MaxValue, BitConverter.ToUInt64(clValue.Bytes)); + Assert.AreEqual(ulong.MaxValue, BitConverterExtensions.ToUInt64(clValue.Bytes)); Assert.AreEqual(ulong.MaxValue, clValue.Parsed); } diff --git a/Casper.Network.SDK.Test/CLValueToTypeTest.cs b/Casper.Network.SDK.Test/CLValueToTypeTest.cs index 028c06f..80db6e0 100644 --- a/Casper.Network.SDK.Test/CLValueToTypeTest.cs +++ b/Casper.Network.SDK.Test/CLValueToTypeTest.cs @@ -214,7 +214,7 @@ public void CLValueToBigInteger() Assert.AreEqual(new BigInteger(5123456789012), clValue.ToBigInteger()); Assert.AreEqual(new BigInteger(5123456789012), (BigInteger) clValue); - var bigInt = new BigInteger(Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"), true); + var bigInt = BigIntegerCompat.Create(Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"), true); clValue = CLValue.U128(bigInt); Assert.AreEqual(bigInt, clValue.ToBigInteger()); Assert.AreEqual(bigInt, (BigInteger) clValue); diff --git a/Casper.Network.SDK.Test/Casper.Network.SDK.Test.csproj b/Casper.Network.SDK.Test/Casper.Network.SDK.Test.csproj index e14e06f..70b9c66 100644 --- a/Casper.Network.SDK.Test/Casper.Network.SDK.Test.csproj +++ b/Casper.Network.SDK.Test/Casper.Network.SDK.Test.csproj @@ -2,9 +2,8 @@ net7.0 - + 9.0 false - NetCasperTest @@ -15,10 +14,19 @@ - - + + + $(TEST_FRAMEWORK) + + net7.0 + + + + + + + - PreserveNewest diff --git a/Casper.Network.SDK.Test/KeysTest.cs b/Casper.Network.SDK.Test/KeysTest.cs index ba11605..6dfae71 100644 --- a/Casper.Network.SDK.Test/KeysTest.cs +++ b/Casper.Network.SDK.Test/KeysTest.cs @@ -21,7 +21,7 @@ public void TestValidBlakeEd25519() var publicKey = PublicKey.FromHexString(ED25519publicKey); Assert.AreEqual(KeyAlgo.ED25519, publicKey.KeyAlgorithm); Assert.AreEqual(ED25519publicKey, publicKey.ToAccountHex()); - Assert.IsTrue(Hex.Decode(ED25519publicKey)[1..].SequenceEqual(publicKey.RawBytes)); + Assert.IsTrue(Hex.Decode(ED25519publicKey).Slice(1).SequenceEqual(publicKey.RawBytes)); var hash = publicKey.GetAccountHash(); Assert.AreEqual(ED25519hash, hash.Substring("account-hash-".Length), "Unexpected ED25519 hash value"); @@ -29,19 +29,19 @@ public void TestValidBlakeEd25519() var pk2 = PublicKey.FromBytes(Hex.Decode(ED25519publicKey)); Assert.AreEqual(KeyAlgo.ED25519, pk2.KeyAlgorithm); Assert.AreEqual(ED25519publicKey, pk2.ToAccountHex()); - Assert.IsTrue(Hex.Decode(ED25519publicKey)[1..].SequenceEqual(pk2.RawBytes)); + Assert.IsTrue(Hex.Decode(ED25519publicKey).Slice(1).SequenceEqual(pk2.RawBytes)); - var pk3 = PublicKey.FromRawBytes(Hex.Decode(ED25519publicKey)[1..], KeyAlgo.ED25519); + var pk3 = PublicKey.FromRawBytes(Hex.Decode(ED25519publicKey).Slice(1), KeyAlgo.ED25519); Assert.AreEqual(KeyAlgo.ED25519, pk3.KeyAlgorithm); Assert.AreEqual(ED25519publicKey, pk3.ToAccountHex()); - Assert.IsTrue(Hex.Decode(ED25519publicKey)[1..].SequenceEqual(pk3.RawBytes)); + Assert.IsTrue(Hex.Decode(ED25519publicKey).Slice(1).SequenceEqual(pk3.RawBytes)); var pemfile = TestContext.CurrentContext.TestDirectory + "/TestData/test-ed25519-pk.pem"; var pk4 = PublicKey.FromPem(pemfile); Assert.AreEqual(KeyAlgo.ED25519, pk4.KeyAlgorithm); Assert.AreEqual(ED25519publicKey, pk4.ToAccountHex()); - Assert.IsTrue(Hex.Decode(ED25519publicKey)[1..].SequenceEqual(pk4.RawBytes)); + Assert.IsTrue(Hex.Decode(ED25519publicKey).Slice(1).SequenceEqual(pk4.RawBytes)); Assert.IsTrue(Hex.Decode(ED25519publicKey).SequenceEqual(pk4.GetBytes())); var hash3 = pk4.GetAccountHash(); @@ -60,19 +60,19 @@ public void TestValidBlakeSecp256k1() var pk2 = PublicKey.FromBytes(Hex.Decode(SECP256K1publicKey)); Assert.AreEqual(KeyAlgo.SECP256K1, pk2.KeyAlgorithm); Assert.AreEqual(SECP256K1publicKey, pk2.ToAccountHex()); - Assert.IsTrue(Hex.Decode(SECP256K1publicKey)[1..].SequenceEqual(pk2.RawBytes)); + Assert.IsTrue(Hex.Decode(SECP256K1publicKey).Slice(1).SequenceEqual(pk2.RawBytes)); - var pk3 = PublicKey.FromRawBytes(Hex.Decode(SECP256K1publicKey)[1..], KeyAlgo.SECP256K1); + var pk3 = PublicKey.FromRawBytes(Hex.Decode(SECP256K1publicKey).Slice(1), KeyAlgo.SECP256K1); Assert.AreEqual(KeyAlgo.SECP256K1, pk3.KeyAlgorithm); Assert.AreEqual(SECP256K1publicKey, pk3.ToAccountHex()); - Assert.IsTrue(Hex.Decode(SECP256K1publicKey)[1..].SequenceEqual(pk3.RawBytes)); + Assert.IsTrue(Hex.Decode(SECP256K1publicKey).Slice(1).SequenceEqual(pk3.RawBytes)); var pemfile = TestContext.CurrentContext.TestDirectory + "/TestData/test-secp256k1-pk.pem"; var pk4 = PublicKey.FromPem(pemfile); Assert.AreEqual(KeyAlgo.SECP256K1, pk4.KeyAlgorithm); Assert.AreEqual(SECP256K1publicKey, pk4.ToAccountHex()); - Assert.IsTrue(Hex.Decode(SECP256K1publicKey)[1..].SequenceEqual(pk4.RawBytes)); + Assert.IsTrue(Hex.Decode(SECP256K1publicKey).Slice(1).SequenceEqual(pk4.RawBytes)); Assert.IsTrue(Hex.Decode(SECP256K1publicKey).SequenceEqual(pk4.GetBytes())); var hash3 = pk4.GetAccountHash(); diff --git a/Casper.Network.SDK.Test/NctlContractTest.cs b/Casper.Network.SDK.Test/NctlContractTest.cs index 3e5ae2f..df520d2 100644 --- a/Casper.Network.SDK.Test/NctlContractTest.cs +++ b/Casper.Network.SDK.Test/NctlContractTest.cs @@ -25,7 +25,7 @@ public class NctlContractTest : NctlBase [Test, Order(1)] public async Task DeployContractTest() { - var wasmBytes = await File.ReadAllBytesAsync(_wasmFile); + var wasmBytes = await FileExtensions.ReadAllBytesAsync(_wasmFile); var deploy = DeployTemplates.ContractDeploy( wasmBytes, diff --git a/Casper.Network.SDK.Test/NctlMyDictContractTest.cs b/Casper.Network.SDK.Test/NctlMyDictContractTest.cs index f3513ad..5e3a2e2 100644 --- a/Casper.Network.SDK.Test/NctlMyDictContractTest.cs +++ b/Casper.Network.SDK.Test/NctlMyDictContractTest.cs @@ -26,7 +26,7 @@ public class NctlMyDictContractTest : NctlBase [Test, Order(1)] public async Task DeployContractTest() { - var wasmBytes = await File.ReadAllBytesAsync(_wasmFile); + var wasmBytes = await FileExtensions.ReadAllBytesAsync(_wasmFile); var deploy = DeployTemplates.ContractDeploy( wasmBytes, diff --git a/Casper.Network.SDK.Test/NctlSpeculativeExecutionTest.cs b/Casper.Network.SDK.Test/NctlSpeculativeExecutionTest.cs index ee1da46..72217a9 100644 --- a/Casper.Network.SDK.Test/NctlSpeculativeExecutionTest.cs +++ b/Casper.Network.SDK.Test/NctlSpeculativeExecutionTest.cs @@ -40,7 +40,7 @@ public void Setup() [Test, Order(1)] public async Task SpeculativeExecutionTest() { - var wasmBytes = await File.ReadAllBytesAsync(_wasmFile); + var wasmBytes = await FileExtensions.ReadAllBytesAsync(_wasmFile); var deploy = DeployTemplates.ContractDeploy( wasmBytes, diff --git a/Casper.Network.SDK.sln.DotSettings.user b/Casper.Network.SDK.sln.DotSettings.user index b2dd7b0..2c5113e 100644 --- a/Casper.Network.SDK.sln.DotSettings.user +++ b/Casper.Network.SDK.sln.DotSettings.user @@ -1,2 +1,4 @@  - C:\Users\d\AppData\Local\JetBrains\Rider2021.3\resharper-host\temp\Rider\vAny\CoverageData\_Casper.Network.SDK.-947408436\Snapshot\snapshot.utdcvr \ No newline at end of file + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> \ No newline at end of file diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index ec9c00a..f43e346 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -1,8 +1,9 @@ - net7.0;netstandard2.0 + net7.0;netstandard2.0 9.0 + CS1591 2.2.0.0 2.2.0 2.2.0 diff --git a/Casper.Network.SDK/Compat/BigIntegerCompat.cs b/Casper.Network.SDK/Compat/BigIntegerCompat.cs index ee52d0a..6f4ae31 100644 --- a/Casper.Network.SDK/Compat/BigIntegerCompat.cs +++ b/Casper.Network.SDK/Compat/BigIntegerCompat.cs @@ -1,5 +1,3 @@ -#if NETSTANDARD2_0 - using System; using System.Numerics; @@ -7,6 +5,9 @@ public class BigIntegerCompat { public static BigInteger Create(byte[] value, bool isUnsigned = false, bool isBigEndian = false) { +#if NET7_0_OR_GREATER + return new BigInteger(value, true, false); +#elif NETSTANDARD2_0 if (value == null) { throw new ArgumentNullException(nameof(value)); @@ -28,7 +29,7 @@ public static BigInteger Create(byte[] value, bool isUnsigned = false, bool isBi } return new BigInteger(value); +#endif } } -#endif diff --git a/Casper.Network.SDK/Compat/BigIntegerExtensions.cs b/Casper.Network.SDK/Compat/BigIntegerExtensions.cs index cc2d2a9..b6b2b55 100644 --- a/Casper.Network.SDK/Compat/BigIntegerExtensions.cs +++ b/Casper.Network.SDK/Compat/BigIntegerExtensions.cs @@ -27,6 +27,36 @@ public static byte[] ToByteArray(this BigInteger value, bool isUnsigned = false) return bytes; } + + public static int GetBitLength(this BigInteger value) + { + // If the value is zero, its bit length is 0 + if (value == BigInteger.Zero) + return 0; + + // Get the byte array without the sign + byte[] bytes = value.ToByteArray(); + + // Find the highest-order byte with a non-zero value + int highestByte = bytes.Length - 1; + while (highestByte > 0 && bytes[highestByte] == 0) + { + highestByte--; + } + + // Count the bits in the last used byte + int bitsInLastByte = 0; + byte lastByte = bytes[highestByte]; + while (lastByte != 0) + { + bitsInLastByte++; + lastByte >>= 1; + } + + // Calculate the total bit length + // (Number of full bytes minus 1) * 8 + bits in last byte + return highestByte * 8 + bitsInLastByte; + } } #endif diff --git a/Casper.Network.SDK/Compat/BitConverterExtensions.cs b/Casper.Network.SDK/Compat/BitConverterExtensions.cs index 50fbcf1..dcad241 100644 --- a/Casper.Network.SDK/Compat/BitConverterExtensions.cs +++ b/Casper.Network.SDK/Compat/BitConverterExtensions.cs @@ -1,4 +1,3 @@ -#if NETSTANDARD2_0 using System; @@ -25,4 +24,3 @@ public static UInt32 ToUInt32(byte[] value, int startIndex = 0) } } -#endif diff --git a/Casper.Network.SDK/Compat/BytesExtensions.cs b/Casper.Network.SDK/Compat/BytesExtensions.cs index a6db9c4..592d8c3 100644 --- a/Casper.Network.SDK/Compat/BytesExtensions.cs +++ b/Casper.Network.SDK/Compat/BytesExtensions.cs @@ -1,4 +1,3 @@ -#if NETSTANDARD2_0 using System; @@ -22,4 +21,3 @@ public static byte[] Slice(this byte[] bytes, int from, int? to = null) } } -#endif diff --git a/Casper.Network.SDK/Compat/DateTimeCompat.cs b/Casper.Network.SDK/Compat/DateTimeCompat.cs index ef13228..3322c41 100644 --- a/Casper.Network.SDK/Compat/DateTimeCompat.cs +++ b/Casper.Network.SDK/Compat/DateTimeCompat.cs @@ -1,11 +1,12 @@ -#if NETSTANDARD2_0 - using System; using System.Globalization; public static class DateTimeCompat { +#if NET7_0_OR_GREATER + public static readonly DateTime UnixEpoch = DateTime.UnixEpoch; +#elif NETSTANDARD2_0 public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); +#endif } -#endif diff --git a/Casper.Network.SDK/Compat/EnumCompat.cs b/Casper.Network.SDK/Compat/EnumCompat.cs index c2c8734..cae5ad5 100644 --- a/Casper.Network.SDK/Compat/EnumCompat.cs +++ b/Casper.Network.SDK/Compat/EnumCompat.cs @@ -1,5 +1,3 @@ -#if NETSTANDARD2_0 - using System; using System.Linq; @@ -15,5 +13,3 @@ public static string GetName(TEnum value) where TEnum : Enum return Enum.GetName(typeof(TEnum), value); } } - -#endif diff --git a/Casper.Network.SDK/Compat/FileExtensions.cs b/Casper.Network.SDK/Compat/FileExtensions.cs new file mode 100644 index 0000000..9b4b1b9 --- /dev/null +++ b/Casper.Network.SDK/Compat/FileExtensions.cs @@ -0,0 +1,38 @@ +using System.IO; +using System.Threading.Tasks; + +public static class FileExtensions +{ + public static async Task ReadAllBytesAsync(string path) + { +#if NET7_0_OR_GREATER + return await File.ReadAllBytesAsync(path); +#elif NETSTANDARD2_0 + + // Using FileStream with asynchronous flag + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, + FileOptions.Asynchronous)) + { + // Allocate memory for the file's content + byte[] bytes = new byte[stream.Length]; + // Read the entire file asynchronously + int numBytesToRead = (int)stream.Length; + int numBytesRead = 0; + while (numBytesToRead > 0) + { + // Read may return anything from 0 to numBytesToRead. + int n = await stream.ReadAsync(bytes, numBytesRead, numBytesToRead); + // Break when the end of the file is reached. + if (n == 0) + break; + + numBytesRead += n; + numBytesToRead -= n; + } + + return bytes; + } +#endif + } +} + diff --git a/Casper.Network.SDK/Types/CLValue.cs b/Casper.Network.SDK/Types/CLValue.cs index ee1abf7..670dd23 100644 --- a/Casper.Network.SDK/Types/CLValue.cs +++ b/Casper.Network.SDK/Types/CLValue.cs @@ -946,7 +946,7 @@ public Dictionary ToDictionary() } /// - /// Converts Tuple1 CLValue to Tuple<T1;>. + /// Converts Tuple1 CLValue to Tuple<T1>. /// public Tuple ToTuple1() { @@ -969,7 +969,7 @@ public Tuple ToTuple1() } /// - /// Converts Tuple2 CLValue to Tuple<T1,T2;>. + /// Converts Tuple2 CLValue to Tuple<T1,T2>. /// public Tuple ToTuple2() { @@ -992,7 +992,7 @@ public Tuple ToTuple2() } /// - /// Converts Tuple2 CLValue to Tuple<T1,T2,T3;>. + /// Converts Tuple2 CLValue to Tuple<T1,T2,T3>. /// public Tuple ToTuple3() { @@ -1015,7 +1015,7 @@ public Tuple ToTuple3() } /// - /// Converts Result CLValue to Result<TOk,TErr;>. + /// Converts Result CLValue to Result<TOk,TErr>. /// public Result ToResult() { diff --git a/README.md b/README.md index 3c7fddf..c980519 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,12 @@ dotnet test --filter 'TestCategory!~NCTL' On Windows use a PowerShell terminal to run the tests. +To test against `netstandard2.0` framework, launch the tests as follows: + +``` +TEST_FRAMEWORK=netstandard2.0 dotnet test --filter 'TestCategory!~NCTL' +``` + ### Integration tests The command above excludes integration tests. If you're running a Casper network locally with NCTL, follow these steps to run the integrations tests: @@ -70,6 +76,12 @@ dotnet test --settings Casper.Network.SDK.Test/test.runsettings --filter 'TestCa NOTE: Make sure your NCTL network has booted up and nodes are emitting blocks before running the tests. +To test against `netstandard2.0` framework, launch the tests as follows: + +``` +TEST_FRAMEWORK=netstandard2.0 dotnet test --settings Casper.Network.SDK.Test/test.runsettings --filter 'TestCategory~NCTL' +``` + ## Create a workspace in Gitpod Click the button to start coding in Gitpod with an online IDE. From ab81ba4da13c89f08a051d57cfad2f2c6632e7fa Mon Sep 17 00:00:00 2001 From: David Hernando Date: Fri, 12 Apr 2024 13:07:12 +0200 Subject: [PATCH 20/22] fix test pipeline Signed-off-by: David Hernando --- .github/workflows/build-and-test.yml | 2 +- .github/workflows/unity-compat.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 93d1b01..3ada82d 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -29,4 +29,4 @@ jobs: - name: Build run: dotnet build --no-restore - name: Test - run: TEST_FRAMEWORK ${{ matrix.framework }} dotnet test --no-build --verbosity normal --filter "TestCategory!~NCTL" + run: TEST_FRAMEWORK=${{ matrix.framework }} dotnet test --no-build --verbosity normal --filter "TestCategory!~NCTL" diff --git a/.github/workflows/unity-compat.yml b/.github/workflows/unity-compat.yml index 4e64782..03be418 100644 --- a/.github/workflows/unity-compat.yml +++ b/.github/workflows/unity-compat.yml @@ -1,4 +1,4 @@ -name: Unity Compat - Build and Test +ame: Unity Compat - Build and Test on: push: From 9800e2d5c6815edecee3948482eb4144584aee36 Mon Sep 17 00:00:00 2001 From: David Hernando Date: Fri, 12 Apr 2024 13:16:29 +0200 Subject: [PATCH 21/22] test against net7.0 and netstandard2.0 frameworks Signed-off-by: David Hernando --- .github/workflows/integration-testing.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-testing.yml b/.github/workflows/integration-testing.yml index a8b62be..58a3727 100644 --- a/.github/workflows/integration-testing.yml +++ b/.github/workflows/integration-testing.yml @@ -9,6 +9,14 @@ jobs: # The type of runner that the job will run on runs-on: ubuntu-latest + strategy: + matrix: + include: + - name: net7.0 + framework: net7.0 + - name: netstandard2.0 + framework: netstandard2.0 + # Service containers to run with `runner-job` services: # Label used to access the service container @@ -37,4 +45,4 @@ jobs: - name: Build run: dotnet build --no-restore - name: Test - run: dotnet test --no-build --verbosity normal --settings Casper.Network.SDK.Test/test.runsettings --filter="TestCategory=NCTL" + run: TEST_FRAMEWORK=${{ matrix.framework }} dotnet test --no-build --verbosity normal --settings Casper.Network.SDK.Test/test.runsettings --filter="TestCategory=NCTL" From bc174668cbd4a85522876f2abebbb38e5afe4c9d Mon Sep 17 00:00:00 2001 From: David Hernando Date: Fri, 12 Apr 2024 13:34:29 +0200 Subject: [PATCH 22/22] Bump up version to 3.0 fix xml documentation location Signed-off-by: David Hernando --- Casper.Network.SDK/Casper.Network.SDK.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Casper.Network.SDK/Casper.Network.SDK.csproj b/Casper.Network.SDK/Casper.Network.SDK.csproj index f43e346..ef16c9f 100644 --- a/Casper.Network.SDK/Casper.Network.SDK.csproj +++ b/Casper.Network.SDK/Casper.Network.SDK.csproj @@ -4,9 +4,9 @@ net7.0;netstandard2.0 9.0 CS1591 - 2.2.0.0 - 2.2.0 - 2.2.0 + 2.3.0.0 + 2.3.0 + 2.3.0 Casper.Network.SDK make-software https://github.com/make-software/casper-net-sdk @@ -20,7 +20,7 @@ Casper.Network.SDK true - bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + bin\$(Configuration)\$(AssemblyName).xml