Exemplo n.º 1
0
    def add_in_transaction(self, tx_hash, index: int, keys: KeysBTC):
        """Add an input to the transaction"""

        # Convert tx_hash to bytes if it's str
        tx_hash = bytes.fromhex(tx_hash) \
            if isinstance(tx_hash, str) else tx_hash

        # Init a dictionary for an input
        tx_in = {}

        # Previous transaction hash -- tx_hash
        tx_in["previous_tx_hash"] = tx_hash[::-1]

        # Output point index -- index
        tx_in["previous_txout_index"] = struct.pack("<L", index)

        # Temporary signature script = output script
        # Generate a script with BTC-address for -- keys
        tx_in["script_sig"] = self.get_script_p2pkh(keys.get_pubkey_hash())

        # Temporary signature script length
        tx_in["script_length"] = struct.pack("<B", len(tx_in["script_sig"]))

        # Sequence 0xFFFFFFFF
        tx_in["sequence"] = b"\xff\xff\xff\xff"

        # Set a KeysBTC object using to sign this input
        tx_in["keys"] = keys

        # Add the dictionary with the input to the transaction
        self.ins[len(self.ins)] = tx_in
        return
Exemplo n.º 2
0
    def add_out_transaction(self, to_hash, value: int, tx_type: str = "p2pkh"):
        """Add an output to the transaction"""

        # Convert to_hash to public key hash if it's str
        to_hash = KeysBTC.address_to_pubkey_hash(to_hash) \
            if isinstance(to_hash, str) else to_hash

        # Init a dictionary for an output
        tx_out = {}

        # Amount in satoshies (8 bytes) -- value
        tx_out["value"] = struct.pack("<Q", value)

        # Output script (depends on type: p2pkh or p2sh)
        if tx_type == "p2pkh":
            tx_out["script_pubkey"] = self.get_script_p2pkh(to_hash)
        elif tx_type == "p2sh":
            tx_out["script_pubkey"] = self.get_script_p2sh(to_hash)
        else:
            raise ValueError("Invalid transaction type: {:s}".format(tx_type))

        # Output script length
        tx_out["script_length"] = \
            struct.pack("<B", len(tx_out["script_pubkey"]))

        # Add the dictionary with the output to the transaction
        self.outs[len(self.outs)] = tx_out
        return
Exemplo n.º 3
0
    def serialize(self):
        """Return serialized format (str) of this key (xprv / xpub)"""
        if self.is_private():
            ser_key = (
                MAINNET_PRIVATE +
                int2bytes(self.level, 1) +
                self.fingerprint +
                int2bytes(self.index, 4) +
                self.chain_code +
                b"\x00" +
                self.key
            )
        elif self.is_public():
            ser_key = (
                MAINNET_PUBLIC +
                int2bytes(self.level, 1) +
                self.fingerprint +
                int2bytes(self.index, 4) +
                self.chain_code +
                KeysBTC.point_to_publickey(self.key)
            )
        else:
            raise ValueError("Invalid extended key")

        checksum = sha256(sha256(ser_key))[:4]

        return base58_encode(ser_key + checksum)
Exemplo n.º 4
0
    def prv_to_child(parent_prv: ExtendedKey, index: int):
        """Return an extended child private key.

        Parameters:
            parent_prv -- a parent private key,
            index -- an index of a parent private key
        """
        cur_key = KeysBTC(parent_prv.key)
        ser32_index = int2bytes(index, 4)

        # If a hardened index the take the private key,
        # otherwise, take the public key.
        if index >= 2 ** 31:
            data = b"\x00" + cur_key.get_private_key() + ser32_index
        else:
            data = cur_key.get_public_key() + ser32_index

        child_hash = hmac_sha512(parent_prv.chain_code, data)

        child_hash_left = bytes2int(child_hash[:32])
        k_i = (child_hash_left + cur_key.get_private_key_int()) % \
              ECPoint.get_secp256k1_order()
        # Check the left part
        if child_hash_left >= ECPoint.get_secp256k1_order() or k_i == 0:
            raise ValueError("The resulting key is invalid")

        # The right part is child_hash[32:]
        return ExtendedKey(
            int2bytes(k_i),
            child_hash[32:],
            parent_prv.level + 1,    # increase level
            index,
            ExtendedKey.get_fingerprint(cur_key.get_public_key())
        )
