4 using System.Collections;
5 using System.Collections.Generic;
10 public enum opcodetype
52 OP_FROMALTSTACK = 0x6c,
84 OP_EQUALVERIFY = 0x88,
109 OP_NUMEQUALVERIFY = 0x9d,
110 OP_NUMNOTEQUAL = 0x9e,
112 OP_GREATERTHAN = 0xa0,
113 OP_LESSTHANOREQUAL = 0xa1,
114 OP_GREATERTHANOREQUAL = 0xa2,
126 OP_CODESEPARATOR = 0xab,
128 OP_CHECKSIGVERIFY = 0xad,
129 OP_CHECKMULTISIG = 0xae,
130 OP_CHECKMULTISIGVERIFY = 0xaf,
144 // template matching params
146 OP_SMALLINTEGER = 0xfa,
148 OP_PUBKEYHASH = 0xfd,
151 OP_INVALIDOPCODE = 0xff,
156 private byte[] scriptCode = {};
162 private string GetOpName(opcodetype opcode)
166 case opcodetype.OP_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:
176 case opcodetype.OP_RESERVED:
177 return "OP_RESERVED";
178 case opcodetype.OP_1:
180 case opcodetype.OP_2:
182 case opcodetype.OP_3:
184 case opcodetype.OP_4:
186 case opcodetype.OP_5:
188 case opcodetype.OP_6:
190 case opcodetype.OP_7:
192 case opcodetype.OP_8:
194 case opcodetype.OP_9:
196 case opcodetype.OP_10:
198 case opcodetype.OP_11:
200 case opcodetype.OP_12:
202 case opcodetype.OP_13:
204 case opcodetype.OP_14:
206 case opcodetype.OP_15:
208 case opcodetype.OP_16:
212 case opcodetype.OP_NOP:
214 case opcodetype.OP_VER:
216 case opcodetype.OP_IF:
218 case opcodetype.OP_NOTIF:
220 case opcodetype.OP_VERIF:
222 case opcodetype.OP_VERNOTIF:
223 return "OP_VERNOTIF";
224 case opcodetype.OP_ELSE:
226 case opcodetype.OP_ENDIF:
228 case opcodetype.OP_VERIFY:
230 case opcodetype.OP_RETURN:
234 case opcodetype.OP_TOALTSTACK:
235 return "OP_TOALTSTACK";
236 case opcodetype.OP_FROMALTSTACK:
237 return "OP_FROMALTSTACK";
238 case opcodetype.OP_2DROP:
240 case opcodetype.OP_2DUP:
242 case opcodetype.OP_3DUP:
244 case opcodetype.OP_2OVER:
246 case opcodetype.OP_2ROT:
248 case opcodetype.OP_2SWAP:
250 case opcodetype.OP_IFDUP:
252 case opcodetype.OP_DEPTH:
254 case opcodetype.OP_DROP:
256 case opcodetype.OP_DUP:
258 case opcodetype.OP_NIP:
260 case opcodetype.OP_OVER:
262 case opcodetype.OP_PICK:
264 case opcodetype.OP_ROLL:
266 case opcodetype.OP_ROT:
268 case opcodetype.OP_SWAP:
270 case opcodetype.OP_TUCK:
274 case opcodetype.OP_CAT:
276 case opcodetype.OP_SUBSTR:
278 case opcodetype.OP_LEFT:
280 case opcodetype.OP_RIGHT:
282 case opcodetype.OP_SIZE:
286 case opcodetype.OP_INVERT:
288 case opcodetype.OP_AND:
290 case opcodetype.OP_OR:
292 case opcodetype.OP_XOR:
294 case opcodetype.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";
304 case opcodetype.OP_1ADD:
306 case opcodetype.OP_1SUB:
308 case opcodetype.OP_2MUL:
310 case opcodetype.OP_2DIV:
312 case opcodetype.OP_NEGATE:
314 case opcodetype.OP_ABS:
316 case opcodetype.OP_NOT:
318 case opcodetype.OP_0NOTEQUAL:
319 return "OP_0NOTEQUAL";
320 case opcodetype.OP_ADD:
322 case opcodetype.OP_SUB:
324 case opcodetype.OP_MUL:
326 case opcodetype.OP_DIV:
328 case opcodetype.OP_MOD:
330 case opcodetype.OP_LSHIFT:
332 case opcodetype.OP_RSHIFT:
334 case opcodetype.OP_BOOLAND:
336 case opcodetype.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:
354 case opcodetype.OP_MAX:
356 case opcodetype.OP_WITHIN:
360 case opcodetype.OP_RIPEMD160:
361 return "OP_RIPEMD160";
362 case opcodetype.OP_SHA1:
364 case opcodetype.OP_SHA256:
366 case opcodetype.OP_HASH160:
368 case opcodetype.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";
382 case opcodetype.OP_NOP1:
384 case opcodetype.OP_NOP2:
386 case opcodetype.OP_NOP3:
388 case opcodetype.OP_NOP4:
390 case opcodetype.OP_NOP5:
392 case opcodetype.OP_NOP6:
394 case opcodetype.OP_NOP7:
396 case opcodetype.OP_NOP8:
398 case opcodetype.OP_NOP9:
400 case opcodetype.OP_NOP10:
403 // template matching params
404 case opcodetype.OP_PUBKEYHASH:
405 return "OP_PUBKEYHASH";
406 case opcodetype.OP_PUBKEY:
408 case opcodetype.OP_SMALLDATA:
409 return "OP_SMALLDATA";
411 case opcodetype.OP_INVALIDOPCODE:
412 return "OP_INVALIDOPCODE";
418 public bool GetOp(ref IEnumerator<byte> codeBytes, ref opcodetype opcodeRet, ref byte[] bytesRet)
420 opcodeRet = opcodetype.OP_INVALIDOPCODE;
422 // Initialize local byte list
423 List<byte> bytesRetIn = new List<byte> ();
426 if (!codeBytes.MoveNext())
428 opcodetype opcode = (opcodetype)codeBytes.Current;
431 if (opcode <= opcodetype.OP_PUSHDATA4)
434 if (opcode < opcodetype.OP_PUSHDATA1) { // False values
436 } else if (opcode == opcodetype.OP_PUSHDATA1) { // One byte size prefix
437 if (!codeBytes.MoveNext ())
439 nSize = codeBytes.Current;
440 } else if (opcode == opcodetype.OP_PUSHDATA2) { // Two bytes size prefix
441 byte[] SizeBytes = {0,0};
443 for (int i = 0; i < 2; i++) { // TODO: implement some intelligent solution instead
444 if (!codeBytes.MoveNext ())
447 SizeBytes [i] = codeBytes.Current;
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};
455 for (int i = 0; i < 4; i++) {
456 if (!codeBytes.MoveNext ())
459 SizeBytes [i] = codeBytes.Current;
462 Array.Reverse (SizeBytes);
463 nSize = BitConverter.ToInt32 (SizeBytes, 0);
466 for (int i = 0; i < nSize; i++) {
467 if (!codeBytes.MoveNext ())
470 bytesRetIn.Add (codeBytes.Current);
473 // Return OP_PUSHDATA arguments
474 bytesRet = bytesRetIn.ToArray ();
482 // Encode/decode small integers:
483 static int DecodeOP_N(opcodetype opcode)
485 if (opcode == opcodetype.OP_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);
491 static opcodetype EncodeOP_N(int n)
493 if (!(n >= 0 && n <= 16))
494 throw new Exception ("! (n >= 0 && n <= 16)");
496 return opcodetype.OP_0;
497 return (opcodetype)(opcodetype.OP_1+n-1);
500 public override string ToString()
504 StringBuilder sb = new StringBuilder(scriptCode.Length * 2);
505 foreach (byte b in scriptCode)
507 sb.AppendFormat ("{0:x2}", b);
509 return sb.ToString();