Exemple #1
0
    def hash(self):
        """ Computes the double SHA-256 hash of the serialized object.

        Returns:
            Hash: object containing the hash
        """
        return Hash.dhash(bytes(self))
Exemple #2
0
    def hash(self):
        """ Computes the double SHA-256 hash of the serialized object.

        Returns:
            Hash: object containing the hash
        """
        return Hash.dhash(bytes(self))
Exemple #3
0
    def hash(self):
        """ Computes the hash of the transaction.

        Returns:
            dhash (bytes): Double SHA-256 hash of the serialized transaction.
        """
        return Hash.dhash(bytes(self))
Exemple #4
0
    def hash(self):
        """ Computes the hash of the transaction.

        Returns:
            dhash (bytes): Double SHA-256 hash of the serialized transaction.
        """
        return Hash.dhash(bytes(self))
    def _op_hash256(self):
        """ The input is hashed two times with SHA-256.
        """
        self._check_stack_len(1)

        x = self._stack.pop()
        self._stack.append(bytes(Hash.dhash(x)))
    def _op_hash256(self):
        """ The input is hashed two times with SHA-256.
        """
        self._check_stack_len(1)

        x = self._stack.pop()
        self._stack.append(bytes(Hash.dhash(x)))
Exemple #7
0
    def _complete_merkle_edge(self):
        if self._cb_txn is None:
            # TODO: raise an error?
            return

        cur_hash = self._cb_txn.hash

        for e in self.merkle_edge:
            cur_hash = Hash.dhash(bytes(cur_hash) + bytes(e))

        self.block_header.merkle_root_hash = cur_hash
Exemple #8
0
    def _complete_merkle_edge(self):
        if self._cb_txn is None:
            # TODO: raise an error?
            return

        cur_hash = self._cb_txn.hash

        for e in self.merkle_edge:
            cur_hash = Hash.dhash(bytes(cur_hash) + bytes(e))

        self.block_header.merkle_root_hash = cur_hash
Exemple #9
0
    def _invalidate_coinbase(self, merkle_node=None):
        if merkle_node is None:
            merkle_node = self.merkle_tree

        if(merkle_node.left_child is None and
           merkle_node.right_child is None):
            # This is the node corresponding to the coinbase, update hash
            merkle_node.hash = self.coinbase_transaction.hash
            return
        else:
            self._invalidate_coinbase(merkle_node.left_child)

        merkle_node.hash = Hash.dhash(bytes(merkle_node.left_child.hash) +
                                      bytes(merkle_node.right_child.hash))

        # If we're back at the root, update the blockheader
        if merkle_node is self.merkle_tree:
            self.block_header.merkle_root_hash = self.merkle_tree.hash
Exemple #10
0
    def _invalidate_coinbase(self, merkle_node=None):
        if merkle_node is None:
            merkle_node = self.merkle_tree

        if(merkle_node.left_child is None and
           merkle_node.right_child is None):
            # This is the node corresponding to the coinbase, update hash
            merkle_node.hash = self.coinbase_transaction.hash
            return
        else:
            self._invalidate_coinbase(merkle_node.left_child)

        merkle_node.hash = Hash.dhash(bytes(merkle_node.left_child.hash) +
                                      bytes(merkle_node.right_child.hash))

        # If we're back at the root, update the blockheader
        if merkle_node is self.merkle_tree:
            self.block_header.merkle_root_hash = self.merkle_tree.hash