Exemplo n.º 5
0
    def pub_to_child(parent_pub: ExtendedKey, index: int):
        """Return an extended child public key.

        Parameters:
            parent_pub -- a parent public key,
            index -- an index of a parent public key
        """
        # Check if index is not a hardened key
        if index >= 2 ** 31:
            raise ValueError(
                "Cannot generate a child public key because "
                "it is a hardened key"
            )

        ser32_index = int2bytes(index, 4)
        public_key = KeysBTC.point_to_publickey(parent_pub.key)

        data = public_key + ser32_index

        child_hash = hmac_sha512(parent_pub.chain_code, data)

        child_hash_left = bytes2int(child_hash[:32])
        K_i = KeysBTC.get_generator_point() * child_hash_left + parent_pub.key
        # Check the left part
        if child_hash_left >= ECPoint.get_secp256k1_order() or \
                K_i == ECPoint.infinity():
            raise ValueError(
                "The resulting key is invalid for index {:d}".format(index)
            )

        # The right part is child_hash[32:]
        return ExtendedKey(
            K_i,
            child_hash[32:],
            parent_pub.level + 1,    # increase level
            index,
            ExtendedKey.get_fingerprint(public_key)
        )
Exemplo n.º 6
0
    def __init__(self, master: ExtendedKey, level_indexes=None):
        """Construct an object.

        Parameters:
        master -- an extended master (root) key (ExtendedKey)
        level_indexes -- a path to the last key level (list),
                         ex. for m/0/1/0/<list> - [0, 1, 0]
        """
        self.level_indexes = [] if level_indexes is None else level_indexes

        if master.is_private():
            self.master_prv = master
            self.master_pub = \
                ExtendedKey(
                    KeysBTC(self.master_prv.key).get_public_point(),
                    self.master_prv.chain_code
                )
        elif master.is_public():
            self.master_prv = None
            self.master_pub = master
        else:
            raise ValueError("Invalid master key: {:s}", master)
Exemplo n.º 7
0
# --- Usage and testing ---
if __name__ == "__main__":

    from btc.utils import sha256
    from btc.keys import KeysBTC

    k = KeysBTC("96a69d6682a4b2eb522e896c2fa1b8ada485c472b983e27266d1d5c8c77ec374")

    # Check the right values at https://www.bitaddress.org
    # An object methods
    print("Private key (hex): ", k.get_private_key_hex())
    print("Private key (WIF-compressed): ", k.get_private_key_wif(True))
    print("Private key (WIF-uncompressed): ", k.get_private_key_wif(False))
    print("Public point: ", k.get_public_point())
    print("Public key (hex): ", k.get_public_key(compressed=True).hex(),)
    print("Is public key compressed: ", k.is_pubkey_compressed())
    print("Public key HASH160: ", k.get_pubkey_hash().hex())
    print("Address: ", k.get_address())

    # Static methods (convertions)
    print("Generator point: ", k.get_generator_point())
    print("Private key to WIF: ", k.privatekey_to_wif(k._private_key, compressed=False))
    print("WIF to private key", k.privatekey_from_wif(k.get_private_key_wif()).hex())
    print(k.address_to_pubkey_hash(k.get_address()).hex())

    # Sign and verify
    message = sha256(b"sample")
    r, s = k.sign(message)
    print(k.verify(message, r, s))
Exemplo n.º 8
0
if __name__ == "__main__":

    from btc.keys import KeysBTC
    from btc.transact import TransactBTC

    # Prepare transaction
    keys_from = KeysBTC(
        "5842f1ee4fe0517a09acf03a21798bd88b30611e34a3a6092ac2ae4c27c2ae27")
    keys_from.get_address(version=keys_from.get_addr_ver_test())  # testnet
    print(keys_from)

    # Prepare a transaction
    tx = TransactBTC(keys_from)

    tx.add_in_transaction(
        # previous ttransaction hash
        "fd17a13054a3c1647120d5280f416878d5f375ccc864d29e7902cfd8fbde6284",
        1,  # output
        keys_from  # KeysBTC object for signing
    )  # for example, the output is 0.50000000 btc

    tx.add_out_transaction(
        "2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF",
        49950000,  # value
        tx_type="p2sh"  # pay-to-script-hash
    )

    tx.sign_all_inputs()

    print(tx)
Exemplo n.º 9
0
        [
            BIP32.hardened_index(44),
            BIP32.hardened_index(0),
            BIP32.hardened_index(0)
        ]  # path -- m/44'/0'/0'
    )

    # Master private
    print(bip32_1.master_prv.serialize())

    # Master public
    print(bip32_1.master_pub.serialize())

    # Child private keys with indexes in [0, 9] from parent private key
    child_prv = [
        KeysBTC.privatekey_to_wif(c.key)
        for c in bip32_1.ckd_priv(range(0, 10))
    ]
    print("Child private keys from the parent private m/44'/0'/0'/[0, 9]: ",
          dict(zip(range(0, 10), child_prv)))

    # BIP32 with m/517/377/11
    root_pub = ExtendedKey(
        KeysBTC(root_prv.key).get_public_point(), root_prv.chain_code)
    bip32_2 = BIP32(root_pub, [517, 377, 11])  # path -- m/517/377/11

    # Child public keys from parent public key, only for non-hardened keys
    child_public = [
        KeysBTC.point_to_publickey(c.key).hex()
        for c in bip32_2.ckd_pub(range(0, 10))
    ]