Skip to content

Commit

Permalink
feat(net): introduce abstractions for Remoting (#607)
Browse files Browse the repository at this point in the history
  • Loading branch information
DennisInSky authored Oct 23, 2024
1 parent 6e0b976 commit 69444fa
Show file tree
Hide file tree
Showing 15 changed files with 478 additions and 5 deletions.
24 changes: 24 additions & 0 deletions Sails.Net.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sails.Net", "net\src\Sails.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.Gear.Api", "net\src\Substrate.Gear.Api\Substrate.Gear.Api.csproj", "{DAAAEB57-08B5-434E-8339-113F9335571F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sails.Remoting.Abstractions", "net\src\Sails.Remoting.Abstractions\Sails.Remoting.Abstractions.csproj", "{0442F9DE-9775-4787-866B-22869C681995}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sails.Remoting", "net\src\Sails.Remoting\Sails.Remoting.csproj", "{4C15C311-F328-480C-A102-3DCDC2C0AF11}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{17A264B0-419F-46D2-8ACE-662FB478E570}"
ProjectSection(SolutionItems) = preProject
net\Directory.Build.props = net\Directory.Build.props
net\Directory.Packages.props = net\Directory.Packages.props
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Substrate.Gear.Client", "net\src\Substrate.Gear.Client\Substrate.Gear.Client.csproj", "{1589D5A4-0CC4-4855-89E0-2E61BBC5E0B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +33,18 @@ Global
{DAAAEB57-08B5-434E-8339-113F9335571F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAAAEB57-08B5-434E-8339-113F9335571F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAAAEB57-08B5-434E-8339-113F9335571F}.Release|Any CPU.Build.0 = Release|Any CPU
{0442F9DE-9775-4787-866B-22869C681995}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0442F9DE-9775-4787-866B-22869C681995}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0442F9DE-9775-4787-866B-22869C681995}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0442F9DE-9775-4787-866B-22869C681995}.Release|Any CPU.Build.0 = Release|Any CPU
{4C15C311-F328-480C-A102-3DCDC2C0AF11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C15C311-F328-480C-A102-3DCDC2C0AF11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C15C311-F328-480C-A102-3DCDC2C0AF11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C15C311-F328-480C-A102-3DCDC2C0AF11}.Release|Any CPU.Build.0 = Release|Any CPU
{1589D5A4-0CC4-4855-89E0-2E61BBC5E0B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1589D5A4-0CC4-4855-89E0-2E61BBC5E0B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1589D5A4-0CC4-4855-89E0-2E61BBC5E0B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1589D5A4-0CC4-4855-89E0-2E61BBC5E0B0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
20 changes: 20 additions & 0 deletions net/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project>

<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>12.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Roslynator.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Formatting.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions net/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project>

<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

<ItemGroup>
<PackageVersion Include="Ensure.That" Version="10.1.0" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="RequiredMemberAttribute" Version="1.0.0" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.8" />
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.12.8" />
<PackageVersion Include="Substrate.NET.API" Version="0.9.24-rc6" />
</ItemGroup>

</Project>
5 changes: 1 addition & 4 deletions net/src/Sails.Net/Sails.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable;4014</WarningsAsErrors>
<LangVersion>latest</LangVersion>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

</Project>
33 changes: 33 additions & 0 deletions net/src/Sails.Remoting.Abstractions/IRemoting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Substrate.Gear.Api.Generated.Model.gprimitives;
using GasUnit = Substrate.NetApi.Model.Types.Primitive.U64;
using ValueUnit = Substrate.NetApi.Model.Types.Primitive.U128;

namespace Sails.Remoting.Abstractions;

public interface IRemoting
{
Task<(ActorId ProgramId, byte[] EncodedReply)> ActivateAsync(
CodeId codeId,
IReadOnlyCollection<byte> salt,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken);

Task<byte[]> MessageAsync(
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken);

Task<byte[]> QueryAsync(
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken);
}
54 changes: 54 additions & 0 deletions net/src/Sails.Remoting.Abstractions/IRemotingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Substrate.Gear.Api.Generated.Model.gprimitives;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using EnsureThat;
using ValueUnit = Substrate.NetApi.Model.Types.Primitive.U128;

namespace Sails.Remoting.Abstractions;

public static class IRemotingExtensions
{
public static Task<(ActorId ProgramId, byte[] EncodedReply)> ActivateAsync(
this IRemoting remoting,
CodeId codeId,
IReadOnlyCollection<byte> salt,
IReadOnlyCollection<byte> encodedPayload,
CancellationToken cancellationToken)
=> EnsureArg.IsNotNull(remoting, nameof(remoting))
.ActivateAsync(
codeId,
salt,
encodedPayload,
gasLimit: null,
ZeroValue,
cancellationToken);

public static Task<byte[]> MessageAsync(
this IRemoting remoting,
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
CancellationToken cancellationToken)
=> EnsureArg.IsNotNull(remoting, nameof(remoting))
.MessageAsync(
programId,
encodedPayload,
gasLimit: null,
ZeroValue,
cancellationToken);

public static Task<byte[]> QueryAsync(
this IRemoting remoting,
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
CancellationToken cancellationToken)
=> EnsureArg.IsNotNull(remoting, nameof(remoting))
.QueryAsync(
programId,
encodedPayload,
gasLimit: null,
ZeroValue,
cancellationToken);

private static readonly ValueUnit ZeroValue = new(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ensure.That" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Substrate.Gear.Api\Substrate.Gear.Api.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using EnsureThat;
using Microsoft.Extensions.DependencyInjection;
using Sails.Remoting.Abstractions;
using Sails.Remoting.Options;

namespace Sails.Remoting.DependencyInjection;

public static class IServiceCollectionExtensions
{
public static IServiceCollection AddRemotingViaSubstrateClient(
this IServiceCollection services,
RemotingViaSubstrateClientOptions options)
{
EnsureArg.IsNotNull(services, nameof(services));
EnsureArg.IsNotNull(options, nameof(options));

services.AddSingleton(options);

services.AddTransient<IRemoting, RemotingViaSubstrateClient>();

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace Sails.Remoting.Options;

public sealed record RemotingViaSubstrateClientOptions
{
public Uri? GearNodeUri { get; init; }
}
88 changes: 88 additions & 0 deletions net/src/Sails.Remoting/RemotingViaSubstrateClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using EnsureThat;
using Sails.Remoting.Abstractions;
using Sails.Remoting.Options;
using Substrate.Gear.Api.Generated;
using Substrate.Gear.Api.Generated.Model.gprimitives;
using Substrate.NetApi.Model.Extrinsics;
using GasUnit = Substrate.NetApi.Model.Types.Primitive.U64;
using ValueUnit = Substrate.NetApi.Model.Types.Primitive.U128;

namespace Sails.Remoting;

internal sealed class RemotingViaSubstrateClient : IDisposable, IRemoting
{
public RemotingViaSubstrateClient(RemotingViaSubstrateClientOptions options)
{
EnsureArg.IsNotNull(options, nameof(options));
EnsureArg.IsNotNull(options.GearNodeUri, nameof(options.GearNodeUri));

this.nodeClient = new SubstrateClientExt(options.GearNodeUri, ChargeTransactionPayment.Default());
this.isNodeClientConnected = false;
}

private readonly SubstrateClientExt nodeClient;
private bool isNodeClientConnected;

public void Dispose()
{
this.nodeClient.Dispose();
GC.SuppressFinalize(this);
}

public async Task<(ActorId ProgramId, byte[] EncodedReply)> ActivateAsync(
CodeId codeId,
IReadOnlyCollection<byte> salt,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(codeId, nameof(codeId));
EnsureArg.IsNotNull(salt, nameof(salt));
EnsureArg.IsNotNull(encodedPayload, nameof(encodedPayload));

await this.GetConnectedNodeClientAsync(cancellationToken).ConfigureAwait(false);

throw new NotImplementedException();
}

public Task<byte[]> MessageAsync(
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(programId, nameof(programId));
EnsureArg.IsNotNull(encodedPayload, nameof(encodedPayload));

throw new NotImplementedException();
}

public Task<byte[]> QueryAsync(
ActorId programId,
IReadOnlyCollection<byte> encodedPayload,
GasUnit? gasLimit,
ValueUnit value,
CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(programId, nameof(programId));
EnsureArg.IsNotNull(encodedPayload, nameof(encodedPayload));

throw new NotImplementedException();
}

private async Task<SubstrateClientExt> GetConnectedNodeClientAsync(CancellationToken cancellationToken)
{
if (!this.isNodeClientConnected)
{
await this.nodeClient.ConnectAsync(cancellationToken).ConfigureAwait(false);
this.isNodeClientConnected = true;
}
return this.nodeClient;
}
}
21 changes: 21 additions & 0 deletions net/src/Sails.Remoting/Sails.Remoting.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="IsExternalInit">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
</ItemGroup>


<ItemGroup>
<ProjectReference Include="..\Sails.Remoting.Abstractions\Sails.Remoting.Abstractions.csproj" />
<ProjectReference Include="..\Substrate.Gear.Client\Substrate.Gear.Client.csproj" />
</ItemGroup>

</Project>
7 changes: 6 additions & 1 deletion net/src/Substrate.Gear.Api/Substrate.Gear.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Substrate.NET.API" Version="0.9.24-rc6" />
<PackageReference Include="Substrate.NET.API" />
</ItemGroup>

<ItemGroup>
<PackageReference Remove="Roslynator.Formatting.Analyzers" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions net/src/Substrate.Gear.Client/GasInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using GasUnit = Substrate.NetApi.Model.Types.Primitive.U64;

namespace Substrate.Gear.Client;

public sealed record GasInfo
{
/// Represents minimum gas limit required for execution.
public required GasUnit MinLimit { get; init; }
/// Gas amount that we reserve for some other on-chain interactions.
public required GasUnit Reserved { get; init; }
/// Contains number of gas burned during message processing.
public required GasUnit Burned { get; init; }
/// The value may be returned if a program happens to be executed
/// the second or next time in a block.
public required GasUnit MayBeReturned { get; init; }
/// Was the message placed into waitlist at the end of calculating.
///
/// This flag shows, that `min_limit` makes sense and have some guarantees
/// only before insertion into waitlist.
public bool IsInWaitList { get; init; }
}
Loading

0 comments on commit 69444fa

Please sign in to comment.