From 07221c9bf3606c08e8c7d49a53b2f49bde06bb5c Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Mon, 17 Aug 2015 03:03:26 +0300 Subject: [PATCH] New interop methods, ToString() implementation for transaction structures + quick testt executable project --- Novacoin.sln | 49 ++++++++++++++---------- Novacoin/CTransaction.cs | 26 ++++++++++++- Novacoin/CTxIn.cs | 9 ++++- Novacoin/CTxOut.cs | 9 ++++- Novacoin/Hash.cs | 7 +--- Novacoin/Interop.cs | 18 ++++++++- Novacoin/ScriptOpcode.cs | 13 +----- NovacoinTest/App.config | 6 +++ NovacoinTest/NovacoinTest.csproj | 64 +++++++++++++++++++++++++++++++ NovacoinTest/Program.cs | 25 ++++++++++++ NovacoinTest/Properties/AssemblyInfo.cs | 36 +++++++++++++++++ 11 files changed, 221 insertions(+), 41 deletions(-) create mode 100644 NovacoinTest/App.config create mode 100644 NovacoinTest/NovacoinTest.csproj create mode 100644 NovacoinTest/Program.cs create mode 100644 NovacoinTest/Properties/AssemblyInfo.cs diff --git a/Novacoin.sln b/Novacoin.sln index e64f8e3..eb3aedf 100644 --- a/Novacoin.sln +++ b/Novacoin.sln @@ -1,20 +1,29 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novacoin", "Novacoin\Novacoin.csproj", "{6C657EA6-E9FB-41D7-B949-B41DD5136748}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Novacoin\Novacoin.csproj - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Desktop +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novacoin", "Novacoin\Novacoin.csproj", "{6C657EA6-E9FB-41D7-B949-B41DD5136748}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NovacoinTest", "NovacoinTest\NovacoinTest.csproj", "{BFBAD4AE-BCD5-4025-9637-3CE724126448}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C657EA6-E9FB-41D7-B949-B41DD5136748}.Release|Any CPU.Build.0 = Release|Any CPU + {BFBAD4AE-BCD5-4025-9637-3CE724126448}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFBAD4AE-BCD5-4025-9637-3CE724126448}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFBAD4AE-BCD5-4025-9637-3CE724126448}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFBAD4AE-BCD5-4025-9637-3CE724126448}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Novacoin\Novacoin.csproj + EndGlobalSection +EndGlobal diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index 77d6a62..f317d31 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Collections.Generic; namespace Novacoin @@ -50,6 +51,8 @@ namespace Novacoin for (int nCurrentInput = 0; nCurrentInput < nInputs; nCurrentInput++) { // Fill inputs array + inputs[nCurrentInput] = new CTxIn(); + inputs[nCurrentInput].txID = new Hash256(wBytes.GetItems(32)); inputs[nCurrentInput].n = Interop.LEBytesToUInt32(wBytes.GetItems(4)); inputs[nCurrentInput].scriptSig = wBytes.GetItems((int)VarInt.ReadVarInt(wBytes)); @@ -59,9 +62,10 @@ namespace Novacoin int nOutputs = (int)VarInt.ReadVarInt(wBytes); outputs = new CTxOut[nOutputs]; - for (int nCurrentOutput = 0; nCurrentOutput < nInputs; nCurrentOutput++) + for (int nCurrentOutput = 0; nCurrentOutput < nOutputs; nCurrentOutput++) { // Fill outputs array + outputs[nCurrentOutput] = new CTxOut(); outputs[nCurrentOutput].nValue = Interop.LEBytesToUInt64(wBytes.GetItems(8)); outputs[nCurrentOutput].scriptPubKey = wBytes.GetItems((int)VarInt.ReadVarInt(wBytes)); } @@ -136,7 +140,27 @@ namespace Novacoin resultBytes.AddRange(Interop.LEBytes(nLockTime)); return resultBytes; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat("CTransaction(\n nVersion={0},\n nTime={1},\n", nVersion, nTime); + + foreach (CTxIn txin in inputs) + { + sb.AppendFormat(" {0},\n", txin.ToString()); + } + + foreach (CTxOut txout in outputs) + { + sb.AppendFormat(" {0},\n", txout.ToString()); + } + + sb.AppendFormat("nLockTime={0})\n", nLockTime); + return sb.ToString(); } } } diff --git a/Novacoin/CTxIn.cs b/Novacoin/CTxIn.cs index d079d15..a712606 100644 --- a/Novacoin/CTxIn.cs +++ b/Novacoin/CTxIn.cs @@ -42,6 +42,13 @@ namespace Novacoin } /// + /// Initialize an empty instance of CTxIn class + /// + public CTxIn() + { + } + + /// /// Get raw bytes representation of our input. /// /// Byte sequence. @@ -61,7 +68,7 @@ namespace Novacoin public override string ToString () { StringBuilder sb = new StringBuilder (); - sb.AppendFormat ("CTxIn(txId={0},n={1},scriptSig={2}", txID.ToString(), n, scriptSig.ToString()); + sb.AppendFormat ("CTxIn(txId={0},n={1},scriptSig={2})", txID.ToString(), n, (new CScript(scriptSig)).ToString()); return sb.ToString (); } diff --git a/Novacoin/CTxOut.cs b/Novacoin/CTxOut.cs index aec5a88..0bb013c 100644 --- a/Novacoin/CTxOut.cs +++ b/Novacoin/CTxOut.cs @@ -30,6 +30,13 @@ namespace Novacoin } /// + /// Initialize an empty instance of CTxOut class + /// + public CTxOut() + { + } + + /// /// Get raw bytes representation of our output. /// /// Byte sequence. @@ -47,7 +54,7 @@ namespace Novacoin public override string ToString () { StringBuilder sb = new StringBuilder (); - sb.AppendFormat ("CTxOut(nValue={0},scriptPubKey={1}", nValue, scriptPubKey.ToString()); + sb.AppendFormat ("CTxOut(nValue={0},scriptPubKey={1})", nValue, (new CScript(scriptPubKey)).ToString()); return sb.ToString (); } diff --git a/Novacoin/Hash.cs b/Novacoin/Hash.cs index f448894..8049394 100644 --- a/Novacoin/Hash.cs +++ b/Novacoin/Hash.cs @@ -57,12 +57,7 @@ namespace Novacoin public override string ToString() { - StringBuilder sb = new StringBuilder(hashSize * 2); - foreach (byte b in _hashBytes) - { - sb.AppendFormat("{0:x2}", b); - } - return sb.ToString(); + return Interop.ToHex(_hashBytes); } } } diff --git a/Novacoin/Interop.cs b/Novacoin/Interop.cs index 0081b46..2405890 100644 --- a/Novacoin/Interop.cs +++ b/Novacoin/Interop.cs @@ -23,7 +23,7 @@ namespace Novacoin } } - class Interop + public class Interop { public static byte[] LEBytes(ushort n) { @@ -199,5 +199,21 @@ namespace Novacoin return BitConverter.ToUInt64(bytes, 0); } + public static IEnumerable ParseHex(string hex) + { + return Enumerable.Range(0, hex.Length) + .Where(x => x % 2 == 0) + .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)); + } + + public static string ToHex(IEnumerable bytes) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in bytes) + { + sb.AppendFormat("{0:x2}", b); + } + return sb.ToString(); + } } } diff --git a/Novacoin/ScriptOpcode.cs b/Novacoin/ScriptOpcode.cs index 4631bae..a5a524c 100644 --- a/Novacoin/ScriptOpcode.cs +++ b/Novacoin/ScriptOpcode.cs @@ -519,20 +519,11 @@ namespace Novacoin byte[] valueBytes = new byte[4] {0, 0, 0, 0}; bytes.ToArray().CopyTo(valueBytes, valueBytes.Length - bytes.Count()); - // Reverse array if we are on little-endian machine - if (BitConverter.IsLittleEndian) - { - Array.Reverse(valueBytes); - } - - sb.Append(BitConverter.ToInt32(valueBytes, 0)); + sb.Append(Interop.BEBytesToUInt32(valueBytes)); } else { - foreach (byte b in bytes) - { - sb.AppendFormat("{0:x2}", b); - } + return Interop.ToHex(bytes); } return sb.ToString(); diff --git a/NovacoinTest/App.config b/NovacoinTest/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/NovacoinTest/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/NovacoinTest/NovacoinTest.csproj b/NovacoinTest/NovacoinTest.csproj new file mode 100644 index 0000000..18fa9b3 --- /dev/null +++ b/NovacoinTest/NovacoinTest.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {BFBAD4AE-BCD5-4025-9637-3CE724126448} + Exe + Properties + NovacoinTest + NovacoinTest + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + {6c657ea6-e9fb-41d7-b949-b41dd5136748} + Novacoin + + + + + \ No newline at end of file diff --git a/NovacoinTest/Program.cs b/NovacoinTest/Program.cs new file mode 100644 index 0000000..17ab6be --- /dev/null +++ b/NovacoinTest/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace NovacoinTest +{ + using Novacoin; + + class Program + { + static void Main(string[] args) + { + string strTx = "0100000078b4c95306340d96b77ec4ee9d42b31cadc2fab911e48d48c36274d516f226d5e85bbc512c010000006b483045022100c8df1fc17b6ea1355a39b92146ec67b3b53565e636e028010d3a8a87f6f805f202203888b9b74df03c3960773f2a81b2dfd1efb08bb036a8f3600bd24d5ed694cd5a0121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffff364c640420de8fa77313475970bf09ce4d0b1f8eabb8f1d6ea49d90c85b202ee010000006b483045022100b651bf3a6835d714d2c990c742136d769258d0170c9aac24803b986050a8655b0220623651077ff14b0a9d61e30e30f2c15352f70491096f0ec655ae1c79a44e53aa0121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffff7adbd5f2e521f567bfea2cb63e65d55e66c83563fe253464b75184a5e462043d000000006a4730440220183609f2b995993acc9df241aff722d48b9a731b0cd376212934565723ed81f00220737e7ce75ef39bdc061d0dcdba3ee24e43b899696a7c96803cee0a79e1f78ecb0121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffff999eb03e00a41c2f9fde8865a554ceebbc48d30f4c8ba22dd88da8c9b46fa920030000006b483045022100ec1ab104ef086ba79b0f2611ebf1bfdd22a7a1020f6630fa1c6707546626e0db022056093d4048a999392185ccc735ef736a5497bd68f60b42e6c0c93ba770b54d010121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffffc0543b86be257ddd85b014a76718a70fab9eaa3c477460e4ca187094d86f369c0500000069463043021f24275c72f952043174daf01d7f713f878625f0522124a3cab48a0a2e12604202201b47742e6697b0ebdd1e4ba49c74baf142a0228ad0e0ee847488994c9dce78470121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffffe1793d4519147782293dd1db6d90e461265d91db2cc6889c37209394d42ad10d050000006a473044022018a0c3d73b2765d75380614ab36ee8e3c937080894a19166128b1e3357b208fb0220233c9609985f535547381431526867ad0255ec4969afe5c360544992ed6b3ed60121030dd13e6d3c63fa10cc0b6bf968fbbfcb9a988b333813b1f22d04fa60e344bc4cffffffff02e5420000000000001976a91457d84c814b14bd86bf32f106b733baa693db7dc788ac409c0000000000001976a91408c8768d5d6bf7c1d9609da4e766c3f1752247b188ac00000000"; + + CTransaction tx = new CTransaction(Interop.ParseHex(strTx).ToList()); + + Console.WriteLine(tx.ToString()); + + Console.ReadLine(); + } + } +} diff --git a/NovacoinTest/Properties/AssemblyInfo.cs b/NovacoinTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5d1888c --- /dev/null +++ b/NovacoinTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("NovacoinTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NovacoinTest")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("00060b81-3d2f-4ded-8219-fbf299cedf39")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] -- 1.7.1