From d0ef9896808935e81c9d058b49f5191560b58d54 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sat, 15 Aug 2015 01:46:53 +0300 Subject: [PATCH] Use List wrapper instead of Enumerator --- Novacoin/Hash160.cs | 28 ++++++++++--- Novacoin/Hash256.cs | 70 +++++++++++++++++++++----------- Novacoin/Novacoin.csproj | 3 +- Novacoin/ScriptOpcode.cs | 100 ++++++++++++++++++++++++---------------------- Novacoin/WrappedList.cs | 79 ++++++++++++++++++++++++++++++++++++ 5 files changed, 200 insertions(+), 80 deletions(-) create mode 100644 Novacoin/WrappedList.cs diff --git a/Novacoin/Hash160.cs b/Novacoin/Hash160.cs index 993e4c9..a611e6c 100644 --- a/Novacoin/Hash160.cs +++ b/Novacoin/Hash160.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text; using System.Linq; @@ -9,30 +10,45 @@ namespace Novacoin /// public class Hash160 { + // 20 bytes + const int hashSize = 20; + /// /// Array of digest bytes. /// - private byte[] h; + private byte[] hashBytes = new byte[hashSize]; /// /// Initializes an empty instance of the Hash160 class. /// public Hash160 () { - // Fill with 20 zero bytes - h = Enumerable.Repeat (0, 20).ToArray (); + hashBytes = Enumerable.Repeat(0, hashSize).ToArray(); } + /// + /// Initializes a new instance of Hash160 class with first 20 bytes from supplied list + /// + /// List of bytes + public Hash160(List bytesList) + { + hashBytes = bytesList.Take(hashSize).ToArray(); + } + + public Hash160(byte[] bytesArray) + { + hashBytes = bytesArray; + } + public override string ToString() { - StringBuilder sb = new StringBuilder(h.Length * 2); - foreach (byte b in h) + StringBuilder sb = new StringBuilder(hashSize * 2); + foreach (byte b in hashBytes) { sb.AppendFormat ("{0:x2}", b); } return sb.ToString(); } - } } diff --git a/Novacoin/Hash256.cs b/Novacoin/Hash256.cs index 365f778..8a4f983 100644 --- a/Novacoin/Hash256.cs +++ b/Novacoin/Hash256.cs @@ -1,36 +1,56 @@ using System; using System.Text; using System.Linq; +using System.Collections.Generic; + namespace Novacoin { /// /// Representation of SHA-256 hash /// - public class Hash256 - { - /// - /// Array of digest bytes. - /// - private byte[] h; - - /// - /// Initializes an empty instance of the Hash256 class. - /// - public Hash256 () - { - h = Enumerable.Repeat(0, 32).ToArray(); - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(h.Length * 2); - foreach (byte b in h) - { - sb.AppendFormat ("{0:x2}", b); - } - return sb.ToString(); - } - } + public class Hash256 + { + // 32 bytes + const int hashSize = 32; + + /// + /// Array of digest bytes. + /// + private byte[] hashBytes = new byte[hashSize]; + + /// + /// Initializes an empty instance of the Hash256 class. + /// + public Hash256() + { + hashBytes = Enumerable.Repeat(0, hashSize).ToArray(); + } + + /// + /// Initializes a new instance of Hash256 class with first 32 bytes from supplied list + /// + /// List of bytes + public Hash256(List bytesList) + { + hashBytes = bytesList.Take(hashSize).ToArray(); + } + + public Hash256(byte[] bytesArray) + { + hashBytes = bytesArray; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(hashSize * 2); + foreach (byte b in hashBytes) + { + sb.AppendFormat("{0:x2}", b); + } + return sb.ToString(); + } + + } } diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index 6360d2e..ae41a60 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -1,4 +1,4 @@ - + Debug @@ -31,6 +31,7 @@ + diff --git a/Novacoin/ScriptOpcode.cs b/Novacoin/ScriptOpcode.cs index ad7a2d5..86147a3 100644 --- a/Novacoin/ScriptOpcode.cs +++ b/Novacoin/ScriptOpcode.cs @@ -419,75 +419,79 @@ namespace Novacoin } /// - /// Get next opcode from passed enumerator and extract push arguments if there are some. + /// Get next opcode from passed list of bytes and extract push arguments if there are some. /// - /// Enumerator reference. + /// WrappedList reference. /// Opcode reference. - /// Bytes array reference which is used to get the push arguments. + /// IEnumerable reference which is used to get the push arguments. /// Result of operation - public static bool GetOp(ref IEnumerator codeBytes, ref opcodetype opcodeRet, ref List bytesRet) + public static bool GetOp(ref WrappedList codeBytes, ref opcodetype opcodeRet, ref IEnumerable bytesRet) { bytesRet = new List(); opcodeRet = opcodetype.OP_INVALIDOPCODE; - // Read instruction - if (!codeBytes.MoveNext()) + opcodetype opcode; + + try + { + // Read instruction + opcode = (opcodetype)codeBytes.GetItem(); + } + catch (WrappedListException) + { + // No instruction found there return false; - opcodetype opcode = (opcodetype)codeBytes.Current; + } // Immediate operand if (opcode <= opcodetype.OP_PUSHDATA4) { - int nSize = 0; - List szList = new List(); + byte[] szBytes = null; - if (opcode < opcodetype.OP_PUSHDATA1) - { // False values - szList.Add((byte)opcode); - } - else if (opcode == opcodetype.OP_PUSHDATA1) - { - // The next byte contains the number of bytes to be pushed onto the stack, - // i.e. you have something like OP_PUSHDATA1 0x01 [0x5a] - if (!codeBytes.MoveNext()) - return false; - szList.Add(codeBytes.Current); - } - else if (opcode == opcodetype.OP_PUSHDATA2) + try { - // The next two bytes contain the number of bytes to be pushed onto the stack. - // i.e. now your operation will seem like this: OP_PUSHDATA2 0x00 0x01 [0x5a] - for (int i = 0; i < 2; i++) + if (opcode < opcodetype.OP_PUSHDATA1) { - if (!codeBytes.MoveNext()) - return false; - szList.Add(codeBytes.Current); + // Zero values + szBytes = new byte[1] { (byte)opcode }; } - } - else if (opcode == opcodetype.OP_PUSHDATA4) - { - // The next four bytes contain the number of bytes to be pushed onto the stack. - // OP_PUSHDATA4 0x00 0x00 0x00 0x01 [0x5a] - for (int i = 0; i < 4; i++) + else if (opcode == opcodetype.OP_PUSHDATA1) { - if (!codeBytes.MoveNext()) - return false; - szList.Add(codeBytes.Current); + // The next byte contains the number of bytes to be pushed onto the stack, + // i.e. you have something like OP_PUSHDATA1 0x01 [0x5a] + szBytes = new byte[1] { codeBytes.GetItem() }; + } + else if (opcode == opcodetype.OP_PUSHDATA2) + { + // The next two bytes contain the number of bytes to be pushed onto the stack. + // i.e. now your operation will seem like this: OP_PUSHDATA2 0x00 0x01 [0x5a] + szBytes = codeBytes.GetItems(2); + } + else if (opcode == opcodetype.OP_PUSHDATA4) + { + // The next four bytes contain the number of bytes to be pushed onto the stack. + // OP_PUSHDATA4 0x00 0x00 0x00 0x01 [0x5a] + szBytes = codeBytes.GetItems(4); } } - - // Got all size bytes, now convert it to integer value - byte[] SizeBytes = szList.ToArray(); - Array.Reverse(SizeBytes); - nSize = BitConverter.ToInt32(SizeBytes, 0); - - // Read found number of bytes into list of OP_PUSHDATAn arguments. - for (int i = 0; i < nSize; i++) + catch (WrappedListException) { - if (!codeBytes.MoveNext()) - return false; + // Unable to read operand length + return false; + } + + Array.Reverse(szBytes); + int nSize = BitConverter.ToInt32(szBytes, 0); - bytesRet.Add(codeBytes.Current); + try + { + // Read found number of bytes into list of OP_PUSHDATAn arguments. + bytesRet = codeBytes.GetEnumerableItems(nSize); + } + catch (WrappedListException) + { + // Unable to read data + return false; } } diff --git a/Novacoin/WrappedList.cs b/Novacoin/WrappedList.cs new file mode 100644 index 0000000..83a85bb --- /dev/null +++ b/Novacoin/WrappedList.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Novacoin +{ + public class WrappedListException : Exception + { + public WrappedListException() + { + } + + public WrappedListException(string message) + : base(message) + { + } + + public WrappedListException(string message, Exception inner) + : base(message, inner) + { + } + } + + public class WrappedList + { + private int Index; + private List Elements; + + public WrappedList(List List, int Start) + { + Elements = List; + Index = Start; + } + + public WrappedList(List List) + { + Elements = List; + Index = 0; + } + + public T GetItem() + { + if (Elements.Count <= Index) + { + throw new WrappedListException("No elements left."); + } + + return Elements[Index++]; + } + + public T[] GetItems(int Count) + { + if (Elements.Count - Index < Count) + { + throw new WrappedListException("Unable to read requested amount of data."); + } + + T[] result = Elements.Skip(Index).Take(Count).ToArray(); + Index += Count; + + return result; + } + + public IEnumerable GetEnumerableItems(int Count) + { + if (Elements.Count - Index < Count) + { + throw new WrappedListException("Unable to read requested amount of data."); + } + + IEnumerable result = Elements.Skip(Index).Take(Count); + Index += Count; + + return result; + } + } +} -- 1.7.1