Fix PushData and add RemovePattern function
authorCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 17:43:45 +0000 (20:43 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 17:43:45 +0000 (20:43 +0300)
Novacoin/CScript.cs
Novacoin/ScriptOpcode.cs

index a6f16a2..47ad01c 100644 (file)
@@ -1,4 +1,5 @@
 \feffusing System;
+using System.Linq;
 using System.Text;
 
 using System.Collections;
@@ -94,41 +95,91 @@ namespace Novacoin
             codeBytes.AddRange(hash.hashBytes);
         }
 
+        /// <summary>
+        /// Create new OP_PUSHDATAn operator and add it to opcode bytes list
+        /// </summary>
+        /// <param name="dataBytes">List of data bytes</param>
         public void PushData(IList<byte> dataBytes)
         {
             if (dataBytes.Count < (int)opcodetype.OP_PUSHDATA1)
             {
+                // OP_0 and OP_FALSE
                 codeBytes.Add((byte)dataBytes.Count);
             }
             else if (dataBytes.Count < 0xff)
             {
+                // OP_PUSHDATA1 0x01 [0x5a]
                 codeBytes.Add((byte)opcodetype.OP_PUSHDATA1);
                 codeBytes.Add((byte)dataBytes.Count);
             }
             else if (dataBytes.Count < 0xffff)
             {
+                // OP_PUSHDATA1 0x00 0x01 [0x5a]
                 codeBytes.Add((byte)opcodetype.OP_PUSHDATA2);
 
                 byte[] szBytes = BitConverter.GetBytes((short)dataBytes.Count);
                 if (BitConverter.IsLittleEndian)
+                {
                     Array.Reverse(szBytes);
-
+                }
                 codeBytes.AddRange(szBytes);
             }
             else if ((uint)dataBytes.Count < 0xffffffff)
             {
-                codeBytes.Add((byte)opcodetype.OP_PUSHDATA2);
+                // OP_PUSHDATA1 0x00 0x00 0x00 0x01 [0x5a]
+                codeBytes.Add((byte)opcodetype.OP_PUSHDATA4);
 
                 byte[] szBytes = BitConverter.GetBytes((uint)dataBytes.Count);
                 if (BitConverter.IsLittleEndian)
+                {
                     Array.Reverse(szBytes);
-
+                }
                 codeBytes.AddRange(szBytes);
             }
+
+            // Add data bytes
             codeBytes.AddRange(dataBytes);
         }
 
         /// <summary>
+        /// Scan code bytes for pattern
+        /// </summary>
+        /// <param name="pattern">Pattern sequence</param>
+        /// <returns>Matches enumerator</returns>
+        private IEnumerable<int> FindPattern(IList<byte> pattern)
+        {
+            for (int i = 0; i < codeBytes.Count; i++)
+            {
+                if (codeBytes.Skip(i).Take(pattern.Count).SequenceEqual(pattern))
+                {
+                    yield return i;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Scan code bytes for pattern and remove it
+        /// </summary>
+        /// <param name="pattern">Pattern sequence</param>
+        /// <returns>Matches number</returns>
+        public int RemovePattern(IList<byte> pattern)
+        {
+            List<byte> resultBytes = new List<byte>(codeBytes);
+            int count = 0;
+            int patternLen = pattern.Count;
+                        
+            foreach (int i in FindPattern(pattern))
+            {
+                resultBytes.RemoveRange(i - count * patternLen, patternLen);
+                count++;
+            }
+
+            codeBytes = resultBytes;
+            
+            return count;
+        }
+
+        /// <summary>
         /// Disassemble current script code
         /// </summary>
         /// <returns>Code listing</returns>
index 19cde31..b967b5a 100644 (file)
@@ -488,15 +488,19 @@ namespace Novacoin
 
                 int nSize = BitConverter.ToInt32(szBytes, 0);
 
-                try
+                if (nSize > 0)
                 {
-                    // Read found number of bytes into list of OP_PUSHDATAn arguments.
-                    bytesRet = codeBytes.GetEnumerableItems(nSize);
-                }
-                catch (WrappedListException)
-                {
-                    // Unable to read data
-                    return false;
+                    // If nSize is greater than zero then there is some data available
+                    try
+                    {
+                        // Read found number of bytes into list of OP_PUSHDATAn arguments.
+                        bytesRet = codeBytes.GetEnumerableItems(nSize);
+                    }
+                    catch (WrappedListException)
+                    {
+                        // Unable to read data
+                        return false;
+                    }
                 }
             }