From 69054a3d3d3895a456b18ea45252911358813174 Mon Sep 17 00:00:00 2001 From: "cedric.decoster" Date: Wed, 17 Jan 2024 18:27:15 +0100 Subject: [PATCH 1/8] added comments removed create from json from account --- Substrate.NetApi/Model/Types/Account.cs | 17 ++++++++++++++--- Substrate.NetApi/Model/Types/Base/BaseType.cs | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index a08a67d..8716d6a 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -8,17 +8,22 @@ namespace Substrate.NetApi.Model.Types { /// - /// Represents a key type. + /// Enum KeyType represents the type of cryptographic keys used in digital signatures. /// public enum KeyType { /// - /// Ed25519 + /// Ed25519: Elliptic Curve Digital Signature Algorithm using SHA-512 and Curve25519. + /// Preferred for its balance of security and performance, suitable for scenarios + /// requiring fast signature verification. Commonly used in secure communication, + /// authentication, and blockchain applications. /// Ed25519, /// - /// Sr25519 + /// Sr25519: Schnorr signature scheme using SHA-512 and Curve25519, implemented in Schnorrkel. + /// Offers advantages in complex cryptographic constructions and potentially better performance. + /// Frequently used in decentralized systems and advanced cryptographic protocols. /// Sr25519 } @@ -106,6 +111,12 @@ public void Create(KeyType keyType, byte[] publicKey) Create(keyType, null, publicKey); } + /// + public override void CreateFromJson(string str) + { + throw new NotSupportedException("CreateFromJson is not supported for Account."); + } + /// /// Builds the specified key type. /// diff --git a/Substrate.NetApi/Model/Types/Base/BaseType.cs b/Substrate.NetApi/Model/Types/Base/BaseType.cs index d39c2c4..89ff712 100644 --- a/Substrate.NetApi/Model/Types/Base/BaseType.cs +++ b/Substrate.NetApi/Model/Types/Base/BaseType.cs @@ -56,13 +56,13 @@ public virtual void Create(byte[] byteArray) } /// - /// Create from a json string + /// Create from JSON is used to deserialize in GenericTypeConverters, to automatically convert scale encoded JSON Rust types to C# types. /// /// public virtual void CreateFromJson(string str) => Create(Utils.HexToByteArray(str)); /// - /// New + /// Create a new instance of the type, this uses the default constructor. /// /// public IType New() => this; From c4ea9185b0add2db9d3d0a813c6d459990ad4b1b Mon Sep 17 00:00:00 2001 From: "cedric.decoster" Date: Sun, 28 Jan 2024 14:32:29 +0100 Subject: [PATCH 2/8] added interface async signraw and signpayload --- Substrate.NetApi.Test/Keys/Ed25519Tests.cs | 5 +-- Substrate.NetApi.Test/Keys/Sr25519Tests.cs | 5 +-- Substrate.NetApi/Model/Extrinsics/Payload.cs | 15 +++++++-- Substrate.NetApi/Model/Types/Account.cs | 34 ++++++++++++++++---- Substrate.NetApi/RequestGenerator.cs | 14 ++++---- Substrate.NetApi/Substrate.NetApi.csproj | 2 +- Substrate.NetApi/SubstrateClient.cs | 4 ++- 7 files changed, 56 insertions(+), 23 deletions(-) diff --git a/Substrate.NetApi.Test/Keys/Ed25519Tests.cs b/Substrate.NetApi.Test/Keys/Ed25519Tests.cs index beb6354..e7c4304 100644 --- a/Substrate.NetApi.Test/Keys/Ed25519Tests.cs +++ b/Substrate.NetApi.Test/Keys/Ed25519Tests.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using Substrate.NetApi.Model.Types; using Substrate.NetApi.Model.Types.Base; @@ -133,7 +134,7 @@ public void Ed25519SignatureTestComparePolkadotJs(string polkadotJsSignature) [Test] [TestCase("0xd2baabb61bcd0026e797136cb0938d55e3c3ea8825c163eb3d1738b3c79af8e8f4953ba4767dc5477202756d3fba97bc50fc3ac8355ff5acfba88a36311f2f0f")] - public void AccountEd25519SignatureTestComparePolkadotJs(string polkadotJsSignature) + public async Task AccountEd25519SignatureTestComparePolkadotJsAsync(string polkadotJsSignature) { var rawSeed = "0x70f93a75dbc6ad5b0c051210704a00a9937732d0c360792b0fea24efb8ea8465"; @@ -146,7 +147,7 @@ public void AccountEd25519SignatureTestComparePolkadotJs(string polkadotJsSignat // According to https://github.com/polkadot-js/apps/blob/master/packages/page-signing/src/Sign.tsx#L93 var messageBytes = WrapMessage.Wrap(message); - var signature = account.Sign(messageBytes); + var signature = await account.SignRawAsync(messageBytes); var singatureHexString = Utils.Bytes2HexString(signature); // SIGn C#: 0x679FA7BC8B2A7C40B5ECD50CA041E961DB8971D2B454DB7DE64E543B3C1892A6D3F223DDA01C66B9878C149CFCC8B86ECF2B20F11F7610596F51479405776907 diff --git a/Substrate.NetApi.Test/Keys/Sr25519Tests.cs b/Substrate.NetApi.Test/Keys/Sr25519Tests.cs index 9f69c96..9bd7f22 100644 --- a/Substrate.NetApi.Test/Keys/Sr25519Tests.cs +++ b/Substrate.NetApi.Test/Keys/Sr25519Tests.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using Schnorrkel.Keys; using Substrate.NetApi.Model.Types; +using System.Threading.Tasks; namespace Substrate.NetApi.Test.Keys { @@ -88,7 +89,7 @@ public void Sr25519SignatureTestComparePolkadotJs(string polkadotJsSignature) [Test] [TestCase("0x5c42ac4e2d55b8e59d9b255af370de03fe177f5545eecbbd784531cb2eb1f2553e0e2b91656f99fae930eb6ff8ac1a3eca4e19d307ecb39832a479a478a8608a")] - public void AccountSr25519SignatureTestComparePolkadotJs(string polkadotJsSignature) + public async Task AccountSr25519SignatureTestComparePolkadotJsAsync(string polkadotJsSignature) { var miniSecretAlice = new MiniSecret(Utils.HexToByteArray("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"), ExpandMode.Ed25519); @@ -97,7 +98,7 @@ public void AccountSr25519SignatureTestComparePolkadotJs(string polkadotJsSignat var message = "I test this signature!"; var messageBytes = WrapMessage.Wrap(message); - var simpleSign = account.Sign(messageBytes); + var simpleSign = await account.SignRawAsync(messageBytes); var singatureHexString = Utils.Bytes2HexString(simpleSign); // SIGn C#: 0x2A6346A8707A9929B65167C448F719FE977F2EE04D2CB250685C98C79CCBF2458901F9B386D08422D9102FBD8BF7CFECDF7605F4CDC5FA8D121E2E9730F9098C diff --git a/Substrate.NetApi/Model/Extrinsics/Payload.cs b/Substrate.NetApi/Model/Extrinsics/Payload.cs index 5199b10..0afa883 100644 --- a/Substrate.NetApi/Model/Extrinsics/Payload.cs +++ b/Substrate.NetApi/Model/Extrinsics/Payload.cs @@ -1,11 +1,12 @@ -using System.Linq; +using Substrate.NetApi.Model.Types; +using System.Linq; namespace Substrate.NetApi.Model.Extrinsics { /// /// Payload /// - public class Payload + public class Payload : IEncodable { private readonly Method _call; @@ -23,12 +24,20 @@ public Payload(Method call, SignedExtensions signedExtensions) } /// - /// Encodes this instance. + /// Encodes this instance, returns the encoded bytes. Additionally, if + /// the encoded bytes are longer than 256 bytes, they are hashed using `blake2_256`. /// /// public byte[] Encode() { byte[] bytes = _call.Encode().Concat(_signedExtension.Encode()).ToArray(); + + // Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + if (bytes.Length > 256) + { + bytes = HashExtension.Blake2(bytes, 256); + } + return bytes; } } diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index 8716d6a..ce542fb 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -1,9 +1,11 @@ using Chaos.NaCl; using Newtonsoft.Json; using Schnorrkel; +using Substrate.NetApi.Model.Extrinsics; using Substrate.NetApi.Model.Types.Base; using System; using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; namespace Substrate.NetApi.Model.Types { @@ -36,9 +38,16 @@ public interface IAccount /// /// Sign the specified message. /// - /// + /// The message bytes. /// - byte[] Sign(byte[] message); + Task SignRawAsync(byte[] message); + + /// + /// Sign the specified payload. + /// + /// The payload. + /// + Task SignPayloadAsync(Payload payload); /// /// Verifies a signature from this account. @@ -131,27 +140,39 @@ public static Account Build(KeyType keyType, byte[] privateKey, byte[] publicKey return account; } + /// - /// Signs the specified message. + /// Asynchronously signs the specified message. /// /// /// /// - public byte[] Sign(byte[] message) + public async Task SignRawAsync(byte[] message) { switch (KeyType) { case KeyType.Ed25519: - return Ed25519.Sign(message, PrivateKey); + return await Task.Run(() => Ed25519.Sign(message, PrivateKey)); case KeyType.Sr25519: - return Sr25519v091.SignSimple(Bytes, PrivateKey, message); + return await Task.Run(() => Sr25519v091.SignSimple(Bytes, PrivateKey, message)); default: throw new NotSupportedException($"Unknown key type found '{KeyType}'."); } } + /// + /// Asynchronously signs the specified payload. + /// + /// + /// + /// + public async Task SignPayloadAsync(Payload payload) + { + return await SignRawAsync(payload.Encode()); + } + /// /// Verifies a signature from this account. /// @@ -185,5 +206,6 @@ public bool Verify(byte[] signature, byte[] publicKey, byte[] message) throw new NotSupportedException($"Unknown key type found '{KeyType}'."); } } + } } \ No newline at end of file diff --git a/Substrate.NetApi/RequestGenerator.cs b/Substrate.NetApi/RequestGenerator.cs index 01a4873..9b757f2 100644 --- a/Substrate.NetApi/RequestGenerator.cs +++ b/Substrate.NetApi/RequestGenerator.cs @@ -8,6 +8,7 @@ using Substrate.NetApi.Model.Types.Base; using Chaos.NaCl; using Schnorrkel; +using System.Threading.Tasks; namespace Substrate.NetApi { @@ -70,13 +71,13 @@ public static byte[] GetStorageKeyBytesHash(string module, string item) /// The method. /// The era. /// The nonce. - /// The tip. + /// The charge. /// The genesis. /// The start era. /// The runtime. /// /// signed, account, method, era, nonce, tip, genesis, startEra - public static UnCheckedExtrinsic SubmitExtrinsic(bool signed, Account account, Method method, Era era, + public static async Task SubmitExtrinsicAsync(bool signed, Account account, Method method, Era era, uint nonce, ChargeType charge, Hash genesis, Hash startEra, RuntimeVersion runtime) { var uncheckedExtrinsic = @@ -87,13 +88,10 @@ public static UnCheckedExtrinsic SubmitExtrinsic(bool signed, Account account, M return uncheckedExtrinsic; } - var payload = uncheckedExtrinsic.GetPayload(runtime).Encode(); + Payload payload = uncheckedExtrinsic.GetPayload(runtime); - /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. - if (payload.Length > 256) payload = HashExtension.Blake2(payload, 256); - - /// sign payload with the - byte[] signature = account.Sign(payload); + // sign payload with the, Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + byte[] signature = await account.SignPayloadAsync(payload); uncheckedExtrinsic.AddPayloadSignature(signature); diff --git a/Substrate.NetApi/Substrate.NetApi.csproj b/Substrate.NetApi/Substrate.NetApi.csproj index 67e2ed8..95739a0 100644 --- a/Substrate.NetApi/Substrate.NetApi.csproj +++ b/Substrate.NetApi/Substrate.NetApi.csproj @@ -3,7 +3,7 @@ Substrate.NET.API netstandard2.0;netstandard2.1;net6.0 - 0.9.15 + 0.9.16 Substrate Gaming Substrate Gaming true diff --git a/Substrate.NetApi/SubstrateClient.cs b/Substrate.NetApi/SubstrateClient.cs index e0e98f7..6ad66f8 100644 --- a/Substrate.NetApi/SubstrateClient.cs +++ b/Substrate.NetApi/SubstrateClient.cs @@ -359,7 +359,9 @@ public async Task GetExtrinsicParametersAsync(Method method, era = Era.Create(lifeTime, finalizedHeader.Number.Value); } - return RequestGenerator.SubmitExtrinsic(signed, account, method, era, nonce, charge, GenesisHash, startEra, RuntimeVersion); + var uncheckedExtrinsic = await RequestGenerator.SubmitExtrinsicAsync(signed, account, method, era, nonce, charge, GenesisHash, startEra, RuntimeVersion); ; + + return uncheckedExtrinsic; } /// From 27c781128f1213c17c484e13775ef9e0c3414cf6 Mon Sep 17 00:00:00 2001 From: "cedric.decoster" Date: Sun, 28 Jan 2024 14:40:16 +0100 Subject: [PATCH 3/8] #72 implemented fixed some comments --- .../Model/Extrinsics/Extrinsic.cs | 5 +-- Substrate.NetApi/RequestGenerator.cs | 14 ++++---- Substrate.NetApi/SubstrateClient.cs | 33 ++++++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs index 877d6de..315fed2 100644 --- a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs @@ -62,14 +62,15 @@ public Extrinsic(string str, ChargeType chargeType) : this(Utils.HexToByteArray( /// /// Initializes a new instance of the class. /// - /// The memory. + /// + /// internal Extrinsic(Memory memory, ChargeType chargeType) { int p = 0; int m; // length - var length = CompactInteger.Decode(memory.ToArray(), ref p); + _ = CompactInteger.Decode(memory.ToArray(), ref p); // signature version m = 1; diff --git a/Substrate.NetApi/RequestGenerator.cs b/Substrate.NetApi/RequestGenerator.cs index 9b757f2..473761d 100644 --- a/Substrate.NetApi/RequestGenerator.cs +++ b/Substrate.NetApi/RequestGenerator.cs @@ -18,15 +18,15 @@ namespace Substrate.NetApi public class RequestGenerator { /// - /// Create a request for a storage call, for generated code. + /// Get the storage key. /// - /// - /// - /// - /// - /// - /// + /// The module name. + /// The item name. + /// The storage type. + /// The hashers. + /// The keys. /// + /// public static string GetStorage(string module, string item, Storage.Type type, Storage.Hasher[] hashers = null, IType[] keys = null) { var keybytes = GetStorageKeyBytesHash(module, item); diff --git a/Substrate.NetApi/SubstrateClient.cs b/Substrate.NetApi/SubstrateClient.cs index 6ad66f8..3b0fd59 100644 --- a/Substrate.NetApi/SubstrateClient.cs +++ b/Substrate.NetApi/SubstrateClient.cs @@ -141,31 +141,43 @@ public bool SetJsonRPCTraceLevel(SourceLevels sourceLevels) return true; } - /// Connects an asynchronous. - /// 19.09.2020. - /// An asynchronous result. + /// + /// Asynchronously connects to the node. + /// + /// public async Task ConnectAsync() { await ConnectAsync(true, CancellationToken.None); } - /// Connects an asynchronous. - /// 19.09.2020. - /// An asynchronous result. + /// + /// Asynchronously connects to the node. + /// + /// Cancellation token. + /// public async Task ConnectAsync(CancellationToken token) { await ConnectAsync(true, token); } + /// + /// Asynchronously connects to the node. + /// + /// Parse metadata on connect. + /// Cancellation token. + /// public async Task ConnectAsync(bool useMetaData, CancellationToken token) { await ConnectAsync(useMetaData, true, token); } - /// Connects an asynchronous. - /// 19.09.2020. - /// A token that allows processing to be cancelled. - /// An asynchronous result. + /// + /// Asynchronously connects to the node. + /// + /// Parse metadata on connect. + /// Get blocknumber and runtime information from standard susbtrate node. + /// Cancellation token. + /// public async Task ConnectAsync(bool useMetaData, bool standardSubstrate, CancellationToken token) { if (_socket != null && _socket.State == WebSocketState.Open) @@ -186,7 +198,6 @@ public async Task ConnectAsync(bool useMetaData, bool standardSubstrate, Cancell _socket.Options.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true; #endif } - } _connectTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); From 813a48be3a3e5826f4c27e9e5ea0bba1f4102f58 Mon Sep 17 00:00:00 2001 From: rostislavlitovkin Date: Sun, 28 Jan 2024 23:53:29 +0100 Subject: [PATCH 4/8] Virtual methods in Account --- Substrate.NetApi/Model/Types/Account.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index ce542fb..53cb0d6 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -140,14 +140,13 @@ public static Account Build(KeyType keyType, byte[] privateKey, byte[] publicKey return account; } - /// /// Asynchronously signs the specified message. /// /// /// /// - public async Task SignRawAsync(byte[] message) + public virtual async Task SignRawAsync(byte[] message) { switch (KeyType) { @@ -168,7 +167,7 @@ public async Task SignRawAsync(byte[] message) /// /// /// - public async Task SignPayloadAsync(Payload payload) + public virtual async Task SignPayloadAsync(Payload payload) { return await SignRawAsync(payload.Encode()); } From 1f3b8c89f05e2c6866b3cd3aa6441ea300ca4dfa Mon Sep 17 00:00:00 2001 From: rostislavlitovkin Date: Sun, 28 Jan 2024 23:53:55 +0100 Subject: [PATCH 5/8] Public properties in Payload and SignedExtensions --- Substrate.NetApi/Model/Extrinsics/Payload.cs | 10 ++--- .../Model/Extrinsics/SignedExtensions.cs | 42 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Substrate.NetApi/Model/Extrinsics/Payload.cs b/Substrate.NetApi/Model/Extrinsics/Payload.cs index 0afa883..5a9ed89 100644 --- a/Substrate.NetApi/Model/Extrinsics/Payload.cs +++ b/Substrate.NetApi/Model/Extrinsics/Payload.cs @@ -8,9 +8,9 @@ namespace Substrate.NetApi.Model.Extrinsics /// public class Payload : IEncodable { - private readonly Method _call; + public readonly Method Call; - private readonly SignedExtensions _signedExtension; + public readonly SignedExtensions SignedExtension; /// /// Initializes a new instance of the class. @@ -19,8 +19,8 @@ public class Payload : IEncodable /// The signed extensions. public Payload(Method call, SignedExtensions signedExtensions) { - _call = call; - _signedExtension = signedExtensions; + Call = call; + SignedExtension = signedExtensions; } /// @@ -30,7 +30,7 @@ public Payload(Method call, SignedExtensions signedExtensions) /// public byte[] Encode() { - byte[] bytes = _call.Encode().Concat(_signedExtension.Encode()).ToArray(); + byte[] bytes = Call.Encode().Concat(SignedExtension.Encode()).ToArray(); // Payloads longer than 256 bytes are going to be `blake2_256`-hashed. if (bytes.Length > 256) diff --git a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs index b9a3870..6a92de9 100644 --- a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs +++ b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs @@ -8,19 +8,19 @@ namespace Substrate.NetApi.Model.Extrinsics /// public class SignedExtensions { - private readonly uint _specVersion; + public readonly uint SpecVersion; - private readonly uint _txVersion; + public readonly uint TxVersion; - private readonly Hash _genesis; + public readonly Hash Genesis; - private readonly Hash _startEra; + public readonly Hash StartEra; - private readonly Era _mortality; + public readonly Era Mortality; - private readonly CompactInteger _nonce; + public readonly CompactInteger Nonce; - private readonly ChargeType _charge; + public readonly ChargeType Charge; /// /// Initializes a new instance of the class. @@ -34,13 +34,13 @@ public class SignedExtensions /// The charge transaction payment. public SignedExtensions(uint specVersion, uint txVersion, Hash genesis, Hash startEra, Era mortality, CompactInteger nonce, ChargeType charge) { - _specVersion = specVersion; - _txVersion = txVersion; - _genesis = genesis; - _startEra = startEra; - _mortality = mortality; - _nonce = nonce; - _charge = charge; + SpecVersion = specVersion; + TxVersion = txVersion; + Genesis = genesis; + StartEra = startEra; + Mortality = mortality; + Nonce = nonce; + Charge = charge; } /// @@ -52,13 +52,13 @@ public byte[] GetExtra() var bytes = new List(); // CheckMortality - bytes.AddRange(_mortality.Encode()); + bytes.AddRange(Mortality.Encode()); // CheckNonce - bytes.AddRange(_nonce.Encode()); + bytes.AddRange(Nonce.Encode()); // ChargeType - bytes.AddRange(_charge.Encode()); + bytes.AddRange(Charge.Encode()); return bytes.ToArray(); } @@ -72,16 +72,16 @@ public byte[] GetAdditionalSigned() var bytes = new List(); // CheckSpecVersion - bytes.AddRange(Utils.Value2Bytes(_specVersion)); + bytes.AddRange(Utils.Value2Bytes(SpecVersion)); // CheckTxVersion - bytes.AddRange(Utils.Value2Bytes(_txVersion)); + bytes.AddRange(Utils.Value2Bytes(TxVersion)); // CheckGenesis - bytes.AddRange(_genesis.Bytes); + bytes.AddRange(Genesis.Bytes); // CheckMortality, Additional Blockhash check. Immortal = genesis_hash, Mortal = logic - bytes.AddRange(_startEra.Bytes); + bytes.AddRange(StartEra.Bytes); return bytes.ToArray(); } From 8a9999692a650172e612f270fa775862cf24ca5a Mon Sep 17 00:00:00 2001 From: "cedric.decoster" Date: Mon, 29 Jan 2024 12:57:46 +0100 Subject: [PATCH 6/8] added propeorties to the client on connect. updated some checks --- Substrate.NetApi.Test/Keys/Ed25519Tests.cs | 10 +++-- Substrate.NetApi.Test/Keys/Sr25519Tests.cs | 14 ++++--- .../Model/Extrinsics/Extrinsic.cs | 5 ++- Substrate.NetApi/Model/Extrinsics/Payload.cs | 12 ++++-- .../Model/Extrinsics/SignedExtensions.cs | 37 +++++++++++++++---- .../Model/Extrinsics/UnCheckedExtrinsic.cs | 25 +++++++++---- Substrate.NetApi/Model/Types/Account.cs | 30 ++++++++++++--- Substrate.NetApi/SubstrateClient.cs | 13 ++++++- 8 files changed, 107 insertions(+), 39 deletions(-) diff --git a/Substrate.NetApi.Test/Keys/Ed25519Tests.cs b/Substrate.NetApi.Test/Keys/Ed25519Tests.cs index e7c4304..a9dc9ef 100644 --- a/Substrate.NetApi.Test/Keys/Ed25519Tests.cs +++ b/Substrate.NetApi.Test/Keys/Ed25519Tests.cs @@ -147,12 +147,14 @@ public async Task AccountEd25519SignatureTestComparePolkadotJsAsync(string polka // According to https://github.com/polkadot-js/apps/blob/master/packages/page-signing/src/Sign.tsx#L93 var messageBytes = WrapMessage.Wrap(message); - var signature = await account.SignRawAsync(messageBytes); - var singatureHexString = Utils.Bytes2HexString(signature); + var signature1 = await Task.Run(() => account.Sign(messageBytes)); + var signature2 = await account.SignAsync(messageBytes); - // SIGn C#: 0x679FA7BC8B2A7C40B5ECD50CA041E961DB8971D2B454DB7DE64E543B3C1892A6D3F223DDA01C66B9878C149CFCC8B86ECF2B20F11F7610596F51479405776907 + Assert.IsTrue(signature1.SequenceEqual(signature2)); + + Assert.True(account.Verify(signature1, account.Bytes, messageBytes)); + Assert.True(account.Verify(signature2, account.Bytes, messageBytes)); - // SIGn PolkaJS:0xd2baabb61bcd0026e797136cb0938d55e3c3ea8825c163eb3d1738b3c79af8e8f4953ba4767dc5477202756d3fba97bc50fc3ac8355ff5acfba88a36311f2f0f Assert.True(account.Verify(Utils.HexToByteArray(polkadotJsSignature), account.Bytes, messageBytes)); } } diff --git a/Substrate.NetApi.Test/Keys/Sr25519Tests.cs b/Substrate.NetApi.Test/Keys/Sr25519Tests.cs index 9bd7f22..90b8a3a 100644 --- a/Substrate.NetApi.Test/Keys/Sr25519Tests.cs +++ b/Substrate.NetApi.Test/Keys/Sr25519Tests.cs @@ -5,6 +5,7 @@ using Schnorrkel.Keys; using Substrate.NetApi.Model.Types; using System.Threading.Tasks; +using System.Linq; namespace Substrate.NetApi.Test.Keys { @@ -98,13 +99,14 @@ public async Task AccountSr25519SignatureTestComparePolkadotJsAsync(string polka var message = "I test this signature!"; var messageBytes = WrapMessage.Wrap(message); - var simpleSign = await account.SignRawAsync(messageBytes); - var singatureHexString = Utils.Bytes2HexString(simpleSign); - // SIGn C#: 0x2A6346A8707A9929B65167C448F719FE977F2EE04D2CB250685C98C79CCBF2458901F9B386D08422D9102FBD8BF7CFECDF7605F4CDC5FA8D121E2E9730F9098C + var signature1 = await Task.Run(() => account.Sign(messageBytes)); + var signature2 = await account.SignAsync(messageBytes); - // SIGn PolkaJS:0x5c42ac4e2d55b8e59d9b255af370de03fe177f5545eecbbd784531cb2eb1f2553e0e2b91656f99fae930eb6ff8ac1a3eca4e19d307ecb39832a479a478a8608a - var simpleSign2 = Utils.HexToByteArray(polkadotJsSignature); - Assert.True(account.Verify(simpleSign2, account.Bytes, messageBytes)); + Assert.True(account.Verify(signature1, account.Bytes, messageBytes)); + Assert.True(account.Verify(signature2, account.Bytes, messageBytes)); + + var signature3 = Utils.HexToByteArray(polkadotJsSignature); + Assert.True(account.Verify(signature3, account.Bytes, messageBytes)); } } } \ No newline at end of file diff --git a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs index 315fed2..fd9d3cc 100644 --- a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs @@ -55,7 +55,8 @@ public class Extrinsic /// /// The string. /// - public Extrinsic(string str, ChargeType chargeType) : this(Utils.HexToByteArray(str).AsMemory(), chargeType) + public Extrinsic(string str, ChargeType chargeType) + : this(Utils.HexToByteArray(str).AsMemory(), chargeType) { } @@ -84,7 +85,7 @@ internal Extrinsic(Memory memory, ChargeType chargeType) { // start bytes m = 1; - var _startBytes = memory.Slice(p, m).ToArray()[0]; + _ = memory.Slice(p, m).ToArray()[0]; p += m; // sender public key diff --git a/Substrate.NetApi/Model/Extrinsics/Payload.cs b/Substrate.NetApi/Model/Extrinsics/Payload.cs index 5a9ed89..6a1b84c 100644 --- a/Substrate.NetApi/Model/Extrinsics/Payload.cs +++ b/Substrate.NetApi/Model/Extrinsics/Payload.cs @@ -8,9 +8,15 @@ namespace Substrate.NetApi.Model.Extrinsics /// public class Payload : IEncodable { - public readonly Method Call; - - public readonly SignedExtensions SignedExtension; + /// + /// The call + /// + public Method Call { get; } + + /// + /// Signed extension + /// + public SignedExtensions SignedExtension { get; } /// /// Initializes a new instance of the class. diff --git a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs index 6a92de9..bc6bc5c 100644 --- a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs +++ b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs @@ -8,19 +8,40 @@ namespace Substrate.NetApi.Model.Extrinsics /// public class SignedExtensions { - public readonly uint SpecVersion; + /// + /// Specification Version + /// + public uint SpecVersion { get; } - public readonly uint TxVersion; + /// + /// Transaction Version + /// + public uint TxVersion { get; } - public readonly Hash Genesis; + /// + /// Genesis Hash + /// + public Hash Genesis { get; } - public readonly Hash StartEra; + /// + /// Start Era + /// + public Hash StartEra { get; } - public readonly Era Mortality; + /// + /// Mortality + /// + public Era Mortality { get; } - public readonly CompactInteger Nonce; + /// + /// Nonce + /// + public CompactInteger Nonce { get; } - public readonly ChargeType Charge; + /// + /// Charge + /// + public ChargeType Charge { get; } /// /// Initializes a new instance of the class. @@ -31,7 +52,7 @@ public class SignedExtensions /// The start era. /// The mortality. /// The nonce. - /// The charge transaction payment. + /// The charge transaction payment. public SignedExtensions(uint specVersion, uint txVersion, Hash genesis, Hash startEra, Era mortality, CompactInteger nonce, ChargeType charge) { SpecVersion = specVersion; diff --git a/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs b/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs index f2d77ef..2175740 100644 --- a/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs @@ -6,11 +6,20 @@ namespace Substrate.NetApi.Model.Extrinsics { + /// + /// Unchecked Extrinsic + /// public class UnCheckedExtrinsic : Extrinsic { - private readonly Hash _genesis; + /// + /// Genesis Hash + /// + private Hash Genesis { get; } - private readonly Hash _startEra; + /// + /// Start Era + /// + private Hash StartEra { get; } /// /// Initializes a new instance of the class. @@ -26,8 +35,8 @@ public class UnCheckedExtrinsic : Extrinsic public UnCheckedExtrinsic(bool signed, Account account, Method method, Era era, CompactInteger nonce, ChargeType charge, Hash genesis, Hash startEra) : base(signed, account, nonce, method, era, charge) { - _genesis = genesis; - _startEra = startEra; + Genesis = genesis; + StartEra = startEra; } /// @@ -37,7 +46,7 @@ public UnCheckedExtrinsic(bool signed, Account account, Method method, Era era, /// public Payload GetPayload(RuntimeVersion runtime) { - return new Payload(Method, new SignedExtensions(runtime.SpecVersion, runtime.TransactionVersion, _genesis, _startEra, Era, Nonce, Charge)); + return new Payload(Method, new SignedExtensions(runtime.SpecVersion, runtime.TransactionVersion, Genesis, StartEra, Era, Nonce, Charge)); } /// @@ -50,11 +59,11 @@ public void AddPayloadSignature(byte[] signature) } /// - /// Encodes this instance. + /// Encode this instance, returns the encoded bytes. /// /// - /// Missing payload signature for signed transaction. - public byte[] Encode() + /// + public new byte[] Encode() { if (Signed && Signature == null) { diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index 53cb0d6..a347e14 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -38,12 +38,19 @@ public interface IAccount /// /// Sign the specified message. /// + /// + /// + byte[] Sign(byte[] message); + + /// + /// Asynchronouslys sign the specified message. + /// /// The message bytes. /// - Task SignRawAsync(byte[] message); + Task SignAsync(byte[] message); /// - /// Sign the specified payload. + /// Asynchronouslys sign the specified payload. /// /// The payload. /// @@ -146,15 +153,26 @@ public static Account Build(KeyType keyType, byte[] privateKey, byte[] publicKey /// /// /// - public virtual async Task SignRawAsync(byte[] message) + public virtual async Task SignAsync(byte[] message) + { + return await Task.Run(() => Sign(message)); + } + + /// + /// Signs the specified message. + /// + /// + /// + /// + public byte[] Sign(byte[] message) { switch (KeyType) { case KeyType.Ed25519: - return await Task.Run(() => Ed25519.Sign(message, PrivateKey)); + return Ed25519.Sign(message, PrivateKey); case KeyType.Sr25519: - return await Task.Run(() => Sr25519v091.SignSimple(Bytes, PrivateKey, message)); + return Sr25519v091.SignSimple(Bytes, PrivateKey, message); default: throw new NotSupportedException($"Unknown key type found '{KeyType}'."); @@ -169,7 +187,7 @@ public virtual async Task SignRawAsync(byte[] message) /// public virtual async Task SignPayloadAsync(Payload payload) { - return await SignRawAsync(payload.Encode()); + return await SignAsync(payload.Encode()); } /// diff --git a/Substrate.NetApi/SubstrateClient.cs b/Substrate.NetApi/SubstrateClient.cs index 3b0fd59..b55dacb 100644 --- a/Substrate.NetApi/SubstrateClient.cs +++ b/Substrate.NetApi/SubstrateClient.cs @@ -87,10 +87,16 @@ public SubstrateClient(Uri uri, ChargeType chargeType, bool bypassRemoteCertific /// Information describing the meta. public MetaData MetaData { get; private set; } - /// Gets or sets information describing the runtime version. - /// Information describing the runtime version. + /// + /// Network runtime version + /// public RuntimeVersion RuntimeVersion { get; private set; } + /// + /// Network propoerties + /// + public Properties Properties { get; private set; } + /// Gets or sets the genesis hash. /// The genesis hash. public Hash GenesisHash { get; private set; } @@ -246,6 +252,9 @@ public async Task ConnectAsync(bool useMetaData, bool standardSubstrate, Cancell RuntimeVersion = await State.GetRuntimeVersionAsync(token); Logger.Debug("Runtime version parsed."); + + Properties = await System.PropertiesAsync(token); + Logger.Debug("Properties parsed."); } //_jsonRpc.TraceSource.Switch.Level = SourceLevels.All; From cab1ea2ae525569950df3235f3c76e31892cf70e Mon Sep 17 00:00:00 2001 From: rostislavlitovkin Date: Mon, 29 Jan 2024 13:25:48 +0100 Subject: [PATCH 7/8] Mark Sign as deprecated --- Substrate.NetApi/Model/Types/Account.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index a347e14..b5d862c 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -40,6 +40,7 @@ public interface IAccount /// /// /// + [Obsolete("Sign is deprecated, please use SignAsync instead.")] byte[] Sign(byte[] message); /// @@ -163,7 +164,8 @@ public virtual async Task SignAsync(byte[] message) /// /// /// - /// + /// ) + [Obsolete("Sign is deprecated, please use SignAsync instead.")] public byte[] Sign(byte[] message) { switch (KeyType) From cada9444fdd1b930871a200eb046f55529124d8a Mon Sep 17 00:00:00 2001 From: "cedric.decoster" Date: Tue, 30 Jan 2024 17:26:14 +0100 Subject: [PATCH 8/8] updated to a more consitent version --- Substrate.NetApi/Model/Types/Account.cs | 38 ++++++++----------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/Substrate.NetApi/Model/Types/Account.cs b/Substrate.NetApi/Model/Types/Account.cs index b5d862c..9bcd701 100644 --- a/Substrate.NetApi/Model/Types/Account.cs +++ b/Substrate.NetApi/Model/Types/Account.cs @@ -35,14 +35,6 @@ public enum KeyType /// public interface IAccount { - /// - /// Sign the specified message. - /// - /// - /// - [Obsolete("Sign is deprecated, please use SignAsync instead.")] - byte[] Sign(byte[] message); - /// /// Asynchronouslys sign the specified message. /// @@ -58,13 +50,13 @@ public interface IAccount Task SignPayloadAsync(Payload payload); /// - /// Verifies a signature from this account. + /// Asynchronouslys verifies a signature from this account. /// - /// - /// - /// + /// The signature to verify. + /// The public key to verify the signature with. + /// The message to verify the signature with. /// - bool Verify(byte[] signature, byte[] publicKey, byte[] message); + Task VerifyAsync(byte[] signature, byte[] publicKey, byte[] message); } /// @@ -148,12 +140,7 @@ public static Account Build(KeyType keyType, byte[] privateKey, byte[] publicKey return account; } - /// - /// Asynchronously signs the specified message. - /// - /// - /// - /// + /// public virtual async Task SignAsync(byte[] message) { return await Task.Run(() => Sign(message)); @@ -165,7 +152,6 @@ public virtual async Task SignAsync(byte[] message) /// /// /// ) - [Obsolete("Sign is deprecated, please use SignAsync instead.")] public byte[] Sign(byte[] message) { switch (KeyType) @@ -181,12 +167,7 @@ public byte[] Sign(byte[] message) } } - /// - /// Asynchronously signs the specified payload. - /// - /// - /// - /// + /// public virtual async Task SignPayloadAsync(Payload payload) { return await SignAsync(payload.Encode()); @@ -226,5 +207,10 @@ public bool Verify(byte[] signature, byte[] publicKey, byte[] message) } } + /// + public async Task VerifyAsync(byte[] signature, byte[] publicKey, byte[] message) + { + return await Task.Run(() => Verify(signature, publicKey, message)); + } } } \ No newline at end of file