diff --git a/Substrate.NetApi.Test/Extrinsic/InstanceTest.cs b/Substrate.NetApi.Test/Extrinsic/InstanceTest.cs index 6b206f9..8294fcf 100644 --- a/Substrate.NetApi.Test/Extrinsic/InstanceTest.cs +++ b/Substrate.NetApi.Test/Extrinsic/InstanceTest.cs @@ -11,14 +11,15 @@ namespace Substrate.NetApi.Test.Extrinsic public class InstanceTest { + // Extrinsics created and signed with polkadot-js/apps. public static string[] Extrinsic = new string[] { // Timestamp set(now) with now = 1673908758014 - "0x280403000bfea5bcbc8501", + "0xc50184001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0188f4859d09355d8f964b8cbb8b84c5e0e2f86a423d30027d15764996dc198532044424e6cc2e281f4d23174b6bfb3d2af64917b7356e570f41a1e44bcaa47385650300000001000bfea5bcbc8501", // Staking bondExtra(maxAdditional) with maxAditional = 60000000000 - "0xbd01840021e64ca11afde772615b240dd09ada3fc96e46619b77f9c0ce3dcebc67878939006ac2017f7951358d09ca1c6da63501b8d00dd72703e593b4a0ca924d59360d4968abaf6361999a21943618ce0850f8b5f8dd51c54c772ffccb35ff63208a1d0025012000070107005847f80d", + "0x710284001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c01d0e951a27297d1418d17fcbadfc19441d2d276f358965a94ff87f1b1db287c4cae203b65dab926627c80deae720bca1335d771389843b1bf69b9e85139922b819503000000070000001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0a000000000000000000000000000000", // Balances transferKeepAlive(dest, value) - "0x45028400f371affe2fd3ebd6f0a607e983bc8f905cea0ca2668667a229e112b30c5f9bbd0096f3ac43319d2e980db0aaf2b7e5e985055ea87f7b2a91a2ee09a934aef55bad4ec0dfd93e7010bc5dbf290403051ec40d475534df90ce3e1dd8a5b1ab3f7a0e4502cd0e000503001c3ef60163945e2b4602f7c6b27fc1f8e79d7c3430e3518cf63dc8a6ee84e9740700325f9d08" + "0x4d0284001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c01e6da8673127ec665dbfb76322ffe12721caa9b747abc5b6ec8ab73ff34f07831ed9edc49d185483a0c538a120149b7b6367bcde7088873408cc49ec280976c8ba5000000000403001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0f0080c6a47e8d03" }; [Test] diff --git a/Substrate.NetApi.Test/Extrinsic/PayloadTest.cs b/Substrate.NetApi.Test/Extrinsic/PayloadTest.cs index 7c86299..a3e375d 100644 --- a/Substrate.NetApi.Test/Extrinsic/PayloadTest.cs +++ b/Substrate.NetApi.Test/Extrinsic/PayloadTest.cs @@ -59,7 +59,7 @@ public void EncodeExtraTest() var payload = new Payload(method, signedExtensions); var payloadBytes = Utils.StringValueArrayBytesArray( - "6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1, 58, 6, 0, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); + "6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1, 58, 6, 0, 0, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); Assert.AreEqual(payloadBytes, payload.Encode()); } diff --git a/Substrate.NetApi.Test/Extrinsic/SignedExtensionsTest.cs b/Substrate.NetApi.Test/Extrinsic/SignedExtensionsTest.cs index 0ddf35c..c3aa7db 100644 --- a/Substrate.NetApi.Test/Extrinsic/SignedExtensionsTest.cs +++ b/Substrate.NetApi.Test/Extrinsic/SignedExtensionsTest.cs @@ -41,10 +41,10 @@ public void EncodeExtraTest() var signedExtensions = new SignedExtensions(259, 1, genesis, startEra, era, 0, assetTxPayment); var bytes = Utils.StringValueArrayBytesArray( - "58, 6, 0, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); + "58, 6, 0, 0, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); - Assert.AreEqual(bytes.AsMemory().Slice(0, 5).ToArray(), signedExtensions.GetExtra()); - Assert.AreEqual(bytes.AsMemory().Slice(5, 72).ToArray(), signedExtensions.GetAdditionalSigned()); + Assert.AreEqual(bytes.AsMemory().Slice(0, 6).ToArray(), signedExtensions.GetExtra()); + Assert.AreEqual(bytes.AsMemory().Slice(6, 73).ToArray(), signedExtensions.GetAdditionalSigned()); Assert.AreEqual(bytes, signedExtensions.Encode()); } } diff --git a/Substrate.NetApi/Model/Extrinsics/CheckMetadataHash.cs b/Substrate.NetApi/Model/Extrinsics/CheckMetadataHash.cs new file mode 100644 index 0000000..d7085af --- /dev/null +++ b/Substrate.NetApi/Model/Extrinsics/CheckMetadataHash.cs @@ -0,0 +1,76 @@ +using Substrate.NetApi.Model.Types.Base; +using System; + +namespace Substrate.NetApi.Model.Extrinsics +{ + + /// + /// If the runtime should expect a metadata hash that has been signed in the additional signed. + /// + public enum Mode + { + /// + /// `None` has been signed in the CheckMetadataHash additional signed. + /// + Disabled, + /// + /// `Some(MetadataHash)` has been signed in the CheckMetadataHash additional signed. + /// + Enabled + } + /// + /// CheckMetadataHash signed extension. + /// + public class CheckMetadataHash: BaseType + { + private Mode _mode; + + /// + /// Initialize with `Mode.Disabled`. + /// + public CheckMetadataHash() { + // Don't allow enabling the mode, as we don't support it. + _mode = Mode.Disabled; + } + + /// + /// Corresponds to the `Extra` that is sent with the extrinsic. + /// + /// + public override byte[] Encode() + { + return EncodeExtra(); + } + + /// + /// Corresponds to the extra that _is_ sent with the extrinsic. + /// + /// + public byte[] EncodeExtra() + { + return new BaseEnum(_mode).Encode(); + } + + /// + /// Corresponds to the `Additional` that is signed, but _not_ sent with the extrinsic. + /// + /// + public byte[] EncodeAdditional() + { + // We provide no metadata hash in the signer payload to align with the above. + return new byte[1]; + } + + /// + public override void Decode(byte[] byteArray, ref int p) + { + uint modeByte = byteArray[p++]; + + if (modeByte > 1) { + throw new ArgumentException($"{modeByte} is not a valid representation of CheckMetadata Mode."); + } + + _mode = modeByte == 0 ? Mode.Disabled : Mode.Enabled; + } + } +} \ No newline at end of file diff --git a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs index fd9d3cc..e689ad4 100644 --- a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs @@ -44,6 +44,11 @@ public class Extrinsic /// Method /// public Method Method { get; set; } + + /// + /// CheckMetadataHash + /// + public CheckMetadataHash CheckMetadataHash { get; set; } /// /// Signature @@ -124,6 +129,9 @@ internal Extrinsic(Memory memory, ChargeType chargeType) // charge type Charge = chargeType; Charge.Decode(memory.ToArray(), ref p); + + CheckMetadataHash = new CheckMetadataHash(); + CheckMetadataHash.Decode(memory.ToArray(), ref p); } // method @@ -154,6 +162,7 @@ public Extrinsic(bool signed, Account account, CompactInteger nonce, Method meth Era = era; Nonce = nonce; Charge = charge; + CheckMetadataHash = new CheckMetadataHash(); Method = method; } @@ -176,6 +185,7 @@ public byte[] Encode() result.AddRange(Era.Encode()); result.AddRange(Nonce.Encode()); result.AddRange(Charge.Encode()); + result.AddRange(CheckMetadataHash.EncodeExtra()); } result.AddRange(Method.Encode()); diff --git a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs index bc6bc5c..3e59f29 100644 --- a/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs +++ b/Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs @@ -42,6 +42,11 @@ public class SignedExtensions /// Charge /// public ChargeType Charge { get; } + + /// + /// CheckMetadataHash; only disabled supported for now. + /// + public CheckMetadataHash MetadataHashSignedExt { get; } /// /// Initializes a new instance of the class. @@ -62,6 +67,7 @@ public SignedExtensions(uint specVersion, uint txVersion, Hash genesis, Hash sta Mortality = mortality; Nonce = nonce; Charge = charge; + MetadataHashSignedExt = new CheckMetadataHash(); } /// @@ -80,6 +86,9 @@ public byte[] GetExtra() // ChargeType bytes.AddRange(Charge.Encode()); + + // CheckMetadataHash + bytes.AddRange(MetadataHashSignedExt.EncodeExtra()); return bytes.ToArray(); } @@ -103,6 +112,9 @@ public byte[] GetAdditionalSigned() // CheckMortality, Additional Blockhash check. Immortal = genesis_hash, Mortal = logic bytes.AddRange(StartEra.Bytes); + + // CheckMetadataHash + bytes.AddRange(MetadataHashSignedExt.EncodeAdditional()); return bytes.ToArray(); } diff --git a/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs b/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs index 2175740..ab8d809 100644 --- a/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs @@ -93,8 +93,10 @@ public void AddPayloadSignature(byte[] signature) list.AddRange(Charge.Encode()); + list.AddRange(CheckMetadataHash.EncodeExtra()); + list.AddRange(Method.Encode()); - + return Utils.SizePrefixedByteArray(list); } }