示例#1
0
 def op_for_int(self, value):
     """Get a small int or push operation for value."""
     cls = types.opcode_by_name('OP_%d' % value)
     if cls:
         return cls()
     value = formats.int_to_bytearray(value)
     return types.Push(data=value)
示例#2
0
 def op_for_int(self, value):
     """Get a small int or push operation for value."""
     cls = types.opcode_by_name('OP_%d'%value)
     if cls:
         return cls()
     value = formats.int_to_bytearray(value)
     return types.Push(data=value)
示例#3
0
def format_structural_op(op):
    """Format an op for human-readability."""
    def format_statements(statements):
        return '; '.join(map(format_structural_op, statements)) + ';'
    def format_args(arguments):
        args = map(format_structural_op, arguments)
        args_str = ''
        for i, arg in enumerate(args):
            args_str += arg
            if i < len(args) - 1:
                args_str += ', '
        return args_str

    if isinstance(op, structural_nodes.Script):
        return format_statements(op.statements)
    elif isinstance(op, (structural_nodes.Int, structural_nodes.Bytes, structural_nodes.Symbol)):
        s = str(op)
        # Hex-encode numeric values.
        if isinstance(op, (structural_nodes.Int, structural_nodes.Bytes)) and abs(int(op)) > 16:
            s = hex(int(op))
        return s
    elif isinstance(op, structural_nodes.Declaration):
        return 'let %s%s = %s' % ('mutable ' if op.mutable else '', op.name, format_structural_op(op.value))
    elif isinstance(op, structural_nodes.Assignment):
        return '%s = %s' % (op.name, format_structural_op(op.value))
    elif isinstance(op, structural_nodes.Function):
        args_str = format_args(op.args)
        body_str = format_statements(op.body)
        return 'func %s(%s) {%s}' % (op.name, args_str, body_str)
    elif isinstance(op, structural_nodes.FunctionCall):
        args_str = format_args(op.args)
        return '%s(%s)' % (op.name, args_str)
    elif isinstance(op, structural_nodes.If):
        test = format_structural_op(op.test)
        true_branch = format_statements(op.truebranch)
        s = 'if %s {%s}' % (test, true_branch)
        if op.falsebranch:
            s += ' else {%s}' % format_statements(op.falsebranch)
        return s
    elif isinstance(op, structural_nodes.InnerScript):
        return format_statements(op.statements)
    if not hasattr(op, 'name'):
        return
    linear = linear_nodes.opcode_by_name(op.name)
    if not linear:
        return
    if not linear.opstr:
        return op.name

    if linear.is_unary():
        return linear.opstr.format(format_structural_op(op.operand))
    elif linear.is_binary():
        return linear.opstr.format(*map(format_structural_op, [op.left, op.right]))
    elif linear.is_ternary():
        return linear.opstr.format(*map(format_structural_op, op.operands[0:3]))
示例#4
0
 def process_value(self, value):
     # Encode integer.
     if isinstance(value, (int, long)):
         push = formats.int_to_bytearray(value)
         self.add_instruction(types.Push(data=push))
     else:
         try:
             opcode = types.small_int_opcode(int(value))()
         except (TypeError, ValueError):
             opcode = types.opcode_by_name('OP_%s' % value)()
         self.add_instruction(opcode)
示例#5
0
 def process_value(self, value):
     # Encode integer.
     if isinstance(value, int):
         push = formats.int_to_bytearray(value)
         self.add_instruction(types.Push(data=push))
     else:
         try:
             opcode = types.small_int_opcode(int(value))()
         except (TypeError, ValueError):
             opcode = types.opcode_by_name('OP_%s' % value)()
         self.add_instruction(opcode)
示例#6
0
 def visit_UnaryOpCode(self, node):
     if SInstructions.is_arithmetic_op(node) and isinstance(node.operand, (structural_nodes.Int, structural_nodes.Bytes)):
         if not formats.is_strict_num(int(node.operand)):
             msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, node.operand)
             if self.options.strict_num:
                 self.error(msg, node.lineno)
                 raise IRStrictNumError(msg)
             else:
                 self.warning(msg, node.lineno)
     return_value = self.visit(node.operand)
     op = types.opcode_by_name(node.name)()
     return return_value + [op]
