Beispiel #1
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)
Beispiel #2
0
    def test_shortcut_ops(self):
        for script in [
            [types.Five(), types.One(), types.Add()],
            [types.One(), types.Five(), types.Add()],
        ]:
            self._do_test('OP_5 OP_1ADD', script)

        self._do_test('OP_1ADD', [types.Assumption('testItem'), types.One(), types.Add()])

        script = [types.Five(), types.One(), types.Sub()]
        self._do_test('OP_5 OP_1SUB', script)

        for script in [
            [types.Five(), types.Two(), types.Mul()],
            [types.Two(), types.Five(), types.Mul()],
        ]:
            self._do_test('OP_5 OP_2MUL', script)

        self._do_test('OP_2MUL', [types.Assumption('testItem'), types.Two(), types.Mul()])

        script = [types.Five(), types.Two(), types.Div()]
        self._do_test('OP_5 OP_2DIV', script)

        script = [types.Five(), types.One(), types.Negate()]
        self._do_test('OP_5 OP_1NEGATE', script)
Beispiel #3
0
 def test_small_int(self):
     items = [
         (LInstructions([types.One(), types.Two(), types.IfDup()]), 1),
         (LInstructions([types.One(), types.Zero(), types.IfDup()]), 0),
     ]
     for script, expected_delta in items:
         self._do_context(script)
         ifdup = script[2]
         self.assertIsInstance(ifdup, types.IfDup)
         self.assertEqual(expected_delta, ifdup.delta)
Beispiel #4
0
    def test_optimize_stack_ops(self):
        script = [types.Five(), types.One(), types.Pick()]
        self._do_test('OP_5 OP_OVER', script)

        script = [types.Five(), types.One(), types.Roll(), types.Drop()]
        self._do_test('OP_5 OP_NIP', script)

        script = [types.Zero(), types.Pick()]
        self._do_test('OP_DUP', script)

        script = [types.Five(), types.Zero(), types.Roll()]
        self._do_test('OP_5', script)

        script = [types.Five(), types.Six(), types.One(), types.Roll(), types.One(), types.Roll()]
        self._do_test('OP_5 OP_6', script)
Beispiel #5
0
def optimize_stack_ops(instructions):
    """Optimize stack operations."""
    for template, replacement in [
        # OP_1 OP_PICK -> OP_OVER
        ([types.One(), types.Pick()], [types.Over()]),
        # OP_1 OP_ROLL OP_DROP -> OP_NIP
        ([types.One(), types.Roll(), types.Drop()], [types.Nip()]),
        # OP_0 OP_PICK -> OP_DUP
        ([types.Zero(), types.Pick()], [types.Dup()]),
        # OP_0 OP_ROLL -> _
        ([types.Zero(), types.Roll()], []),
        # OP_1 OP_ROLL OP_1 OP_ROLL -> _
        ([types.One(), types.Roll(), types.One(), types.Roll()], []),
        # OP_1 OP_ROLL -> OP_SWAP
        ([types.One(), types.Roll()], [types.Swap()]),
        # OP_NIP OP_DROP -> OP_2DROP
        ([types.Nip(), types.Drop()], [types.TwoDrop()]),
        # OP_OVER OP_OVER -> OP_2DUP
        ([types.Over(), types.Over()], [types.TwoDup()]),
    ]:
        callback = lambda values, replacement=replacement: replacement
        instructions.replace_template(template, callback)
Beispiel #6
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)
Beispiel #7
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)