Split static functions off to separate class;
authorCryptoManiac <balthazar@yandex.ru>
Thu, 6 Aug 2015 22:03:27 +0000 (01:03 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Thu, 6 Aug 2015 22:03:27 +0000 (01:03 +0300)
Implement ValueString, StackString, DecodeOP_N/EncodeOP_N functions.

Novacoin/CScript.cs
Novacoin/Novacoin.csproj
Novacoin/ScriptOpcode.cs [new file with mode: 0644]

index b79f2ff..7728d4c 100644 (file)
@@ -6,507 +6,25 @@ using System.Collections.Generic;
 
 namespace Novacoin
 {
-       /** Script opcodes */
-       public enum opcodetype
+       public class CScript : List<byte>
        {
-               // push value
-               OP_0 = 0x00,
-               OP_FALSE = OP_0,
-               OP_PUSHDATA1 = 0x4c,
-               OP_PUSHDATA2 = 0x4d,
-               OP_PUSHDATA4 = 0x4e,
-               OP_1NEGATE = 0x4f,
-               OP_RESERVED = 0x50,
-               OP_1 = 0x51,
-               OP_TRUE=OP_1,
-               OP_2 = 0x52,
-               OP_3 = 0x53,
-               OP_4 = 0x54,
-               OP_5 = 0x55,
-               OP_6 = 0x56,
-               OP_7 = 0x57,
-               OP_8 = 0x58,
-               OP_9 = 0x59,
-               OP_10 = 0x5a,
-               OP_11 = 0x5b,
-               OP_12 = 0x5c,
-               OP_13 = 0x5d,
-               OP_14 = 0x5e,
-               OP_15 = 0x5f,
-               OP_16 = 0x60,
-
-               // control
-               OP_NOP = 0x61,
-               OP_VER = 0x62,
-               OP_IF = 0x63,
-               OP_NOTIF = 0x64,
-               OP_VERIF = 0x65,
-               OP_VERNOTIF = 0x66,
-               OP_ELSE = 0x67,
-               OP_ENDIF = 0x68,
-               OP_VERIFY = 0x69,
-               OP_RETURN = 0x6a,
-
-               // stack ops
-               OP_TOALTSTACK = 0x6b,
-               OP_FROMALTSTACK = 0x6c,
-               OP_2DROP = 0x6d,
-               OP_2DUP = 0x6e,
-               OP_3DUP = 0x6f,
-               OP_2OVER = 0x70,
-               OP_2ROT = 0x71,
-               OP_2SWAP = 0x72,
-               OP_IFDUP = 0x73,
-               OP_DEPTH = 0x74,
-               OP_DROP = 0x75,
-               OP_DUP = 0x76,
-               OP_NIP = 0x77,
-               OP_OVER = 0x78,
-               OP_PICK = 0x79,
-               OP_ROLL = 0x7a,
-               OP_ROT = 0x7b,
-               OP_SWAP = 0x7c,
-               OP_TUCK = 0x7d,
-
-               // splice ops
-               OP_CAT = 0x7e,
-               OP_SUBSTR = 0x7f,
-               OP_LEFT = 0x80,
-               OP_RIGHT = 0x81,
-               OP_SIZE = 0x82,
-
-               // bit logic
-               OP_INVERT = 0x83,
-               OP_AND = 0x84,
-               OP_OR = 0x85,
-               OP_XOR = 0x86,
-               OP_EQUAL = 0x87,
-               OP_EQUALVERIFY = 0x88,
-               OP_RESERVED1 = 0x89,
-               OP_RESERVED2 = 0x8a,
-
-               // numeric
-               OP_1ADD = 0x8b,
-               OP_1SUB = 0x8c,
-               OP_2MUL = 0x8d,
-               OP_2DIV = 0x8e,
-               OP_NEGATE = 0x8f,
-               OP_ABS = 0x90,
-               OP_NOT = 0x91,
-               OP_0NOTEQUAL = 0x92,
-
-               OP_ADD = 0x93,
-               OP_SUB = 0x94,
-               OP_MUL = 0x95,
-               OP_DIV = 0x96,
-               OP_MOD = 0x97,
-               OP_LSHIFT = 0x98,
-               OP_RSHIFT = 0x99,
-
-               OP_BOOLAND = 0x9a,
-               OP_BOOLOR = 0x9b,
-               OP_NUMEQUAL = 0x9c,
-               OP_NUMEQUALVERIFY = 0x9d,
-               OP_NUMNOTEQUAL = 0x9e,
-               OP_LESSTHAN = 0x9f,
-               OP_GREATERTHAN = 0xa0,
-               OP_LESSTHANOREQUAL = 0xa1,
-               OP_GREATERTHANOREQUAL = 0xa2,
-               OP_MIN = 0xa3,
-               OP_MAX = 0xa4,
-
-               OP_WITHIN = 0xa5,
-
-               // crypto
-               OP_RIPEMD160 = 0xa6,
-               OP_SHA1 = 0xa7,
-               OP_SHA256 = 0xa8,
-               OP_HASH160 = 0xa9,
-               OP_HASH256 = 0xaa,
-               OP_CODESEPARATOR = 0xab,
-               OP_CHECKSIG = 0xac,
-               OP_CHECKSIGVERIFY = 0xad,
-               OP_CHECKMULTISIG = 0xae,
-               OP_CHECKMULTISIGVERIFY = 0xaf,
-
-               // expansion
-               OP_NOP1 = 0xb0,
-               OP_NOP2 = 0xb1,
-               OP_NOP3 = 0xb2,
-               OP_NOP4 = 0xb3,
-               OP_NOP5 = 0xb4,
-               OP_NOP6 = 0xb5,
-               OP_NOP7 = 0xb6,
-               OP_NOP8 = 0xb7,
-               OP_NOP9 = 0xb8,
-               OP_NOP10 = 0xb9,
-
-               // template matching params
-               OP_SMALLDATA = 0xf9,
-               OP_SMALLINTEGER = 0xfa,
-               OP_PUBKEYS = 0xfb,
-               OP_PUBKEYHASH = 0xfd,
-               OP_PUBKEY = 0xfe,
-
-               OP_INVALIDOPCODE = 0xff,
-       };
-
-       public class CScript
-       {
-               private byte[] scriptCode = {};
-
                public CScript ()
                {
                }
 
-               private string GetOpName(opcodetype opcode)
-               {
-                       switch (opcode) {
-                       // push value
-                       case opcodetype.OP_0:
-                               return "0";
-                       case opcodetype.OP_PUSHDATA1:
-                               return "OP_PUSHDATA1";
-                       case opcodetype.OP_PUSHDATA2:
-                               return "OP_PUSHDATA2";
-                       case opcodetype.OP_PUSHDATA4:
-                               return "OP_PUSHDATA4";
-                       case opcodetype.OP_1NEGATE:
-                               return "-1";
-                       case opcodetype.OP_RESERVED:
-                               return "OP_RESERVED";
-                       case opcodetype.OP_1:
-                               return "1";
-                       case opcodetype.OP_2:
-                               return "2";
-                       case opcodetype.OP_3:
-                               return "3";
-                       case opcodetype.OP_4:
-                               return "4";
-                       case opcodetype.OP_5:
-                               return "5";
-                       case opcodetype.OP_6:
-                               return "6";
-                       case opcodetype.OP_7:
-                               return "7";
-                       case opcodetype.OP_8:
-                               return "8";
-                       case opcodetype.OP_9:
-                               return "9";
-                       case opcodetype.OP_10:
-                               return "10";
-                       case opcodetype.OP_11:
-                               return "11";
-                       case opcodetype.OP_12:
-                               return "12";
-                       case opcodetype.OP_13:
-                               return "13";
-                       case opcodetype.OP_14:
-                               return "14";
-                       case opcodetype.OP_15:
-                               return "15";
-                       case opcodetype.OP_16:
-                               return "16";
-
-                       // control
-                       case opcodetype.OP_NOP:
-                               return "OP_NOP";
-                       case opcodetype.OP_VER:
-                               return "OP_VER";
-                       case opcodetype.OP_IF:
-                               return "OP_IF";
-                       case opcodetype.OP_NOTIF:
-                               return "OP_NOTIF";
-                       case opcodetype.OP_VERIF:
-                               return "OP_VERIF";
-                       case opcodetype.OP_VERNOTIF:
-                               return "OP_VERNOTIF";
-                       case opcodetype.OP_ELSE:
-                               return "OP_ELSE";
-                       case opcodetype.OP_ENDIF:
-                               return "OP_ENDIF";
-                       case opcodetype.OP_VERIFY:
-                               return "OP_VERIFY";
-                       case opcodetype.OP_RETURN:
-                               return "OP_RETURN";
-
-                       // stack ops
-                       case opcodetype.OP_TOALTSTACK:
-                               return "OP_TOALTSTACK";
-                       case opcodetype.OP_FROMALTSTACK:
-                               return "OP_FROMALTSTACK";
-                       case opcodetype.OP_2DROP:
-                               return "OP_2DROP";
-                       case opcodetype.OP_2DUP:
-                               return "OP_2DUP";
-                       case opcodetype.OP_3DUP:
-                               return "OP_3DUP";
-                       case opcodetype.OP_2OVER:
-                               return "OP_2OVER";
-                       case opcodetype.OP_2ROT:
-                               return "OP_2ROT";
-                       case opcodetype.OP_2SWAP:
-                               return "OP_2SWAP";
-                       case opcodetype.OP_IFDUP:
-                               return "OP_IFDUP";
-                       case opcodetype.OP_DEPTH:
-                               return "OP_DEPTH";
-                       case opcodetype.OP_DROP:
-                               return "OP_DROP";
-                       case opcodetype.OP_DUP:
-                               return "OP_DUP";
-                       case opcodetype.OP_NIP:
-                               return "OP_NIP";
-                       case opcodetype.OP_OVER:
-                               return "OP_OVER";
-                       case opcodetype.OP_PICK:
-                               return "OP_PICK";
-                       case opcodetype.OP_ROLL:
-                               return "OP_ROLL";
-                       case opcodetype.OP_ROT:
-                               return "OP_ROT";
-                       case opcodetype.OP_SWAP:
-                               return "OP_SWAP";
-                       case opcodetype.OP_TUCK:
-                               return "OP_TUCK";
-
-                       // splice ops
-                       case opcodetype.OP_CAT:
-                               return "OP_CAT";
-                       case opcodetype.OP_SUBSTR:
-                               return "OP_SUBSTR";
-                       case opcodetype.OP_LEFT:
-                               return "OP_LEFT";
-                       case opcodetype.OP_RIGHT:
-                               return "OP_RIGHT";
-                       case opcodetype.OP_SIZE:
-                               return "OP_SIZE";
-
-                       // bit logic
-                       case opcodetype.OP_INVERT:
-                               return "OP_INVERT";
-                       case opcodetype.OP_AND:
-                               return "OP_AND";
-                       case opcodetype.OP_OR:
-                               return "OP_OR";
-                       case opcodetype.OP_XOR:
-                               return "OP_XOR";
-                       case opcodetype.OP_EQUAL:
-                               return "OP_EQUAL";
-                       case opcodetype.OP_EQUALVERIFY:
-                               return "OP_EQUALVERIFY";
-                       case opcodetype.OP_RESERVED1:
-                               return "OP_RESERVED1";
-                       case opcodetype.OP_RESERVED2:
-                               return "OP_RESERVED2";
-
-                       // numeric
-                       case opcodetype.OP_1ADD:
-                               return "OP_1ADD";
-                       case opcodetype.OP_1SUB:
-                               return "OP_1SUB";
-                       case opcodetype.OP_2MUL:
-                               return "OP_2MUL";
-                       case opcodetype.OP_2DIV:
-                               return "OP_2DIV";
-                       case opcodetype.OP_NEGATE:
-                               return "OP_NEGATE";
-                       case opcodetype.OP_ABS:
-                               return "OP_ABS";
-                       case opcodetype.OP_NOT:
-                               return "OP_NOT";
-                       case opcodetype.OP_0NOTEQUAL:
-                               return "OP_0NOTEQUAL";
-                       case opcodetype.OP_ADD:
-                               return "OP_ADD";
-                       case opcodetype.OP_SUB:
-                               return "OP_SUB";
-                       case opcodetype.OP_MUL:
-                               return "OP_MUL";
-                       case opcodetype.OP_DIV:
-                               return "OP_DIV";
-                       case opcodetype.OP_MOD:
-                               return "OP_MOD";
-                       case opcodetype.OP_LSHIFT:
-                               return "OP_LSHIFT";
-                       case opcodetype.OP_RSHIFT:
-                               return "OP_RSHIFT";
-                       case opcodetype.OP_BOOLAND:
-                               return "OP_BOOLAND";
-                       case opcodetype.OP_BOOLOR:
-                               return "OP_BOOLOR";
-                       case opcodetype.OP_NUMEQUAL:
-                               return "OP_NUMEQUAL";
-                       case opcodetype.OP_NUMEQUALVERIFY:
-                               return "OP_NUMEQUALVERIFY";
-                       case opcodetype.OP_NUMNOTEQUAL:
-                               return "OP_NUMNOTEQUAL";
-                       case opcodetype.OP_LESSTHAN:
-                               return "OP_LESSTHAN";
-                       case opcodetype.OP_GREATERTHAN:
-                               return "OP_GREATERTHAN";
-                       case opcodetype.OP_LESSTHANOREQUAL:
-                               return "OP_LESSTHANOREQUAL";
-                       case opcodetype.OP_GREATERTHANOREQUAL:
-                               return "OP_GREATERTHANOREQUAL";
-                       case opcodetype.OP_MIN:
-                               return "OP_MIN";
-                       case opcodetype.OP_MAX:
-                               return "OP_MAX";
-                       case opcodetype.OP_WITHIN:
-                               return "OP_WITHIN";
-
-                       // crypto
-                       case opcodetype.OP_RIPEMD160:
-                               return "OP_RIPEMD160";
-                       case opcodetype.OP_SHA1:
-                               return "OP_SHA1";
-                       case opcodetype.OP_SHA256:
-                               return "OP_SHA256";
-                       case opcodetype.OP_HASH160:
-                               return "OP_HASH160";
-                       case opcodetype.OP_HASH256:
-                               return "OP_HASH256";
-                       case opcodetype.OP_CODESEPARATOR:
-                               return "OP_CODESEPARATOR";
-                       case opcodetype.OP_CHECKSIG:
-                               return "OP_CHECKSIG";
-                       case opcodetype.OP_CHECKSIGVERIFY:
-                               return "OP_CHECKSIGVERIFY";
-                       case opcodetype.OP_CHECKMULTISIG:
-                               return "OP_CHECKMULTISIG";
-                       case opcodetype.OP_CHECKMULTISIGVERIFY:
-                               return "OP_CHECKMULTISIGVERIFY";
-
-                       // expanson
-                       case opcodetype.OP_NOP1:
-                               return "OP_NOP1";
-                       case opcodetype.OP_NOP2:
-                               return "OP_NOP2";
-                       case opcodetype.OP_NOP3:
-                               return "OP_NOP3";
-                       case opcodetype.OP_NOP4:
-                               return "OP_NOP4";
-                       case opcodetype.OP_NOP5:
-                               return "OP_NOP5";
-                       case opcodetype.OP_NOP6:
-                               return "OP_NOP6";
-                       case opcodetype.OP_NOP7:
-                               return "OP_NOP7";
-                       case opcodetype.OP_NOP8:
-                               return "OP_NOP8";
-                       case opcodetype.OP_NOP9:
-                               return "OP_NOP9";
-                       case opcodetype.OP_NOP10:
-                               return "OP_NOP10";
-
-                       // template matching params
-                       case opcodetype.OP_PUBKEYHASH:
-                               return "OP_PUBKEYHASH";
-                       case opcodetype.OP_PUBKEY:
-                               return "OP_PUBKEY";
-                       case opcodetype.OP_SMALLDATA:
-                               return "OP_SMALLDATA";
-
-                       case opcodetype.OP_INVALIDOPCODE:
-                               return "OP_INVALIDOPCODE";
-                       default:
-                               return "OP_UNKNOWN";
-                       }
-               }
-
-               public bool GetOp(ref IEnumerator<byte> codeBytes, ref opcodetype opcodeRet, ref byte[] bytesRet)
-               {
-                       opcodeRet = opcodetype.OP_INVALIDOPCODE;
-
-                       // Initialize local byte list
-                       List<byte> bytesRetIn = new List<byte> ();
-
-                       // Read instruction
-                       if (!codeBytes.MoveNext())
-                               return false;
-                       opcodetype opcode = (opcodetype)codeBytes.Current;
-
-                       // Immediate operand
-                       if (opcode <= opcodetype.OP_PUSHDATA4)
-                       {
-                               int nSize = 0;
-                               if (opcode < opcodetype.OP_PUSHDATA1) { // False values
-                                       nSize = (int)opcode;
-                               } else if (opcode == opcodetype.OP_PUSHDATA1) { // One byte size prefix
-                                       if (!codeBytes.MoveNext ())
-                                               return false;
-                                       nSize = codeBytes.Current;
-                               } else if (opcode == opcodetype.OP_PUSHDATA2) { // Two bytes size prefix
-                                       byte[] SizeBytes = {0,0};
-
-                                       for (int i = 0; i < 2; i++) { // TODO: implement some intelligent solution instead
-                                               if (!codeBytes.MoveNext ())
-                                                       return false;
-
-                                               SizeBytes [i] = codeBytes.Current; 
-                                       }
-
-                                       Array.Reverse (SizeBytes);
-                                       BitConverter.ToUInt32(SizeBytes, 0);
-                               } else if (opcode == opcodetype.OP_PUSHDATA4) { // Four bytes size prefix
-                                       byte[] SizeBytes = {0,0,0,0};
-
-                                       for (int i = 0; i < 4; i++) {
-                                               if (!codeBytes.MoveNext ())
-                                                       return false;
 
-                                               SizeBytes [i] = codeBytes.Current; 
-                                       }
 
-                                       Array.Reverse (SizeBytes);
-                                       nSize = BitConverter.ToInt32 (SizeBytes, 0);
-                               }
-
-                               for (int i = 0; i < nSize; i++) {
-                                       if (!codeBytes.MoveNext ())
-                                               return false;
-
-                                       bytesRetIn.Add (codeBytes.Current);
-                               }
-
-                               // Return OP_PUSHDATA arguments
-                               bytesRet = bytesRetIn.ToArray ();
-                       }
-
-                       opcodeRet = opcode;
                
-                       return true;
-               }
-
-               // Encode/decode small integers:
-               static int DecodeOP_N(opcodetype opcode)
-               {
-                       if (opcode == opcodetype.OP_0)
-                               return 0;
-                       if(! (opcode >= opcodetype.OP_1 && opcode <= opcodetype.OP_16))
-                               throw new Exception ("! (opcode >= opcodetype.OP_1 && opcode <= opcodetype.OP_16)");
-                       return (int)opcode - (int)(opcodetype.OP_1 - 1);
-               }
-               static opcodetype EncodeOP_N(int n)
-               {
-                       if (!(n >= 0 && n <= 16))
-                               throw new Exception ("! (n >= 0 && n <= 16)");
-                       if (n == 0)
-                               return opcodetype.OP_0;
-                       return (opcodetype)(opcodetype.OP_1+n-1);
-               }
 
                public override string ToString()
                {
                        // TODO: disassembly 
 
-                       StringBuilder sb = new StringBuilder(scriptCode.Length * 2);
-                       foreach (byte b in scriptCode)
-                       {
-                               sb.AppendFormat ("{0:x2}", b);
-                       }
-                       return sb.ToString();
+                       StringBuilder sb = new StringBuilder();
+
+            //
+            
+            return sb.ToString();
                }
        }
 }
index 9c9934b..6360d2e 100644 (file)
@@ -40,6 +40,7 @@
     <Compile Include="CBlockHeader.cs" />
     <Compile Include="CBlock.cs" />
     <Compile Include="CScript.cs" />
+    <Compile Include="ScriptOpcode.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/Novacoin/ScriptOpcode.cs b/Novacoin/ScriptOpcode.cs
new file mode 100644 (file)
index 0000000..ad7a2d5
--- /dev/null
@@ -0,0 +1,573 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Novacoin
+{
+    /// <summary>
+    /// Script opcodes
+    /// </summary>
+    public enum opcodetype
+    {
+        // push value
+        OP_0 = 0x00,
+        OP_FALSE = OP_0,
+        OP_PUSHDATA1 = 0x4c,
+        OP_PUSHDATA2 = 0x4d,
+        OP_PUSHDATA4 = 0x4e,
+        OP_1NEGATE = 0x4f,
+        OP_RESERVED = 0x50,
+        OP_1 = 0x51,
+        OP_TRUE = OP_1,
+        OP_2 = 0x52,
+        OP_3 = 0x53,
+        OP_4 = 0x54,
+        OP_5 = 0x55,
+        OP_6 = 0x56,
+        OP_7 = 0x57,
+        OP_8 = 0x58,
+        OP_9 = 0x59,
+        OP_10 = 0x5a,
+        OP_11 = 0x5b,
+        OP_12 = 0x5c,
+        OP_13 = 0x5d,
+        OP_14 = 0x5e,
+        OP_15 = 0x5f,
+        OP_16 = 0x60,
+
+        // control
+        OP_NOP = 0x61,
+        OP_VER = 0x62,
+        OP_IF = 0x63,
+        OP_NOTIF = 0x64,
+        OP_VERIF = 0x65,
+        OP_VERNOTIF = 0x66,
+        OP_ELSE = 0x67,
+        OP_ENDIF = 0x68,
+        OP_VERIFY = 0x69,
+        OP_RETURN = 0x6a,
+
+        // stack ops
+        OP_TOALTSTACK = 0x6b,
+        OP_FROMALTSTACK = 0x6c,
+        OP_2DROP = 0x6d,
+        OP_2DUP = 0x6e,
+        OP_3DUP = 0x6f,
+        OP_2OVER = 0x70,
+        OP_2ROT = 0x71,
+        OP_2SWAP = 0x72,
+        OP_IFDUP = 0x73,
+        OP_DEPTH = 0x74,
+        OP_DROP = 0x75,
+        OP_DUP = 0x76,
+        OP_NIP = 0x77,
+        OP_OVER = 0x78,
+        OP_PICK = 0x79,
+        OP_ROLL = 0x7a,
+        OP_ROT = 0x7b,
+        OP_SWAP = 0x7c,
+        OP_TUCK = 0x7d,
+
+        // splice ops
+        OP_CAT = 0x7e,
+        OP_SUBSTR = 0x7f,
+        OP_LEFT = 0x80,
+        OP_RIGHT = 0x81,
+        OP_SIZE = 0x82,
+
+        // bit logic
+        OP_INVERT = 0x83,
+        OP_AND = 0x84,
+        OP_OR = 0x85,
+        OP_XOR = 0x86,
+        OP_EQUAL = 0x87,
+        OP_EQUALVERIFY = 0x88,
+        OP_RESERVED1 = 0x89,
+        OP_RESERVED2 = 0x8a,
+
+        // numeric
+        OP_1ADD = 0x8b,
+        OP_1SUB = 0x8c,
+        OP_2MUL = 0x8d,
+        OP_2DIV = 0x8e,
+        OP_NEGATE = 0x8f,
+        OP_ABS = 0x90,
+        OP_NOT = 0x91,
+        OP_0NOTEQUAL = 0x92,
+
+        OP_ADD = 0x93,
+        OP_SUB = 0x94,
+        OP_MUL = 0x95,
+        OP_DIV = 0x96,
+        OP_MOD = 0x97,
+        OP_LSHIFT = 0x98,
+        OP_RSHIFT = 0x99,
+
+        OP_BOOLAND = 0x9a,
+        OP_BOOLOR = 0x9b,
+        OP_NUMEQUAL = 0x9c,
+        OP_NUMEQUALVERIFY = 0x9d,
+        OP_NUMNOTEQUAL = 0x9e,
+        OP_LESSTHAN = 0x9f,
+        OP_GREATERTHAN = 0xa0,
+        OP_LESSTHANOREQUAL = 0xa1,
+        OP_GREATERTHANOREQUAL = 0xa2,
+        OP_MIN = 0xa3,
+        OP_MAX = 0xa4,
+
+        OP_WITHIN = 0xa5,
+
+        // crypto
+        OP_RIPEMD160 = 0xa6,
+        OP_SHA1 = 0xa7,
+        OP_SHA256 = 0xa8,
+        OP_HASH160 = 0xa9,
+        OP_HASH256 = 0xaa,
+        OP_CODESEPARATOR = 0xab,
+        OP_CHECKSIG = 0xac,
+        OP_CHECKSIGVERIFY = 0xad,
+        OP_CHECKMULTISIG = 0xae,
+        OP_CHECKMULTISIGVERIFY = 0xaf,
+
+        // expansion
+        OP_NOP1 = 0xb0,
+        OP_NOP2 = 0xb1,
+        OP_NOP3 = 0xb2,
+        OP_NOP4 = 0xb3,
+        OP_NOP5 = 0xb4,
+        OP_NOP6 = 0xb5,
+        OP_NOP7 = 0xb6,
+        OP_NOP8 = 0xb7,
+        OP_NOP9 = 0xb8,
+        OP_NOP10 = 0xb9,
+
+        // template matching params
+        OP_SMALLDATA = 0xf9,
+        OP_SMALLINTEGER = 0xfa,
+        OP_PUBKEYS = 0xfb,
+        OP_PUBKEYHASH = 0xfd,
+        OP_PUBKEY = 0xfe,
+
+        OP_INVALIDOPCODE = 0xff,
+    };
+
+    public static class ScriptOpcode
+    {
+        
+        /// <summary>
+        /// Get the name of supplied opcode
+        /// </summary>
+        /// <param name="opcode">Opcode</param>
+        /// <returns>Opcode name</returns>
+        public static string GetOpName(opcodetype opcode)
+        {
+            switch (opcode)
+            {
+                // push value
+                case opcodetype.OP_0:
+                    return "0";
+                case opcodetype.OP_PUSHDATA1:
+                    return "OP_PUSHDATA1";
+                case opcodetype.OP_PUSHDATA2:
+                    return "OP_PUSHDATA2";
+                case opcodetype.OP_PUSHDATA4:
+                    return "OP_PUSHDATA4";
+                case opcodetype.OP_1NEGATE:
+                    return "-1";
+                case opcodetype.OP_RESERVED:
+                    return "OP_RESERVED";
+                case opcodetype.OP_1:
+                    return "1";
+                case opcodetype.OP_2:
+                    return "2";
+                case opcodetype.OP_3:
+                    return "3";
+                case opcodetype.OP_4:
+                    return "4";
+                case opcodetype.OP_5:
+                    return "5";
+                case opcodetype.OP_6:
+                    return "6";
+                case opcodetype.OP_7:
+                    return "7";
+                case opcodetype.OP_8:
+                    return "8";
+                case opcodetype.OP_9:
+                    return "9";
+                case opcodetype.OP_10:
+                    return "10";
+                case opcodetype.OP_11:
+                    return "11";
+                case opcodetype.OP_12:
+                    return "12";
+                case opcodetype.OP_13:
+                    return "13";
+                case opcodetype.OP_14:
+                    return "14";
+                case opcodetype.OP_15:
+                    return "15";
+                case opcodetype.OP_16:
+                    return "16";
+
+                // control
+                case opcodetype.OP_NOP:
+                    return "OP_NOP";
+                case opcodetype.OP_VER:
+                    return "OP_VER";
+                case opcodetype.OP_IF:
+                    return "OP_IF";
+                case opcodetype.OP_NOTIF:
+                    return "OP_NOTIF";
+                case opcodetype.OP_VERIF:
+                    return "OP_VERIF";
+                case opcodetype.OP_VERNOTIF:
+                    return "OP_VERNOTIF";
+                case opcodetype.OP_ELSE:
+                    return "OP_ELSE";
+                case opcodetype.OP_ENDIF:
+                    return "OP_ENDIF";
+                case opcodetype.OP_VERIFY:
+                    return "OP_VERIFY";
+                case opcodetype.OP_RETURN:
+                    return "OP_RETURN";
+
+                // stack ops
+                case opcodetype.OP_TOALTSTACK:
+                    return "OP_TOALTSTACK";
+                case opcodetype.OP_FROMALTSTACK:
+                    return "OP_FROMALTSTACK";
+                case opcodetype.OP_2DROP:
+                    return "OP_2DROP";
+                case opcodetype.OP_2DUP:
+                    return "OP_2DUP";
+                case opcodetype.OP_3DUP:
+                    return "OP_3DUP";
+                case opcodetype.OP_2OVER:
+                    return "OP_2OVER";
+                case opcodetype.OP_2ROT:
+                    return "OP_2ROT";
+                case opcodetype.OP_2SWAP:
+                    return "OP_2SWAP";
+                case opcodetype.OP_IFDUP:
+                    return "OP_IFDUP";
+                case opcodetype.OP_DEPTH:
+                    return "OP_DEPTH";
+                case opcodetype.OP_DROP:
+                    return "OP_DROP";
+                case opcodetype.OP_DUP:
+                    return "OP_DUP";
+                case opcodetype.OP_NIP:
+                    return "OP_NIP";
+                case opcodetype.OP_OVER:
+                    return "OP_OVER";
+                case opcodetype.OP_PICK:
+                    return "OP_PICK";
+                case opcodetype.OP_ROLL:
+                    return "OP_ROLL";
+                case opcodetype.OP_ROT:
+                    return "OP_ROT";
+                case opcodetype.OP_SWAP:
+                    return "OP_SWAP";
+                case opcodetype.OP_TUCK:
+                    return "OP_TUCK";
+
+                // splice ops
+                case opcodetype.OP_CAT:
+                    return "OP_CAT";
+                case opcodetype.OP_SUBSTR:
+                    return "OP_SUBSTR";
+                case opcodetype.OP_LEFT:
+                    return "OP_LEFT";
+                case opcodetype.OP_RIGHT:
+                    return "OP_RIGHT";
+                case opcodetype.OP_SIZE:
+                    return "OP_SIZE";
+
+                // bit logic
+                case opcodetype.OP_INVERT:
+                    return "OP_INVERT";
+                case opcodetype.OP_AND:
+                    return "OP_AND";
+                case opcodetype.OP_OR:
+                    return "OP_OR";
+                case opcodetype.OP_XOR:
+                    return "OP_XOR";
+                case opcodetype.OP_EQUAL:
+                    return "OP_EQUAL";
+                case opcodetype.OP_EQUALVERIFY:
+                    return "OP_EQUALVERIFY";
+                case opcodetype.OP_RESERVED1:
+                    return "OP_RESERVED1";
+                case opcodetype.OP_RESERVED2:
+                    return "OP_RESERVED2";
+
+                // numeric
+                case opcodetype.OP_1ADD:
+                    return "OP_1ADD";
+                case opcodetype.OP_1SUB:
+                    return "OP_1SUB";
+                case opcodetype.OP_2MUL:
+                    return "OP_2MUL";
+                case opcodetype.OP_2DIV:
+                    return "OP_2DIV";
+                case opcodetype.OP_NEGATE:
+                    return "OP_NEGATE";
+                case opcodetype.OP_ABS:
+                    return "OP_ABS";
+                case opcodetype.OP_NOT:
+                    return "OP_NOT";
+                case opcodetype.OP_0NOTEQUAL:
+                    return "OP_0NOTEQUAL";
+                case opcodetype.OP_ADD:
+                    return "OP_ADD";
+                case opcodetype.OP_SUB:
+                    return "OP_SUB";
+                case opcodetype.OP_MUL:
+                    return "OP_MUL";
+                case opcodetype.OP_DIV:
+                    return "OP_DIV";
+                case opcodetype.OP_MOD:
+                    return "OP_MOD";
+                case opcodetype.OP_LSHIFT:
+                    return "OP_LSHIFT";
+                case opcodetype.OP_RSHIFT:
+                    return "OP_RSHIFT";
+                case opcodetype.OP_BOOLAND:
+                    return "OP_BOOLAND";
+                case opcodetype.OP_BOOLOR:
+                    return "OP_BOOLOR";
+                case opcodetype.OP_NUMEQUAL:
+                    return "OP_NUMEQUAL";
+                case opcodetype.OP_NUMEQUALVERIFY:
+                    return "OP_NUMEQUALVERIFY";
+                case opcodetype.OP_NUMNOTEQUAL:
+                    return "OP_NUMNOTEQUAL";
+                case opcodetype.OP_LESSTHAN:
+                    return "OP_LESSTHAN";
+                case opcodetype.OP_GREATERTHAN:
+                    return "OP_GREATERTHAN";
+                case opcodetype.OP_LESSTHANOREQUAL:
+                    return "OP_LESSTHANOREQUAL";
+                case opcodetype.OP_GREATERTHANOREQUAL:
+                    return "OP_GREATERTHANOREQUAL";
+                case opcodetype.OP_MIN:
+                    return "OP_MIN";
+                case opcodetype.OP_MAX:
+                    return "OP_MAX";
+                case opcodetype.OP_WITHIN:
+                    return "OP_WITHIN";
+
+                // crypto
+                case opcodetype.OP_RIPEMD160:
+                    return "OP_RIPEMD160";
+                case opcodetype.OP_SHA1:
+                    return "OP_SHA1";
+                case opcodetype.OP_SHA256:
+                    return "OP_SHA256";
+                case opcodetype.OP_HASH160:
+                    return "OP_HASH160";
+                case opcodetype.OP_HASH256:
+                    return "OP_HASH256";
+                case opcodetype.OP_CODESEPARATOR:
+                    return "OP_CODESEPARATOR";
+                case opcodetype.OP_CHECKSIG:
+                    return "OP_CHECKSIG";
+                case opcodetype.OP_CHECKSIGVERIFY:
+                    return "OP_CHECKSIGVERIFY";
+                case opcodetype.OP_CHECKMULTISIG:
+                    return "OP_CHECKMULTISIG";
+                case opcodetype.OP_CHECKMULTISIGVERIFY:
+                    return "OP_CHECKMULTISIGVERIFY";
+
+                // expanson
+                case opcodetype.OP_NOP1:
+                    return "OP_NOP1";
+                case opcodetype.OP_NOP2:
+                    return "OP_NOP2";
+                case opcodetype.OP_NOP3:
+                    return "OP_NOP3";
+                case opcodetype.OP_NOP4:
+                    return "OP_NOP4";
+                case opcodetype.OP_NOP5:
+                    return "OP_NOP5";
+                case opcodetype.OP_NOP6:
+                    return "OP_NOP6";
+                case opcodetype.OP_NOP7:
+                    return "OP_NOP7";
+                case opcodetype.OP_NOP8:
+                    return "OP_NOP8";
+                case opcodetype.OP_NOP9:
+                    return "OP_NOP9";
+                case opcodetype.OP_NOP10:
+                    return "OP_NOP10";
+
+                // template matching params
+                case opcodetype.OP_PUBKEYHASH:
+                    return "OP_PUBKEYHASH";
+                case opcodetype.OP_PUBKEY:
+                    return "OP_PUBKEY";
+                case opcodetype.OP_SMALLDATA:
+                    return "OP_SMALLDATA";
+
+                case opcodetype.OP_INVALIDOPCODE:
+                    return "OP_INVALIDOPCODE";
+                default:
+                    return "OP_UNKNOWN";
+            }
+        }
+
+        /// <summary>
+        /// Get next opcode from passed enumerator and extract push arguments if there are some.
+        /// </summary>
+        /// <param name="codeBytes">Enumerator reference.</param>
+        /// <param name="opcodeRet">Opcode reference.</param>
+        /// <param name="bytesRet">Bytes array 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)
+        {
+            bytesRet = new List<byte>();
+            opcodeRet = opcodetype.OP_INVALIDOPCODE;
+
+            // Read instruction
+            if (!codeBytes.MoveNext())
+                return false;
+            opcodetype opcode = (opcodetype)codeBytes.Current;
+
+            // Immediate operand
+            if (opcode <= opcodetype.OP_PUSHDATA4)
+            {
+                int nSize = 0;
+                List<byte> szList = new List<byte>();
+
+                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)
+                {
+                    // 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 (!codeBytes.MoveNext())
+                            return false;
+                        szList.Add(codeBytes.Current);
+                    }
+                }
+                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++)
+                    {
+                        if (!codeBytes.MoveNext())
+                            return false;
+                        szList.Add(codeBytes.Current);
+                    }
+                }
+
+                // 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++)
+                {
+                    if (!codeBytes.MoveNext())
+                        return false;
+
+                    bytesRet.Add(codeBytes.Current);
+                }
+            }
+
+            opcodeRet = opcode;
+
+            return true;
+        }
+
+        /// <summary>
+        /// Convert value bytes into readable representation.
+        /// </summary>
+        /// <param name="bytesList">List of value bytes.</param>
+        /// <returns>Formatted value.</returns>
+        public static string ValueString(List<byte> bytesList)
+        {
+            StringBuilder sb = new StringBuilder();
+            byte[] valueBytes = bytesList.ToArray();
+
+            if (bytesList.Count <= 4){
+                Array.Reverse(valueBytes);
+                sb.Append(BitConverter.ToInt32(valueBytes, 0));
+            }
+            else 
+            {
+                foreach (byte b in bytesList)
+                {
+                    sb.AppendFormat("{0:x2}", b);
+                }
+            }
+
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// Convert list of stack items into human readable representation.
+        /// </summary>
+        /// <param name="stackList">List of stack items.</param>
+        /// <returns>Formatted value.</returns>
+        public static string StackString(List<List<byte>> stackList)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach(List<byte> bytesList in stackList)
+            {
+                sb.Append(ValueString(bytesList));
+            }
+
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// Decode small integer
+        /// </summary>
+        /// <param name="opcode">Small integer opcode (OP_0 - OP_16)</param>
+        /// <returns>Small integer</returns>
+        static int DecodeOP_N(opcodetype opcode)
+        {
+            if (opcode == opcodetype.OP_0)
+                return 0;
+
+            // Only OP_n opcodes are supported, throw exception otherwise.
+            if (opcode < opcodetype.OP_1 || opcode > opcodetype.OP_16)
+                throw new Exception("Invalid small integer opcode.");
+            return (int)opcode - (int)(opcodetype.OP_1 - 1);
+        }
+
+        /// <summary>
+        /// Converts small integer into opcode
+        /// </summary>
+        /// <param name="n">Small integer from the range of 0 up to 16.</param>
+        /// <returns>Corresponding opcode.</returns>
+        static opcodetype EncodeOP_N(int n)
+        {
+            // The n value must be in the range of 0 to 16.
+            if (n < 0 || n > 16)
+                throw new Exception("Invalid small integer value.");
+            if (n == 0)
+                return opcodetype.OP_0;
+            return (opcodetype)(opcodetype.OP_1 + n - 1);
+        }
+
+
+    };
+}