Example #1
0
 def test_sequence(self):
     sequence_0 = Sequence()
     self.assertEqual(sequence_0, MAX_SEQUENCE)
     self.assertTrue(sequence_0.is_max())
     self.assertFalse(sequence_0.is_relative())
     self.assertIsNone(sequence_0.relative_blocks())
     self.assertIsNone(sequence_0.relative_time())
     self.assertEqual(Sequence.parse(BytesIO(sequence_0.serialize())),
                      sequence_0)
     time_amount = 512 * 1000
     sequence_1 = Sequence.from_relative_time(time_amount)
     self.assertFalse(sequence_1.is_comparable(sequence_0))
     self.assertIsNone(sequence_1.relative_blocks())
     self.assertEqual(sequence_1.relative_time(), time_amount)
     self.assertEqual(Sequence.parse(BytesIO(sequence_1.serialize())),
                      sequence_1)
     blocks_amount = 144
     sequence_2 = Sequence.from_relative_blocks(blocks_amount)
     self.assertIsNone(sequence_2.relative_time())
     self.assertEqual(sequence_2.relative_blocks(), blocks_amount)
     self.assertFalse(sequence_1.is_comparable(sequence_2))
     sequence_3 = Sequence.from_relative_time(512 * 100)
     self.assertTrue(sequence_3 < sequence_1)
     with self.assertRaises(ValueError):
         sequence_2 < sequence_0
     with self.assertRaises(ValueError):
         sequence_2 < sequence_1
     with self.assertRaises(ValueError):
         Sequence(-1)
     with self.assertRaises(ValueError):
         Sequence(1 << 32)
Example #2
0
 def __init__(self, prev_tx, prev_index, script_sig=None, sequence=None):
     self.prev_tx = prev_tx
     self.prev_index = prev_index
     if script_sig is None:
         self.script_sig = Script()
     else:
         self.script_sig = script_sig
     if sequence is None:
         self.sequence = Sequence()
     else:
         self.sequence = Sequence(sequence)
     self._value = None
     self._script_pubkey = None
     self.witness = Witness()
     self.tap_script = None
Example #3
0
 def test_op_cltv(self):
     locktime_0 = Locktime(1234)
     locktime_1 = Locktime(2345)
     sequence = Sequence()
     tx_in = TxIn(b"\x00" * 32, 0, sequence=sequence)
     tx_out = TxOut(1, Script())
     tx_obj = Tx(1, [tx_in], [tx_out], locktime_1)
     stack = []
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     tx_in.sequence = Sequence(0xFFFFFFFE)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     stack = [encode_num(-5)]
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     stack = [encode_num(locktime_0)]
     self.assertTrue(op_checklocktimeverify(stack, tx_obj, 0))
     tx_obj.locktime = Locktime(1582820194)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     tx_obj.locktime = Locktime(500)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
Example #4
0
 def test_op_csv(self):
     sequence_0 = Sequence()
     sequence_1 = Sequence(2345)
     tx_in = TxIn(b"\x00" * 32, 0, sequence=sequence_0)
     tx_out = TxOut(1, Script())
     tx_obj = Tx(1, [tx_in], [tx_out])
     stack = []
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     tx_in.sequence = sequence_1
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(-5)]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     tx_obj.version = 2
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(1234 | (1 << 22))]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(9999)]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(1234)]
     self.assertTrue(op_checksequenceverify(stack, tx_obj, 0))
Example #5
0
 def degrading_multisig_tap_node(self,
                                 sequence_block_interval=None,
                                 sequence_time_interval=None):
     """Can unlock with multisig as k-of-n, or (k-1)-of-n after a
     sequence_block_interval/sequence_time_interval amount of time,
     (k-2)-of-n after 2*sequence_block_interval/sequence_time_interval
     amount of time, (k-3)-of-n after 3*sequence_block_interval/
     sequence_time_interval amount of time and so on."""
     leaves = []
     for num_keys_needed in range(self.k, 0, -1):
         if num_keys_needed == self.k:
             sequence = None
         elif sequence_block_interval:
             sequence = Sequence.from_relative_blocks(
                 sequence_block_interval * (self.k - num_keys_needed))
         elif sequence_time_interval:
             sequence = Sequence.from_relative_time(
                 sequence_time_interval * (self.k - num_keys_needed))
         for pubkeys in combinations(self.points, num_keys_needed):
             tap_script = MultiSigTapScript(pubkeys,
                                            num_keys_needed,
                                            sequence=sequence)
             leaves.append(tap_script.tap_leaf())
     return TapBranch.combine(leaves)
