using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace Novacoin
{
public class CScriptException : Exception
{
public CScriptException()
{
}
public CScriptException(string message)
: base(message)
{
}
public CScriptException(string message, Exception inner)
: base(message, inner)
{
}
}
///
/// Representation of script code
///
public class CScript
{
private List codeBytes;
///
/// Initializes an empty instance of CScript
///
public CScript ()
{
codeBytes = new List();
}
///
/// Initializes new instance of CScript and fills it with supplied bytes
///
/// List of bytes
public CScript(IList bytes)
{
codeBytes = new List(bytes);
}
///
/// Initializes new instance of CScript and fills it with supplied bytes
///
/// Array of bytes
public CScript(byte[] bytes)
{
codeBytes = new List(bytes);
}
///
/// Adds specified operation to opcode bytes list
///
///
public void AddOp(opcodetype opcode)
{
if (opcode < opcodetype.OP_0 || opcode > opcodetype.OP_INVALIDOPCODE)
{
throw new CScriptException("CScript::AddOp() : invalid opcode");
}
codeBytes.Add((byte)opcode);
}
///
/// Adds hash to opcode bytes list.
/// New items are added in this format:
/// hash_length_byte hash_bytes
///
/// Hash160 instance
public void AddHash(Hash160 hash)
{
codeBytes.Add((byte)hash.hashSize);
codeBytes.AddRange(hash.hashBytes);
}
///
/// Adds hash to opcode bytes list.
/// New items are added in this format:
/// hash_length_byte hash_bytes
///
/// Hash256 instance
public void AddHash(Hash256 hash)
{
codeBytes.Add((byte)hash.hashSize);
codeBytes.AddRange(hash.hashBytes);
}
public void PushData(IList dataBytes)
{
if (dataBytes.Count < (int)opcodetype.OP_PUSHDATA1)
{
codeBytes.Add((byte)dataBytes.Count);
}
else if (dataBytes.Count < 0xff)
{
codeBytes.Add((byte)opcodetype.OP_PUSHDATA1);
codeBytes.Add((byte)dataBytes.Count);
}
else if (dataBytes.Count < 0xffff)
{
codeBytes.Add((byte)opcodetype.OP_PUSHDATA2);
byte[] szBytes = BitConverter.GetBytes((short)dataBytes.Count);
if (BitConverter.IsLittleEndian)
Array.Reverse(szBytes);
codeBytes.AddRange(szBytes);
}
else if ((uint)dataBytes.Count < 0xffffffff)
{
codeBytes.Add((byte)opcodetype.OP_PUSHDATA2);
byte[] szBytes = BitConverter.GetBytes((uint)dataBytes.Count);
if (BitConverter.IsLittleEndian)
Array.Reverse(szBytes);
codeBytes.AddRange(szBytes);
}
codeBytes.AddRange(dataBytes);
}
///
/// Disassemble current script code
///
/// Code listing
public override string ToString()
{
StringBuilder sb = new StringBuilder();
WrappedList wCodeBytes = new WrappedList(codeBytes);
opcodetype opcode; // Current opcode
IEnumerable pushArgs; // OP_PUSHDATAn argument
while (ScriptOpcode.GetOp(ref wCodeBytes, out opcode, out pushArgs))
{
if (sb.Length != 0)
{
sb.Append(" ");
}
if (0 <= opcode && opcode <= opcodetype.OP_PUSHDATA4)
{
sb.Append(ScriptOpcode.ValueString(pushArgs));
}
else
{
sb.Append(ScriptOpcode.GetOpName(opcode));
}
}
return sb.ToString();
}
}
}