Remove unnecessary usings, rewrite pubkey serialization code
[NovacoinLibrary.git] / Novacoin / ScriptOpcode.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Novacoin
7 {
8     /// <summary>
9     /// Script opcodes
10     /// </summary>
11     public enum opcodetype
12     {
13         // push value
14         OP_0 = 0x00,
15         OP_FALSE = OP_0,
16         OP_PUSHDATA1 = 0x4c,
17         OP_PUSHDATA2 = 0x4d,
18         OP_PUSHDATA4 = 0x4e,
19         OP_1NEGATE = 0x4f,
20         OP_RESERVED = 0x50,
21         OP_1 = 0x51,
22         OP_TRUE = OP_1,
23         OP_2 = 0x52,
24         OP_3 = 0x53,
25         OP_4 = 0x54,
26         OP_5 = 0x55,
27         OP_6 = 0x56,
28         OP_7 = 0x57,
29         OP_8 = 0x58,
30         OP_9 = 0x59,
31         OP_10 = 0x5a,
32         OP_11 = 0x5b,
33         OP_12 = 0x5c,
34         OP_13 = 0x5d,
35         OP_14 = 0x5e,
36         OP_15 = 0x5f,
37         OP_16 = 0x60,
38
39         // control
40         OP_NOP = 0x61,
41         OP_VER = 0x62,
42         OP_IF = 0x63,
43         OP_NOTIF = 0x64,
44         OP_VERIF = 0x65,
45         OP_VERNOTIF = 0x66,
46         OP_ELSE = 0x67,
47         OP_ENDIF = 0x68,
48         OP_VERIFY = 0x69,
49         OP_RETURN = 0x6a,
50
51         // stack ops
52         OP_TOALTSTACK = 0x6b,
53         OP_FROMALTSTACK = 0x6c,
54         OP_2DROP = 0x6d,
55         OP_2DUP = 0x6e,
56         OP_3DUP = 0x6f,
57         OP_2OVER = 0x70,
58         OP_2ROT = 0x71,
59         OP_2SWAP = 0x72,
60         OP_IFDUP = 0x73,
61         OP_DEPTH = 0x74,
62         OP_DROP = 0x75,
63         OP_DUP = 0x76,
64         OP_NIP = 0x77,
65         OP_OVER = 0x78,
66         OP_PICK = 0x79,
67         OP_ROLL = 0x7a,
68         OP_ROT = 0x7b,
69         OP_SWAP = 0x7c,
70         OP_TUCK = 0x7d,
71
72         // splice ops
73         OP_CAT = 0x7e,
74         OP_SUBSTR = 0x7f,
75         OP_LEFT = 0x80,
76         OP_RIGHT = 0x81,
77         OP_SIZE = 0x82,
78
79         // bit logic
80         OP_INVERT = 0x83,
81         OP_AND = 0x84,
82         OP_OR = 0x85,
83         OP_XOR = 0x86,
84         OP_EQUAL = 0x87,
85         OP_EQUALVERIFY = 0x88,
86         OP_RESERVED1 = 0x89,
87         OP_RESERVED2 = 0x8a,
88
89         // numeric
90         OP_1ADD = 0x8b,
91         OP_1SUB = 0x8c,
92         OP_2MUL = 0x8d,
93         OP_2DIV = 0x8e,
94         OP_NEGATE = 0x8f,
95         OP_ABS = 0x90,
96         OP_NOT = 0x91,
97         OP_0NOTEQUAL = 0x92,
98
99         OP_ADD = 0x93,
100         OP_SUB = 0x94,
101         OP_MUL = 0x95,
102         OP_DIV = 0x96,
103         OP_MOD = 0x97,
104         OP_LSHIFT = 0x98,
105         OP_RSHIFT = 0x99,
106
107         OP_BOOLAND = 0x9a,
108         OP_BOOLOR = 0x9b,
109         OP_NUMEQUAL = 0x9c,
110         OP_NUMEQUALVERIFY = 0x9d,
111         OP_NUMNOTEQUAL = 0x9e,
112         OP_LESSTHAN = 0x9f,
113         OP_GREATERTHAN = 0xa0,
114         OP_LESSTHANOREQUAL = 0xa1,
115         OP_GREATERTHANOREQUAL = 0xa2,
116         OP_MIN = 0xa3,
117         OP_MAX = 0xa4,
118
119         OP_WITHIN = 0xa5,
120
121         // crypto
122         OP_RIPEMD160 = 0xa6,
123         OP_SHA1 = 0xa7,
124         OP_SHA256 = 0xa8,
125         OP_HASH160 = 0xa9,
126         OP_HASH256 = 0xaa,
127         OP_CODESEPARATOR = 0xab,
128         OP_CHECKSIG = 0xac,
129         OP_CHECKSIGVERIFY = 0xad,
130         OP_CHECKMULTISIG = 0xae,
131         OP_CHECKMULTISIGVERIFY = 0xaf,
132
133         // expansion
134         OP_NOP1 = 0xb0,
135         OP_NOP2 = 0xb1,
136         OP_NOP3 = 0xb2,
137         OP_NOP4 = 0xb3,
138         OP_NOP5 = 0xb4,
139         OP_NOP6 = 0xb5,
140         OP_NOP7 = 0xb6,
141         OP_NOP8 = 0xb7,
142         OP_NOP9 = 0xb8,
143         OP_NOP10 = 0xb9,
144
145         // template matching params
146         OP_SMALLDATA = 0xf9,
147         OP_SMALLINTEGER = 0xfa,
148         OP_PUBKEYS = 0xfb,
149         OP_PUBKEYHASH = 0xfd,
150         OP_PUBKEY = 0xfe,
151
152         OP_INVALIDOPCODE = 0xff,
153     };
154
155     public static class ScriptOpcode
156     {
157         
158         /// <summary>
159         /// Get the name of supplied opcode
160         /// </summary>
161         /// <param name="opcode">Opcode</param>
162         /// <returns>Opcode name</returns>
163         public static string GetOpName(opcodetype opcode)
164         {
165             switch (opcode)
166             {
167                 // push value
168                 case opcodetype.OP_0:
169                     return "0";
170                 case opcodetype.OP_PUSHDATA1:
171                     return "OP_PUSHDATA1";
172                 case opcodetype.OP_PUSHDATA2:
173                     return "OP_PUSHDATA2";
174                 case opcodetype.OP_PUSHDATA4:
175                     return "OP_PUSHDATA4";
176                 case opcodetype.OP_1NEGATE:
177                     return "-1";
178                 case opcodetype.OP_RESERVED:
179                     return "OP_RESERVED";
180                 case opcodetype.OP_1:
181                     return "1";
182                 case opcodetype.OP_2:
183                     return "2";
184                 case opcodetype.OP_3:
185                     return "3";
186                 case opcodetype.OP_4:
187                     return "4";
188                 case opcodetype.OP_5:
189                     return "5";
190                 case opcodetype.OP_6:
191                     return "6";
192                 case opcodetype.OP_7:
193                     return "7";
194                 case opcodetype.OP_8:
195                     return "8";
196                 case opcodetype.OP_9:
197                     return "9";
198                 case opcodetype.OP_10:
199                     return "10";
200                 case opcodetype.OP_11:
201                     return "11";
202                 case opcodetype.OP_12:
203                     return "12";
204                 case opcodetype.OP_13:
205                     return "13";
206                 case opcodetype.OP_14:
207                     return "14";
208                 case opcodetype.OP_15:
209                     return "15";
210                 case opcodetype.OP_16:
211                     return "16";
212
213                 // control
214                 case opcodetype.OP_NOP:
215                     return "OP_NOP";
216                 case opcodetype.OP_VER:
217                     return "OP_VER";
218                 case opcodetype.OP_IF:
219                     return "OP_IF";
220                 case opcodetype.OP_NOTIF:
221                     return "OP_NOTIF";
222                 case opcodetype.OP_VERIF:
223                     return "OP_VERIF";
224                 case opcodetype.OP_VERNOTIF:
225                     return "OP_VERNOTIF";
226                 case opcodetype.OP_ELSE:
227                     return "OP_ELSE";
228                 case opcodetype.OP_ENDIF:
229                     return "OP_ENDIF";
230                 case opcodetype.OP_VERIFY:
231                     return "OP_VERIFY";
232                 case opcodetype.OP_RETURN:
233                     return "OP_RETURN";
234
235                 // stack ops
236                 case opcodetype.OP_TOALTSTACK:
237                     return "OP_TOALTSTACK";
238                 case opcodetype.OP_FROMALTSTACK:
239                     return "OP_FROMALTSTACK";
240                 case opcodetype.OP_2DROP:
241                     return "OP_2DROP";
242                 case opcodetype.OP_2DUP:
243                     return "OP_2DUP";
244                 case opcodetype.OP_3DUP:
245                     return "OP_3DUP";
246                 case opcodetype.OP_2OVER:
247                     return "OP_2OVER";
248                 case opcodetype.OP_2ROT:
249                     return "OP_2ROT";
250                 case opcodetype.OP_2SWAP:
251                     return "OP_2SWAP";
252                 case opcodetype.OP_IFDUP:
253                     return "OP_IFDUP";
254                 case opcodetype.OP_DEPTH:
255                     return "OP_DEPTH";
256                 case opcodetype.OP_DROP:
257                     return "OP_DROP";
258                 case opcodetype.OP_DUP:
259                     return "OP_DUP";
260                 case opcodetype.OP_NIP:
261                     return "OP_NIP";
262                 case opcodetype.OP_OVER:
263                     return "OP_OVER";
264                 case opcodetype.OP_PICK:
265                     return "OP_PICK";
266                 case opcodetype.OP_ROLL:
267                     return "OP_ROLL";
268                 case opcodetype.OP_ROT:
269                     return "OP_ROT";
270                 case opcodetype.OP_SWAP:
271                     return "OP_SWAP";
272                 case opcodetype.OP_TUCK:
273                     return "OP_TUCK";
274
275                 // splice ops
276                 case opcodetype.OP_CAT:
277                     return "OP_CAT";
278                 case opcodetype.OP_SUBSTR:
279                     return "OP_SUBSTR";
280                 case opcodetype.OP_LEFT:
281                     return "OP_LEFT";
282                 case opcodetype.OP_RIGHT:
283                     return "OP_RIGHT";
284                 case opcodetype.OP_SIZE:
285                     return "OP_SIZE";
286
287                 // bit logic
288                 case opcodetype.OP_INVERT:
289                     return "OP_INVERT";
290                 case opcodetype.OP_AND:
291                     return "OP_AND";
292                 case opcodetype.OP_OR:
293                     return "OP_OR";
294                 case opcodetype.OP_XOR:
295                     return "OP_XOR";
296                 case opcodetype.OP_EQUAL:
297                     return "OP_EQUAL";
298                 case opcodetype.OP_EQUALVERIFY:
299                     return "OP_EQUALVERIFY";
300                 case opcodetype.OP_RESERVED1:
301                     return "OP_RESERVED1";
302                 case opcodetype.OP_RESERVED2:
303                     return "OP_RESERVED2";
304
305                 // numeric
306                 case opcodetype.OP_1ADD:
307                     return "OP_1ADD";
308                 case opcodetype.OP_1SUB:
309                     return "OP_1SUB";
310                 case opcodetype.OP_2MUL:
311                     return "OP_2MUL";
312                 case opcodetype.OP_2DIV:
313                     return "OP_2DIV";
314                 case opcodetype.OP_NEGATE:
315                     return "OP_NEGATE";
316                 case opcodetype.OP_ABS:
317                     return "OP_ABS";
318                 case opcodetype.OP_NOT:
319                     return "OP_NOT";
320                 case opcodetype.OP_0NOTEQUAL:
321                     return "OP_0NOTEQUAL";
322                 case opcodetype.OP_ADD:
323                     return "OP_ADD";
324                 case opcodetype.OP_SUB:
325                     return "OP_SUB";
326                 case opcodetype.OP_MUL:
327                     return "OP_MUL";
328                 case opcodetype.OP_DIV:
329                     return "OP_DIV";
330                 case opcodetype.OP_MOD:
331                     return "OP_MOD";
332                 case opcodetype.OP_LSHIFT:
333                     return "OP_LSHIFT";
334                 case opcodetype.OP_RSHIFT:
335                     return "OP_RSHIFT";
336                 case opcodetype.OP_BOOLAND:
337                     return "OP_BOOLAND";
338                 case opcodetype.OP_BOOLOR:
339                     return "OP_BOOLOR";
340                 case opcodetype.OP_NUMEQUAL:
341                     return "OP_NUMEQUAL";
342                 case opcodetype.OP_NUMEQUALVERIFY:
343                     return "OP_NUMEQUALVERIFY";
344                 case opcodetype.OP_NUMNOTEQUAL:
345                     return "OP_NUMNOTEQUAL";
346                 case opcodetype.OP_LESSTHAN:
347                     return "OP_LESSTHAN";
348                 case opcodetype.OP_GREATERTHAN:
349                     return "OP_GREATERTHAN";
350                 case opcodetype.OP_LESSTHANOREQUAL:
351                     return "OP_LESSTHANOREQUAL";
352                 case opcodetype.OP_GREATERTHANOREQUAL:
353                     return "OP_GREATERTHANOREQUAL";
354                 case opcodetype.OP_MIN:
355                     return "OP_MIN";
356                 case opcodetype.OP_MAX:
357                     return "OP_MAX";
358                 case opcodetype.OP_WITHIN:
359                     return "OP_WITHIN";
360
361                 // crypto
362                 case opcodetype.OP_RIPEMD160:
363                     return "OP_RIPEMD160";
364                 case opcodetype.OP_SHA1:
365                     return "OP_SHA1";
366                 case opcodetype.OP_SHA256:
367                     return "OP_SHA256";
368                 case opcodetype.OP_HASH160:
369                     return "OP_HASH160";
370                 case opcodetype.OP_HASH256:
371                     return "OP_HASH256";
372                 case opcodetype.OP_CODESEPARATOR:
373                     return "OP_CODESEPARATOR";
374                 case opcodetype.OP_CHECKSIG:
375                     return "OP_CHECKSIG";
376                 case opcodetype.OP_CHECKSIGVERIFY:
377                     return "OP_CHECKSIGVERIFY";
378                 case opcodetype.OP_CHECKMULTISIG:
379                     return "OP_CHECKMULTISIG";
380                 case opcodetype.OP_CHECKMULTISIGVERIFY:
381                     return "OP_CHECKMULTISIGVERIFY";
382
383                 // expansion
384                 case opcodetype.OP_NOP1:
385                     return "OP_NOP1";
386                 case opcodetype.OP_NOP2:
387                     return "OP_NOP2";
388                 case opcodetype.OP_NOP3:
389                     return "OP_NOP3";
390                 case opcodetype.OP_NOP4:
391                     return "OP_NOP4";
392                 case opcodetype.OP_NOP5:
393                     return "OP_NOP5";
394                 case opcodetype.OP_NOP6:
395                     return "OP_NOP6";
396                 case opcodetype.OP_NOP7:
397                     return "OP_NOP7";
398                 case opcodetype.OP_NOP8:
399                     return "OP_NOP8";
400                 case opcodetype.OP_NOP9:
401                     return "OP_NOP9";
402                 case opcodetype.OP_NOP10:
403                     return "OP_NOP10";
404
405                 // template matching params
406                 case opcodetype.OP_PUBKEYHASH:
407                     return "OP_PUBKEYHASH";
408                 case opcodetype.OP_PUBKEY:
409                     return "OP_PUBKEY";
410                 case opcodetype.OP_SMALLDATA:
411                     return "OP_SMALLDATA";
412
413                 case opcodetype.OP_INVALIDOPCODE:
414                     return "OP_INVALIDOPCODE";
415                 default:
416                     return "OP_UNKNOWN";
417             }
418         }
419
420         /// <summary>
421         /// Get next opcode from passed list of bytes and extract push arguments if there are some.
422         /// </summary>
423         /// <param name="codeBytes">WrappedList reference.</param>
424         /// <param name="opcodeRet">Found opcode.</param>
425         /// <param name="bytesRet">IEnumerable out param which is used to get the push arguments.</param>
426         /// <returns>Result of operation</returns>
427         public static bool GetOp(ref WrappedList<byte> codeBytes, out opcodetype opcodeRet, out IEnumerable<byte> bytesRet)
428         {
429             bytesRet = new List<byte>();
430             opcodeRet = opcodetype.OP_INVALIDOPCODE;
431
432             opcodetype opcode;
433
434             try
435             {
436                 // Read instruction
437                 opcode = (opcodetype)codeBytes.GetItem();
438             }
439             catch (WrappedListException)
440             {
441                 // No instruction found there
442                 return false;
443             }
444
445             // Immediate operand
446             if (opcode <= opcodetype.OP_PUSHDATA4)
447             {
448                 byte[] szBytes = new byte[4] {0, 0, 0, 0}; // Zero length
449
450                 try
451                 {
452                     if (opcode < opcodetype.OP_PUSHDATA1)
453                     {
454                         // Zero value opcodes (OP_0, OP_FALSE)
455                         szBytes[3] = (byte)opcode;
456                     }
457                     else if (opcode == opcodetype.OP_PUSHDATA1)
458                     {
459                         // The next byte contains the number of bytes to be pushed onto the stack, 
460                         //    i.e. you have something like OP_PUSHDATA1 0x01 [0x5a]
461                         szBytes[3] = (byte) codeBytes.GetItem();
462                     }
463                     else if (opcode == opcodetype.OP_PUSHDATA2)
464                     {
465                         // The next two bytes contain the number of bytes to be pushed onto the stack,
466                         //    i.e. now your operation will seem like this: OP_PUSHDATA2 0x00 0x01 [0x5a]
467                         codeBytes.GetItems(2).CopyTo(szBytes, 2);
468                     }
469                     else if (opcode == opcodetype.OP_PUSHDATA4)
470                     {
471                         // The next four bytes contain the number of bytes to be pushed onto the stack,
472                         //   OP_PUSHDATA4 0x00 0x00 0x00 0x01 [0x5a]
473                         szBytes = codeBytes.GetItems(4);
474                     }
475                 }
476                 catch (WrappedListException)
477                 {
478                     // Unable to read operand length
479                     return false;
480                 }
481
482                 int nSize = (int)Interop.BEBytesToUInt32(szBytes);
483
484                 if (nSize > 0)
485                 {
486                     // If nSize is greater than zero then there is some data available
487                     try
488                     {
489                         // Read found number of bytes into list of OP_PUSHDATAn arguments.
490                         bytesRet = codeBytes.GetEnumerableItems(nSize);
491                     }
492                     catch (WrappedListException)
493                     {
494                         // Unable to read data
495                         return false;
496                     }
497                 }
498             }
499
500             opcodeRet = opcode;
501
502             return true;
503         }
504
505         /// <summary>
506         /// Convert value bytes into readable representation.
507         /// 
508         /// 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.
509         /// </summary>
510         /// <param name="bytes">Collection of value bytes.</param>
511         /// <returns>Formatted value.</returns>
512         public static string ValueString(IEnumerable<byte> bytes)
513         {
514             StringBuilder sb = new StringBuilder();
515
516             if (bytes.Count() <= 4)
517             {
518                 byte[] valueBytes = new byte[4] {0, 0, 0, 0};
519                 bytes.ToArray().CopyTo(valueBytes, valueBytes.Length - bytes.Count());
520
521                 sb.Append(Interop.BEBytesToUInt32(valueBytes));
522             }
523             else
524             {
525                 return Interop.ToHex(bytes);
526             }
527
528             return sb.ToString();
529         }
530
531         /// <summary>
532         /// Convert list of stack items into human readable representation.
533         /// </summary>
534         /// <param name="stackList">List of stack items.</param>
535         /// <returns>Formatted value.</returns>
536         public static string StackString(IList<IList<byte>> stackList)
537         {
538             StringBuilder sb = new StringBuilder();
539             foreach(IList<byte> bytesList in stackList)
540             {
541                 sb.Append(ValueString(bytesList));
542             }
543
544             return sb.ToString();
545         }
546
547         /// <summary>
548         /// Decode small integer
549         /// </summary>
550         /// <param name="opcode">Small integer opcode (OP_0 - OP_16)</param>
551         /// <returns>Small integer</returns>
552         public static int DecodeOP_N(opcodetype opcode)
553         {
554             if (opcode == opcodetype.OP_0)
555                 return 0;
556
557             // Only OP_n opcodes are supported, throw exception otherwise.
558             if (opcode < opcodetype.OP_1 || opcode > opcodetype.OP_16)
559                 throw new Exception("Invalid small integer opcode.");
560             return (int)opcode - (int)(opcodetype.OP_1 - 1);
561         }
562
563         /// <summary>
564         /// Converts small integer into opcode
565         /// </summary>
566         /// <param name="n">Small integer from the range of 0 up to 16.</param>
567         /// <returns>Corresponding opcode.</returns>
568         public static opcodetype EncodeOP_N(int n)
569         {
570             // The n value must be in the range of 0 to 16.
571             if (n < 0 || n > 16)
572                 throw new Exception("Invalid small integer value.");
573             if (n == 0)
574                 return opcodetype.OP_0;
575             return (opcodetype)(opcodetype.OP_1 + n - 1);
576         }
577
578
579     };
580 }