CScript: disassembly support
authorCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 16:17:45 +0000 (19:17 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 16:17:45 +0000 (19:17 +0300)
Novacoin/CScript.cs
Novacoin/ScriptOpcode.cs
Novacoin/WrappedList.cs

index 0b5cb2b..9ada832 100644 (file)
@@ -128,14 +128,41 @@ namespace Novacoin
             codeBytes.AddRange(dataBytes);
         }
 
+        /// <summary>
+        /// Disassemble current script code
+        /// </summary>
+        /// <returns>Code listing</returns>
                public override string ToString()
                {
-                       // TODO: disassembly 
-
                        StringBuilder sb = new StringBuilder();
 
-            //
-            
+            WrappedList<byte> wCodeBytes = new WrappedList<byte>(codeBytes);
+
+            while (wCodeBytes.ItemsLeft > 0)
+            {
+                if (sb.Length != 0)
+                {
+                    sb.Append(" ");
+                }
+
+                opcodetype opcode;
+                IEnumerable<byte> pushArgs;
+                if (!ScriptOpcode.GetOp(ref wCodeBytes, out opcode, out pushArgs))
+                {
+                    sb.Append("[error]");
+                    break;
+                }
+
+                if (0 <= opcode && opcode <= opcodetype.OP_PUSHDATA4)
+                {
+                    sb.Append(ScriptOpcode.ValueString(pushArgs));
+                }
+                else
+                {
+                    sb.Append(ScriptOpcode.GetOpName(opcode));
+                }
+            }
+
             return sb.ToString();
                }
        }
index 0790c4c..19cde31 100644 (file)
@@ -422,10 +422,10 @@ namespace Novacoin
         /// Get next opcode from passed list of bytes and extract push arguments if there are some.
         /// </summary>
         /// <param name="codeBytes">WrappedList reference.</param>
-        /// <param name="opcodeRet">Opcode reference.</param>
-        /// <param name="bytesRet">IEnumerable reference which is used to get the push arguments.</param>
+        /// <param name="opcodeRet">Found opcode.</param>
+        /// <param name="bytesRet">IEnumerable out param which is used to get the push arguments.</param>
         /// <returns>Result of operation</returns>
-        public static bool GetOp(ref WrappedList<byte> codeBytes, ref opcodetype opcodeRet, ref IEnumerable<byte> bytesRet)
+        public static bool GetOp(ref WrappedList<byte> codeBytes, out opcodetype opcodeRet, out IEnumerable<byte> bytesRet)
         {
             bytesRet = new List<byte>();
             opcodeRet = opcodetype.OP_INVALIDOPCODE;
@@ -510,16 +510,16 @@ namespace Novacoin
         /// 
         /// If list lengh is equal or lesser than 4 bytes then bytes are interpreted as integer value. Otherwise you will get hex representation of supplied data.
         /// </summary>
-        /// <param name="bytesList">List of value bytes.</param>
+        /// <param name="bytes">Collection of value bytes.</param>
         /// <returns>Formatted value.</returns>
-        public static string ValueString(IList<byte> bytesList)
+        public static string ValueString(IEnumerable<byte> bytes)
         {
             StringBuilder sb = new StringBuilder();
 
-            if (bytesList.Count <= 4)
+            if (bytes.Count() <= 4)
             {
                 byte[] valueBytes = new byte[4] {0, 0, 0, 0};
-                bytesList.ToArray().CopyTo(valueBytes, valueBytes.Length - bytesList.Count);
+                bytes.ToArray().CopyTo(valueBytes, valueBytes.Length - bytes.Count());
 
                 // Reverse array if we are on little-endian machine
                 if (BitConverter.IsLittleEndian)
@@ -531,7 +531,7 @@ namespace Novacoin
             }
             else
             {
-                foreach (byte b in bytesList)
+                foreach (byte b in bytes)
                 {
                     sb.AppendFormat("{0:x2}", b);
                 }
index 79068c3..e871025 100644 (file)
@@ -28,6 +28,11 @@ namespace Novacoin
         private int Index;
         private List<T> Elements;
 
+        public int ItemsLeft
+        {
+            get { return Elements.Count - Index; }
+        }
+
         public WrappedList(IList<T> List, int Start)
         {
             Elements = new List<T>(List);
@@ -52,7 +57,7 @@ namespace Novacoin
 
         public T[] GetItems(int Count)
         {
-            if (Elements.Count - Index < Count)
+            if (ItemsLeft < Count)
             {
                 throw new WrappedListException("Unable to read requested amount of data.");
             }