Exemple #11
0
    def get_signature_for_input(self, input_index, hash_type, private_key,
                                sub_script):
        """ Returns the signature for an input.

            This function only returns the signature for an input, it
            does not insert the signature into the script member of
            the input. It also does not validate that the given private key
            matches any public keys in the sub_script.

        Args:
            input_index (int): The index of the input to sign.
            hash_type (int): What kind of signature hash to do.
            private_key (crypto.PrivateKey): private key with which
                to sign the transaction.
            sub_script (Script): the scriptPubKey of the corresponding
                utxo being spent if the outpoint is P2PKH or the redeem
                script if the outpoint is P2SH.

        Returns:
            tuple: A tuple containing the signature object and the message that
                was signed.
        """
        if input_index < 0 or input_index >= len(self.inputs):
            raise ValueError("Invalid input index.")

        tmp_script = sub_script.remove_op("OP_CODESEPARATOR")
        if hash_type & 0x1f == self.SIG_HASH_SINGLE and len(self.inputs) > len(
                self.outputs):
            # This is to deal with the bug where specifying an index
            # that is out of range (wrt outputs) results in a
            # signature hash of 0x1 (little-endian)
            msg_to_sign = 0x1.to_bytes(32, 'little')
        else:
            txn_copy = self._copy_for_sig(input_index, hash_type, tmp_script)

            msg_to_sign = bytes(
                Hash.dhash(bytes(txn_copy) + pack_u32(hash_type)))

        sig = private_key.sign(msg_to_sign, False)

        return sig, msg_to_sign
Exemple #12
0
 def _compute_merkle_tree(self):
     """ Computes the merkle tree from the transactions in self.transactions.
         The merkle root is the top node in the tree and can be accessed as
         self.merkle_tree.merkle_hash.
     """
     # Tree gets built bottom up
     level_nodes = [MerkleNode(t.hash, None, None) for t in self.txns]
     while True:
         if len(level_nodes) == 1:
             self.merkle_tree = level_nodes[0]  # This is the root
             return
         if len(level_nodes) % 2 != 0:
             # Make sure there are an even number of nodes
             level_nodes.append(level_nodes[-1])
         new_level = []
         for i in range(0, len(level_nodes), 2):
             left = level_nodes[i]
             right = level_nodes[i+1]
             n = MerkleNode(Hash.dhash(bytes(left.hash) + bytes(right.hash)), left, right)
             new_level.append(n)
         level_nodes = new_level
Exemple #13
0
 def _compute_merkle_tree(self):
     """ Computes the merkle tree from the transactions in self.transactions.
         The merkle root is the top node in the tree and can be accessed as
         self.merkle_tree.merkle_hash.
     """
     # Tree gets built bottom up
     level_nodes = [MerkleNode(t.hash, None, None) for t in self.txns]
     while True:
         if len(level_nodes) == 1:
             self.merkle_tree = level_nodes[0]  # This is the root
             return
         if len(level_nodes) % 2 != 0:
             # Make sure there are an even number of nodes
             level_nodes.append(level_nodes[-1])
         new_level = []
         for i in range(0, len(level_nodes), 2):
             left = level_nodes[i]
             right = level_nodes[i+1]
             n = MerkleNode(Hash.dhash(bytes(left.hash) + bytes(right.hash)), left, right)
             new_level.append(n)
         level_nodes = new_level
Exemple #14
0
    def get_signature_for_input(self, input_index, hash_type, private_key,
                                sub_script):
        """ Returns the signature for an input.

            This function only returns the signature for an input, it
            does not insert the signature into the script member of
            the input. It also does not validate that the given private key
            matches any public keys in the sub_script.

        Args:
            input_index (int): The index of the input to sign.
            hash_type (int): What kind of signature hash to do.
            private_key (crypto.PrivateKey): private key with which
                to sign the transaction.
            sub_script (Script): the scriptPubKey of the corresponding
                utxo being spent if the outpoint is P2PKH or the redeem
                script if the outpoint is P2SH.

        Returns:
            tuple: A tuple containing the signature object and the message that
                was signed.
        """
        if input_index < 0 or input_index >= len(self.inputs):
            raise ValueError("Invalid input index.")

        tmp_script = sub_script.remove_op("OP_CODESEPARATOR")
        if hash_type & 0x1f == self.SIG_HASH_SINGLE and len(self.inputs) > len(self.outputs):
            # This is to deal with the bug where specifying an index
            # that is out of range (wrt outputs) results in a
            # signature hash of 0x1 (little-endian)
            msg_to_sign = 0x1.to_bytes(32, 'little')
        else:
            txn_copy = self._copy_for_sig(input_index, hash_type, tmp_script)

            msg_to_sign = bytes(Hash.dhash(bytes(txn_copy) +
                                           pack_u32(hash_type)))

        sig = private_key.sign(msg_to_sign, False)

        return sig, msg_to_sign
