Exemple #1
0
 def test_invalid_hash256(self):
     for script in [
         [types.Five(), types.Hash256(), types.Push(b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'), types.EqualVerify()],
         [types.Five(), types.Sha256(), types.Push(b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'), types.EqualVerify()],
     ]:
         script = LInstructions(script)
         self.assertRaises(IRError, self._do_context, script)
Exemple #2
0
def replace_shortcut_ops(instructions):
    """Replace opcodes with a corresponding shortcut form."""
    optimizations = []
    # Replace division by 2.
    # OP_2 OP_DIV -> OP_2DIV
    optimizations.append(([types.Two(), types.Div()], lambda values: [types.Div2()]))
    # Replace subtraction by 1.
    # OP_1 OP_SUB -> OP_1SUB
    optimizations.append(([types.One(), types.Sub()], lambda values: [types.Sub1()]))
    # Replace 1 * -1 with -1.
    # OP_1 OP_NEGATE -> OP_1NEGATE
    optimizations.append(([types.One(), types.Negate()], lambda values: [types.NegativeOne()]))
    # Replace addition by 1.
    # OP_1 OP_ADD -> OP_1ADD
    for permutation in permutations([types.Push(), types.One()]) + permutations([types.SmallIntOpCode(), types.One()]):
        idx = 0 if not isinstance(permutation[0], types.One) else 1
        optimizations.append((permutation + [types.Add()], lambda values, idx=idx: [values[idx], types.Add1()]))
    optimizations.append(([types.Assumption(), types.One(), types.Add()], lambda values: [values[0], types.Add1()]))
    # Replace multiplication by 2.
    # OP_2 OP_MUL -> OP_2MUL
    for permutation in permutations([types.Push(), types.Two()]) + permutations([types.SmallIntOpCode(), types.Two()]):
        idx = 0 if not isinstance(permutation[0], types.Two) else 1
        optimizations.append((permutation + [types.Mul()], lambda values, idx=idx: [values[idx], types.Mul2()]))
    optimizations.append(([types.Assumption(), types.Two(), types.Mul()], lambda values: [values[0], types.Mul2()]))


    for template, callback in optimizations:
        instructions.replace_template(template, callback, strict=False)
Exemple #3
0
 def test_valid_hash256(self):
     for script in [
         [types.Five(), types.Hash256(), types.Push(b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'), types.EqualVerify()],
         [types.Five(), types.Sha256(), types.Push(b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'), types.EqualVerify()],
     ]:
         script = LInstructions(script)
         self._do_context(script)
Exemple #4
0
    def test_arithmetic_ops(self):
        script = [types.Five(), types.Five(), types.Equal(), types.Not()]
        self._do_test('OP_5 OP_5 OP_NUMNOTEQUAL', script)

        script = [types.Five(), types.Push(b'\x01\x02\x03\x04'), types.Equal(), types.Not()]
        self._do_test('OP_5 01020304 OP_NUMNOTEQUAL', script)

        # A value longer than 4 bytes won't be optimized this way.
        script = [types.Five(), types.Push(b'\x01\x02\x03\x04\x05'), types.Equal(), types.Not()]
        self._do_test('OP_5 0102030405 OP_EQUAL OP_NOT', script)
Exemple #5
0
    def test_multisig(self):
        sigs = [types.Push(formats.int_to_bytearray(i)) for i in [100]]
        pubs = [types.Push(formats.int_to_bytearray(i)) for i in [300, 400]]

        script = [types.Zero()] # Dummy value.
        script.extend(sigs + [types.One()]) # 1 signature.
        script.extend(pubs + [types.Two()]) # 2 public keys.
        script.append(types.CheckMultiSig())
        script = LInstructions(script)
        self._do_context(script)

        checkmultisig = script[6]
        self.assertIsInstance(checkmultisig, types.CheckMultiSig)
        self.assertEqual(2, checkmultisig.num_pubkeys)
        self.assertEqual(1, checkmultisig.num_sigs)
Exemple #6
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)
Exemple #7
0
    def state_append(self, op):
        """Append op to the stack state."""
        if isinstance(op, StackItem):
            op = copy.deepcopy(op)
        elif isinstance(op, int):
            smallint = types.small_int_opcode(op)
            if smallint:
                op = smallint()
            else:
                op = types.Push(data=op)

            op = StackItem(op)
        elif isinstance(op, str):
            op = StackItem(types.Push(data=op))

        self.state.append(op)
Exemple #8
0
def use_small_int_opcodes(instructions):
    """Convert data pushes to equivalent small integer opcodes."""
    def convert_push(push):
        push = push[0]
        try:
            i = formats.bytearray_to_int(push.data)
            return [types.small_int_opcode(i)()]
        except TypeError:
            pass
        return [push]
    instructions.replace_template([types.Push()], convert_push, strict=False)
Exemple #9
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)
Exemple #10
0
 def visit_InnerScript(self, node):
     s = []
     for op in node.ops:
         result = self.visit(op)
         if isinstance(result, list):
             result = ''.join(result).replace('0x', '')
         s.append(result)
     s = ''.join(s)
     data = x(s)
     if self.little_endian:
         data = lx(s)
     return self.visit(types.Push(data=data))
Exemple #11
0
def use_arithmetic_ops(instructions):
    """Replace ops with more convenient arithmetic ops."""
    optimizations = []
    _two_values = permutations([types.SmallIntOpCode(), types.Push()])
    _two_values.append([types.SmallIntOpCode()] * 2)
    _two_values.append([types.Push()] * 2)

    def all_strict_nums(numbers):
        """Evaluate whether instances represent strict numbers."""
        return all(formats.is_strict_num(i) for i in map(LInstructions.instruction_to_int, numbers))

    # Use NUMNOTEQUAL if both values are numbers.
    def numnotequal_callback(values):
        if not all_strict_nums(values[0:2]):
            return values
        return values[0:2] + [types.NumNotEqual()]

    for permutation in _two_values:
        optimizations.append((permutation + [types.Equal(), types.Not()], numnotequal_callback))

    for template, callback in optimizations:
        instructions.replace_template(template, callback, strict=False)
Exemple #12
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
Exemple #13
0
 def visit_Bytes(self, node):
     try:
         return types.small_int_opcode(int(node.data, 16))()
     except (TypeError, ValueError):
         return types.Push(formats.hex_to_bytearray(node.data))
Exemple #14
0
 def visit_Int(self, node):
     smallint = types.small_int_opcode(int(node))
     if smallint:
         return smallint()
     else:
         return types.Push(formats.int_to_bytearray(node.value))
Exemple #15
0
 def test_push(self):
     script = LInstructions([types.One(), types.Push(formats.int_to_bytearray(20)), types.IfDup()])
     self._do_context(script)
     ifdup = script[2]
     self.assertIsInstance(ifdup, types.IfDup)
     self.assertEqual(1, ifdup.delta)
Exemple #16
0
 def test_convert_to_small_int(self):
     script = [types.Push(b'\x05')]
     self._do_test('OP_5', script)