From 70c6f23891b719dacc4c6b55a0a6c749d069136a Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Mon, 24 Aug 2015 12:59:37 +0300 Subject: [PATCH] Fix RemovePattern issues --- Novacoin/CScript.cs | 81 +++++++++++++++++++++++++++++++++++++---------- Novacoin/ScriptCode.cs | 2 +- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index 3127ec6..f5ea036 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -152,39 +152,84 @@ namespace Novacoin } /// - /// Scan code bytes for pattern + /// Scan pushed data bytes for pattern and, in case of exact match, remove it. /// /// Pattern sequence - /// Matches enumerator - private IEnumerable FindPattern(byte[] pattern) + /// Matches count + 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; } /// - /// Scan code bytes for pattern and remove it + /// Scan script for specific instruction and remove it if there are some matches. /// - /// Pattern sequence - /// Matches number - public int RemovePattern(byte[] pattern) + /// Instruction + /// Matches count + public int RemoveInstruction(instruction op) { - var resultBytes = new List(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; } diff --git a/Novacoin/ScriptCode.cs b/Novacoin/ScriptCode.cs index eb5f4dc..19850c9 100644 --- a/Novacoin/ScriptCode.cs +++ b/Novacoin/ScriptCode.cs @@ -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++) -- 1.7.1