Exemple #15
0
    def sign_input(self, input_index, hash_type, private_key, sub_script):
        """ Signs an input.

        Args:
            input_index (int): The index of the input to sign.
            hash_type (int): What kind of signature hash to do.
            private_key (crypto.PrivateKey): private key with which
                to sign the transaction.
            sub_script (Script): the scriptPubKey of the corresponding
                utxo being spent if the outpoint is P2PKH or the redeem
                script if the outpoint is P2SH.
        """
        if input_index < 0 or input_index >= len(self.inputs):
            raise ValueError("Invalid input index.")

        inp = self.inputs[input_index]

        curr_script_sig = inp.script
        multisig = False
        multisig_params = None
        multisig_key_index = -1
        if sub_script.is_multisig_redeem():
            multisig = True
            multisig_params = sub_script.extract_multisig_redeem_info()
        elif not sub_script.is_p2pkh():
            raise TypeError("Signing arbitrary redeem scripts is not currently supported.")

        tmp_script = sub_script.remove_op("OP_CODESEPARATOR")

        compressed = False
        if hash_type & 0x1f == self.SIG_HASH_SINGLE and len(self.inputs) > len(self.outputs):
            # This is to deal with the bug where specifying an index
            # that is out of range (wrt outputs) results in a
            # signature hash of 0x1 (little-endian)
            msg_to_sign = 0x1.to_bytes(32, 'little')
        else:
            txn_copy = self._copy_for_sig(input_index, hash_type, tmp_script)

            if multisig:
                # Determine which of the public keys this private key
                # corresponds to.
                public_keys = multisig_params['public_keys']
                pub_key_full = self._get_public_key_bytes(private_key, False)
                pub_key_comp = self._get_public_key_bytes(private_key, True)

                for i, p in enumerate(public_keys):
                    if pub_key_full == p or pub_key_comp == p:
                        multisig_key_index = i
                        break

                if multisig_key_index == -1:
                    raise ValueError(
                        "Public key derived from private key does not match any of the public keys in redeem script.")
            else:
                # Before signing we should verify that the address in the
                # sub_script corresponds to that of the private key
                script_pub_key_h160_hex = tmp_script.get_hash160()
                if script_pub_key_h160_hex is None:
                    raise ValueError("Couldn't find public key hash in sub_script!")

                # first try uncompressed key
                h160 = None
                for compressed in [True, False]:
                    h160 = private_key.public_key.hash160(compressed)
                    if h160 != bytes.fromhex(script_pub_key_h160_hex[2:]):
                        h160 = None
                    else:
                        break

                if h160 is None:
                    raise ValueError("Address derived from private key does not match sub_script!")

            msg_to_sign = bytes(Hash.dhash(bytes(txn_copy) +
                                           pack_u32(hash_type)))

        sig = private_key.sign(msg_to_sign, False)

        if multisig:
            # For multisig, we need to determine if there are already
            # signatures and if so, where we insert this signature
            inp.script = self._do_multisig_script([dict(index=multisig_key_index,
                                                        signature=sig)],
                                                  msg_to_sign,
                                                  curr_script_sig,
                                                  tmp_script,
                                                  hash_type)
        else:
            pub_key_bytes = self._get_public_key_bytes(private_key, compressed)
            pub_key_str = pack_var_str(pub_key_bytes)
            script_sig = pack_var_str(
                sig.to_der() + pack_compact_int(hash_type)) + pub_key_str
            inp.script = Script(script_sig)

        return True