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