SignatureHash
[NovacoinLibrary.git] / Novacoin / ScriptCode.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     /// <summary>
156     /// Transaction output types.
157     /// </summary>
158     public enum txnouttype
159     {
160         TX_NONSTANDARD,
161
162         // 'standard' transaction types:
163         TX_PUBKEY,
164         TX_PUBKEYHASH,
165         TX_SCRIPTHASH,
166         TX_MULTISIG,
167         TX_NULL_DATA,
168     };
169
170     /// <summary>
171     /// Signature hash types/flags
172     /// </summary>
173     public enum sigflag
174     {
175         SIGHASH_ALL = 1,
176         SIGHASH_NONE = 2,
177         SIGHASH_SINGLE = 3,
178         SIGHASH_ANYONECANPAY = 0x80,
179     };
180
181     public static class ScriptCode
182     {
183
184         /// <summary>
185         /// Get the name of supplied opcode
186         /// </summary>
187         /// <param name="opcode">Opcode</param>
188         /// <returns>Opcode name</returns>
189         public static string GetOpName(opcodetype opcode)
190         {
191             switch (opcode)
192             {
193                 // push value
194                 case opcodetype.OP_0:
195                     return "0";
196                 case opcodetype.OP_PUSHDATA1:
197                     return "OP_PUSHDATA1";
198                 case opcodetype.OP_PUSHDATA2:
199                     return "OP_PUSHDATA2";
200                 case opcodetype.OP_PUSHDATA4:
201                     return "OP_PUSHDATA4";
202                 case opcodetype.OP_1NEGATE:
203                     return "-1";
204                 case opcodetype.OP_RESERVED:
205                     return "OP_RESERVED";
206                 case opcodetype.OP_1:
207                     return "1";
208                 case opcodetype.OP_2:
209                     return "2";
210                 case opcodetype.OP_3:
211                     return "3";
212                 case opcodetype.OP_4:
213                     return "4";
214                 case opcodetype.OP_5:
215                     return "5";
216                 case opcodetype.OP_6:
217                     return "6";
218                 case opcodetype.OP_7:
219                     return "7";
220                 case opcodetype.OP_8:
221                     return "8";
222                 case opcodetype.OP_9:
223                     return "9";
224                 case opcodetype.OP_10:
225                     return "10";
226                 case opcodetype.OP_11:
227                     return "11";
228                 case opcodetype.OP_12:
229                     return "12";
230                 case opcodetype.OP_13:
231                     return "13";
232                 case opcodetype.OP_14:
233                     return "14";
234                 case opcodetype.OP_15:
235                     return "15";
236                 case opcodetype.OP_16:
237                     return "16";
238
239                 // control
240                 case opcodetype.OP_NOP:
241                     return "OP_NOP";
242                 case opcodetype.OP_VER:
243                     return "OP_VER";
244                 case opcodetype.OP_IF:
245                     return "OP_IF";
246                 case opcodetype.OP_NOTIF:
247                     return "OP_NOTIF";
248                 case opcodetype.OP_VERIF:
249                     return "OP_VERIF";
250                 case opcodetype.OP_VERNOTIF:
251                     return "OP_VERNOTIF";
252                 case opcodetype.OP_ELSE:
253                     return "OP_ELSE";
254                 case opcodetype.OP_ENDIF:
255                     return "OP_ENDIF";
256                 case opcodetype.OP_VERIFY:
257                     return "OP_VERIFY";
258                 case opcodetype.OP_RETURN:
259                     return "OP_RETURN";
260
261                 // stack ops
262                 case opcodetype.OP_TOALTSTACK:
263                     return "OP_TOALTSTACK";
264                 case opcodetype.OP_FROMALTSTACK:
265                     return "OP_FROMALTSTACK";
266                 case opcodetype.OP_2DROP:
267                     return "OP_2DROP";
268                 case opcodetype.OP_2DUP:
269                     return "OP_2DUP";
270                 case opcodetype.OP_3DUP:
271                     return "OP_3DUP";
272                 case opcodetype.OP_2OVER:
273                     return "OP_2OVER";
274                 case opcodetype.OP_2ROT:
275                     return "OP_2ROT";
276                 case opcodetype.OP_2SWAP:
277                     return "OP_2SWAP";
278                 case opcodetype.OP_IFDUP:
279                     return "OP_IFDUP";
280                 case opcodetype.OP_DEPTH:
281                     return "OP_DEPTH";
282                 case opcodetype.OP_DROP:
283                     return "OP_DROP";
284                 case opcodetype.OP_DUP:
285                     return "OP_DUP";
286                 case opcodetype.OP_NIP:
287                     return "OP_NIP";
288                 case opcodetype.OP_OVER:
289                     return "OP_OVER";
290                 case opcodetype.OP_PICK:
291                     return "OP_PICK";
292                 case opcodetype.OP_ROLL:
293                     return "OP_ROLL";
294                 case opcodetype.OP_ROT:
295                     return "OP_ROT";
296                 case opcodetype.OP_SWAP:
297                     return "OP_SWAP";
298                 case opcodetype.OP_TUCK:
299                     return "OP_TUCK";
300
301                 // splice ops
302                 case opcodetype.OP_CAT:
303                     return "OP_CAT";
304                 case opcodetype.OP_SUBSTR:
305                     return "OP_SUBSTR";
306                 case opcodetype.OP_LEFT:
307                     return "OP_LEFT";
308                 case opcodetype.OP_RIGHT:
309                     return "OP_RIGHT";
310                 case opcodetype.OP_SIZE:
311                     return "OP_SIZE";
312
313                 // bit logic
314                 case opcodetype.OP_INVERT:
315                     return "OP_INVERT";
316                 case opcodetype.OP_AND:
317                     return "OP_AND";
318                 case opcodetype.OP_OR:
319                     return "OP_OR";
320                 case opcodetype.OP_XOR:
321                     return "OP_XOR";
322                 case opcodetype.OP_EQUAL:
323                     return "OP_EQUAL";
324                 case opcodetype.OP_EQUALVERIFY:
325                     return "OP_EQUALVERIFY";
326                 case opcodetype.OP_RESERVED1:
327                     return "OP_RESERVED1";
328                 case opcodetype.OP_RESERVED2:
329                     return "OP_RESERVED2";
330
331                 // numeric
332                 case opcodetype.OP_1ADD:
333                     return "OP_1ADD";
334                 case opcodetype.OP_1SUB:
335                     return "OP_1SUB";
336                 case opcodetype.OP_2MUL:
337                     return "OP_2MUL";
338                 case opcodetype.OP_2DIV:
339                     return "OP_2DIV";
340                 case opcodetype.OP_NEGATE:
341                     return "OP_NEGATE";
342                 case opcodetype.OP_ABS:
343                     return "OP_ABS";
344                 case opcodetype.OP_NOT:
345                     return "OP_NOT";
346                 case opcodetype.OP_0NOTEQUAL:
347                     return "OP_0NOTEQUAL";
348                 case opcodetype.OP_ADD:
349                     return "OP_ADD";
350                 case opcodetype.OP_SUB:
351                     return "OP_SUB";
352                 case opcodetype.OP_MUL:
353                     return "OP_MUL";
354                 case opcodetype.OP_DIV:
355                     return "OP_DIV";
356                 case opcodetype.OP_MOD:
357                     return "OP_MOD";
358                 case opcodetype.OP_LSHIFT:
359                     return "OP_LSHIFT";
360                 case opcodetype.OP_RSHIFT:
361                     return "OP_RSHIFT";
362                 case opcodetype.OP_BOOLAND:
363                     return "OP_BOOLAND";
364                 case opcodetype.OP_BOOLOR:
365                     return "OP_BOOLOR";
366                 case opcodetype.OP_NUMEQUAL:
367                     return "OP_NUMEQUAL";
368                 case opcodetype.OP_NUMEQUALVERIFY:
369                     return "OP_NUMEQUALVERIFY";
370                 case opcodetype.OP_NUMNOTEQUAL:
371                     return "OP_NUMNOTEQUAL";
372                 case opcodetype.OP_LESSTHAN:
373                     return "OP_LESSTHAN";
374                 case opcodetype.OP_GREATERTHAN:
375                     return "OP_GREATERTHAN";
376                 case opcodetype.OP_LESSTHANOREQUAL:
377                     return "OP_LESSTHANOREQUAL";
378                 case opcodetype.OP_GREATERTHANOREQUAL:
379                     return "OP_GREATERTHANOREQUAL";
380                 case opcodetype.OP_MIN:
381                     return "OP_MIN";
382                 case opcodetype.OP_MAX:
383                     return "OP_MAX";
384                 case opcodetype.OP_WITHIN:
385                     return "OP_WITHIN";
386
387                 // crypto
388                 case opcodetype.OP_RIPEMD160:
389                     return "OP_RIPEMD160";
390                 case opcodetype.OP_SHA1:
391                     return "OP_SHA1";
392                 case opcodetype.OP_SHA256:
393                     return "OP_SHA256";
394                 case opcodetype.OP_HASH160:
395                     return "OP_HASH160";
396                 case opcodetype.OP_HASH256:
397                     return "OP_HASH256";
398                 case opcodetype.OP_CODESEPARATOR:
399                     return "OP_CODESEPARATOR";
400                 case opcodetype.OP_CHECKSIG:
401                     return "OP_CHECKSIG";
402                 case opcodetype.OP_CHECKSIGVERIFY:
403                     return "OP_CHECKSIGVERIFY";
404                 case opcodetype.OP_CHECKMULTISIG:
405                     return "OP_CHECKMULTISIG";
406                 case opcodetype.OP_CHECKMULTISIGVERIFY:
407                     return "OP_CHECKMULTISIGVERIFY";
408
409                 // expansion
410                 case opcodetype.OP_NOP1:
411                     return "OP_NOP1";
412                 case opcodetype.OP_NOP2:
413                     return "OP_NOP2";
414                 case opcodetype.OP_NOP3:
415                     return "OP_NOP3";
416                 case opcodetype.OP_NOP4:
417                     return "OP_NOP4";
418                 case opcodetype.OP_NOP5:
419                     return "OP_NOP5";
420                 case opcodetype.OP_NOP6:
421                     return "OP_NOP6";
422                 case opcodetype.OP_NOP7:
423                     return "OP_NOP7";
424                 case opcodetype.OP_NOP8:
425                     return "OP_NOP8";
426                 case opcodetype.OP_NOP9:
427                     return "OP_NOP9";
428                 case opcodetype.OP_NOP10:
429                     return "OP_NOP10";
430
431                 // template matching params
432                 case opcodetype.OP_PUBKEYHASH:
433                     return "OP_PUBKEYHASH";
434                 case opcodetype.OP_PUBKEY:
435                     return "OP_PUBKEY";
436                 case opcodetype.OP_SMALLDATA:
437                     return "OP_SMALLDATA";
438
439                 case opcodetype.OP_INVALIDOPCODE:
440                     return "OP_INVALIDOPCODE";
441                 default:
442                     return "OP_UNKNOWN";
443             }
444         }
445
446         /// <summary>
447         /// Get next opcode from passed list of bytes and extract push arguments if there are some.
448         /// </summary>
449         /// <param name="codeBytes">WrappedList reference.</param>
450         /// <param name="opcodeRet">Found opcode.</param>
451         /// <param name="bytesRet">IEnumerable out param which is used to get the push arguments.</param>
452         /// <returns>Result of operation</returns>
453         public static bool GetOp(ref WrappedList<byte> codeBytes, out opcodetype opcodeRet, out IEnumerable<byte> bytesRet)
454         {
455             bytesRet = new List<byte>();
456             opcodeRet = opcodetype.OP_INVALIDOPCODE;
457
458             opcodetype opcode;
459
460             try
461             {
462                 // Read instruction
463                 opcode = (opcodetype)codeBytes.GetItem();
464             }
465             catch (WrappedListException)
466             {
467                 // No instruction found there
468                 return false;
469             }
470
471             // Immediate operand
472             if (opcode <= opcodetype.OP_PUSHDATA4)
473             {
474                 byte[] szBytes = new byte[4] { 0, 0, 0, 0 }; // Zero length
475
476                 try
477                 {
478                     if (opcode < opcodetype.OP_PUSHDATA1)
479                     {
480                         // Zero value opcodes (OP_0, OP_FALSE)
481                         szBytes[3] = (byte)opcode;
482                     }
483                     else if (opcode == opcodetype.OP_PUSHDATA1)
484                     {
485                         // The next byte contains the number of bytes to be pushed onto the stack, 
486                         //    i.e. you have something like OP_PUSHDATA1 0x01 [0x5a]
487                         szBytes[3] = (byte)codeBytes.GetItem();
488                     }
489                     else if (opcode == opcodetype.OP_PUSHDATA2)
490                     {
491                         // The next two bytes contain the number of bytes to be pushed onto the stack,
492                         //    i.e. now your operation will seem like this: OP_PUSHDATA2 0x00 0x01 [0x5a]
493                         codeBytes.GetItems(2).CopyTo(szBytes, 2);
494                     }
495                     else if (opcode == opcodetype.OP_PUSHDATA4)
496                     {
497                         // The next four bytes contain the number of bytes to be pushed onto the stack,
498                         //   OP_PUSHDATA4 0x00 0x00 0x00 0x01 [0x5a]
499                         szBytes = codeBytes.GetItems(4);
500                     }
501                 }
502                 catch (WrappedListException)
503                 {
504                     // Unable to read operand length
505                     return false;
506                 }
507
508                 int nSize = (int)Interop.BEBytesToUInt32(szBytes);
509
510                 if (nSize > 0)
511                 {
512                     // If nSize is greater than zero then there is some data available
513                     try
514                     {
515                         // Read found number of bytes into list of OP_PUSHDATAn arguments.
516                         bytesRet = codeBytes.GetEnumerableItems(nSize);
517                     }
518                     catch (WrappedListException)
519                     {
520                         // Unable to read data
521                         return false;
522                     }
523                 }
524             }
525
526             opcodeRet = opcode;
527
528             return true;
529         }
530
531         /// <summary>
532         /// Convert value bytes into readable representation.
533         /// 
534         /// 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.
535         /// </summary>
536         /// <param name="bytes">Collection of value bytes.</param>
537         /// <returns>Formatted value.</returns>
538         public static string ValueString(IEnumerable<byte> bytes)
539         {
540             StringBuilder sb = new StringBuilder();
541
542             if (bytes.Count() <= 4)
543             {
544                 byte[] valueBytes = new byte[4] { 0, 0, 0, 0 };
545                 bytes.ToArray().CopyTo(valueBytes, valueBytes.Length - bytes.Count());
546
547                 sb.Append(Interop.BEBytesToUInt32(valueBytes));
548             }
549             else
550             {
551                 return Interop.ToHex(bytes);
552             }
553
554             return sb.ToString();
555         }
556
557         /// <summary>
558         /// Convert list of stack items into human readable representation.
559         /// </summary>
560         /// <param name="stackList">List of stack items.</param>
561         /// <returns>Formatted value.</returns>
562         public static string StackString(IList<IList<byte>> stackList)
563         {
564             StringBuilder sb = new StringBuilder();
565             foreach (IList<byte> bytesList in stackList)
566             {
567                 sb.Append(ValueString(bytesList));
568             }
569
570             return sb.ToString();
571         }
572
573         /// <summary>
574         /// Decode small integer
575         /// </summary>
576         /// <param name="opcode">Small integer opcode (OP_0 - OP_16)</param>
577         /// <returns>Small integer</returns>
578         public static int DecodeOP_N(opcodetype opcode)
579         {
580             if (opcode == opcodetype.OP_0)
581                 return 0;
582
583             // Only OP_n opcodes are supported, throw exception otherwise.
584             if (opcode < opcodetype.OP_1 || opcode > opcodetype.OP_16)
585                 throw new Exception("Invalid small integer opcode.");
586             return (int)opcode - (int)(opcodetype.OP_1 - 1);
587         }
588
589         /// <summary>
590         /// Converts small integer into opcode
591         /// </summary>
592         /// <param name="n">Small integer from the range of 0 up to 16.</param>
593         /// <returns>Corresponding opcode.</returns>
594         public static opcodetype EncodeOP_N(int n)
595         {
596             // The n value must be in the range of 0 to 16.
597             if (n < 0 || n > 16)
598                 throw new Exception("Invalid small integer value.");
599             if (n == 0)
600                 return opcodetype.OP_0;
601             return (opcodetype)(opcodetype.OP_1 + n - 1);
602         }
603
604         public static int ScriptSigArgsExpected(txnouttype t, IList<IEnumerable<byte>> solutions)
605         {
606             switch (t)
607             {
608                 case txnouttype.TX_NONSTANDARD:
609                     return -1;
610                 case txnouttype.TX_NULL_DATA:
611                     return 1;
612                 case txnouttype.TX_PUBKEY:
613                     return 1;
614                 case txnouttype.TX_PUBKEYHASH:
615                     return 2;
616                 case txnouttype.TX_MULTISIG:
617                     if (solutions.Count() < 1 || solutions.First().Count() < 1)
618                         return -1;
619                     return solutions.First().First() + 1;
620                 case txnouttype.TX_SCRIPTHASH:
621                     return 1; // doesn't include args needed by the script
622             }
623             return -1;
624         }
625
626
627         public static bool IsStandard(CScript scriptPubKey, out txnouttype whichType)
628         {
629             IList<IEnumerable<byte>> solutions = new List<IEnumerable<byte>>();
630
631             if (!Solver(scriptPubKey, out whichType, out solutions))
632             {
633                 // No solutions found
634                 return false;
635             }
636
637             if (whichType == txnouttype.TX_MULTISIG)
638             {
639                 byte m = solutions.First().First();
640                 byte n = solutions.Last().First();
641
642                 // Support up to x-of-3 multisig txns as standard
643                 if (n < 1 || n > 3)
644                 {
645                     return false;
646                 }
647                 if (m < 1 || m > n)
648                 {
649                     return false;
650                 }
651             }
652
653             return whichType != txnouttype.TX_NONSTANDARD;
654         }
655
656         /// <summary>
657         /// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
658         /// </summary>
659         /// <param name="scriptPubKey">CScript instance</param>
660         /// <param name="typeRet">Output type</param>
661         /// <param name="solutions">Set of solutions</param>
662         /// <returns>Result</returns>
663         public static bool Solver(CScript scriptPubKey, out txnouttype typeRet, out IList<IEnumerable<byte>> solutions)
664         {
665             solutions = new List<IEnumerable<byte>>();
666
667             // There are shortcuts for pay-to-script-hash and pay-to-pubkey-hash, which are more constrained than the other types:
668
669             // It is always OP_HASH160 20 [20 byte hash] OP_EQUAL
670             if (scriptPubKey.IsPayToScriptHash)
671             {
672                 typeRet = txnouttype.TX_SCRIPTHASH;
673
674                 // Take 20 bytes with offset of 2 bytes
675                 IEnumerable<byte> hashBytes = scriptPubKey.Bytes.Skip(2).Take(20);
676                 solutions.Add(hashBytes);
677
678                 return true;
679             }
680
681             // It is always OP_DUP OP_HASH160 20 [20 byte hash] OP_EQUALVERIFY OP_CHECKSIG
682             if (scriptPubKey.IsPayToPubKeyHash)
683             {
684                 typeRet = txnouttype.TX_PUBKEYHASH;
685
686                 // Take 20 bytes with offset of 3 bytes
687                 IEnumerable<byte> hashBytes = scriptPubKey.Bytes.Skip(3).Take(20);
688                 solutions.Add(hashBytes);
689
690                 return true;
691             }
692
693             List<Tuple<txnouttype, IEnumerable<byte>>> templateTuples = new List<Tuple<txnouttype, IEnumerable<byte>>>();
694
695             // Sender provides pubkey, receiver adds signature
696             // [ECDSA public key] OP_CHECKSIG
697             templateTuples.Add(
698                 new Tuple<txnouttype, IEnumerable<byte>>(
699                     txnouttype.TX_PUBKEY,
700                     new byte[] { (byte)opcodetype.OP_PUBKEY, (byte)opcodetype.OP_CHECKSIG })
701             );
702
703             // Sender provides N pubkeys, receivers provides M signatures
704             // N [pubkey1] [pubkey2] ... [pubkeyN] M OP_CHECKMULTISIG
705             // Where N and M are small integer opcodes (OP1 ... OP_16)
706             templateTuples.Add(
707                 new Tuple<txnouttype, IEnumerable<byte>>(
708                     txnouttype.TX_MULTISIG,
709                     new byte[] { (byte)opcodetype.OP_SMALLINTEGER, (byte)opcodetype.OP_PUBKEYS, (byte)opcodetype.OP_SMALLINTEGER, (byte)opcodetype.OP_CHECKMULTISIG })
710             );
711
712             // Data-carrying output
713             // OP_RETURN [up to 80 bytes of data]
714             templateTuples.Add(
715                 new Tuple<txnouttype, IEnumerable<byte>>(
716                     txnouttype.TX_NULL_DATA,
717                     new byte[] { (byte)opcodetype.OP_RETURN, (byte)opcodetype.OP_SMALLDATA })
718             );
719
720             // Nonstandard tx output
721             typeRet = txnouttype.TX_NONSTANDARD;
722
723             foreach (Tuple<txnouttype, IEnumerable<byte>> templateTuple in templateTuples)
724             {
725                 CScript script1 = scriptPubKey;
726                 CScript script2 = new CScript(templateTuple.Item2);
727
728                 opcodetype opcode1, opcode2;
729
730                 // Compare
731                 WrappedList<byte> wl1 = script1.GetWrappedList();
732                 WrappedList<byte> wl2 = script2.GetWrappedList();
733
734                 IEnumerable<byte> args1, args2;
735
736                 byte last1 = script1.Bytes.Last();
737                 byte last2 = script2.Bytes.Last();
738
739                 while (true)
740                 {
741                     if (wl1.GetCurrentItem() == last1 && wl2.GetCurrentItem() == last2)
742                     {
743                         // Found a match
744                         typeRet = templateTuple.Item1;
745                         if (typeRet == txnouttype.TX_MULTISIG)
746                         {
747                             // Additional checks for TX_MULTISIG:
748                             byte m = solutions.First().First();
749                             byte n = solutions.Last().First();
750
751                             if (m < 1 || n < 1 || m > n || solutions.Count - 2 != n)
752                             {
753                                 return false;
754                             }
755                         }
756                         return true;
757                     }
758
759                     if (!GetOp(ref wl1, out opcode1, out args1))
760                     {
761                         break;
762                     }
763                     if (!GetOp(ref wl2, out opcode2, out args2))
764                     {
765                         break;
766                     }
767
768                     // Template matching opcodes:
769                     if (opcode2 == opcodetype.OP_PUBKEYS)
770                     {
771                         while (args1.Count() >= 33 && args1.Count() <= 120)
772                         {
773                             solutions.Add(args1);
774                             if (!GetOp(ref wl1, out opcode1, out args1))
775                             {
776                                 break;
777                             }
778                         }
779                         if (!GetOp(ref wl2, out opcode2, out args2))
780                             break;
781                         // Normal situation is to fall through
782                         // to other if/else statements
783                     }
784                     if (opcode2 == opcodetype.OP_PUBKEY)
785                     {
786                         if (args1.Count() < 33 || args1.Count() > 120)
787                         {
788                             break;
789                         }
790                         solutions.Add(args1);
791                     }
792                     else if (opcode2 == opcodetype.OP_PUBKEYHASH)
793                     {
794                         if (args1.Count() != 20) // hash160 size
795                         {
796                             break;
797                         }
798                         solutions.Add(args1);
799                     }
800                     else if (opcode2 == opcodetype.OP_SMALLINTEGER)
801                     {
802                         // Single-byte small integer pushed onto solutions
803                         if (opcode1 == opcodetype.OP_0 || (opcode1 >= opcodetype.OP_1 && opcode1 <= opcodetype.OP_16))
804                         {
805                             byte n = (byte)DecodeOP_N(opcode1);
806                             solutions.Add(new byte[] { n });
807                         }
808                         else
809                         {
810                             break;
811                         }
812                     }
813                     else if (opcode2 == opcodetype.OP_SMALLDATA)
814                     {
815                         // small pushdata, <= 80 bytes
816                         if (args1.Count() > 80)
817                         {
818                             break;
819                         }
820                     }
821                     else if (opcode1 != opcode2 || !args1.SequenceEqual(args2))
822                     {
823                         // Others must match exactly
824                         break;
825                     }
826                 }
827             }
828
829             solutions.Clear();
830             typeRet = txnouttype.TX_NONSTANDARD;
831
832             return false;
833         }
834
835         public static Hash256 SignatureHash(CScript scriptCode, CTransaction txTo, int nIn, int nHashType)
836         {
837             if (nIn >= txTo.vin.Length)
838             {
839                 StringBuilder sb = new StringBuilder();
840                 sb.AppendFormat("ERROR: SignatureHash() : nIn={0} out of range\n", nIn);
841                 throw new ArgumentOutOfRangeException("nIn", sb.ToString());
842             }
843
844             CTransaction txTmp = new CTransaction(txTo);
845
846             // In case concatenating two scripts ends up with two codeseparators,
847             // or an extra one at the end, this prevents all those possible incompatibilities.
848             scriptCode.RemovePattern(new byte[] { (byte)opcodetype.OP_CODESEPARATOR });
849
850             // Blank out other inputs' signatures
851             for (int i = 0; i < txTmp.vin.Length; i++)
852             {
853                 txTmp.vin[i].scriptSig = new CScript();
854             }
855             txTmp.vin[nIn].scriptSig = scriptCode;
856
857             // Blank out some of the outputs
858             if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_NONE)
859             {
860                 // Wildcard payee
861                 txTmp.vout = null;
862
863                 // Let the others update at will
864                 for (int i = 0; i < txTmp.vin.Length; i++)
865                 {
866                     if (i != nIn)
867                     {
868                         txTmp.vin[i].nSequence = 0;
869                     }
870                 }
871             }
872             else if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_SINGLE)
873             {
874                 // Only lock-in the txout payee at same index as txin
875                 int nOut = nIn;
876                 if (nOut >= txTmp.vout.Length)
877                 {
878                     StringBuilder sb = new StringBuilder();
879                     sb.AppendFormat("ERROR: SignatureHash() : nOut={0} out of range\n", nOut);
880                     throw new ArgumentOutOfRangeException("nOut", sb.ToString());
881                 }
882                 Array.Resize(ref txTmp.vout, nOut + 1);
883
884                 for (int i = 0; i < nOut; i++)
885                 {
886                     txTmp.vout[i] = new CTxOut();
887                 }
888
889                 // Let the others update at will
890                 for (int i = 0; i < txTmp.vin.Length; i++)
891                 {
892                     if (i != nIn)
893                     {
894                         txTmp.vin[i].nSequence = 0;
895                     }
896                 }
897             }
898
899             // Blank out other inputs completely, not recommended for open transactions
900             if ((nHashType & (int)sigflag.SIGHASH_ANYONECANPAY) != 0)
901             {
902                 txTmp.vin[0] = txTmp.vin[nIn];
903                 Array.Resize(ref txTmp.vin, 1);
904             }
905
906             // Serialize and hash
907             List<byte> b = new List<byte>();
908             b.AddRange(txTmp.Bytes);
909             b.AddRange(BitConverter.GetBytes(nHashType));
910
911             return Hash256.Compute256(b);
912         }
913
914     };
915 }