diff --git a/csharp/.gitignore b/csharp/.gitignore new file mode 100644 index 00000000..0c055039 --- /dev/null +++ b/csharp/.gitignore @@ -0,0 +1,274 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Mono auto generated files +mono_crash.* + +/.project + +# Coverlet code coverage output +**/coverage.json +**/coverage.opencover.xml +CodeCoverage/ + +# Sonarqube +.sonarqube diff --git a/csharp/BlockChain.Console/App.config b/csharp/BlockChain.Console/App.config deleted file mode 100644 index 089f2495..00000000 --- a/csharp/BlockChain.Console/App.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/csharp/BlockChain.Console/BlockChain.Console.csproj b/csharp/BlockChain.Console/BlockChain.Console.csproj index 5bc56703..5a59c04f 100644 --- a/csharp/BlockChain.Console/BlockChain.Console.csproj +++ b/csharp/BlockChain.Console/BlockChain.Console.csproj @@ -1,63 +1,28 @@ - - - + + - Debug - AnyCPU - {D0C795A0-6F20-4A8E-BE44-801678754DA4} Exe - BlockChainDemo.Console - BlockChainDemo.Console - v4.5.1 - 512 - true - SAK - SAK - SAK - SAK - + net6.0 + enable + enable - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + + false + - - - - - - - - - - - - + + - + + + - - {e06fc4ce-77d0-4a64-94a6-32a08920e481} - BlockChain - + + PreserveNewest + - - \ No newline at end of file + diff --git a/csharp/BlockChain.Console/Program.cs b/csharp/BlockChain.Console/Program.cs index 2573f931..cbc9bc3f 100644 --- a/csharp/BlockChain.Console/Program.cs +++ b/csharp/BlockChain.Console/Program.cs @@ -1,12 +1,17 @@ namespace BlockChainDemo.Console { - class Program + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main(string[] args) { - static void Main(string[] args) - { - var chain = new BlockChain(); - var server = new WebServer(chain); - System.Console.Read(); - } + var chain = new BlockChain(); + var config = new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .Build(); + var server = new WebServer(chain, config); + System.Console.Read(); } + } } diff --git a/csharp/BlockChain.Console/Properties/AssemblyInfo.cs b/csharp/BlockChain.Console/Properties/AssemblyInfo.cs index 2b25de21..0bb611b2 100644 --- a/csharp/BlockChain.Console/Properties/AssemblyInfo.cs +++ b/csharp/BlockChain.Console/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/csharp/BlockChain.Console/appsettings.json b/csharp/BlockChain.Console/appsettings.json new file mode 100644 index 00000000..3d0d8732 --- /dev/null +++ b/csharp/BlockChain.Console/appsettings.json @@ -0,0 +1,4 @@ +{ + "host": "localhost", + "port": "5000" +} diff --git a/csharp/BlockChain.sln b/csharp/BlockChain.sln index 0175024f..47d552cf 100644 --- a/csharp/BlockChain.sln +++ b/csharp/BlockChain.sln @@ -1,43 +1,28 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2008 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30114.105 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockChain", "BlockChain\BlockChain.csproj", "{E06FC4CE-77D0-4A64-94A6-32A08920E481}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockChain", "BlockChain\BlockChain.csproj", "{C420D6B3-543C-4526-BB5F-4319AB6CEE6B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockChain.Console", "BlockChain.Console\BlockChain.Console.csproj", "{D0C795A0-6F20-4A8E-BE44-801678754DA4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockChain.Console", "BlockChain.Console\BlockChain.Console.csproj", "{B6202B59-6049-436D-B047-3D01D96CC470}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E06FC4CE-77D0-4A64-94A6-32A08920E481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E06FC4CE-77D0-4A64-94A6-32A08920E481}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E06FC4CE-77D0-4A64-94A6-32A08920E481}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E06FC4CE-77D0-4A64-94A6-32A08920E481}.Release|Any CPU.Build.0 = Release|Any CPU - {D0C795A0-6F20-4A8E-BE44-801678754DA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0C795A0-6F20-4A8E-BE44-801678754DA4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0C795A0-6F20-4A8E-BE44-801678754DA4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0C795A0-6F20-4A8E-BE44-801678754DA4}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7FB3650B-CAFB-4A71-940B-0CA6F0377422} - EndGlobalSection - GlobalSection(TeamFoundationVersionControl) = preSolution - SccNumberOfProjects = 3 - SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} - SccTeamFoundationServer = https://devfire.visualstudio.com/ - SccLocalPath0 = . - SccProjectUniqueName1 = BlockChain\\BlockChain.csproj - SccProjectName1 = BlockChain - SccLocalPath1 = BlockChain - SccProjectUniqueName2 = BlockChain.Console\\BlockChain.Console.csproj - SccProjectName2 = BlockChain.Console - SccLocalPath2 = BlockChain.Console + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C420D6B3-543C-4526-BB5F-4319AB6CEE6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C420D6B3-543C-4526-BB5F-4319AB6CEE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C420D6B3-543C-4526-BB5F-4319AB6CEE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C420D6B3-543C-4526-BB5F-4319AB6CEE6B}.Release|Any CPU.Build.0 = Release|Any CPU + {B6202B59-6049-436D-B047-3D01D96CC470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6202B59-6049-436D-B047-3D01D96CC470}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6202B59-6049-436D-B047-3D01D96CC470}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6202B59-6049-436D-B047-3D01D96CC470}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/csharp/BlockChain/Block.cs b/csharp/BlockChain/Block.cs index 9ca9d808..11fccd1e 100644 --- a/csharp/BlockChain/Block.cs +++ b/csharp/BlockChain/Block.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; - -namespace BlockChainDemo +namespace BlockChainDemo { - public class Block - { - public int Index { get; set; } - public DateTime Timestamp { get; set; } - public List Transactions { get; set; } - public int Proof { get; set; } - public string PreviousHash { get; set; } + using System; + using System.Collections.Generic; - public override string ToString() - { - return $"{Index} [{Timestamp.ToString("yyyy-MM-dd HH:mm:ss")}] Proof: {Proof} | PrevHash: {PreviousHash} | Trx: {Transactions.Count}"; - } + public class Block + { + public int Index { get; set; } + public DateTime Timestamp { get; set; } + public List Transactions { get; set; } + public int Proof { get; set; } + public string PreviousHash { get; set; } + + public override string ToString() + { + return $"{Index} [{Timestamp.ToString("yyyy-MM-dd HH:mm:ss")}] Proof: {Proof} | PrevHash: {PreviousHash} | Trx: {Transactions.Count}"; } -} \ No newline at end of file + } +} diff --git a/csharp/BlockChain/BlockChain.cs b/csharp/BlockChain/BlockChain.cs index 250d6f86..4502916f 100644 --- a/csharp/BlockChain/BlockChain.cs +++ b/csharp/BlockChain/BlockChain.cs @@ -1,226 +1,234 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Security.Cryptography; -using System.Text; - -namespace BlockChainDemo +namespace BlockChainDemo { - public class BlockChain + using Newtonsoft.Json; + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Net; + using System.Security.Cryptography; + using System.Text; + + public class BlockChain + { + private List _currentTransactions = new List(); + private List _chain = new List(); + private List _nodes = new List(); + private Block _lastBlock => _chain.Last(); + + public string NodeId { get; private set; } + + //ctor + public BlockChain() { - private List _currentTransactions = new List(); - private List _chain = new List(); - private List _nodes = new List(); - private Block _lastBlock => _chain.Last(); + NodeId = Guid.NewGuid().ToString().Replace("-", ""); + CreateNewBlock(proof: 100, previousHash: "1"); //genesis block + } - public string NodeId { get; private set; } + //private functionality + private void RegisterNode(string address) + { + _nodes.Add(new Node { Address = new Uri(address) }); + } - //ctor - public BlockChain() + private bool IsValidChain(List chain) + { + Block block; + var lastBlock = chain.First(); + var currentIndex = 1; + while (currentIndex < chain.Count) + { + block = chain.ElementAt(currentIndex); + Debug.WriteLine($"{lastBlock}"); + Debug.WriteLine($"{block}"); + Debug.WriteLine("----------------------------"); + + //Check that the hash of the block is correct + if (block.PreviousHash != GetHash(lastBlock)) { - NodeId = Guid.NewGuid().ToString().Replace("-", ""); - CreateNewBlock(proof: 100, previousHash: "1"); //genesis block + return false; } - //private functionality - private void RegisterNode(string address) + //Check that the Proof of Work is correct + if (!IsValidProof(lastBlock.Proof, block.Proof, lastBlock.PreviousHash)) { - _nodes.Add(new Node { Address = new Uri(address) }); + return false; } - private bool IsValidChain(List chain) - { - Block block = null; - Block lastBlock = chain.First(); - int currentIndex = 1; - while (currentIndex < chain.Count) - { - block = chain.ElementAt(currentIndex); - Debug.WriteLine($"{lastBlock}"); - Debug.WriteLine($"{block}"); - Debug.WriteLine("----------------------------"); - - //Check that the hash of the block is correct - if (block.PreviousHash != GetHash(lastBlock)) - return false; - - //Check that the Proof of Work is correct - if (!IsValidProof(lastBlock.Proof, block.Proof, lastBlock.PreviousHash)) - return false; - - lastBlock = block; - currentIndex++; - } - - return true; - } + lastBlock = block; + currentIndex++; + } - private bool ResolveConflicts() - { - List newChain = null; - int maxLength = _chain.Count; - - foreach (Node node in _nodes) - { - var url = new Uri(node.Address, "/chain"); - var request = (HttpWebRequest)WebRequest.Create(url); - var response = (HttpWebResponse)request.GetResponse(); - - if (response.StatusCode == HttpStatusCode.OK) - { - var model = new - { - chain = new List(), - length = 0 - }; - string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); - var data = JsonConvert.DeserializeAnonymousType(json, model); - - if (data.chain.Count > _chain.Count && IsValidChain(data.chain)) - { - maxLength = data.chain.Count; - newChain = data.chain; - } - } - } - - if (newChain != null) - { - _chain = newChain; - return true; - } - - return false; - } + return true; + } + + private bool ResolveConflicts() + { + List newChain = null; + var maxLength = _chain.Count; - private Block CreateNewBlock(int proof, string previousHash = null) + foreach (Node node in _nodes) + { + var url = new Uri(node.Address, "/chain"); + var request = (HttpWebRequest)WebRequest.Create(url); + var response = (HttpWebResponse)request.GetResponse(); + + if (response.StatusCode == HttpStatusCode.OK) { - var block = new Block - { - Index = _chain.Count, - Timestamp = DateTime.UtcNow, - Transactions = _currentTransactions.ToList(), - Proof = proof, - PreviousHash = previousHash ?? GetHash(_chain.Last()) - }; - - _currentTransactions.Clear(); - _chain.Add(block); - return block; + var model = new + { + chain = new List(), + length = 0 + }; + var json = new StreamReader(response.GetResponseStream()).ReadToEnd(); + var data = JsonConvert.DeserializeAnonymousType(json, model); + + if (data.chain.Count > _chain.Count && IsValidChain(data.chain)) + { + maxLength = data.chain.Count; + newChain = data.chain; + } } + } - private int CreateProofOfWork(int lastProof, string previousHash) - { - int proof = 0; - while (!IsValidProof(lastProof, proof, previousHash)) - proof++; + if (newChain != null) + { + _chain = newChain; + return true; + } - return proof; - } + return false; + } - private bool IsValidProof(int lastProof, int proof, string previousHash) - { - string guess = $"{lastProof}{proof}{previousHash}"; - string result = GetSha256(guess); - return result.StartsWith("0000"); - } + private Block CreateNewBlock(int proof, string previousHash = null) + { + var block = new Block + { + Index = _chain.Count, + Timestamp = DateTime.UtcNow, + Transactions = _currentTransactions.ToList(), + Proof = proof, + PreviousHash = previousHash ?? GetHash(_chain.Last()) + }; + + _currentTransactions.Clear(); + _chain.Add(block); + return block; + } - private string GetHash(Block block) - { - string blockText = JsonConvert.SerializeObject(block); - return GetSha256(blockText); - } + private int CreateProofOfWork(int lastProof, string previousHash) + { + var proof = 0; + while (!IsValidProof(lastProof, proof, previousHash)) + { + proof++; + } - private string GetSha256(string data) - { - var sha256 = new SHA256Managed(); - var hashBuilder = new StringBuilder(); + return proof; + } - byte[] bytes = Encoding.Unicode.GetBytes(data); - byte[] hash = sha256.ComputeHash(bytes); + private bool IsValidProof(int lastProof, int proof, string previousHash) + { + var guess = $"{lastProof}{proof}{previousHash}"; + var result = GetSha256(guess); + return result.StartsWith("0000"); + } - foreach (byte x in hash) - hashBuilder.Append($"{x:x2}"); + private string GetHash(Block block) + { + var blockText = JsonConvert.SerializeObject(block); + return GetSha256(blockText); + } - return hashBuilder.ToString(); - } + private string GetSha256(string data) + { + var sha256 = new SHA256Managed(); + var hashBuilder = new StringBuilder(); - //web server calls - internal string Mine() - { - int proof = CreateProofOfWork(_lastBlock.Proof, _lastBlock.PreviousHash); + var bytes = Encoding.Unicode.GetBytes(data); + var hash = sha256.ComputeHash(bytes); - CreateTransaction(sender: "0", recipient: NodeId, amount: 1); - Block block = CreateNewBlock(proof /*, _lastBlock.PreviousHash*/); + foreach (byte x in hash) + { + hashBuilder.Append($"{x:x2}"); + } - var response = new - { - Message = "New Block Forged", - Index = block.Index, - Transactions = block.Transactions.ToArray(), - Proof = block.Proof, - PreviousHash = block.PreviousHash - }; + return hashBuilder.ToString(); + } - return JsonConvert.SerializeObject(response); - } + //web server calls + internal string Mine() + { + var proof = CreateProofOfWork(_lastBlock.Proof, _lastBlock.PreviousHash); - internal string GetFullChain() - { - var response = new - { - chain = _chain.ToArray(), - length = _chain.Count - }; + CreateTransaction(sender: "0", recipient: NodeId, amount: 1); + var block = CreateNewBlock(proof /*, _lastBlock.PreviousHash*/); - return JsonConvert.SerializeObject(response); - } + var response = new + { + Message = "New Block Forged", + Index = block.Index, + Transactions = block.Transactions.ToArray(), + Proof = block.Proof, + PreviousHash = block.PreviousHash + }; - internal string RegisterNodes(string[] nodes) - { - var builder = new StringBuilder(); - foreach (string node in nodes) - { - string url = $"http://{node}"; - RegisterNode(url); - builder.Append($"{url}, "); - } - - builder.Insert(0, $"{nodes.Count()} new nodes have been added: "); - string result = builder.ToString(); - return result.Substring(0, result.Length - 2); - } + return JsonConvert.SerializeObject(response); + } - internal string Consensus() - { - bool replaced = ResolveConflicts(); - string message = replaced ? "was replaced" : "is authoritive"; - - var response = new - { - Message = $"Our chain {message}", - Chain = _chain - }; - - return JsonConvert.SerializeObject(response); - } + internal string GetFullChain() + { + var response = new + { + chain = _chain.ToArray(), + length = _chain.Count + }; - internal int CreateTransaction(string sender, string recipient, int amount) - { - var transaction = new Transaction - { - Sender = sender, - Recipient = recipient, - Amount = amount - }; + return JsonConvert.SerializeObject(response); + } - _currentTransactions.Add(transaction); + internal string RegisterNodes(string[] nodes) + { + var builder = new StringBuilder(); + foreach (string node in nodes) + { + var url = $"http://{node}"; + RegisterNode(url); + builder.Append($"{url}, "); + } + + builder.Insert(0, $"{nodes.Count()} new nodes have been added: "); + var result = builder.ToString(); + return result.Substring(0, result.Length - 2); + } - return _lastBlock != null ? _lastBlock.Index + 1 : 0; - } + internal string Consensus() + { + var replaced = ResolveConflicts(); + var message = replaced ? "was replaced" : "is authoritive"; + + var response = new + { + Message = $"Our chain {message}", + Chain = _chain + }; + + return JsonConvert.SerializeObject(response); + } + + internal int CreateTransaction(string sender, string recipient, int amount) + { + var transaction = new Transaction + { + Sender = sender, + Recipient = recipient, + Amount = amount + }; + + _currentTransactions.Add(transaction); + + return _lastBlock != null ? _lastBlock.Index + 1 : 0; } + } } diff --git a/csharp/BlockChain/BlockChain.csproj b/csharp/BlockChain/BlockChain.csproj index 86681aca..1310d221 100644 --- a/csharp/BlockChain/BlockChain.csproj +++ b/csharp/BlockChain/BlockChain.csproj @@ -1,73 +1,19 @@ - - - + + - Debug - AnyCPU - {E06FC4CE-77D0-4A64-94A6-32A08920E481} - Library - Properties - BlockChainDemo - BlockChainDemo - v4.5.1 - 512 - SAK - SAK - SAK - SAK - + net6.0 + enable + enable - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + + false + - - ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - ..\packages\TinyWebServer.dll.1.0.1\lib\net40\TinyWebServer.dll - - - - - - - - - - - - + + + - - - \ No newline at end of file + + diff --git a/csharp/BlockChain/Node.cs b/csharp/BlockChain/Node.cs index 5ba425f9..35d41f89 100644 --- a/csharp/BlockChain/Node.cs +++ b/csharp/BlockChain/Node.cs @@ -1,9 +1,9 @@ -using System; - -namespace BlockChainDemo +namespace BlockChainDemo { - public class Node - { - public Uri Address { get; set; } - } -} \ No newline at end of file + using System; + + public class Node + { + public Uri Address { get; set; } + } +} diff --git a/csharp/BlockChain/Properties/AssemblyInfo.cs b/csharp/BlockChain/Properties/AssemblyInfo.cs index 87b9d4eb..76b787cb 100644 --- a/csharp/BlockChain/Properties/AssemblyInfo.cs +++ b/csharp/BlockChain/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/csharp/BlockChain/Transaction.cs b/csharp/BlockChain/Transaction.cs index 1cbaeb7a..8de83ff2 100644 --- a/csharp/BlockChain/Transaction.cs +++ b/csharp/BlockChain/Transaction.cs @@ -1,9 +1,9 @@ namespace BlockChainDemo { - public class Transaction - { - public int Amount { get; set; } - public string Recipient { get; set; } - public string Sender { get; set; } - } -} \ No newline at end of file + public class Transaction + { + public int Amount { get; set; } + public string Recipient { get; set; } + public string Sender { get; set; } + } +} diff --git a/csharp/BlockChain/WebServer.cs b/csharp/BlockChain/WebServer.cs index cd7b86b5..3f3b4302 100644 --- a/csharp/BlockChain/WebServer.cs +++ b/csharp/BlockChain/WebServer.cs @@ -1,78 +1,77 @@ -using Newtonsoft.Json; -using System.Configuration; -using System.IO; -using System.Net; -using System.Net.Http; - -namespace BlockChainDemo +namespace BlockChainDemo { - public class WebServer + using System.IO; + using System.Net; + using System.Net.Http; + using Microsoft.Extensions.Configuration; + using Newtonsoft.Json; + + public class WebServer + { + public WebServer(BlockChain chain, IConfiguration config) { - public WebServer(BlockChain chain) - { - var settings = ConfigurationManager.AppSettings; - string host = settings["host"]?.Length > 1 ? settings["host"] : "localhost"; - string port = settings["port"]?.Length > 1 ? settings["port"] : "12345"; + string host = config["host"]?.Length > 1 ? config["host"] : "localhost"; + string port = config["port"]?.Length > 1 ? config["port"] : "12345"; - var server = new TinyWebServer.WebServer(request => - { - string path = request.Url.PathAndQuery.ToLower(); - string query = ""; - string json = ""; - if (path.Contains("?")) - { - string[] parts = path.Split('?'); - path = parts[0]; - query = parts[1]; - } + var server = new TinyWebServer.WebServer(request => + { + string path = request.Url.PathAndQuery.ToLower(); + string query = ""; + string json = ""; + if (path.Contains("?")) + { + string[] parts = path.Split('?'); + path = parts[0]; + query = parts[1]; + } - switch (path) - { - //GET: http://localhost:12345/mine - case "/mine": - return chain.Mine(); + switch (path) + { + //GET: http://localhost:12345/mine + case "/mine": + return chain.Mine(); - //POST: http://localhost:12345/transactions/new - //{ "Amount":123, "Recipient":"ebeabf5cc1d54abdbca5a8fe9493b479", "Sender":"31de2e0ef1cb4937830fcfd5d2b3b24f" } - case "/transactions/new": - if (request.HttpMethod != HttpMethod.Post.Method) - return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}"; + //POST: http://localhost:12345/transactions/new + //{ "Amount":123, "Recipient":"ebeabf5cc1d54abdbca5a8fe9493b479", "Sender":"31de2e0ef1cb4937830fcfd5d2b3b24f" } + case "/transactions/new": + if (request.HttpMethod != HttpMethod.Post.Method) + return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}"; - json = new StreamReader(request.InputStream).ReadToEnd(); - Transaction trx = JsonConvert.DeserializeObject(json); - int blockId = chain.CreateTransaction(trx.Sender, trx.Recipient, trx.Amount); - return $"Your transaction will be included in block {blockId}"; + json = new StreamReader(request.InputStream).ReadToEnd(); + Transaction trx = JsonConvert.DeserializeObject(json); + int blockId = chain.CreateTransaction(trx.Sender, trx.Recipient, trx.Amount); + return $"Your transaction will be included in block {blockId}"; - //GET: http://localhost:12345/chain - case "/chain": - return chain.GetFullChain(); + //GET: http://localhost:12345/chain + case "/chain": + return chain.GetFullChain(); - //POST: http://localhost:12345/nodes/register - //{ "Urls": ["localhost:54321", "localhost:54345", "localhost:12321"] } - case "/nodes/register": - if (request.HttpMethod != HttpMethod.Post.Method) - return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}"; + //POST: http://localhost:12345/nodes/register + //{ "Urls": ["localhost:54321", "localhost:54345", "localhost:12321"] } + case "/nodes/register": + if (request.HttpMethod != HttpMethod.Post.Method) + return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}"; - json = new StreamReader(request.InputStream).ReadToEnd(); - var urlList = new { Urls = new string[0] }; - var obj = JsonConvert.DeserializeAnonymousType(json, urlList); - return chain.RegisterNodes(obj.Urls); + json = new StreamReader(request.InputStream).ReadToEnd(); + var urlList = new { Urls = new string[0] }; + var obj = JsonConvert.DeserializeAnonymousType(json, urlList); + return chain.RegisterNodes(obj.Urls); - //GET: http://localhost:12345/nodes/resolve - case "/nodes/resolve": - return chain.Consensus(); - } + //GET: http://localhost:12345/nodes/resolve + case "/nodes/resolve": + return chain.Consensus(); + } - return ""; - }, - $"http://{host}:{port}/mine/", - $"http://{host}:{port}/transactions/new/", - $"http://{host}:{port}/chain/", - $"http://{host}:{port}/nodes/register/", - $"http://{host}:{port}/nodes/resolve/" - ); + return ""; + }, + $"http://{host}:{port}/mine/", + $"http://{host}:{port}/transactions/new/", + $"http://{host}:{port}/chain/", + $"http://{host}:{port}/nodes/register/", + $"http://{host}:{port}/nodes/resolve/" + ); - server.Run(); - } + server.Run(); } + } } diff --git a/csharp/BlockChain/packages.config b/csharp/BlockChain/packages.config deleted file mode 100644 index 4c8c0646..00000000 --- a/csharp/BlockChain/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file