From 3873f3ffa728da77ccd2429ecdc527ee408ea40f Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Mon, 3 Aug 2015 23:20:23 +0300 Subject: [PATCH 1/1] Initial commit --- Stratum.sln | 26 ++++ StratumLibrary/Attributes.cs | 27 ++++ StratumLibrary/Properties/AssemblyInfo.cs | 36 ++++++ StratumLibrary/Stratum.cs | 193 +++++++++++++++++++++++++++++ StratumLibrary/Stratum.csproj | 61 +++++++++ StratumLibrary/StratumException.cs | 32 +++++ StratumLibrary/StratumReadState.cs | 34 +++++ StratumLibrary/StratumRequest.cs | 36 ++++++ StratumLibrary/StratumResponse.cs | 54 ++++++++ StratumLibrary/packages.config | 9 ++ StratumTest/App.config | 6 + StratumTest/Program.cs | 27 ++++ StratumTest/Properties/AssemblyInfo.cs | 36 ++++++ StratumTest/StratumTest.csproj | 65 ++++++++++ StratumTest/packages.config | 4 + 15 files changed, 646 insertions(+), 0 deletions(-) create mode 100644 Stratum.sln create mode 100644 StratumLibrary/Attributes.cs create mode 100644 StratumLibrary/Properties/AssemblyInfo.cs create mode 100644 StratumLibrary/Stratum.cs create mode 100644 StratumLibrary/Stratum.csproj create mode 100644 StratumLibrary/StratumException.cs create mode 100644 StratumLibrary/StratumReadState.cs create mode 100644 StratumLibrary/StratumRequest.cs create mode 100644 StratumLibrary/StratumResponse.cs create mode 100644 StratumLibrary/packages.config create mode 100644 StratumTest/App.config create mode 100644 StratumTest/Program.cs create mode 100644 StratumTest/Properties/AssemblyInfo.cs create mode 100644 StratumTest/StratumTest.csproj create mode 100644 StratumTest/packages.config diff --git a/Stratum.sln b/Stratum.sln new file mode 100644 index 0000000..95d9e47 --- /dev/null +++ b/Stratum.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Desktop +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stratum", "StratumLibrary\Stratum.csproj", "{27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StratumTest", "StratumTest\StratumTest.csproj", "{FB61065F-93BA-497B-A2D5-3574D23B0B62}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8}.Release|Any CPU.Build.0 = Release|Any CPU + {FB61065F-93BA-497B-A2D5-3574D23B0B62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB61065F-93BA-497B-A2D5-3574D23B0B62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB61065F-93BA-497B-A2D5-3574D23B0B62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB61065F-93BA-497B-A2D5-3574D23B0B62}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/StratumLibrary/Attributes.cs b/StratumLibrary/Attributes.cs new file mode 100644 index 0000000..664aaa3 --- /dev/null +++ b/StratumLibrary/Attributes.cs @@ -0,0 +1,27 @@ +using System; + +namespace Stratum +{ + /// + /// Required to expose a method to the Stratum service. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + public sealed class StratumMethodAttribute : Attribute + { + readonly string stratumMethodName; + + /// + /// Required to expose a method to the Stratum service. + /// + /// Lets you specify the method name as it will be referred to by JsonRpc. + public StratumMethodAttribute(string MethodName = "") + { + this.stratumMethodName = MethodName; + } + + public string StratumMethodName + { + get { return stratumMethodName; } + } + } +} diff --git a/StratumLibrary/Properties/AssemblyInfo.cs b/StratumLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..56f8b19 --- /dev/null +++ b/StratumLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("ClassLibrary1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ClassLibrary1")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("75774b8a-8cf8-44ce-bd6b-6a1254d0cbb5")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/StratumLibrary/Stratum.cs b/StratumLibrary/Stratum.cs new file mode 100644 index 0000000..56520ed --- /dev/null +++ b/StratumLibrary/Stratum.cs @@ -0,0 +1,193 @@ +using System; +using System.Net; +using Newtonsoft.Json.Linq; + +using System.Text; +using System.Threading; +using System.Net.Sockets; + +namespace Stratum +{ + public class Stratum + { + private Socket client; + + /// + /// Constructor of Stratum interface class + /// + /// IPv4 address + /// Port number + public Stratum(string ipAddress, int port) + { + // End point for the remote device + IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipAddress), port); + + // Create TCP socket + client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + // Connect done event + ManualResetEvent connectDone = new ManualResetEvent(false); + + Action ConnectCallback = null; + ConnectCallback = (IAsyncResult ar) => + { + // Retrieve socket from the state object + Socket cli = (Socket)ar.AsyncState; + + // Complete the connection + cli.EndConnect(ar); + + // Signal that connection has been established + connectDone.Set(); + }; + + // Connect to the remote device + client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); + + // Wait for signal + connectDone.WaitOne(); + } + + ~Stratum() + { + // Release the socket + client.Shutdown(SocketShutdown.Both); + client.Close(); + } + + private void Send(Socket client, String data) + { + // Send done event + ManualResetEvent sendDone = new ManualResetEvent(false); + + Action SendCallback = null; + SendCallback = (IAsyncResult ar) => + { + // Retrieve the socket from the state object + Socket cli = (Socket)ar.AsyncState; + + // Complete sending the data to the remote device + int bytesSent = cli.EndSend(ar); + + // Signal that all bytes have been sent + sendDone.Set(); + }; + + // Convert the string data to byte data using ASCII encoding. + byte[] byteData = Encoding.ASCII.GetBytes(data); + + // Begin sending the data to the remote device. + client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client); + + // Wait for signal + sendDone.WaitOne(); + } + + /// + /// Invoke remote method + /// + /// Return type + /// Method name + /// Argument + /// StratumResponse object + public StratumResponse Invoke(string method, object arg) + { + var req = new StratumRequest() + { + Method = method, + Params = new object[] { arg } + }; + return Invoke(req); + } + + /// + /// Invoke remote method + /// + /// Return type + /// Method name + /// Arguments array + /// StratumResponse object + public StratumResponse Invoke(string method, object[] args) + { + var req = new StratumRequest() + { + Method = method, + Params = args + }; + return Invoke(req); + } + + private StratumResponse Invoke(StratumRequest stratumReq) + { + StratumResponse rjson = null; + + // Serialize stratumReq into JSON string + var reqJSON = Newtonsoft.Json.JsonConvert.SerializeObject(stratumReq) + '\n'; + + // Send JSON data to the remote device. + Send(client, reqJSON); + + // Create the reading state object. + StratumReadState state = new StratumReadState(client); + + // Receive event + ManualResetEvent receiveDone = new ManualResetEvent(false); + + Action ReceiveCallback = null; + ReceiveCallback = (IAsyncResult ar) => + { + // Retrieve the state object and the client socket + // from the asynchronous state object. + StratumReadState st = (StratumReadState)ar.AsyncState; + Socket ci = st.workSocket; + + // Read data from the remote device. + int bytesRead = ci.EndReceive(ar); + + if (bytesRead <= 0) + return; + + lock (st.sb) + { + // There might be more data, so store the data received so far. + st.sb.Append(Encoding.ASCII.GetString(st.buffer, 0, bytesRead)); + + if (st.buffer[bytesRead - 1] != '\n') + { + // No EOL at the end of buffer, going to get the rest of data + ci.BeginReceive(st.buffer, 0, StratumReadState.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), st); + } + else + { + string strResponse = st.sb.ToString(); + + // Deserialize the response + rjson = Newtonsoft.Json.JsonConvert.DeserializeObject>(strResponse); + + if (rjson == null) + { + try + { + JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(strResponse) as JObject; + throw new Exception(jo["Error"].ToString()); + } + catch (Newtonsoft.Json.JsonSerializationException) + { + throw new Exception("Inconsistent or empty response"); + } + } + + // Signal that all bytes have been received. + receiveDone.Set(); + } + } + }; + + // Begin receiving the data from the remote device. + client.BeginReceive(state.buffer, 0, StratumReadState.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); + receiveDone.WaitOne(); + + return rjson; + } + } +} \ No newline at end of file diff --git a/StratumLibrary/Stratum.csproj b/StratumLibrary/Stratum.csproj new file mode 100644 index 0000000..455ee9a --- /dev/null +++ b/StratumLibrary/Stratum.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {27F0C6C3-DCD6-4588-AFBB-DCE22306F5F8} + Library + Properties + Stratum + Stratum + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/StratumLibrary/StratumException.cs b/StratumLibrary/StratumException.cs new file mode 100644 index 0000000..9a26c84 --- /dev/null +++ b/StratumLibrary/StratumException.cs @@ -0,0 +1,32 @@ +using System; +using Newtonsoft.Json; + +namespace Stratum +{ + [Serializable] + [JsonObject(MemberSerialization.OptIn)] + public class StratumException : System.ApplicationException + { + /// + /// Error code + /// + [JsonProperty] + public int code { get; set; } + + /// + /// Human readable error message + /// + [JsonProperty] + public string message { get; set; } + + [JsonProperty] + public object data { get; set; } + + public StratumException(int code, string message, object data) + { + this.code = code; + this.message = message; + this.data = data; + } + } +} diff --git a/StratumLibrary/StratumReadState.cs b/StratumLibrary/StratumReadState.cs new file mode 100644 index 0000000..78898ae --- /dev/null +++ b/StratumLibrary/StratumReadState.cs @@ -0,0 +1,34 @@ +using System.Text; + +using System.Net.Sockets; + +namespace Stratum +{ + /// + /// Represents internal state of Stratum interface + /// + class StratumReadState + { + public StratumReadState(Socket client) + { + workSocket = client; + } + + /// + /// Client socket + /// + public Socket workSocket = null; + /// + /// Receive buffer size + /// + public const int BufferSize = 8; + /// + /// Receive buffer + /// + public byte[] buffer = new byte[BufferSize]; + /// + /// Received data string + /// + public StringBuilder sb = new StringBuilder(); + } +} diff --git a/StratumLibrary/StratumRequest.cs b/StratumLibrary/StratumRequest.cs new file mode 100644 index 0000000..1898096 --- /dev/null +++ b/StratumLibrary/StratumRequest.cs @@ -0,0 +1,36 @@ +using System; +using Newtonsoft.Json; + +namespace Stratum +{ + /// + /// Represents a JsonRpc request + /// + [JsonObject(MemberSerialization.OptIn)] + public class StratumRequest + { + public StratumRequest() + { + Id = Guid.NewGuid().ToString(); + } + + /// + /// Unique request id + /// + [JsonProperty("id")] + public object Id { get; private set; } + + /// + /// Stratum method name + /// + [JsonProperty("method")] + public string Method { get; set; } + + /// + /// Method params + /// + [JsonProperty("params")] + public object Params { get; set; } + + } +} diff --git a/StratumLibrary/StratumResponse.cs b/StratumLibrary/StratumResponse.cs new file mode 100644 index 0000000..1e0df84 --- /dev/null +++ b/StratumLibrary/StratumResponse.cs @@ -0,0 +1,54 @@ +using Newtonsoft.Json; + +namespace Stratum +{ + /// + /// Represents a Stratum Response + /// + [JsonObject(MemberSerialization.OptIn)] + public class StratumResponse + { + /// + /// Response id, should be null or identical to request id + /// + [JsonProperty(PropertyName = "id")] + public object Id { get; set; } + + /// + /// Result object + /// + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] + public object Result { get; set; } + + /// + /// Error object + /// + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] + public StratumException Error { get; set; } + } + + /// + /// Represents a Stratum Response + /// + [JsonObject(MemberSerialization.OptIn)] + public class StratumResponse + { + /// + /// Response id, should be null or identical to request id + /// + [JsonProperty(PropertyName = "id")] + public object Id { get; set; } + + /// + /// Result object + /// + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] + public T Result { get; set; } + + /// + /// Error object + /// + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] + public StratumException Error { get; set; } + } +} diff --git a/StratumLibrary/packages.config b/StratumLibrary/packages.config new file mode 100644 index 0000000..e8ad218 --- /dev/null +++ b/StratumLibrary/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/StratumTest/App.config b/StratumTest/App.config new file mode 100644 index 0000000..fad249e --- /dev/null +++ b/StratumTest/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/StratumTest/Program.cs b/StratumTest/Program.cs new file mode 100644 index 0000000..b8ddf8f --- /dev/null +++ b/StratumTest/Program.cs @@ -0,0 +1,27 @@ +using System; + + +namespace StratumTest +{ + using Stratum; + + class StratumTest + { + static void Main(string[] args) + { + Stratum s = new Stratum("192.168.1.100", 40001); + + while (true) + { + var res = s.Invoke("blockchain.transaction.get", "101379cb55ac431c435db40b4325f858568b0de3d8bd652a23a19e5d62521a72"); + + // var res = s.Invoke("blockchain.address.get_balance", "4PQtUNZ2aBYpZpVMPV2Qgz1PitCqgoT388"); + // var res = s.Invoke("blockchain.address.get_history", "4PQtUNZ2aBYpZpVMPV2Qgz1PitCqgoT388"); + // var res = s.Invoke("blockchain.address.listunspent", "4PQtUNZ2aBYpZpVMPV2Qgz1PitCqgoT388"); + + Console.Write(res.Result.ToString()); + Console.ReadLine(); + } + } + } +} diff --git a/StratumTest/Properties/AssemblyInfo.cs b/StratumTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5b43a28 --- /dev/null +++ b/StratumTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("StratumTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("StratumTest")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("61645f69-d823-495a-ab80-3957c430db6f")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/StratumTest/StratumTest.csproj b/StratumTest/StratumTest.csproj new file mode 100644 index 0000000..47832c1 --- /dev/null +++ b/StratumTest/StratumTest.csproj @@ -0,0 +1,65 @@ + + + + + Debug + AnyCPU + {FB61065F-93BA-497B-A2D5-3574D23B0B62} + Exe + Properties + StratumTest + StratumTest + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + {27f0c6c3-dcd6-4588-afbb-dce22306f5f8} + Stratum + + + + + \ No newline at end of file diff --git a/StratumTest/packages.config b/StratumTest/packages.config new file mode 100644 index 0000000..284ec0a --- /dev/null +++ b/StratumTest/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file -- 1.7.1