Example #6
0
 def parse(cls, s):
     """Takes a byte stream and parses the tx_input at the start
     return a TxIn object
     """
     # s.read(n) will return n bytes
     # prev_tx is 32 bytes, little endian
     prev_tx = s.read(32)[::-1]
     # prev_index is 4 bytes, little endian, interpret as int
     prev_index = little_endian_to_int(s.read(4))
     # script_sig is a variable field (length followed by the data)
     # you can use Script.parse to get the actual script
     script_sig = Script.parse(s)
     # sequence is 4 bytes, little-endian, interpret as int
     sequence = Sequence.parse(s)
     # return an instance of the class (cls(...))
     return cls(prev_tx, prev_index, script_sig, sequence)
Example #7
0
def op_checksequenceverify(stack, tx_obj, input_index):
    sequence = tx_obj.tx_ins[input_index].sequence
    if not sequence.is_relative():
        return False
    if len(stack) < 1:
        return False
    element = decode_num(stack[-1])
    if element < 0:
        return False
    if tx_obj.version < 2:
        return False
    stack_sequence = Sequence(element)
    if not sequence.is_comparable(stack_sequence):
        return False
    if sequence < stack_sequence:
        return False
    return True
Example #8
0
    def sig_hash_legacy(self,
                        input_index,
                        redeem_script=None,
                        hash_type=SIGHASH_ALL):
        """Returns the integer representation of the hash that needs to get
        signed for index input_index"""

        # consensus bugs related to invalid input indices
        DEFAULT = 1 << 248
        if input_index >= len(self.tx_ins):
            return DEFAULT
        elif hash_type & 3 == SIGHASH_SINGLE and input_index >= len(
                self.tx_outs):
            return DEFAULT
        # create the serialization per spec
        # start with version: int_to_little_endian in 4 bytes
        s = int_to_little_endian(self.version, 4)
        # next, how many inputs there are: encode_varint
        s += encode_varint(len(self.tx_ins))
        # loop through each input: for i, tx_in in enumerate(self.tx_ins)
        for i, tx_in in enumerate(self.tx_ins):
            sequence = tx_in.sequence
            # if the input index is the one we're signing
            if i == input_index:
                # if the RedeemScript was passed in, that's the ScriptSig
                if redeem_script:
                    script_sig = redeem_script
                # otherwise the previous tx's ScriptPubkey is the ScriptSig
                else:
                    script_sig = tx_in.script_pubkey(self.network)
            # Otherwise, the ScriptSig is empty
            else:
                script_sig = None
                if hash_type & 3 in (SIGHASH_NONE, SIGHASH_SINGLE):
                    sequence = Sequence(0)
            # create a TxIn object with the prev_tx, prev_index and sequence
            # the same as the current tx_in and the script_sig from above
            new_tx_in = TxIn(
                prev_tx=tx_in.prev_tx,
                prev_index=tx_in.prev_index,
                script_sig=script_sig,
                sequence=sequence,
            )
            # add the serialization of the TxIn object
            if hash_type & SIGHASH_ANYONECANPAY:
                if i == input_index:
                    s += new_tx_in.serialize()
            else:
                s += new_tx_in.serialize()
        # add how many outputs there are using encode_varint
        s += encode_varint(len(self.tx_outs))
        # add the serialization of each output
        for i, tx_out in enumerate(self.tx_outs):
            if hash_type & 3 == SIGHASH_NONE:
                continue
            elif hash_type & 3 == SIGHASH_SINGLE:
                if i == input_index:
                    s += tx_out.serialize()
                    break
                else:
                    s += b"\xff\xff\xff\xff\xff\xff\xff\xff\x00"
            else:
                s += tx_out.serialize()
        # add the locktime using int_to_little_endian in 4 bytes
        s += self.locktime.serialize()
        # add SIGHASH_ALL using int_to_little_endian in 4 bytes
        s += int_to_little_endian(hash_type, 4)
        # hash256 the serialization
        h256 = hash256(s)
        # convert the result to an integer using big_endian_to_int(x)
        return big_endian_to_int(h256)