示例#7
0
def merge_op_and_verify(instructions):
    """Merge opcodes with a corresponding *VERIFY form.

    e.g. OP_EQUAL OP_VERIFY -> OP_EQUALVERIFY
    """
    optimizations = []
    for op in types.iter_opcode_classes():
        if op.name.endswith('VERIFY') and op.name != 'OP_VERIFY':
            base_op = types.opcode_by_name(op.name[:-6])
            if not base_op:
                continue
            template = [base_op(), types.Verify()]
            optimizations.append((template, [op()]))

    for template, replacement in optimizations:
        callback = lambda values, replacement=replacement: replacement
        instructions.replace_template(template, callback)
示例#8
0
def merge_op_and_verify(instructions):
    """Merge opcodes with a corresponding *VERIFY form.

    e.g. OP_EQUAL OP_VERIFY -> OP_EQUALVERIFY
    """
    optimizations = []
    for op in types.iter_opcode_classes():
        if op.name.endswith('VERIFY') and op.name != 'OP_VERIFY':
            base_op = types.opcode_by_name(op.name[:-6])
            if not base_op:
                continue
            template = [base_op(), types.Verify()]
            optimizations.append((template, [op()]))

    for template, replacement in optimizations:
        callback = lambda values, replacement=replacement: replacement
        instructions.replace_template(template, callback)
示例#9
0
    def visit_BinOpCode(self, node):
        # Check for values longer than 4 bytes.
        if SInstructions.is_arithmetic_op(node):
            operands = [node.left, node.right]
            if all(isinstance(i, (structural_nodes.Int, structural_nodes.Bytes)) for i in operands):
                valid = [formats.is_strict_num(int(i)) for i in operands]
                if False in valid:
                    msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, operands[valid.index(False)])
                    if self.options.strict_num:
                        self.error(msg, node.lineno)
                        raise IRStrictNumError(msg)
                    else:
                        self.warning(msg, node.lineno)

        return_value = self.visit(node.left)
        return_value.extend(self.visit(node.right))
        op = types.opcode_by_name(node.name)()
        return return_value + [op]
示例#10
0
文件: btcscript.py 项目: Kefkius/txsc
    def transform(self, source):
        if isinstance(source, list):
            source = ''.join(source)
        if source.startswith('0x'):
            source = source[2:]

        src = script.CScript(x(source))
        iterator = iter(src)
        for value in iterator:
            op = None
            s = str(value)
            if s.startswith('OP_'):
                op = types.opcode_by_name(s)()
            elif isinstance(value, int):
                op = types.small_int_opcode(value)()
            else:
                op = types.Push(data=value)

            if op is not None:
                self.add_instruction(op)

        return self.instructions
示例#11
0
    def transform(self, source):
        if isinstance(source, list):
            source = ''.join(source)
        if source.startswith('0x'):
            source = source[2:]

        src = script.CScript(x(source))
        iterator = iter(src)
        for value in iterator:
            op = None
            s = str(value)
            if s.startswith('OP_'):
                op = types.opcode_by_name(s)()
            elif isinstance(value, int):
                op = types.small_int_opcode(value)()
            else:
                op = types.Push(data=value)

            if op is not None:
                self.add_instruction(op)

        return self.instructions
示例#12
0
 def visit_BinOpCode(self, node):
     return_value = self.visit(node.left)
     return_value.extend(self.visit(node.right))
     op = types.opcode_by_name(node.name)()
     return return_value + [op]
示例#13
0
 def is_byte_string_op(op):
     """Return whether op operates on a string of bytes."""
     linear = linear_nodes.opcode_by_name(op.name)
     if not linear or not issubclass(linear, linear_nodes.OpCode):
         return False
     return linear.byte_manipulator
示例#14
0
 def is_arithmetic_op(op):
     """Return whether op represents an arithmetic operation."""
     linear = linear_nodes.opcode_by_name(op.name)
     if not linear or not issubclass(linear, linear_nodes.OpCode):
         return False
     return linear.arithmetic
示例#15
0
 def visit_OpCode(self, node):
     op = types.opcode_by_name(node.name)()
     return op
示例#16
0
 def visit_VariableArgsOpCode(self, node):
     return_value = []
     for arg in node.operands:
         return_value.extend(self.visit(arg))
     op = types.opcode_by_name(node.name)()
     return return_value + [op]
示例#17
0
 def visit_UnaryOpCode(self, node):
     return_value = self.visit(node.operand)
     op = types.opcode_by_name(node.name)()
     return return_value + [op]
示例#18
0
 def visit_VerifyOpCode(self, node):
     return_value = self.visit(node.test)
     op = types.opcode_by_name(node.name)()
     return return_value + [op]