Use List wrapper instead of Enumerator
authorCryptoManiac <balthazar@yandex.ru>
Fri, 14 Aug 2015 22:46:53 +0000 (01:46 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Fri, 14 Aug 2015 22:46:53 +0000 (01:46 +0300)
Novacoin/Hash160.cs
Novacoin/Hash256.cs
Novacoin/Novacoin.csproj
Novacoin/ScriptOpcode.cs
Novacoin/WrappedList.cs [new file with mode: 0644]

index 993e4c9..a611e6c 100644 (file)
@@ -1,4 +1,5 @@
 \feffusing System;
+using System.Collections.Generic;
 using System.Text;
 using System.Linq;
 
@@ -9,30 +10,45 @@ namespace Novacoin
        /// </summary>
        public class Hash160
        {
+        // 20 bytes
+        const int hashSize = 20;
+
                /// <summary>
                /// Array of digest bytes.
                /// </summary>
-               private byte[] h;
+        private byte[] hashBytes = new byte[hashSize];
 
                /// <summary>
                /// Initializes an empty instance of the Hash160 class.
                /// </summary>
                public Hash160 ()
                {
-                       // Fill with 20 zero bytes
-                       h = Enumerable.Repeat<byte> (0, 20).ToArray ();
+            hashBytes = Enumerable.Repeat<byte>(0, hashSize).ToArray();
                }
 
+        /// <summary>
+        /// Initializes a new instance of Hash160 class with first 20 bytes from supplied list
+        /// </summary>
+        /// <param name="bytesList">List of bytes</param>
+        public Hash160(List<byte> bytesList)
+        {
+            hashBytes = bytesList.Take<byte>(hashSize).ToArray<byte>();
+        }
+
+        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();
                }
-
        }
 }
 
index 365f778..8a4f983 100644 (file)
@@ -1,36 +1,56 @@
 \feffusing System;
 using System.Text;
 using System.Linq;
+using System.Collections.Generic;
+
 
 namespace Novacoin
 {
        /// <summary>
        /// Representation of SHA-256 hash
        /// </summary>
-       public class Hash256
-       {
-               /// <summary>
-               /// Array of digest bytes.
-               /// </summary>
-               private byte[] h;
-
-               /// <summary>
-               /// Initializes an empty instance of the Hash256 class.
-               /// </summary>
-               public Hash256 ()
-               {
-                       h = Enumerable.Repeat<byte>(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;
+
+        /// <summary>
+        /// Array of digest bytes.
+        /// </summary>
+        private byte[] hashBytes = new byte[hashSize];
+
+        /// <summary>
+        /// Initializes an empty instance of the Hash256 class.
+        /// </summary>
+        public Hash256()
+        {
+            hashBytes = Enumerable.Repeat<byte>(0, hashSize).ToArray();
+        }
+
+        /// <summary>
+        /// Initializes a new instance of Hash256 class with first 32 bytes from supplied list
+        /// </summary>
+        /// <param name="bytesList">List of bytes</param>
+        public Hash256(List<byte> bytesList)
+        {
+            hashBytes = bytesList.Take<byte>(hashSize).ToArray<byte>();
+        }
+
+        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();
+        }
+
+    }
 }
 
index 6360d2e..ae41a60 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+\feff<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -31,6 +31,7 @@
     <Reference Include="System" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="WrappedList.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="CTxIn.cs" />
     <Compile Include="CTransaction.cs" />
index ad7a2d5..86147a3 100644 (file)
@@ -419,75 +419,79 @@ namespace Novacoin
         }
 
         /// <summary>
-        /// 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.
         /// </summary>
-        /// <param name="codeBytes">Enumerator reference.</param>
+        /// <param name="codeBytes">WrappedList reference.</param>
         /// <param name="opcodeRet">Opcode reference.</param>
-        /// <param name="bytesRet">Bytes array reference which is used to get the push arguments.</param>
+        /// <param name="bytesRet">IEnumerable reference which is used to get the push arguments.</param>
         /// <returns>Result of operation</returns>
-        public static bool GetOp(ref IEnumerator<byte> codeBytes, ref opcodetype opcodeRet, ref List<byte> bytesRet)
+        public static bool GetOp(ref WrappedList<byte> codeBytes, ref opcodetype opcodeRet, ref IEnumerable<byte> bytesRet)
         {
             bytesRet = new List<byte>();
             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<byte> szList = new List<byte>();
+                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 (file)
index 0000000..83a85bb
--- /dev/null
@@ -0,0 +1,79 @@
+\feffusing 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<T>
+    {
+        private int Index;
+        private List<T> Elements;
+
+        public WrappedList(List<T> List, int Start)
+        {
+            Elements = List;
+            Index = Start;
+        }
+
+        public WrappedList(List<T> 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<T>(Index).Take<T>(Count).ToArray<T>();
+            Index += Count;
+
+            return result;
+        }
+
+        public IEnumerable<T> GetEnumerableItems(int Count)
+        {
+            if (Elements.Count - Index < Count)
+            {
+                throw new WrappedListException("Unable to read requested amount of data.");
+            }
+
+            IEnumerable<T> result = Elements.Skip<T>(Index).Take<T>(Count);
+            Index += Count;
+
+            return result;
+        }
+    }
+}