Fix RemovePattern issues
authorCryptoManiac <balthazar.ad@gmail.com>
Mon, 24 Aug 2015 09:59:37 +0000 (12:59 +0300)
committerCryptoManiac <balthazar.ad@gmail.com>
Mon, 24 Aug 2015 09:59:37 +0000 (12:59 +0300)
Novacoin/CScript.cs
Novacoin/ScriptCode.cs

index 3127ec6..f5ea036 100644 (file)
@@ -152,39 +152,84 @@ namespace Novacoin
         }
 
         /// <summary>
-        /// Scan code bytes for pattern
+        /// Scan pushed data bytes for pattern and, in case of exact match, remove it.
         /// </summary>
         /// <param name="pattern">Pattern sequence</param>
-        /// <returns>Matches enumerator</returns>
-        private IEnumerable<int> FindPattern(byte[] pattern)
+        /// <returns>Matches count</returns>
+        public int RemovePattern(byte[] pattern)
         {
-            for (int i = 0; i < codeBytes.Count; i++)
+            // There is no sense to continue if pattern is longer than script itself
+            if (pattern.Length == 0 || pattern.Length > codeBytes.Count)
+            {
+                return 0;
+            }
+
+            var count = 0;
+            var bq1 = new ByteQueue(codeBytes);
+
+
+            byte[] pushData;
+            instruction opcode;
+
+            var newScript = new CScript();
+
+            while (ScriptCode.GetOp(ref bq1, out opcode, out pushData))
             {
-                if (codeBytes.Skip(i).Take(pattern.Length).SequenceEqual(pattern))
+                if (pushData.Length == 0)
                 {
-                    yield return i;
+                    // No data, put instruction on its place
+                    newScript.AddInstruction(opcode);
+                }
+                else if (!pushData.SequenceEqual(pattern))
+                {
+                    // No match, create push operator
+                    newScript.PushData(pushData);
+                }
+                else
+                {
+                    count++; // match
                 }
             }
+
+            codeBytes = newScript.codeBytes;
+
+            return count;
         }
 
         /// <summary>
-        /// Scan code bytes for pattern and remove it
+        /// Scan script for specific instruction and remove it if there are some matches.
         /// </summary>
-        /// <param name="pattern">Pattern sequence</param>
-        /// <returns>Matches number</returns>
-        public int RemovePattern(byte[] pattern)
+        /// <param name="op">Instruction</param>
+        /// <returns>Matches count</returns>
+        public int RemoveInstruction(instruction op)
         {
-            var resultBytes = new List<byte>(codeBytes);
-            int count = 0;
-                        
-            foreach (int i in FindPattern(pattern))
+            var count = 0;
+            var bq1 = new ByteQueue(codeBytes);
+
+
+            byte[] pushData;
+            instruction opcode;
+
+            var newScript = new CScript();
+
+            while (ScriptCode.GetOp(ref bq1, out opcode, out pushData))
             {
-                resultBytes.RemoveRange(i - count * pattern.Length, pattern.Length);
-                count++;
+                if (pushData.Length != 0)
+                {
+                    newScript.PushData(pushData);
+                }
+                else if (Enum.IsDefined(typeof(instruction), op) && op != opcode)
+                {
+                    newScript.AddInstruction(opcode);
+                }
+                else
+                {
+                    count++; // match
+                }
             }
 
-            codeBytes = resultBytes;
-            
+            codeBytes = newScript.codeBytes;
+
             return count;
         }
 
index eb5f4dc..19850c9 100644 (file)
@@ -685,7 +685,7 @@ namespace Novacoin
 
             // In case concatenating two scripts ends up with two codeseparators,
             // or an extra one at the end, this prevents all those possible incompatibilities.
-            //script.RemovePattern(new byte[] { (byte)instruction.OP_CODESEPARATOR });     // TODO: issue here, due to false matches this breaks the validation of some scripts
+            script.RemoveInstruction(instruction.OP_CODESEPARATOR);
 
             // Blank out other inputs' signatures
             for (int i = 0; i < txTmp.vin.Length; i++)