Skip to content

Commit

Permalink
Add support for the CheckMetadataHash signed extension (#85)
Browse files Browse the repository at this point in the history
* add check-metadata-hash-signed-ext

* fix unit tests

* fix some warnings

* Fix extrinsic tests

* cleanup `CheckMetadataHash`

* Fix: initialize `CheckMetadataHash` in Extrinsic constructor
  • Loading branch information
clangenb authored Jul 31, 2024
1 parent 3e3461f commit 3448b93
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 8 deletions.
7 changes: 4 additions & 3 deletions Substrate.NetApi.Test/Extrinsic/InstanceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion Substrate.NetApi.Test/Extrinsic/PayloadTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
6 changes: 3 additions & 3 deletions Substrate.NetApi.Test/Extrinsic/SignedExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand Down
76 changes: 76 additions & 0 deletions Substrate.NetApi/Model/Extrinsics/CheckMetadataHash.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Substrate.NetApi.Model.Types.Base;
using System;

namespace Substrate.NetApi.Model.Extrinsics
{

/// <summary>
/// If the runtime should expect a metadata hash that has been signed in the additional signed.
/// </summary>
public enum Mode
{
/// <summary>
/// `None` has been signed in the CheckMetadataHash additional signed.
/// </summary>
Disabled,
/// <summary>
/// `Some(MetadataHash)` has been signed in the CheckMetadataHash additional signed.
/// </summary>
Enabled
}
/// <summary>
/// CheckMetadataHash signed extension.
/// </summary>
public class CheckMetadataHash: BaseType
{
private Mode _mode;

/// <summary>
/// Initialize with `Mode.Disabled`.
/// </summary>
public CheckMetadataHash() {
// Don't allow enabling the mode, as we don't support it.
_mode = Mode.Disabled;
}

/// <summary>
/// Corresponds to the `Extra` that is sent with the extrinsic.
/// </summary>
/// <returns></returns>
public override byte[] Encode()
{
return EncodeExtra();
}

/// <summary>
/// Corresponds to the extra that _is_ sent with the extrinsic.
/// </summary>
/// <returns></returns>
public byte[] EncodeExtra()
{
return new BaseEnum<Mode>(_mode).Encode();
}

/// <summary>
/// Corresponds to the `Additional` that is signed, but _not_ sent with the extrinsic.
/// </summary>
/// <returns></returns>
public byte[] EncodeAdditional()
{
// We provide no metadata hash in the signer payload to align with the above.
return new byte[1];
}

/// <inheritdoc />
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;
}
}
}
10 changes: 10 additions & 0 deletions Substrate.NetApi/Model/Extrinsics/Extrinsic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public class Extrinsic
/// Method
/// </summary>
public Method Method { get; set; }

/// <summary>
/// CheckMetadataHash
/// </summary>
public CheckMetadataHash CheckMetadataHash { get; set; }

/// <summary>
/// Signature
Expand Down Expand Up @@ -124,6 +129,9 @@ internal Extrinsic(Memory<byte> memory, ChargeType chargeType)
// charge type
Charge = chargeType;
Charge.Decode(memory.ToArray(), ref p);

CheckMetadataHash = new CheckMetadataHash();
CheckMetadataHash.Decode(memory.ToArray(), ref p);
}

// method
Expand Down Expand Up @@ -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;
}

Expand All @@ -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());
Expand Down
12 changes: 12 additions & 0 deletions Substrate.NetApi/Model/Extrinsics/SignedExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public class SignedExtensions
/// Charge
/// </summary>
public ChargeType Charge { get; }

/// <summary>
/// CheckMetadataHash; only disabled supported for now.
/// </summary>
public CheckMetadataHash MetadataHashSignedExt { get; }

/// <summary>
/// Initializes a new instance of the <see cref="SignedExtensions"/> class.
Expand All @@ -62,6 +67,7 @@ public SignedExtensions(uint specVersion, uint txVersion, Hash genesis, Hash sta
Mortality = mortality;
Nonce = nonce;
Charge = charge;
MetadataHashSignedExt = new CheckMetadataHash();
}

/// <summary>
Expand All @@ -80,6 +86,9 @@ public byte[] GetExtra()

// ChargeType
bytes.AddRange(Charge.Encode());

// CheckMetadataHash
bytes.AddRange(MetadataHashSignedExt.EncodeExtra());

return bytes.ToArray();
}
Expand All @@ -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();
}
Expand Down
4 changes: 3 additions & 1 deletion Substrate.NetApi/Model/Extrinsics/UnCheckedExtrinsic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down

0 comments on commit 3448b93

Please sign in to comment.