def test_null_ops(self): for script in [ [types.Five(), types.Zero(), types.Add()], [types.Zero(), types.Five(), types.Add()], [types.Five(), types.Zero(), types.Sub()], ]: self._do_test('OP_5', script)
def replace_null_ops(instructions): """Replace operations that do nothing.""" # Remove subtraction by 0. # OP_0 OP_SUB -> _ optimizations = [([types.Zero(), types.Sub()], lambda values: [])] # Remove addition by 0. # OP_0 OP_ADD -> _ for permutation in permutations([None, types.Zero()]): idx = 0 if permutation[0] is None else 1 optimizations.append((permutation + [types.Add()], lambda values, idx=idx: [values[idx]])) for template, callback in optimizations: instructions.replace_template(template, callback)
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)
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)
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)
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)