GetOpcode implementation
[NovacoinLibrary.git] / Novacoin / CScript.cs
1 \feffusing System;
2 using System.Text;
3
4 using System.Collections;
5 using System.Collections.Generic;
6
7 namespace Novacoin
8 {
9         /** Script opcodes */
10         public enum opcodetype
11         {
12                 // push value
13                 OP_0 = 0x00,
14                 OP_FALSE = OP_0,
15                 OP_PUSHDATA1 = 0x4c,
16                 OP_PUSHDATA2 = 0x4d,
17                 OP_PUSHDATA4 = 0x4e,
18                 OP_1NEGATE = 0x4f,
19                 OP_RESERVED = 0x50,
20                 OP_1 = 0x51,
21                 OP_TRUE=OP_1,
22                 OP_2 = 0x52,
23                 OP_3 = 0x53,
24                 OP_4 = 0x54,
25                 OP_5 = 0x55,
26                 OP_6 = 0x56,
27                 OP_7 = 0x57,
28                 OP_8 = 0x58,
29                 OP_9 = 0x59,
30                 OP_10 = 0x5a,
31                 OP_11 = 0x5b,
32                 OP_12 = 0x5c,
33                 OP_13 = 0x5d,
34                 OP_14 = 0x5e,
35                 OP_15 = 0x5f,
36                 OP_16 = 0x60,
37
38                 // control
39                 OP_NOP = 0x61,
40                 OP_VER = 0x62,
41                 OP_IF = 0x63,
42                 OP_NOTIF = 0x64,
43                 OP_VERIF = 0x65,
44                 OP_VERNOTIF = 0x66,
45                 OP_ELSE = 0x67,
46                 OP_ENDIF = 0x68,
47                 OP_VERIFY = 0x69,
48                 OP_RETURN = 0x6a,
49
50                 // stack ops
51                 OP_TOALTSTACK = 0x6b,
52                 OP_FROMALTSTACK = 0x6c,
53                 OP_2DROP = 0x6d,
54                 OP_2DUP = 0x6e,
55                 OP_3DUP = 0x6f,
56                 OP_2OVER = 0x70,
57                 OP_2ROT = 0x71,
58                 OP_2SWAP = 0x72,
59                 OP_IFDUP = 0x73,
60                 OP_DEPTH = 0x74,
61                 OP_DROP = 0x75,
62                 OP_DUP = 0x76,
63                 OP_NIP = 0x77,
64                 OP_OVER = 0x78,
65                 OP_PICK = 0x79,
66                 OP_ROLL = 0x7a,
67                 OP_ROT = 0x7b,
68                 OP_SWAP = 0x7c,
69                 OP_TUCK = 0x7d,
70
71                 // splice ops
72                 OP_CAT = 0x7e,
73                 OP_SUBSTR = 0x7f,
74                 OP_LEFT = 0x80,
75                 OP_RIGHT = 0x81,
76                 OP_SIZE = 0x82,
77
78                 // bit logic
79                 OP_INVERT = 0x83,
80                 OP_AND = 0x84,
81                 OP_OR = 0x85,
82                 OP_XOR = 0x86,
83                 OP_EQUAL = 0x87,
84                 OP_EQUALVERIFY = 0x88,
85                 OP_RESERVED1 = 0x89,
86                 OP_RESERVED2 = 0x8a,
87
88                 // numeric
89                 OP_1ADD = 0x8b,
90                 OP_1SUB = 0x8c,
91                 OP_2MUL = 0x8d,
92                 OP_2DIV = 0x8e,
93                 OP_NEGATE = 0x8f,
94                 OP_ABS = 0x90,
95                 OP_NOT = 0x91,
96                 OP_0NOTEQUAL = 0x92,
97
98                 OP_ADD = 0x93,
99                 OP_SUB = 0x94,
100                 OP_MUL = 0x95,
101                 OP_DIV = 0x96,
102                 OP_MOD = 0x97,
103                 OP_LSHIFT = 0x98,
104                 OP_RSHIFT = 0x99,
105
106                 OP_BOOLAND = 0x9a,
107                 OP_BOOLOR = 0x9b,
108                 OP_NUMEQUAL = 0x9c,
109                 OP_NUMEQUALVERIFY = 0x9d,
110                 OP_NUMNOTEQUAL = 0x9e,
111                 OP_LESSTHAN = 0x9f,
112                 OP_GREATERTHAN = 0xa0,
113                 OP_LESSTHANOREQUAL = 0xa1,
114                 OP_GREATERTHANOREQUAL = 0xa2,
115                 OP_MIN = 0xa3,
116                 OP_MAX = 0xa4,
117
118                 OP_WITHIN = 0xa5,
119
120                 // crypto
121                 OP_RIPEMD160 = 0xa6,
122                 OP_SHA1 = 0xa7,
123                 OP_SHA256 = 0xa8,
124                 OP_HASH160 = 0xa9,
125                 OP_HASH256 = 0xaa,
126                 OP_CODESEPARATOR = 0xab,
127                 OP_CHECKSIG = 0xac,
128                 OP_CHECKSIGVERIFY = 0xad,
129                 OP_CHECKMULTISIG = 0xae,
130                 OP_CHECKMULTISIGVERIFY = 0xaf,
131
132                 // expansion
133                 OP_NOP1 = 0xb0,
134                 OP_NOP2 = 0xb1,
135                 OP_NOP3 = 0xb2,
136                 OP_NOP4 = 0xb3,
137                 OP_NOP5 = 0xb4,
138                 OP_NOP6 = 0xb5,
139                 OP_NOP7 = 0xb6,
140                 OP_NOP8 = 0xb7,
141                 OP_NOP9 = 0xb8,
142                 OP_NOP10 = 0xb9,
143
144                 // template matching params
145                 OP_SMALLDATA = 0xf9,
146                 OP_SMALLINTEGER = 0xfa,
147                 OP_PUBKEYS = 0xfb,
148                 OP_PUBKEYHASH = 0xfd,
149                 OP_PUBKEY = 0xfe,
150
151                 OP_INVALIDOPCODE = 0xff,
152         };
153
154         public class CScript
155         {
156                 private byte[] scriptCode = {};
157
158                 public CScript ()
159                 {
160                 }
161
162                 private string GetOpName(opcodetype opcode)
163                 {
164                         switch (opcode) {
165                         // push value
166                         case opcodetype.OP_0:
167                                 return "0";
168                         case opcodetype.OP_PUSHDATA1:
169                                 return "OP_PUSHDATA1";
170                         case opcodetype.OP_PUSHDATA2:
171                                 return "OP_PUSHDATA2";
172                         case opcodetype.OP_PUSHDATA4:
173                                 return "OP_PUSHDATA4";
174                         case opcodetype.OP_1NEGATE:
175                                 return "-1";
176                         case opcodetype.OP_RESERVED:
177                                 return "OP_RESERVED";
178                         case opcodetype.OP_1:
179                                 return "1";
180                         case opcodetype.OP_2:
181                                 return "2";
182                         case opcodetype.OP_3:
183                                 return "3";
184                         case opcodetype.OP_4:
185                                 return "4";
186                         case opcodetype.OP_5:
187                                 return "5";
188                         case opcodetype.OP_6:
189                                 return "6";
190                         case opcodetype.OP_7:
191                                 return "7";
192                         case opcodetype.OP_8:
193                                 return "8";
194                         case opcodetype.OP_9:
195                                 return "9";
196                         case opcodetype.OP_10:
197                                 return "10";
198                         case opcodetype.OP_11:
199                                 return "11";
200                         case opcodetype.OP_12:
201                                 return "12";
202                         case opcodetype.OP_13:
203                                 return "13";
204                         case opcodetype.OP_14:
205                                 return "14";
206                         case opcodetype.OP_15:
207                                 return "15";
208                         case opcodetype.OP_16:
209                                 return "16";
210
211                         // control
212                         case opcodetype.OP_NOP:
213                                 return "OP_NOP";
214                         case opcodetype.OP_VER:
215                                 return "OP_VER";
216                         case opcodetype.OP_IF:
217                                 return "OP_IF";
218                         case opcodetype.OP_NOTIF:
219                                 return "OP_NOTIF";
220                         case opcodetype.OP_VERIF:
221                                 return "OP_VERIF";
222                         case opcodetype.OP_VERNOTIF:
223                                 return "OP_VERNOTIF";
224                         case opcodetype.OP_ELSE:
225                                 return "OP_ELSE";
226                         case opcodetype.OP_ENDIF:
227                                 return "OP_ENDIF";
228                         case opcodetype.OP_VERIFY:
229                                 return "OP_VERIFY";
230                         case opcodetype.OP_RETURN:
231                                 return "OP_RETURN";
232
233                         // stack ops
234                         case opcodetype.OP_TOALTSTACK:
235                                 return "OP_TOALTSTACK";
236                         case opcodetype.OP_FROMALTSTACK:
237                                 return "OP_FROMALTSTACK";
238                         case opcodetype.OP_2DROP:
239                                 return "OP_2DROP";
240                         case opcodetype.OP_2DUP:
241                                 return "OP_2DUP";
242                         case opcodetype.OP_3DUP:
243                                 return "OP_3DUP";
244                         case opcodetype.OP_2OVER:
245                                 return "OP_2OVER";
246                         case opcodetype.OP_2ROT:
247                                 return "OP_2ROT";
248                         case opcodetype.OP_2SWAP:
249                                 return "OP_2SWAP";
250                         case opcodetype.OP_IFDUP:
251                                 return "OP_IFDUP";
252                         case opcodetype.OP_DEPTH:
253                                 return "OP_DEPTH";
254                         case opcodetype.OP_DROP:
255                                 return "OP_DROP";
256                         case opcodetype.OP_DUP:
257                                 return "OP_DUP";
258                         case opcodetype.OP_NIP:
259                                 return "OP_NIP";
260                         case opcodetype.OP_OVER:
261                                 return "OP_OVER";
262                         case opcodetype.OP_PICK:
263                                 return "OP_PICK";
264                         case opcodetype.OP_ROLL:
265                                 return "OP_ROLL";
266                         case opcodetype.OP_ROT:
267                                 return "OP_ROT";
268                         case opcodetype.OP_SWAP:
269                                 return "OP_SWAP";
270                         case opcodetype.OP_TUCK:
271                                 return "OP_TUCK";
272
273                         // splice ops
274                         case opcodetype.OP_CAT:
275                                 return "OP_CAT";
276                         case opcodetype.OP_SUBSTR:
277                                 return "OP_SUBSTR";
278                         case opcodetype.OP_LEFT:
279                                 return "OP_LEFT";
280                         case opcodetype.OP_RIGHT:
281                                 return "OP_RIGHT";
282                         case opcodetype.OP_SIZE:
283                                 return "OP_SIZE";
284
285                         // bit logic
286                         case opcodetype.OP_INVERT:
287                                 return "OP_INVERT";
288                         case opcodetype.OP_AND:
289                                 return "OP_AND";
290                         case opcodetype.OP_OR:
291                                 return "OP_OR";
292                         case opcodetype.OP_XOR:
293                                 return "OP_XOR";
294                         case opcodetype.OP_EQUAL:
295                                 return "OP_EQUAL";
296                         case opcodetype.OP_EQUALVERIFY:
297                                 return "OP_EQUALVERIFY";
298                         case opcodetype.OP_RESERVED1:
299                                 return "OP_RESERVED1";
300                         case opcodetype.OP_RESERVED2:
301                                 return "OP_RESERVED2";
302
303                         // numeric
304                         case opcodetype.OP_1ADD:
305                                 return "OP_1ADD";
306                         case opcodetype.OP_1SUB:
307                                 return "OP_1SUB";
308                         case opcodetype.OP_2MUL:
309                                 return "OP_2MUL";
310                         case opcodetype.OP_2DIV:
311                                 return "OP_2DIV";
312                         case opcodetype.OP_NEGATE:
313                                 return "OP_NEGATE";
314                         case opcodetype.OP_ABS:
315                                 return "OP_ABS";
316                         case opcodetype.OP_NOT:
317                                 return "OP_NOT";
318                         case opcodetype.OP_0NOTEQUAL:
319                                 return "OP_0NOTEQUAL";
320                         case opcodetype.OP_ADD:
321                                 return "OP_ADD";
322                         case opcodetype.OP_SUB:
323                                 return "OP_SUB";
324                         case opcodetype.OP_MUL:
325                                 return "OP_MUL";
326                         case opcodetype.OP_DIV:
327                                 return "OP_DIV";
328                         case opcodetype.OP_MOD:
329                                 return "OP_MOD";
330                         case opcodetype.OP_LSHIFT:
331                                 return "OP_LSHIFT";
332                         case opcodetype.OP_RSHIFT:
333                                 return "OP_RSHIFT";
334                         case opcodetype.OP_BOOLAND:
335                                 return "OP_BOOLAND";
336                         case opcodetype.OP_BOOLOR:
337                                 return "OP_BOOLOR";
338                         case opcodetype.OP_NUMEQUAL:
339                                 return "OP_NUMEQUAL";
340                         case opcodetype.OP_NUMEQUALVERIFY:
341                                 return "OP_NUMEQUALVERIFY";
342                         case opcodetype.OP_NUMNOTEQUAL:
343                                 return "OP_NUMNOTEQUAL";
344                         case opcodetype.OP_LESSTHAN:
345                                 return "OP_LESSTHAN";
346                         case opcodetype.OP_GREATERTHAN:
347                                 return "OP_GREATERTHAN";
348                         case opcodetype.OP_LESSTHANOREQUAL:
349                                 return "OP_LESSTHANOREQUAL";
350                         case opcodetype.OP_GREATERTHANOREQUAL:
351                                 return "OP_GREATERTHANOREQUAL";
352                         case opcodetype.OP_MIN:
353                                 return "OP_MIN";
354                         case opcodetype.OP_MAX:
355                                 return "OP_MAX";
356                         case opcodetype.OP_WITHIN:
357                                 return "OP_WITHIN";
358
359                         // crypto
360                         case opcodetype.OP_RIPEMD160:
361                                 return "OP_RIPEMD160";
362                         case opcodetype.OP_SHA1:
363                                 return "OP_SHA1";
364                         case opcodetype.OP_SHA256:
365                                 return "OP_SHA256";
366                         case opcodetype.OP_HASH160:
367                                 return "OP_HASH160";
368                         case opcodetype.OP_HASH256:
369                                 return "OP_HASH256";
370                         case opcodetype.OP_CODESEPARATOR:
371                                 return "OP_CODESEPARATOR";
372                         case opcodetype.OP_CHECKSIG:
373                                 return "OP_CHECKSIG";
374                         case opcodetype.OP_CHECKSIGVERIFY:
375                                 return "OP_CHECKSIGVERIFY";
376                         case opcodetype.OP_CHECKMULTISIG:
377                                 return "OP_CHECKMULTISIG";
378                         case opcodetype.OP_CHECKMULTISIGVERIFY:
379                                 return "OP_CHECKMULTISIGVERIFY";
380
381                         // expanson
382                         case opcodetype.OP_NOP1:
383                                 return "OP_NOP1";
384                         case opcodetype.OP_NOP2:
385                                 return "OP_NOP2";
386                         case opcodetype.OP_NOP3:
387                                 return "OP_NOP3";
388                         case opcodetype.OP_NOP4:
389                                 return "OP_NOP4";
390                         case opcodetype.OP_NOP5:
391                                 return "OP_NOP5";
392                         case opcodetype.OP_NOP6:
393                                 return "OP_NOP6";
394                         case opcodetype.OP_NOP7:
395                                 return "OP_NOP7";
396                         case opcodetype.OP_NOP8:
397                                 return "OP_NOP8";
398                         case opcodetype.OP_NOP9:
399                                 return "OP_NOP9";
400                         case opcodetype.OP_NOP10:
401                                 return "OP_NOP10";
402
403                         // template matching params
404                         case opcodetype.OP_PUBKEYHASH:
405                                 return "OP_PUBKEYHASH";
406                         case opcodetype.OP_PUBKEY:
407                                 return "OP_PUBKEY";
408                         case opcodetype.OP_SMALLDATA:
409                                 return "OP_SMALLDATA";
410
411                         case opcodetype.OP_INVALIDOPCODE:
412                                 return "OP_INVALIDOPCODE";
413                         default:
414                                 return "OP_UNKNOWN";
415                         }
416                 }
417
418                 public bool GetOp(ref IEnumerator<byte> codeBytes, ref opcodetype opcodeRet, ref byte[] bytesRet)
419                 {
420                         opcodeRet = opcodetype.OP_INVALIDOPCODE;
421
422                         // Initialize local byte list
423                         List<byte> bytesRetIn = new List<byte> ();
424
425                         // Read instruction
426                         if (!codeBytes.MoveNext())
427                                 return false;
428                         opcodetype opcode = (opcodetype)codeBytes.Current;
429
430                         // Immediate operand
431                         if (opcode <= opcodetype.OP_PUSHDATA4)
432                         {
433                                 int nSize = 0;
434                                 if (opcode < opcodetype.OP_PUSHDATA1) { // False values
435                                         nSize = (int)opcode;
436                                 } else if (opcode == opcodetype.OP_PUSHDATA1) { // One byte size prefix
437                                         if (!codeBytes.MoveNext ())
438                                                 return false;
439                                         nSize = codeBytes.Current;
440                                 } else if (opcode == opcodetype.OP_PUSHDATA2) { // Two bytes size prefix
441                                         byte[] SizeBytes = {0,0};
442
443                                         for (int i = 0; i < 2; i++) { // TODO: implement some intelligent solution instead
444                                                 if (!codeBytes.MoveNext ())
445                                                         return false;
446
447                                                 SizeBytes [i] = codeBytes.Current; 
448                                         }
449
450                                         Array.Reverse (SizeBytes);
451                                         BitConverter.ToUInt32(SizeBytes, 0);
452                                 } else if (opcode == opcodetype.OP_PUSHDATA4) { // Four bytes size prefix
453                                         byte[] SizeBytes = {0,0,0,0};
454
455                                         for (int i = 0; i < 4; i++) {
456                                                 if (!codeBytes.MoveNext ())
457                                                         return false;
458
459                                                 SizeBytes [i] = codeBytes.Current; 
460                                         }
461
462                                         Array.Reverse (SizeBytes);
463                                         nSize = BitConverter.ToInt32 (SizeBytes, 0);
464                                 }
465
466                                 for (int i = 0; i < nSize; i++) {
467                                         if (!codeBytes.MoveNext ())
468                                                 return false;
469
470                                         bytesRetIn.Add (codeBytes.Current);
471                                 }
472
473                                 // Return OP_PUSHDATA arguments
474                                 bytesRet = bytesRetIn.ToArray ();
475                         }
476
477                         opcodeRet = opcode;
478                 
479                         return true;
480                 }
481
482                 // Encode/decode small integers:
483                 static int DecodeOP_N(opcodetype opcode)
484                 {
485                         if (opcode == opcodetype.OP_0)
486                                 return 0;
487                         if(! (opcode >= opcodetype.OP_1 && opcode <= opcodetype.OP_16))
488                                 throw new Exception ("! (opcode >= opcodetype.OP_1 && opcode <= opcodetype.OP_16)");
489                         return (int)opcode - (int)(opcodetype.OP_1 - 1);
490                 }
491                 static opcodetype EncodeOP_N(int n)
492                 {
493                         if (!(n >= 0 && n <= 16))
494                                 throw new Exception ("! (n >= 0 && n <= 16)");
495                         if (n == 0)
496                                 return opcodetype.OP_0;
497                         return (opcodetype)(opcodetype.OP_1+n-1);
498                 }
499
500                 public override string ToString()
501                 {
502                         // TODO: disassembly 
503
504                         StringBuilder sb = new StringBuilder(scriptCode.Length * 2);
505                         foreach (byte b in scriptCode)
506                         {
507                                 sb.AppendFormat ("{0:x2}", b);
508                         }
509                         return sb.ToString();
510                 }
511         }
512 }
513