Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Blockcore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.Impleum"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.BCP", "Networks\Blockcore.Networks.BCP\Blockcore.Networks.BCP.csproj", "{120500DF-C04F-43CC-9A1E-523A6429301F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.X1", "Networks\Blockcore.Networks.X1\Blockcore.Networks.X1.csproj", "{9A2BA15A-C316-42B4-8E4D-E01B4873190C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -351,6 +353,10 @@ Global
{120500DF-C04F-43CC-9A1E-523A6429301F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{120500DF-C04F-43CC-9A1E-523A6429301F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{120500DF-C04F-43CC-9A1E-523A6429301F}.Release|Any CPU.Build.0 = Release|Any CPU
{9A2BA15A-C316-42B4-8E4D-E01B4873190C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A2BA15A-C316-42B4-8E4D-E01B4873190C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A2BA15A-C316-42B4-8E4D-E01B4873190C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A2BA15A-C316-42B4-8E4D-E01B4873190C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -411,6 +417,7 @@ Global
{4275AF0C-587B-4C9D-A100-0F2DD1702674} = {64694A14-97E0-4CBC-8032-754F9353B2DD}
{64E9C309-867E-45F6-A88E-7BC061305D0B} = {3B56C02B-4468-4268-B797-851562789FCC}
{120500DF-C04F-43CC-9A1E-523A6429301F} = {3B56C02B-4468-4268-B797-851562789FCC}
{9A2BA15A-C316-42B4-8E4D-E01B4873190C} = {3B56C02B-4468-4268-B797-851562789FCC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6C780ABA-5872-4B83-AD3F-A5BD423AD907}
Expand Down
41 changes: 41 additions & 0 deletions src/Networks/Blockcore.Networks.X1/Blockcore.Networks.X1.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<AssemblyTitle>Blockcore.Networks.Xds</AssemblyTitle>
<AssemblyName>Blockcore.Networks.X1</AssemblyName>
<PackageId>Blockcore.Networks.X1</PackageId>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<IsPackable>true</IsPackable>
<PackageProjectUrl>https://www.blockcore.net</PackageProjectUrl>
<PackageTags>blockchain;cryptocurrency;crypto;C#;.NET;bitcoin;blockcore;x1crypto;x1</PackageTags>
</PropertyGroup>

<ItemGroup>
<EmbeddedResource Include="icon.png" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Cloo.clSharp" Version="1.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Features\Blockcore.Features.Consensus\Blockcore.Features.Consensus.csproj" />
<ProjectReference Include="..\..\Features\Blockcore.Features.MemoryPool\Blockcore.Features.MemoryPool.csproj" />
<ProjectReference Include="..\..\Features\Blockcore.Features.Miner\Blockcore.Features.Miner.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Blockcore.Base;
using Blockcore.Broadcasters;
using Blockcore.Builder;
using Blockcore.Configuration.Logging;
using Blockcore.Consensus;
using Blockcore.Features.Consensus;
using Blockcore.Features.Consensus.CoinViews;
using Blockcore.Features.Consensus.CoinViews.Coindb;
using Blockcore.Features.Consensus.Interfaces;
using Blockcore.Features.Consensus.ProvenBlockHeaders;
using Blockcore.Features.Consensus.Rules;
using Blockcore.Features.MemoryPool;
using Blockcore.Features.Miner;
using Blockcore.Features.Miner.Broadcasters;
using Blockcore.Features.Miner.Interfaces;
using Blockcore.Features.RPC;
using Blockcore.Features.Wallet.UI;
using Blockcore.Interfaces;
using Blockcore.Interfaces.UI;
using Blockcore.Mining;
using Microsoft.Extensions.DependencyInjection;

namespace Blockcore.Networks.X1.Components
{
public static class ComponentRegistration
{
public static IFullNodeBuilder UseX1Consensus(this IFullNodeBuilder fullNodeBuilder)
{
return AddX1PowPosMining(UseX1PosConsensus(fullNodeBuilder));
}

static IFullNodeBuilder UseX1PosConsensus(this IFullNodeBuilder fullNodeBuilder)
{
LoggingConfiguration.RegisterFeatureNamespace<PosConsensusFeature>("posconsensus");

fullNodeBuilder.ConfigureFeature(features =>
{
features
.AddFeature<PosConsensusFeature>()
.FeatureServices(services =>
{
fullNodeBuilder.PersistenceProviderManager.RequirePersistence<PosConsensusFeature>(services);

services.AddSingleton<IStakdb>(provider => (IStakdb)provider.GetService<ICoindb>());
services.AddSingleton<ICoinView, CachedCoinView>();
services.AddSingleton<StakeChainStore>().AddSingleton<IStakeChain, StakeChainStore>(provider => provider.GetService<StakeChainStore>());
services.AddSingleton<IRewindDataIndexCache, RewindDataIndexCache>();
services.AddSingleton<IConsensusRuleEngine, PosConsensusRuleEngine>();
services.AddSingleton<IChainState, ChainState>();
services.AddSingleton<ConsensusQuery>()
.AddSingleton<INetworkDifficulty, ConsensusQuery>(provider => provider.GetService<ConsensusQuery>())
.AddSingleton<IGetUnspentTransaction, ConsensusQuery>(provider => provider.GetService<ConsensusQuery>());
services.AddSingleton<IProvenBlockHeaderStore, ProvenBlockHeaderStore>();

services.AddSingleton<IStakeValidator, X1StakeValidator>();
});
});

return fullNodeBuilder;
}

/// <summary>
/// Adds POW and POS miner components to the node, so that it can mine or stake.
/// </summary>
/// <param name="fullNodeBuilder">The object used to build the current node.</param>
/// <returns>The full node builder, enriched with the new component.</returns>
static IFullNodeBuilder AddX1PowPosMining(this IFullNodeBuilder fullNodeBuilder)
{
LoggingConfiguration.RegisterFeatureNamespace<X1MiningFeature>("x1mining");

fullNodeBuilder.ConfigureFeature(features =>
{
features
.AddFeature<X1MiningFeature>()
.DependOn<MempoolFeature>()
.DependOn<RPCFeature>()
// TODO: Need a better way to check dependencies. This is really just dependent on IWalletManager...
// Alternatively "DependsOn" should take a list of features that will satisfy the dependency.
//.DependOn<WalletFeature>()
.FeatureServices(services =>
{
services.AddSingleton<MinerSettings, X1MinerSettings>();
services.AddSingleton<IPowMining, X1PowMining>();
services.AddSingleton<IPosMinting, X1PosMinting>();

services.AddSingleton<IBlockProvider, BlockProvider>();
services.AddSingleton<BlockDefinition, PowBlockDefinition>();
services.AddSingleton<BlockDefinition, PosBlockDefinition>();
services.AddSingleton<BlockDefinition, PosPowBlockDefinition>();
services.AddSingleton<INavigationItem, StakeNavigationItem>();
services.AddSingleton<IClientEventBroadcaster, StakingBroadcaster>();
});
});

return fullNodeBuilder;
}
}
}
186 changes: 186 additions & 0 deletions src/Networks/Blockcore.Networks.X1/Components/OpenCLMiner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cloo;
using Microsoft.Extensions.Logging;

namespace Blockcore.Networks.X1.Components
{
/// <summary>
/// The famous SpartaCrypt OpenCLMiner, visit the original here:
/// https://github.com/spartacrypt/xds-1/blob/master/src/components/Fullnode/UnnamedCoin.Bitcoin.Features.Miner/OpenCLMiner.cs
/// </summary>
public class OpenCLMiner : IDisposable
{
private const string KernelFunction = "kernel_find_pow";

private readonly ILogger logger;
private readonly ComputeDevice computeDevice;

private List<ComputeKernel> computeKernels = new List<ComputeKernel>();
private ComputeProgram computeProgram;
private ComputeContext computeContext;
private ComputeKernel computeKernel;
private string[] openCLSources;
private bool isDisposed;

/// <summary>
/// Create a new OpenCLMiner instance.
/// </summary>
/// <param name="minerSettings">the minerSettings</param>
/// <param name="loggerFactory">the loggerFactory</param>
public OpenCLMiner(X1MinerSettings minerSettings, ILoggerFactory loggerFactory)
{
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
var devices = ComputePlatform.Platforms.SelectMany(p => p.Devices).Where(d => d.Available && d.CompilerAvailable).ToList();

if (!devices.Any())
{
this.logger.LogWarning($"No OpenCL Devices Found!");
}
else
{
foreach (ComputeDevice device in devices)
{
this.logger.LogInformation($"Found OpenCL Device: Name={device.Name}, MaxClockFrequency{device.MaxClockFrequency}");
}

this.computeDevice = devices.FirstOrDefault(d => d.Name.Equals(minerSettings.OpenCLDevice, StringComparison.OrdinalIgnoreCase)) ?? devices.FirstOrDefault();
if (this.computeDevice != null)
{
this.logger.LogInformation($"Using OpenCL Device: Name={this.computeDevice.Name}");
}
}
}

/// <summary>
/// Destructor.
/// </summary>
~OpenCLMiner()
{
this.DisposeOpenCLResources();
}

/// <summary>
/// If a compute device for mining is available.
/// </summary>
/// <returns>true if a usable device is found, otherwise false</returns>
public bool CanMine()
{
return this.computeDevice != null;
}

/// <summary>
/// Gets the currently used device name.
/// </summary>
/// <returns></returns>
public string GetDeviceName()
{
if (this.computeDevice == null)
{
throw new InvalidOperationException("GPU not found");
}

return this.computeDevice.Name;
}

/// <summary>
/// Finds the nonce for a block header hash that meets the given target.
/// </summary>
/// <param name="header">serialized block header</param>
/// <param name="bits">the target</param>
/// <param name="nonceStart">the first nonce value to try</param>
/// <param name="iterations">the number of iterations</param>
/// <returns></returns>
public uint FindPow(byte[] header, byte[] bits, uint nonceStart, uint iterations)
{
if (this.computeDevice == null)
{
throw new InvalidOperationException("GPU not found");
}

this.ConstructOpenCLResources();

using var headerBuffer = new ComputeBuffer<byte>(this.computeContext, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, header);
using var bitsBuffer = new ComputeBuffer<byte>(this.computeContext, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, bits);
using var powBuffer = new ComputeBuffer<uint>(this.computeContext, ComputeMemoryFlags.WriteOnly, 1);

this.computeKernel.SetMemoryArgument(0, headerBuffer);
this.computeKernel.SetMemoryArgument(1, bitsBuffer);
this.computeKernel.SetValueArgument(2, nonceStart);
this.computeKernel.SetMemoryArgument(3, powBuffer);

using var commands = new ComputeCommandQueue(this.computeContext, this.computeDevice, ComputeCommandQueueFlags.None);
commands.Execute(this.computeKernel, null, new long[] { iterations }, null, null);

var nonceOut = new uint[1];
commands.ReadFromBuffer(powBuffer, ref nonceOut, true, null);
commands.Finish();

this.DisposeOpenCLResources();

return nonceOut[0];
}

private void ConstructOpenCLResources()
{
if (this.computeDevice != null)
{
if (this.openCLSources == null)
{
GetOpenCLSources();
}
var properties = new ComputeContextPropertyList(this.computeDevice.Platform);
this.computeContext = new ComputeContext(new[] { this.computeDevice }, properties, null, IntPtr.Zero);
this.computeProgram = new ComputeProgram(this.computeContext, this.openCLSources);
this.computeProgram.Build(new[] { this.computeDevice }, null, null, IntPtr.Zero);
this.computeKernels = this.computeProgram.CreateAllKernels().ToList();
this.computeKernel = this.computeKernels.First((k) => k.FunctionName == KernelFunction);
}
}

private void GetOpenCLSources()
{
this.openCLSources = new[]
{
Properties.Resources.SpartacryptOpenCLMiner_opencl_device_info_h,
Properties.Resources.SpartacryptOpenCLMiner_opencl_misc_h,
Properties.Resources.SpartacryptOpenCLMiner_opencl_sha2_common_h,
Properties.Resources.SpartacryptOpenCLMiner_opencl_sha512_h,
Properties.Resources.SpartacryptOpenCLMiner_sha512_miner_cl
};
}

private void DisposeOpenCLResources()
{
this.computeKernels.ForEach(k => k.Dispose());
this.computeKernels.Clear();
this.computeProgram?.Dispose();
this.computeProgram = null;
this.computeContext?.Dispose();
this.computeContext = null;
}

/// <summary>
/// Releases the OpenCL resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

void Dispose(bool disposing)
{
if (this.isDisposed)
return;

if (disposing)
{
DisposeOpenCLResources();
}

this.isDisposed = true;
}
}
}
Loading