Exemplo n.º 1
1
    def test_build_spends(self):
        # first, here is the tx database
        TX_DB = {}

        # create a coinbase Tx where we know the public & private key

        exponent = wif_to_secret_exponent("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")
        compressed = False

        public_key_sec = public_pair_to_sec(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent), compressed=compressed
        )

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971)
        TX_DB[the_coinbase_tx.hash()] = the_coinbase_tx

        # now create a Tx that spends the coinbase

        compressed = False

        exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_2), compressed=compressed
        )

        self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ", bitcoin_address_2)

        coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to)
        solver = build_hash160_lookup([exponent])

        coinbase_spend_tx = unsigned_coinbase_spend_tx.sign(solver)

        # now check that it validates
        self.assertEqual(coinbase_spend_tx.bad_signature_count(), 0)

        TX_DB[coinbase_spend_tx.hash()] = coinbase_spend_tx

        ## now try to respend from priv_key_2 to priv_key_3

        compressed = True

        exponent_3 = int("f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff", 16)
        bitcoin_address_3 = public_pair_to_bitcoin_address(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_3), compressed=compressed
        )

        self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5", bitcoin_address_3)

        coins_from = [(coinbase_spend_tx.hash(), 0, coinbase_spend_tx.txs_out[0])]
        unsigned_spend_tx = standard_tx(coins_from, [(int(50 * 1e8), bitcoin_address_3)])
        solver.update(build_hash160_lookup([exponent_2]))
        spend_tx = unsigned_spend_tx.sign(solver)

        # now check that it validates
        self.assertEqual(spend_tx.bad_signature_count(), 0)
Exemplo n.º 2
0
        def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec,
                    address_b58, c_address_b58):
            secret_exponent = int(exp_hex, 16)
            sec = binascii.unhexlify(public_pair_sec)
            c_sec = binascii.unhexlify(c_public_pair_sec)

            self.assertEqual(
                secret_exponent_to_wif(secret_exponent, compressed=False), wif)
            self.assertEqual(
                secret_exponent_to_wif(secret_exponent, compressed=True),
                c_wif)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertFalse(compressed)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                c_wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertTrue(compressed)

            public_pair = public_pair_for_secret_exponent(
                generator_secp256k1, secret_exponent)

            pk_public_pair = public_pair_from_sec(sec)
            compressed = is_sec_compressed(sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertFalse(is_sec_compressed(sec))
            self.assertEqual(
                public_pair_to_sec(pk_public_pair, compressed=False), sec)

            pk_public_pair = public_pair_from_sec(c_sec)
            compressed = is_sec_compressed(c_sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertTrue(compressed)
            self.assertEqual(
                public_pair_to_sec(pk_public_pair, compressed=True), c_sec)

            bca = public_pair_to_bitcoin_address(pk_public_pair,
                                                 compressed=True)
            self.assertEqual(bca, c_address_b58)

            self.assertEqual(
                bitcoin_address_to_ripemd160_sha_sec(c_address_b58),
                public_pair_to_ripemd160_sha_sec(pk_public_pair,
                                                 compressed=True))

            bca = public_pair_to_bitcoin_address(pk_public_pair,
                                                 compressed=False)
            self.assertEqual(bca, address_b58)

            self.assertEqual(
                bitcoin_address_to_ripemd160_sha_sec(address_b58),
                public_pair_to_ripemd160_sha_sec(pk_public_pair,
                                                 compressed=False))
Exemplo n.º 3
0
def main():
    parser = argparse.ArgumentParser(description="Bitcoin utilities. WARNING: obsolete. Use ku instead.")

    parser.add_argument('-a', "--address", help='show as Bitcoin address', action='store_true')
    parser.add_argument('-1', "--hash160", help='show as hash 160', action='store_true')
    parser.add_argument('-v', "--verbose", help='dump all information available', action='store_true')
    parser.add_argument('-w', "--wif", help='show as Bitcoin WIF', action='store_true')
    parser.add_argument('-n', "--uncompressed", help='show in uncompressed form', action='store_true')
    parser.add_argument('item', help='a WIF, secret exponent, X/Y public pair, SEC (as hex), hash160 (as hex), Bitcoin address', nargs="+")
    args = parser.parse_args()

    for c in args.item:
        # figure out what it is:
        #  - secret exponent
        #  - WIF
        #  - X/Y public key (base 10 or hex)
        #  - sec
        #  - hash160
        #  - Bitcoin address
        secret_exponent = parse_as_private_key(c)
        if secret_exponent:
            public_pair = ecdsa.public_pair_for_secret_exponent(secp256k1.generator_secp256k1, secret_exponent)
            print("secret exponent: %d" % secret_exponent)
            print("  hex:           %x" % secret_exponent)
            print("WIF:             %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=True))
            print("  uncompressed:  %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=False))
        else:
            public_pair = parse_as_public_pair(c)
        if public_pair:
            bitcoin_address_uncompressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=False)
            bitcoin_address_compressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=True)
            print("public pair x:   %d" % public_pair[0])
            print("public pair y:   %d" % public_pair[1])
            print("  x as hex:      %x" % public_pair[0])
            print("  y as hex:      %x" % public_pair[1])
            print("y parity:        %s" % "odd" if (public_pair[1] & 1) else "even")
            print("key pair as sec: %s" % b2h(encoding.public_pair_to_sec(public_pair, compressed=True)))
            s = b2h(encoding.public_pair_to_sec(public_pair, compressed=False))
            print("  uncompressed:  %s\\\n                   %s" % (s[:66], s[66:]))
            hash160 = encoding.public_pair_to_hash160_sec(public_pair, compressed=True)
            hash160_unc = encoding.public_pair_to_hash160_sec(public_pair, compressed=False)
            myeccpoint = encoding.public_pair_to_sec(public_pair, compressed=True)
            myhash     = encoding.ripemd160( myeccpoint ).digest(  )
            print("BTSX PubKey:     %s" % BTS_ADDRESS_PREFIX + encoding.b2a_base58(myeccpoint + myhash[ :4 ]))
        else:
            hash160 = parse_as_address(c)
            hash160_unc = None
        if not hash160:
            sys.stderr.write("can't decode input %s\n" % c)
            sys.exit(1)
        print("hash160:         %s" % b2h(hash160))
        if hash160_unc:
            print("  uncompressed:  %s" % b2h(hash160_unc))
        print("Bitcoin address: %s" % encoding.hash160_sec_to_bitcoin_address(hash160))
        if hash160_unc:
            print("  uncompressed:  %s" % encoding.hash160_sec_to_bitcoin_address(hash160_unc))
Exemplo n.º 4
0
        def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec,
                    address_b58, c_address_b58):
            secret_exponent = int(exp_hex, 16)
            sec = h2b(public_pair_sec)
            c_sec = h2b(c_public_pair_sec)

            self.assertEqual(
                secret_exponent_to_wif(secret_exponent, compressed=False), wif)
            self.assertEqual(
                secret_exponent_to_wif(secret_exponent, compressed=True),
                c_wif)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertFalse(compressed)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                c_wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertTrue(compressed)

            public_pair = secret_exponent * secp256k1_generator

            pk_public_pair = sec_to_public_pair(sec)
            compressed = is_sec_compressed(sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertFalse(is_sec_compressed(sec))
            self.assertEqual(
                public_pair_to_sec(pk_public_pair, compressed=False), sec)

            pk_public_pair = sec_to_public_pair(c_sec)
            compressed = is_sec_compressed(c_sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertTrue(compressed)
            self.assertEqual(
                public_pair_to_sec(pk_public_pair, compressed=True), c_sec)

            bca = public_pair_to_bitcoin_address(pk_public_pair,
                                                 compressed=True)
            self.assertEqual(bca, c_address_b58)

            self.assertEqual(
                bitcoin_address_to_hash160_sec(c_address_b58),
                public_pair_to_hash160_sec(pk_public_pair, compressed=True))

            bca = public_pair_to_bitcoin_address(pk_public_pair,
                                                 compressed=False)
            self.assertEqual(bca, address_b58)

            self.assertEqual(
                bitcoin_address_to_hash160_sec(address_b58),
                public_pair_to_hash160_sec(pk_public_pair, compressed=False))
Exemplo n.º 5
0
def main():
    parser = argparse.ArgumentParser(description="Bitcoin utilities.")

    parser.add_argument('-a', "--address", help='show as Bitcoin address', action='store_true')
    parser.add_argument('-1', "--hash160", help='show as hash 160', action='store_true')
    parser.add_argument('-v', "--verbose", help='dump all information available', action='store_true')
    parser.add_argument('-w', "--wif", help='show as Bitcoin WIF', action='store_true')
    parser.add_argument('-n', "--uncompressed", help='show in uncompressed form', action='store_true')
    parser.add_argument('item', help='a WIF, secret exponent, X/Y public pair, SEC (as hex), hash160 (as hex), Bitcoin address', nargs="+")
    args = parser.parse_args()

    for c in args.item:
        # figure out what it is:
        #  - secret exponent
        #  - WIF
        #  - X/Y public key (base 10 or hex)
        #  - sec
        #  - hash160
        #  - Bitcoin address
        secret_exponent = parse_as_private_key(c)
        if secret_exponent:
            public_pair = ecdsa.public_pair_for_secret_exponent(secp256k1.generator_secp256k1, secret_exponent)
            print("secret exponent: %d" % secret_exponent)
            print("  hex:           %x" % secret_exponent)
            print("WIF:             %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=True))
            print("  uncompressed:  %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=False))
        else:
            public_pair = parse_as_public_pair(c)
        if public_pair:
            bitcoin_address_uncompressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=False)
            bitcoin_address_compressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=True)
            print("public pair x:   %d" % public_pair[0])
            print("public pair y:   %d" % public_pair[1])
            print("  x as hex:      %x" % public_pair[0])
            print("  y as hex:      %x" % public_pair[1])
            print("y parity:        %s" % "odd" if (public_pair[1] & 1) else "even")
            print("key pair as sec: %s" % b2h(encoding.public_pair_to_sec(public_pair, compressed=True)))
            s = b2h(encoding.public_pair_to_sec(public_pair, compressed=False))
            print("  uncompressed:  %s\\\n                   %s" % (s[:66], s[66:]))
            hash160 = encoding.public_pair_to_hash160_sec(public_pair, compressed=True)
            hash160_unc = encoding.public_pair_to_hash160_sec(public_pair, compressed=False)
        else:
            hash160 = parse_as_address(c)
            hash160_unc = None
        if not hash160:
            sys.stderr.write("can't decode input %s\n" % c)
            sys.exit(1)
        print("hash160:         %s" % b2h(hash160))
        if hash160_unc:
            print("  uncompressed:  %s" % b2h(hash160_unc))
        print("Bitcoin address: %s" % encoding.hash160_sec_to_bitcoin_address(hash160))
        if hash160_unc:
            print("  uncompressed:  %s" % encoding.hash160_sec_to_bitcoin_address(hash160_unc))
Exemplo n.º 6
0
    def test_build_spends(self):
        # create a coinbase Tx where we know the public & private key

        exponent = wif_to_secret_exponent(
            "5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")
        compressed = False

        public_key_sec = public_pair_to_sec(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1,
                                                  exponent),
            compressed=compressed)

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8),
                                         COINBASE_BYTES_FROM_80971)

        # now create a Tx that spends the coinbase

        compressed = False

        exponent_2 = int(
            "137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1",
            16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1,
                                                  exponent_2),
            compressed=compressed)

        self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ",
                         bitcoin_address_2)

        TX_DB = dict((tx.hash(), tx) for tx in [the_coinbase_tx])

        coins_from = [(the_coinbase_tx.hash(), 0)]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        coinbase_spend_tx = Tx.standard_tx(coins_from, coins_to, TX_DB,
                                           [exponent])
        coinbase_spend_tx.validate(TX_DB)

        ## now try to respend from priv_key_2 to priv_key_3

        compressed = True

        exponent_3 = int(
            "f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff",
            16)
        bitcoin_address_3 = public_pair_to_bitcoin_address(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1,
                                                  exponent_3),
            compressed=compressed)

        self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5",
                         bitcoin_address_3)

        TX_DB = dict((tx.hash(), tx) for tx in [coinbase_spend_tx])

        spend_tx = Tx.standard_tx([(coinbase_spend_tx.hash(), 0)],
                                  [(int(50 * 1e8), bitcoin_address_3)], TX_DB,
                                  [exponent_2])

        spend_tx.validate(TX_DB)
Exemplo n.º 7
0
    def test_signature_hash(self):
        compressed = False
        exponent_2 = int(
            "137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1",
            16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1,
                                                  exponent_2),
            compressed=compressed)
        exponent = wif_to_secret_exponent(
            "5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")

        public_key_sec = public_pair_to_sec(
            ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1,
                                                  exponent),
            compressed=compressed)

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8),
                                         COINBASE_BYTES_FROM_80971)
        coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to)

        tx_out_script_to_check = the_coinbase_tx.txs_out[0].script
        idx = 0
        actual_hash = unsigned_coinbase_spend_tx.signature_hash(
            tx_out_script_to_check, idx, hash_type=SIGHASH_ALL)
        self.assertEqual(
            actual_hash,
            29819170155392455064899446505816569230970401928540834591675173488544269166940
        )
Exemplo n.º 8
0
def private_key_to_public_key(private_key_wif):
    secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
        private_key_wif, is_test=config.TESTNET)
    public_pair = public_pair_for_secret_exponent(generator_secp256k1,
                                                  secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 9
0
Arquivo: Key.py Projeto: Zibbo/pycoin
 def sec(self, use_uncompressed=None):
     """
     Return the SEC representation of this key, if available.
     If use_uncompressed is not set, the preferred representation is returned.
     """
     public_pair = self.public_pair()
     if public_pair is None:
         return None
     return public_pair_to_sec(public_pair, compressed=not self._use_uncompressed(use_uncompressed))
Exemplo n.º 10
0
    def test_build_spends(self):
        # first, here is the tx database
        TX_DB = {}

        def tx_out_for_hash_index_f(tx_hash, tx_out_idx):
            tx = TX_DB.get(tx_hash)
            return tx.txs_out[tx_out_idx]

        # create a coinbase Tx where we know the public & private key

        exponent = wif_to_secret_exponent("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")
        compressed = False

        public_key_sec = public_pair_to_sec(ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent), compressed=compressed)

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971)
        TX_DB[the_coinbase_tx.hash()] = the_coinbase_tx

        # now create a Tx that spends the coinbase

        compressed = False

        exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(
                ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_2),
                compressed=compressed)

        self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ", bitcoin_address_2)

        coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        unsigned_coinbase_spend_tx = UnsignedTx.standard_tx(coins_from, coins_to)
        solver = SecretExponentSolver([exponent])
        coinbase_spend_tx = unsigned_coinbase_spend_tx.sign(solver)

        # now check that it validates
        coinbase_spend_tx.validate(tx_out_for_hash_index_f)

        TX_DB[coinbase_spend_tx.hash()] = coinbase_spend_tx

        ## now try to respend from priv_key_2 to priv_key_3

        compressed = True

        exponent_3 = int("f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff", 16)
        bitcoin_address_3 = public_pair_to_bitcoin_address(
                ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_3),
                compressed=compressed)

        self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5", bitcoin_address_3)

        unsigned_spend_tx = UnsignedTx.standard_tx([(coinbase_spend_tx.hash(), 0, coinbase_spend_tx.txs_out[0])], [(int(50 * 1e8), bitcoin_address_3)])
        solver.add_secret_exponents([exponent_2])
        spend_tx = unsigned_spend_tx.sign(solver)

        # now check that it validates
        spend_tx.validate(tx_out_for_hash_index_f)
Exemplo n.º 11
0
def private_key_to_public_key (private_key_wif):
    try:
        secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif, [wif_prefix(is_test=config.TESTNET)])
    except EncodingError:
        raise exceptions.AltcoinSupportError('pycoin: unsupported WIF prefix')
    public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 12
0
def private_key_to_public_key (private_key_wif):
    try:
        secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif, [wif_prefix(is_test=config.TESTNET)])
    except EncodingError:
        raise exceptions.AltcoinSupportError('pycoin: unsupported WIF prefix')
    public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 13
0
Arquivo: Key.py Projeto: wpr101/pycoin
 def sec(self, use_uncompressed=None):
     """
     Return the SEC representation of this key, if available.
     If use_uncompressed is not set, the preferred representation is returned.
     """
     public_pair = self.public_pair()
     if public_pair is None:
         return None
     return public_pair_to_sec(public_pair, compressed=not self._use_uncompressed(use_uncompressed))
Exemplo n.º 14
0
def compress_pubkey(uncompressed_pubkey):
    """ Convert uncompressed public key to compressed public key.

    Args:
        pubkey (str): Hex encoded 65Byte uncompressed public key

    Return:
        str: Hex encoded 33Byte compressed public key
    """
    public_pair = encoding.sec_to_public_pair(h2b(uncompressed_pubkey))
    return b2h(encoding.public_pair_to_sec(public_pair, compressed=True))
Exemplo n.º 15
0
def uncompress_pubkey(pubkey):
    """ Convert compressed public key to uncompressed public key.

    Args:
        pubkey (str): Hex encoded 33Byte compressed public key

    Return:
        str: Hex encoded uncompressed 65byte public key (4 + x + y).
    """
    public_pair = encoding.sec_to_public_pair(h2b(pubkey))
    return b2h(encoding.public_pair_to_sec(public_pair, compressed=False))
Exemplo n.º 16
0
 def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address):
     self.assertEqual(encoding.sec_to_public_pair(as_sec), as_public_pair)
     self.assertEqual(encoding.public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec)
     self.assertEqual(encoding.is_sec_compressed(as_sec), is_compressed)
     self.assertEqual(encoding.public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed),
                      as_hash160_sec)
     self.assertEqual(encoding.hash160_sec_to_bitcoin_address(as_hash160_sec), as_bitcoin_address)
     self.assertEqual(encoding.public_pair_to_bitcoin_address(as_public_pair, compressed=is_compressed), as_bitcoin_address)
     self.assertTrue(encoding.is_valid_bitcoin_address(as_bitcoin_address))
     bad_address = as_bitcoin_address[:17] + chr(ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:]
     self.assertFalse(encoding.is_valid_bitcoin_address(bad_address))
 def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address):
     self.assertEqual(encoding.sec_to_public_pair(as_sec), as_public_pair)
     self.assertEqual(encoding.public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec)
     self.assertEqual(encoding.is_sec_compressed(as_sec), is_compressed)
     self.assertEqual(encoding.public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed),
                      as_hash160_sec)
     self.assertEqual(encoding.hash160_sec_to_bitcoin_address(as_hash160_sec), as_bitcoin_address)
     self.assertEqual(encoding.public_pair_to_bitcoin_address(as_public_pair, compressed=is_compressed), as_bitcoin_address)
     self.assertTrue(encoding.is_valid_bitcoin_address(as_bitcoin_address))
     bad_address = as_bitcoin_address[:17] + chr(ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:]
     self.assertFalse(encoding.is_valid_bitcoin_address(bad_address))
Exemplo n.º 18
0
 def dumppubkey(self, address):
     if is_valid_bitcoin_address(address)==False:
         return Exception("Invalid address %s" % address)
     try:
         secret_exponent = self.getsecretexponent(address)
         public_pair = ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, secret_exponent)
         pubkey = public_pair_to_sec(public_pair, compressed=True)
         pubkey = b2h(pubkey)
     except:
         raise Exception("Unknown address: %s" % address)
     return pubkey
Exemplo n.º 19
0
        def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58):
            secret_exponent = int(exp_hex, 16)
            sec = h2b(public_pair_sec)
            c_sec = h2b(c_public_pair_sec)

            self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=False), wif)
            self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=True), c_wif)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertFalse(compressed)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(c_wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertTrue(compressed)

            public_pair = secret_exponent * secp256k1_generator

            pk_public_pair = sec_to_public_pair(sec)
            compressed = is_sec_compressed(sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertFalse(is_sec_compressed(sec))
            self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=False), sec)

            pk_public_pair = sec_to_public_pair(c_sec)
            compressed = is_sec_compressed(c_sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertTrue(compressed)
            self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=True), c_sec)

            bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True)
            self.assertEqual(bca, c_address_b58)

            self.assertEqual(bitcoin_address_to_hash160_sec(c_address_b58),
                             public_pair_to_hash160_sec(pk_public_pair, compressed=True))

            bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False)
            self.assertEqual(bca, address_b58)

            self.assertEqual(bitcoin_address_to_hash160_sec(address_b58),
                             public_pair_to_hash160_sec(pk_public_pair, compressed=False))
Exemplo n.º 20
0
 def dumppubkey(self, address):
     if is_valid_bitcoin_address(address) == False:
         return Exception("Invalid address %s" % address)
     try:
         secret_exponent = self.getsecretexponent(address)
         public_pair = ecdsa.public_pair_for_secret_exponent(
             ecdsa.generator_secp256k1, secret_exponent)
         pubkey = public_pair_to_sec(public_pair, compressed=True)
         pubkey = b2h(pubkey)
     except:
         raise Exception("Unknown address: %s" % address)
     return pubkey
Exemplo n.º 21
0
def _report_addresses(irange):
    ms = _get_wallets()
    n = get_n()

    for i in irange:
        try:
            ms_i = [hexlify(public_pair_to_sec(m.subkey(i).public_pair)) 
                    for m in ms]
        except pycoin.wallet.InvalidKeyGeneratedError:
            continue
        info = conf.bitcoind.createmultisig(n, ms_i)
        yield i, info["address"]
Exemplo n.º 22
0
    def _calculate_all(self):
        for attr in "_secret_exponent _public_pair _wif_uncompressed _wif_compressed _sec_compressed" \
                " _sec_uncompressed _hash160_compressed _hash160_uncompressed _address_compressed" \
                " _address_uncompressed _netcode".split():
            setattr(self, attr, getattr(self, attr, None))

        if self._hierarchical_wallet:
            if self._hierarchical_wallet.is_private:
                self._secret_exponent = self._hierarchical_wallet.secret_exponent
            else:
                self._public_pair = self._hierarchical_wallet.public_pair
            self._netcode = self._hierarchical_wallet.netcode

        wif_prefix = wif_prefix_for_netcode(self._netcode)

        if self._secret_exponent:
            self._wif_uncompressed = secret_exponent_to_wif(
                self._secret_exponent, compressed=False, wif_prefix=wif_prefix)
            self._wif_compressed = secret_exponent_to_wif(
                self._secret_exponent, compressed=True, wif_prefix=wif_prefix)
            self._public_pair = ecdsa.public_pair_for_secret_exponent(
                ecdsa.generator_secp256k1, self._secret_exponent)

        if self._public_pair:
            self._sec_compressed = public_pair_to_sec(self._public_pair,
                                                      compressed=True)
            self._sec_uncompressed = public_pair_to_sec(self._public_pair,
                                                        compressed=False)
            self._hash160_compressed = hash160(self._sec_compressed)
            self._hash160_uncompressed = hash160(self._sec_uncompressed)

        address_prefix = address_prefix_for_netcode(self._netcode)

        if self._hash160_compressed:
            self._address_compressed = hash160_sec_to_bitcoin_address(
                self._hash160_compressed, address_prefix=address_prefix)

        if self._hash160_uncompressed:
            self._address_uncompressed = hash160_sec_to_bitcoin_address(
                self._hash160_uncompressed, address_prefix=address_prefix)
        def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58):
            secret_exponent = int(exp_hex, 16)
            sec = binascii.unhexlify(public_pair_sec)
            c_sec = binascii.unhexlify(c_public_pair_sec)

            self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=False), wif)
            self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=True), c_wif)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertFalse(compressed)

            exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(c_wif)
            self.assertEqual(exponent, secret_exponent)
            self.assertTrue(compressed)

            public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)

            pk_public_pair = public_pair_from_sec(sec)
            compressed = is_sec_compressed(sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertFalse(is_sec_compressed(sec))
            self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=False), sec)

            pk_public_pair = public_pair_from_sec(c_sec)
            compressed = is_sec_compressed(c_sec)
            self.assertEqual(pk_public_pair, public_pair)
            self.assertTrue(compressed)
            self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=True), c_sec)

            bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True)
            self.assertEqual(bca, c_address_b58)

            self.assertEqual(bitcoin_address_to_ripemd160_sha_sec(c_address_b58), public_pair_to_ripemd160_sha_sec(pk_public_pair, compressed=True))

            bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False)
            self.assertEqual(bca, address_b58)

            self.assertEqual(bitcoin_address_to_ripemd160_sha_sec(address_b58), public_pair_to_ripemd160_sha_sec(pk_public_pair, compressed=False))
Exemplo n.º 24
0
    def _calculate_all(self):
        for attr in "_secret_exponent _public_pair _wif_uncompressed _wif_compressed _sec_compressed" \
                " _sec_uncompressed _hash160_compressed _hash160_uncompressed _address_compressed" \
                " _address_uncompressed _netcode".split():
                setattr(self, attr, getattr(self, attr, None))

        if self._hierarchical_wallet:
            if self._hierarchical_wallet.is_private:
                self._secret_exponent = self._hierarchical_wallet.secret_exponent
            else:
                self._public_pair = self._hierarchical_wallet.public_pair
            self._netcode = self._hierarchical_wallet.netcode

        wif_prefix = wif_prefix_for_netcode(self._netcode)

        if self._secret_exponent:
            self._wif_uncompressed = secret_exponent_to_wif(
                self._secret_exponent, compressed=False, wif_prefix=wif_prefix)
            self._wif_compressed = secret_exponent_to_wif(
                self._secret_exponent, compressed=True, wif_prefix=wif_prefix)
            self._public_pair = ecdsa.public_pair_for_secret_exponent(
                ecdsa.generator_secp256k1, self._secret_exponent)

        if self._public_pair:
            self._sec_compressed = public_pair_to_sec(self._public_pair, compressed=True)
            self._sec_uncompressed = public_pair_to_sec(self._public_pair, compressed=False)
            self._hash160_compressed = hash160(self._sec_compressed)
            self._hash160_uncompressed = hash160(self._sec_uncompressed)

        address_prefix = address_prefix_for_netcode(self._netcode)

        if self._hash160_compressed:
            self._address_compressed = hash160_sec_to_bitcoin_address(
                self._hash160_compressed, address_prefix=address_prefix)

        if self._hash160_uncompressed:
            self._address_uncompressed = hash160_sec_to_bitcoin_address(
                self._hash160_uncompressed, address_prefix=address_prefix)
Exemplo n.º 25
0
def private_key_to_public_key(private_key_wif):
    if config.TESTNET:
        allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_TESTNET]
    else:
        allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_MAINNET]
    try:
        secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                private_key_wif, allowable_wif_prefixes=allowable_wif_prefixes)
    except EncodingError:
        raise AltcoinSupportError('pycoin: unsupported WIF prefix')
    public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 26
0
def private_key_to_public_key (private_key_wif):
    if config.TESTNET:
        allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_TESTNET]
    else:
        allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_MAINNET]
    try:
        secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                private_key_wif, allowable_wif_prefixes=allowable_wif_prefixes)
    except EncodingError:
        raise AltcoinSupportError('pycoin: unsupported WIF prefix')
    public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 27
0
def create_coinbase_tx(parser):
    args = parser.parse_args()
    try:
        if len(args.txinfo) != 1:
            parser.error("coinbase transactions need exactly one output parameter (wif/BTC count)")
        wif, btc_amount = args.txinfo[0].split("/")
        satoshi_amount = btc_to_satoshi(btc_amount)
        secret_exponent, compressed = encoding.wif_to_tuple_of_secret_exponent_compressed(wif)
        public_pair = ecdsa.public_pair_for_secret_exponent(ecdsa.secp256k1.generator_secp256k1, secret_exponent)
        public_key_sec = encoding.public_pair_to_sec(public_pair, compressed=compressed)
        coinbase_tx = Tx.coinbase_tx(public_key_sec, satoshi_amount)
        return coinbase_tx
    except Exception:
        parser.error("coinbase transactions need exactly one output parameter (wif/BTC count)")
Exemplo n.º 28
0
def create_coinbase_tx(parser):
    args = parser.parse_args()
    try:
        if len(args.txinfo) != 1:
            parser.error("coinbase transactions need exactly one output parameter (wif/BTC count)")
        wif, btc_amount = args.txinfo[0].split("/")
        satoshi_amount = btc_to_satoshi(btc_amount)
        secret_exponent, compressed = encoding.wif_to_tuple_of_secret_exponent_compressed(wif)
        public_pair = ecdsa.public_pair_for_secret_exponent(ecdsa.secp256k1.generator_secp256k1, secret_exponent)
        public_key_sec = encoding.public_pair_to_sec(public_pair, compressed=compressed)
        coinbase_tx = Tx.coinbase_tx(public_key_sec, satoshi_amount)
        return coinbase_tx
    except Exception:
        parser.error("coinbase transactions need exactly one output parameter (wif/BTC count)")
Exemplo n.º 29
0
 def get_auth_data(self, moniker):
     with self.lock:
         coin = self._wallet.make_coin_query({
             'asset': self.get_asset_definition(moniker),
             'spent': False,
         }).get_result()[0]
         pubKey = public_pair_to_sec(coin.address_rec.publicPoint.pair(), compressed=False)
         return {
             'color_set':   clubAsset['color_set'][0],
             'txhash':      coin.txhash,
             'outindex':    coin.outindex,
             'pubkey':      pubKey.encode('hex'),
             'privkey':     coin.address_rec.rawPrivKey,
             'address_rec': coin.address_rec,
         }
Exemplo n.º 30
0
    def test_signature_hash(self):
        compressed = False
        exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(exponent_2 * secp256k1_generator, compressed=compressed)
        exponent = wif_to_secret_exponent("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")

        public_key_sec = public_pair_to_sec(exponent * secp256k1_generator, compressed=compressed)

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971)
        coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to)

        tx_out_script_to_check = the_coinbase_tx.txs_out[0].script
        idx = 0
        actual_hash = unsigned_coinbase_spend_tx.signature_hash(tx_out_script_to_check, idx, hash_type=SIGHASH_ALL)
        self.assertEqual(actual_hash, 29819170155392455064899446505816569230970401928540834591675173488544269166940)
Exemplo n.º 31
0
 def get_auth_data(self, moniker):
     with self.lock:
         coin = self._wallet.make_coin_query({
             'asset':
             self.get_asset_definition(moniker),
             'spent':
             False,
         }).get_result()[0]
         pubKey = public_pair_to_sec(coin.address_rec.publicPoint.pair(),
                                     compressed=False)
         return {
             'color_set': clubAsset['color_set'][0],
             'txhash': coin.txhash,
             'outindex': coin.outindex,
             'pubkey': pubKey.encode('hex'),
             'privkey': coin.address_rec.rawPrivKey,
             'address_rec': coin.address_rec,
         }
Exemplo n.º 32
0
    def test_build_spends(self):
        # create a coinbase Tx where we know the public & private key

        exponent = wif_to_secret_exponent("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y")
        compressed = False

        public_key_sec = public_pair_to_sec(ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent), compressed=compressed)

        the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971)

        # now create a Tx that spends the coinbase

        compressed = False

        exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16)
        bitcoin_address_2 = public_pair_to_bitcoin_address(
                ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_2),
                compressed=compressed)

        self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ", bitcoin_address_2)

        TX_DB = dict((tx.hash(), tx) for tx in [the_coinbase_tx])

        coins_from = [(the_coinbase_tx.hash(), 0)]
        coins_to = [(int(50 * 1e8), bitcoin_address_2)]
        coinbase_spend_tx = Tx.standard_tx(coins_from, coins_to, TX_DB, [exponent])
        coinbase_spend_tx.validate(TX_DB)

        ## now try to respend from priv_key_2 to priv_key_3

        compressed = True

        exponent_3 = int("f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff", 16)
        bitcoin_address_3 = public_pair_to_bitcoin_address(
                ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, exponent_3),
                compressed=compressed)

        self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5", bitcoin_address_3)

        TX_DB = dict((tx.hash(), tx) for tx in [coinbase_spend_tx])

        spend_tx = Tx.standard_tx([(coinbase_spend_tx.hash(), 0)], [(int(50 * 1e8), bitcoin_address_3)], TX_DB, [exponent_2])

        spend_tx.validate(TX_DB)
Exemplo n.º 33
0
    def __call__(self, tx_out_script, signature_hash, signature_type):
        """Figure out how to create a signature for the incoming transaction, and sign it.

        tx_out_script: the tx_out script that needs to be "solved"
        signature_hash: the bignum hash value of the new transaction reassigning the coins
        signature_type: always SIGHASH_ALL (1)
        """

        if signature_hash == 0:
            raise SolvingError("signature_hash can't be 0")

        tx_script = TxScript(tx_out_script)
        opcode_value_list = tx_script.match_script_to_templates()

        ba = bytearray()

        compressed = True
        for opcode, v in opcode_value_list:
            if opcode == opcodes.OP_PUBKEY:
                public_pair = sec_to_public_pair(v)
                bitcoin_address = public_pair_to_bitcoin_address(
                    public_pair, compressed=compressed)
            elif opcode == opcodes.OP_PUBKEYHASH:
                bitcoin_address = hash160_sec_to_bitcoin_address(v)
            else:
                raise SolvingError("can't determine how to sign this script")

            secret_exponent = self.wallet.getsecretexponent(bitcoin_address)

            r, s = ecdsa.sign(ecdsa.generator_secp256k1, secret_exponent,
                              signature_hash)
            sig = der.sigencode_der(r, s) + bytes_from_int(signature_type)
            ba += tools.compile(binascii.hexlify(sig).decode("utf8"))
            if opcode == opcodes.OP_PUBKEYHASH:
                public_pair = ecdsa.public_pair_for_secret_exponent(
                    ecdsa.generator_secp256k1, secret_exponent)
                ba += tools.compile(
                    binascii.hexlify(
                        public_pair_to_sec(
                            public_pair,
                            compressed=compressed)).decode("utf8"))

        return bytes(ba)
    def __call__(self, tx_out_script, signature_hash, signature_type):
        """Figure out how to create a signature for the incoming transaction, and sign it.

        tx_out_script: the tx_out script that needs to be "solved"
        signature_hash: the bignum hash value of the new transaction reassigning the coins
        signature_type: always SIGHASH_ALL (1)
        """

        if signature_hash == 0:
            raise SolvingError("signature_hash can't be 0")

        tx_script = TxScript(tx_out_script)
        opcode_value_list = tx_script.match_script_to_templates()

        ba = bytearray()

        compressed = True
        for opcode, v in opcode_value_list:
            if opcode == opcodes.OP_PUBKEY:
                public_pair = sec_to_public_pair(v)
                bitcoin_address = public_pair_to_bitcoin_address(public_pair, compressed=compressed)
            elif opcode == opcodes.OP_PUBKEYHASH:
                bitcoin_address = hash160_sec_to_bitcoin_address(v)
            else:
                raise SolvingError("can't determine how to sign this script")

            secret_exponent = self.wallet.getsecretexponent(bitcoin_address)

            r, s = ecdsa.sign(ecdsa.generator_secp256k1, secret_exponent, signature_hash)
            sig = der.sigencode_der(r, s) + bytes_from_int(signature_type)
            ba += tools.compile(binascii.hexlify(sig).decode("utf8"))
            if opcode == opcodes.OP_PUBKEYHASH:
                public_pair = ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, secret_exponent)
                ba += tools.compile(
                    binascii.hexlify(public_pair_to_sec(public_pair, compressed=compressed)).decode("utf8")
                )

        return bytes(ba)
Exemplo n.º 35
0
    def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum, change_satoshi, prevtx_keynums, prevtx_outputs, prevtx_inputs):
        """
        Performs a tx signing test, comparing Polly's signed tx against the reference wallet.
    
        Basic tx signing parameters:
        
        keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to 
                          use as tx inputs. Funding above out_satoshi + change_satoshi will be fees.
        out_addr        - output address in bitcoin address format. 
        out_satoshi     - output amount in satoshis.
        change_keynum   - change key index in the wallet, use None for no change.
        change_satoshi  - change amount in satoshis, use 0 for no change. 
        
        
        Supporting (previous) txs will be created to fund keynums and are controlled by these parameters:
        
        prevtx_keynums  - keynums will show up as outputs of previous txs. A number randomly picked 
                          from this list controls how many keynums are chosen to include per prev tx.
        prevtx_outputs  - in addition to previous tx outputs funding keynums, other outputs may 
                          be present. A number randomly picked from this list controls how many 
                          ignored outputs are injected per keynum. 
        prevtx_inputs   - previous txs need inputs too. A number randomly picked from this list 
                          controls how many inputs are chosen per previous tx.
        """
        
        total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi) 
        fee_satoshi      = total_in_satoshi - out_satoshi - change_satoshi
        chain0           = self.wallet.subkey(0, is_hardened = True).subkey(0)
        chain1           = self.wallet.subkey(0, is_hardened = True).subkey(1)
        
        assert total_in_satoshi >= out_satoshi + change_satoshi
        assert len(keynums_satoshi) <= 32
    
        #
        # Step 1: send the inputs and outputs to use in the signed tx
        #
        
        # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now. 
        keys = [(keynum, encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair)) 
                for (keynum, _) in keynums_satoshi] 
        
        # Convert base58 address to raw hex address
        out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr)
        
        print()
        print("Sign tx parameters:", "")
        for i, (keynum, satoshi) in enumerate(keynums_satoshi):
            print("{:<10}{:16.8f} btc < key {}".format (" inputs" if 0 == i else "", satoshi          / 100000000, keynum))
        print("{:<10}{:16.8f} btc > {}".format         (" output",                   out_satoshi      / 100000000, self.hexstr(out_addr_160)))
        print("{:<10}{:16.8f} btc > key {}".format     (" change",                   change_satoshi   / 100000000, change_keynum))
        print("{:<10}{:16.8f} btc".format              (" fee",                      fee_satoshi      / 100000000))
        print("{:<10}{:16.8f} btc".format              (" total",                    total_in_satoshi / 100000000))
       
        print()
        print(self.PAD.format("Send tx parameters"), end='')
        
        # ---> send to Polly 
        self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum, change_satoshi) 

        print(self.__outok())
    
        #
        # Step 2: send previous txs to fund the inputs
        #
    
        print()

        cur = 0
        prevtx_info = []
    
        while cur < len(keynums_satoshi) :
    
            prevtx_outputs_satoshi = []
            
            # Calculate how many keynums will be associated with this prev tx
            end = min(cur + random.choice(prevtx_keynums), len(keynums_satoshi))
            
            # Create the prev tx output list
            for keynum, satoshi in keynums_satoshi[cur:end] :
        
                # Inject a random number of outputs not associated with tx input keynums
                for _ in range(0, random.choice(prevtx_outputs)) :
                    prevtx_outputs_satoshi.append((random.randint(0, 0x7FFFFFFF),  
                                                    random.randint(0, 2099999997690000)))
    
                # Add the outputs funding the tx input keynums 
                prevtx_outputs_satoshi.append((keynum, satoshi))
    
                # Create output script
                addr   = chain0.subkey(keynum, as_private = True).bitcoin_address()
                script = standard_tx_out_script(addr)
    
                # Capture some info we'll use later to verify the signed tx
                prevtx_info.append((keynum, 
                                    satoshi,
                                    script,
                                    0,                                # This is the hash and will be replaced later
                                    len(prevtx_outputs_satoshi) - 1)) # Index of the valid output
                
            print("{:30}{}".format("Make prev tx for keys", " ".join(str(keynum) for (keynum, _, _, _, _) in prevtx_info[cur:])))
            
            # Create the prev tx
            prevtx = self.create_prev_tx(win                 = Wallet.from_master_secret(bytes(0)), # create a dummy wallet 
                                         in_keynum           = list(range(0, random.choice(prevtx_inputs))), 
                                         sources_per_input   = 1, 
                                         wout                = chain0, 
                                         out_keynum_satoshi  = prevtx_outputs_satoshi, 
                                         fees_satoshi        = random.randint(100, 1000))
            
            # We have built the prev tx, calculate its hash (and reverse the bytes) 
            prevtx_hash = encoding.double_sha256(prevtx)[::-1] 
    
            # Update the hashes now that we have a full prev tx
            for i, (keynum, satoshi, script, _, outidx) in enumerate(prevtx_info[cur:]) :
                prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash, outidx)
                
            # Create the index table that matches a keynum index with an ouput index in this prev tx
            idx_table = [(keynum_idx + cur, outidx) for keynum_idx, (_, _, _, _, outidx) in enumerate(prevtx_info[cur:])] 
            
            print(self.PAD.format("Send prev tx "), end='')
            
            # ---> send to Polly
            self.polly.send_prev_tx(idx_table, prevtx)
    
            print(self.__outok())
    
            cur = end
        
        #
        # Step 3: generate a signed tx with the reference wallet and compare against Polly's
        #
    
        spendables = []
        wifs       = []
        
        # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing
        for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info:
            spendables.append(Spendable(satoshi, script, prevtx_hash, outidx))
            wifs.append(chain0.subkey(keynum, as_private = True).wif())
        
        change_addr = chain1.subkey(change_keynum).bitcoin_address()
        
        payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)]
        
        print()
        print(self.PAD.format("Make reference signature"))
    
        signed_tx     = create_signed_tx(spendables, payables, wifs, fee_satoshi)
        signed_tx     = self.get_tx_bytes(signed_tx)
        
        print(self.PAD.format("Get signed tx"), end='', flush = True)
        
        # <--- get the signed tx from Polly
        polly_signed_tx = self.polly.send_get_signed_tx()

        #print(self.txstr(polly_signed_tx))
        #print(self.txstr(signed_tx))
        
        print(self.__outok())
        
        # Compare reference wallet signed tx with polly's 
        assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr(signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
Exemplo n.º 36
0
def coinbase_tx(secret_exponent):
    public_pair = ecdsa.public_pair_for_secret_exponent(
        ecdsa.secp256k1.generator_secp256k1, secret_exponent)
    public_key_sec = public_pair_to_sec(public_pair)
    return Tx.coinbase_tx(public_key_sec, 2500000000)
Exemplo n.º 37
0
def _get_multisig_addr(ms, n, i):
    ms_i = [hexlify(public_pair_to_sec(m.subkey(i).public_pair))
            for m in ms]    
    info = conf.bitcoind.createmultisig(n, ms_i)
    return info
Exemplo n.º 38
0
assert(my_key.sec_as_hex() == bitcoin.core.b2x(my_key.sec()))

print("Public key hash160: ", b2h(my_key.hash160()))
print("      uncompressed: ", b2h(my_key.hash160(use_uncompressed=True)))

#print("Bitcoin Address   : ", my_key.address())
addr_compressed = encoding.public_pair_to_bitcoin_address(public_key, True, my_addr_prefix)
addr_uncompressed = encoding.public_pair_to_bitcoin_address(public_key, False, my_addr_prefix)

print("Bitcoin    Address: ", addr_compressed)
print("      uncompressed: ", addr_uncompressed)

assert(encoding.is_valid_bitcoin_address(addr_compressed, my_addr_prefix))
assert(encoding.is_valid_bitcoin_address(addr_uncompressed, my_addr_prefix))
assert(my_key.address() == addr_compressed)

pubkey_bytes = encoding.public_pair_to_sec(public_key, True);
assert(my_key.sec_as_hex() == b2h(pubkey_bytes))
pubkey_bytes = encoding.public_pair_to_sec(public_key, False);
assert(my_key.sec_as_hex(use_uncompressed=True) == b2h(pubkey_bytes))

print()
#CBitcoinAddress.from_bytes(bitcoin.core.serialize.Hash160(my_key.address()), 111)
btc_addr = CBitcoinAddress.from_bytes(bitcoin.base58.decode(my_key.address()), bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR'])
print("Bitcoin Address hex: ", hexlify(btc_addr.to_bytes()))
assert(bitcoin.base58.encode(btc_addr.to_bytes()) == addr_compressed)

pubkey_b58 = encoding.b2a_base58(pubkey_bytes)
#CBitcoinAddress.from_scriptPubKey(pubkey_b58)

Exemplo n.º 39
0
def transaction(tx_info,
                encoding,
                exact_fee=None,
                fee_provided=0,
                unittest=False,
                public_key_hex=None,
                allow_unconfirmed_inputs=False):

    (source, destination_outputs, data) = tx_info

    if exact_fee and not isinstance(exact_fee, int):
        raise exceptions.TransactionError('Exact fees must be in satoshis.')
    if not isinstance(fee_provided, int):
        raise exceptions.TransactionError('Fee provided must be in satoshis.')
    if encoding not in ('pubkeyhash', 'multisig', 'opreturn'):
        raise exceptions.TransactionError('Unknown encoding‐scheme.')

    # If public key is necessary for construction of (unsigned) transaction,
    # either use the public key provided, or derive it from a private key
    # retrieved from wallet.
    public_key = None
    if encoding in ('multisig', 'pubkeyhash'):
        # get the address type
        pdb.set_trace()
        p2sh = get_address_type(source)
        if p2sh:
            temp = rpc('validateaddress', [source])
            redeemscript = temp['hex']
        else:
            # If no public key was provided, derive from private key.
            if not public_key_hex:
                # Get private key.
                if unittest:
                    private_key_wif = 'cPdUqd5EbBWsjcG9xiL1hz8bEyGFiz4SW99maU9JgpL9TEcxUf3j'
                else:
                    private_key_wif = rpc('dumpprivkey', [source])

                # Derive public key.
                public_key_hex = private_key_to_public_key(private_key_wif)

            pubkeypair = bitcoin_utils.parse_as_public_pair(public_key_hex)
            if not pubkeypair:
                raise exceptions.InputError('Invalid private key.')
            public_key = public_pair_to_sec(pubkeypair, compressed=True)

    # Protocol change.
    if encoding == 'pubkeyhash' and get_block_count(
    ) < 293000 and not config.TESTNET:
        raise exceptions.TransactionError(
            'pubkeyhash encoding unsupported before block 293000')

    if config.PREFIX == config.UNITTEST_PREFIX: unittest = True

    # Validate source and all destination addresses.
    destinations = [address for address, value in destination_outputs]
    for address in destinations + [source]:
        if address:
            try:
                base58_decode(address, config.ADDRESSVERSION,
                              config.ADDRESSVERSION_MULTISIG)
            except Exception:  # TODO
                raise exceptions.AddressError('Invalid Bitcoin address:',
                                              address)

    # Check that the source is in wallet.
    if not unittest and encoding in ('multisig') and not public_key:
        if not rpc('validateaddress', [source])['ismine']:
            raise exceptions.AddressError('Not one of your Bitcoin addresses:',
                                          source)

    # Check that the destination output isn't a dust output.
    # Set null values to dust size.
    new_destination_outputs = []
    for address, value in destination_outputs:
        if encoding == 'multisig':
            if value == None: value = config.MULTISIG_DUST_SIZE
            if not value >= config.MULTISIG_DUST_SIZE:
                raise exceptions.TransactionError(
                    'Destination output is below the dust target value.')
        else:
            if value == None: value = config.REGULAR_DUST_SIZE
            if not value >= config.REGULAR_DUST_SIZE:
                raise exceptions.TransactionError(
                    'Destination output is below the dust target value.')
        new_destination_outputs.append((address, value))
    destination_outputs = new_destination_outputs

    # Divide data into chunks.
    if data:

        def chunks(l, n):
            """ Yield successive n‐sized chunks from l.
            """
            for i in range(0, len(l), n):
                yield l[i:i + n]

        if encoding == 'pubkeyhash':
            data_array = list(chunks(data + config.PREFIX,
                                     20 - 1))  # Prefix is also a suffix here.
        elif encoding == 'multisig':
            data_array = list(chunks(data, 33 - 1))
        elif encoding == 'opreturn':
            data_array = list(chunks(data, 80))
            assert len(
                data_array
            ) == 1  # Only one OP_RETURN output currently supported (messages should all be shorter than 80 bytes, at the moment).
    else:
        data_array = []

    # Calculate total BTC to be sent.
    btc_out = 0
    if encoding == 'multisig': data_value = config.MULTISIG_DUST_SIZE
    elif encoding == 'opreturn': data_value = config.OP_RETURN_VALUE
    else: data_value = config.REGULAR_DUST_SIZE  # Pay‐to‐PubKeyHash
    btc_out = sum([data_value for data_chunk in data_array])
    btc_out += sum([value for address, value in destination_outputs])

    # Get size of outputs.
    if encoding == 'multisig': data_output_size = 81  # 71 for the data
    elif encoding == 'opreturn': data_output_size = 90  # 80 for the data
    else: data_output_size = 25 + 9  # Pay‐to‐PubKeyHash (25 for the data?)
    outputs_size = ((25 + 9) * len(destination_outputs)) + (len(data_array) *
                                                            data_output_size)

    # Get inputs.
    unspent = get_unspent_txouts(source, normalize=True, unittest=unittest)
    unspent = sort_unspent_txouts(unspent, allow_unconfirmed_inputs)

    inputs, btc_in = [], 0
    change_quantity = 0
    sufficient_funds = False
    final_fee = config.FEE_PER_KB
    for coin in unspent:
        inputs.append(coin)
        btc_in += round(coin['amount'] * config.UNIT)

        # If exact fee is specified, use that. Otherwise, calculate size of tx and base fee on that (plus provide a minimum fee for selling BTC).
        if exact_fee:
            final_fee = exact_fee
        else:
            size = 181 * len(inputs) + outputs_size + 10
            necessary_fee = (int(size / 10000) + 1) * config.FEE_PER_KB
            final_fee = max(fee_provided, necessary_fee)
            assert final_fee >= 1 * config.FEE_PER_KB

        # Check if good.
        change_quantity = btc_in - (btc_out + final_fee)
        if change_quantity == 0 or change_quantity >= config.REGULAR_DUST_SIZE:  # If change is necessary, must not be a dust output.
            sufficient_funds = True
            break
    if not sufficient_funds:
        # Approximate needed change, fee by with most recently calculated quantities.
        total_btc_out = btc_out + max(change_quantity, 0) + final_fee
        raise exceptions.BalanceError(
            'Insufficient bitcoins at address {}. (Need approximately {} BTC.)'
            .format(source, total_btc_out / config.UNIT))

    # Construct outputs.
    if data: data_output = (data_array, data_value)
    else: data_output = None
    if change_quantity: change_output = (source, change_quantity)
    else: change_output = None

    # Serialise inputs and outputs.
    transaction = serialise(encoding,
                            inputs,
                            destination_outputs,
                            data_output,
                            change_output,
                            source=source,
                            public_key=public_key)
    unsigned_tx_hex = binascii.hexlify(transaction).decode('utf-8')
    return unsigned_tx_hex
Exemplo n.º 40
0
def generate_new_key():
    secret = secrets.randbits(256)
    secret_hex = b2a_hex(to_bytes_32(secret)).decode()
    key = Key(secret_exponent=secret)
    sec = public_pair_to_sec(key.public_pair())
    return b2a_hex(sec).decode(), secret_hex
def get_compressed_pubkey_format(pubkey):
    public_pair=encoding.sec_to_public_pair(encoding.binascii.unhexlify(pubkey))
    return encoding.binascii.hexlify(encoding.public_pair_to_sec(public_pair))
pubkey_hashed = encoding.public_pair_to_hash160_sec(pubkey_pair, False)
print("      uncompressed: ", bitcoin.core.b2x(pubkey_hashed))
pubkey_addr = encoding.hash160_sec_to_bitcoin_address(
    pubkey_hashed, address_prefix=my_pubaddr_prefix)
assert (addr_uncompressed == pubkey_addr)

print("Bitcoin    Address: ", addr_compressed)
print("      uncompressed: ", addr_uncompressed)
assert (encoding.is_valid_bitcoin_address(
    addr_compressed, allowable_prefixes=my_pubaddr_prefix))
assert (encoding.is_valid_bitcoin_address(
    addr_uncompressed, allowable_prefixes=my_pubaddr_prefix))
print()

## Uncompressed public key
pubkey_bytes = encoding.public_pair_to_sec(pubkey_pair, False)
# uncompressed
pubkey_b58 = encoding.b2a_base58(pubkey_bytes)
assert (pubkey_bytes == encoding.a2b_base58(pubkey_b58))

btc_addr = CBitcoinAddress.from_bytes(
    pubkey_bytes, bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR'])
assert (b2h(cec_key.get_pubkey()) == b2h(btc_addr.to_bytes()))
assert (hexlify(cec_key.get_pubkey()) == hexlify(pubkey_bytes))

#print("Uncompressed public key")
c_pubkey = CPubKey(pubkey_bytes)
#print("Is public key valid? ", c_pubkey.is_valid, ", compressed? ", c_pubkey.is_compressed)
assert (c_pubkey.is_compressed == False)
assert (c_pubkey.is_valid == True)
Exemplo n.º 43
0
def transaction (tx_info, encoding='auto', fee_per_kb=config.DEFAULT_FEE_PER_KB,
                 regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE,
                 multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE,
                 op_return_value=config.DEFAULT_OP_RETURN_VALUE, exact_fee=None,
                 fee_provided=0, public_key_hex=None,
                 allow_unconfirmed_inputs=False, armory=False):

    (source, destination_outputs, data) = tx_info

    # Data encoding methods.
    if data:
        if encoding == 'auto':
            if len(data) <= 40:
                # encoding = 'opreturn'
                encoding = 'multisig'   # BTCGuild isn’t mining OP_RETURN?!
            else:
                encoding = 'multisig'

        if encoding not in ('pubkeyhash', 'multisig', 'opreturn'):
            raise exceptions.TransactionError('Unknown encoding‐scheme.')

    if exact_fee and not isinstance(exact_fee, int):
        raise exceptions.TransactionError('Exact fees must be in satoshis.')
    if not isinstance(fee_provided, int):
        raise exceptions.TransactionError('Fee provided must be in satoshis.')

    # If public key is necessary for construction of (unsigned) transaction,
    # either use the public key provided, or derive it from a private key
    # retrieved from wallet.
    public_key = None
    if encoding in ('multisig', 'pubkeyhash'):
        # If no public key was provided, derive from private key.
        if not public_key_hex:
            # Get private key.
            if config.UNITTEST:
                private_key_wif = config.UNITTEST_PRIVKEY[source]
            else:
                private_key_wif = rpc('dumpprivkey', [source])

            # Derive public key.
            public_key_hex = private_key_to_public_key(private_key_wif)

        pubkeypair = bitcoin_utils.parse_as_public_pair(public_key_hex)
        if not pubkeypair:
            raise exceptions.InputError('Invalid private key.')
        public_key = public_pair_to_sec(pubkeypair, compressed=True)

    # Protocol change.
    if encoding == 'pubkeyhash' and get_block_count() < 293000 and not config.TESTNET:
        raise exceptions.TransactionError('pubkeyhash encoding unsupported before block 293000')

    # Validate source and all destination addresses.
    destinations = [address for address, value in destination_outputs]
    for address in destinations + [source]:
        if address:
            try:
                base58_decode(address, config.ADDRESSVERSION)
            except Exception:   # TODO
                raise exceptions.AddressError('Invalid Bitcoin address:', address)

    # Check that the source is in wallet.
    if not config.UNITTEST and encoding in ('multisig') and not public_key:
        if not rpc('validateaddress', [source])['ismine']:
            raise exceptions.AddressError('Not one of your Bitcoin addresses:', source)

    # Check that the destination output isn't a dust output.
    # Set null values to dust size.
    new_destination_outputs = []
    for address, value in destination_outputs:
        if encoding == 'multisig':
            if value == None: value = multisig_dust_size
            if not value >= multisig_dust_size:
                raise exceptions.TransactionError('Destination output is below the dust target value.')
        else:
            if value == None: value = regular_dust_size
            if not value >= regular_dust_size:
                raise exceptions.TransactionError('Destination output is below the dust target value.')
        new_destination_outputs.append((address, value))
    destination_outputs = new_destination_outputs

    # Divide data into chunks.
    if data:
        def chunks(l, n):
            """ Yield successive n‐sized chunks from l.
            """
            for i in range(0, len(l), n): yield l[i:i+n]
        if encoding == 'pubkeyhash':
            data_array = list(chunks(data + config.PREFIX, 20 - 1)) # Prefix is also a suffix here.
        elif encoding == 'multisig':
            data_array = list(chunks(data, 33 - 1))
        elif encoding == 'opreturn':
            data_array = list(chunks(data, config.OP_RETURN_MAX_SIZE))
            assert len(data_array) == 1 # Only one OP_RETURN output currently supported (OP_RETURN messages should all be shorter than 40 bytes, at the moment).
    else:
        data_array = []

    # Calculate total BTC to be sent.
    btc_out = 0
    if encoding == 'multisig': data_value = multisig_dust_size
    elif encoding == 'opreturn': data_value = op_return_value
    else: data_value = regular_dust_size # Pay‐to‐PubKeyHash
    btc_out = sum([data_value for data_chunk in data_array])
    btc_out += sum([value for address, value in destination_outputs])

    # Get size of outputs.
    if encoding == 'multisig': data_output_size = 81        # 71 for the data
    elif encoding == 'opreturn': data_output_size = 90      # 80 for the data
    else: data_output_size = 25 + 9                         # Pay‐to‐PubKeyHash (25 for the data?)
    outputs_size = ((25 + 9) * len(destination_outputs)) + (len(data_array) * data_output_size)

    # Get inputs.
    unspent = get_unspent_txouts(source, normalize=True)
    unspent = sort_unspent_txouts(unspent, allow_unconfirmed_inputs)
    logging.debug('Sorted UTXOs: {}'.format([print_coin(coin) for coin in unspent]))

    inputs, btc_in = [], 0
    change_quantity = 0
    sufficient_funds = False
    final_fee = fee_per_kb
    for coin in unspent:
        logging.debug('New input: {}'.format(print_coin(coin)))
        inputs.append(coin)
        btc_in += round(coin['amount'] * config.UNIT)

        # If exact fee is specified, use that. Otherwise, calculate size of tx and base fee on that (plus provide a minimum fee for selling BTC).
        if exact_fee:
            final_fee = exact_fee
        else:
            size = 181 * len(inputs) + outputs_size + 10
            necessary_fee = (int(size / 1000) + 1) * fee_per_kb
            final_fee = max(fee_provided, necessary_fee)
            assert final_fee >= 1 * fee_per_kb

        # Check if good.
        change_quantity = btc_in - (btc_out + final_fee)
        logging.debug('Change quantity: {} BTC'.format(change_quantity / config.UNIT))
        if change_quantity == 0 or change_quantity >= regular_dust_size: # If change is necessary, must not be a dust output.
            sufficient_funds = True
            break
    if not sufficient_funds:
        # Approximate needed change, fee by with most recently calculated quantities.
        total_btc_out = btc_out + max(change_quantity, 0) + final_fee
        raise exceptions.BalanceError('Insufficient bitcoins at address {}. (Need approximately {} {}.) To spend unconfirmed coins, use the flag `--unconfirmed`.'.format(source, total_btc_out / config.UNIT, config.BTC))

    # Construct outputs.
    if data: data_output = (data_array, data_value)
    else: data_output = None
    if change_quantity: change_output = (source, change_quantity)
    else: change_output = None

    # Serialise inputs and outputs.
    unsigned_tx = serialise(encoding, inputs, destination_outputs, data_output, change_output, source=source, public_key=public_key)
    unsigned_tx_hex = binascii.hexlify(unsigned_tx).decode('utf-8')

    # bip-0010
    try:
        if armory:
            txdp = []
            dpid = base58_encode(hashlib.sha256(unsigned_tx).digest())[:8]
            txdp.append(('-----BEGIN-TRANSACTION-' + dpid + '-----').ljust(80,'-'))

            magic_bytes = binascii.hexlify(config.MAGIC_BYTES).decode('utf-8')
            varIntTxSize = binascii.hexlify(len(unsigned_tx).to_bytes(2, byteorder='big')).decode('utf-8')
            txdp.append('_TXDIST_{}_{}_{}'.format(magic_bytes, dpid, varIntTxSize))
            tx_list = unsigned_tx_hex
            for coin in inputs:
                tx_list += get_raw_transaction(coin['txid'], json=False)
            for byte in range(0,len(tx_list),80):
                txdp.append(tx_list[byte:byte+80] )

            for index, coin in enumerate(inputs):
                index_fill = str(index).zfill(2)
                value = '{0:.8f}'.format(coin['amount'])
                txdp.append('_TXINPUT_{}_{}'.format(index_fill, value))

            txdp.append(('-----END-TRANSACTION-' + dpid + '-----').ljust(80,'-'))
            unsigned_tx_hex = '\n'.join(txdp)
    except Exception as e:
        print(e)

    return unsigned_tx_hex
Exemplo n.º 44
0
def serialise(inputs,
              destination_output=None,
              data_output=None,
              change_output=None,
              source=None,
              multisig=False):
    s = (1).to_bytes(4, byteorder='little')  # Version

    # Number of inputs.
    s += var_int(int(len(inputs)))

    # List of Inputs.
    for i in range(len(inputs)):
        txin = inputs[i]
        s += binascii.unhexlify(bytes(txin['txid'],
                                      'utf-8'))[::-1]  # TxOutHash
        s += txin['vout'].to_bytes(4, byteorder='little')  # TxOutIndex

        script = str.encode(txin['scriptPubKey'])
        s += var_int(int(len(script)))  # Script length
        s += script  # Script
        s += b'\xff' * 4  # Sequence

    # Number of outputs.
    n = 0
    if destination_output: n += 1
    if data_output:
        data_array, value = data_output
        for data_chunk in data_array:
            n += 1
    else:
        data_array = []
    if change_output: n += 1
    s += var_int(n)

    # Destination output.
    if destination_output:
        address, value = destination_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')  # Value
        script = OP_DUP  # OP_DUP
        script += OP_HASH160  # OP_HASH160
        script += op_push(20)  # Push 0x14 bytes
        script += pubkeyhash  # pubKeyHash
        script += OP_EQUALVERIFY  # OP_EQUALVERIFY
        script += OP_CHECKSIG  # OP_CHECKSIG
        s += var_int(int(len(script)))  # Script length
        s += script

    # Data output.
    for data_chunk in data_array:
        data_array, value = data_output  # DUPE
        s += value.to_bytes(8, byteorder='little')  # Value

        if multisig:
            # Get source public key (either provided as a string or derived from a private key in the wallet).
            if isinstance(multisig, str):
                pubkeypair = bitcoin_utils.parse_as_public_pair(multisig)
                source_pubkey = public_pair_to_sec(pubkeypair, compressed=True)
            else:
                if config.PREFIX == config.UNITTEST_PREFIX:
                    private_key_wif = 'cPdUqd5EbBWsjcG9xiL1hz8bEyGFiz4SW99maU9JgpL9TEcxUf3j'
                else:
                    private_key_wif = rpc('dumpprivkey', [source])
                if private_key_wif[0] == 'c': testnet = True
                else: testnet = False
                secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                    private_key_wif, is_test=testnet)
                public_pair = public_pair_for_secret_exponent(
                    generator_secp256k1, secret_exponent)
                source_pubkey = public_pair_to_sec(public_pair,
                                                   compressed=compressed)

            # Get data (fake) public key.
            pad_length = 33 - 1 - len(data_chunk)
            assert pad_length >= 0
            data_pubkey = bytes([len(data_chunk)
                                 ]) + data_chunk + (pad_length * b'\x00')

            script = OP_1  # OP_1
            script += op_push(
                len(source_pubkey))  # Push bytes of source public key
            script += source_pubkey  # Source public key
            script += op_push(
                len(data_pubkey))  # Push bytes of data chunk (fake) public key
            script += data_pubkey  # Data chunk (fake) public key
            script += OP_2  # OP_2
            script += OP_CHECKMULTISIG  # OP_CHECKMULTISIG
        else:
            script = OP_RETURN  # OP_RETURN
            script += op_push(len(
                data_chunk))  # Push bytes of data chunk (NOTE: OP_SMALLDATA?)
            script += data_chunk  # Data chunk
        s += var_int(int(len(script)))  # Script length
        s += script

    # Change output.
    if change_output:
        address, value = change_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')  # Value
        script = OP_DUP  # OP_DUP
        script += OP_HASH160  # OP_HASH160
        script += op_push(20)  # Push 0x14 bytes
        script += pubkeyhash  # pubKeyHash
        script += OP_EQUALVERIFY  # OP_EQUALVERIFY
        script += OP_CHECKSIG  # OP_CHECKSIG
        s += var_int(int(len(script)))  # Script length
        s += script

    s += (0).to_bytes(4, byteorder='little')  # LockTime
    return s
Exemplo n.º 45
0
def serialise(inputs,
              destination_output=None,
              data_output=None,
              change_output=None,
              multisig=False,
              source=None):
    s = (1).to_bytes(4, byteorder='little')  # Version

    # Number of inputs.
    s += var_int(int(len(inputs)))

    # List of Inputs.
    for i in range(len(inputs)):
        txin = inputs[i]
        s += binascii.unhexlify(bytes(txin['txid'],
                                      'utf-8'))[::-1]  # TxOutHash
        s += txin['vout'].to_bytes(4, byteorder='little')  # TxOutIndex

        # No signature.
        script = b''
        s += var_int(int(len(script)))  # Script length
        s += script  # Script
        s += b'\xff' * 4  # Sequence

    # Number of outputs.
    n = 0
    if destination_output: n += 1
    if data_output:
        data_array, value = data_output
        for data_chunk in data_array:
            n += 1
    else:
        data_array = []
    if change_output: n += 1
    s += var_int(n)

    # Destination output.
    if destination_output:
        address, value = destination_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')  # Value
        script = OP_DUP  # OP_DUP
        script += OP_HASH160  # OP_HASH160
        script += op_push(20)  # Push 0x14 bytes
        script += pubkeyhash  # pubKeyHash
        script += OP_EQUALVERIFY  # OP_EQUALVERIFY
        script += OP_CHECKSIG  # OP_CHECKSIG
        s += var_int(int(len(script)))  # Script length
        s += script

    # Data output.
    for data_chunk in data_array:
        data_array, value = data_output  # DUPE
        s += (value).to_bytes(8, byteorder='little')  # Value

        if multisig:
            # Get source public key.
            from pycoin.ecdsa import generator_secp256k1, public_pair_for_secret_exponent
            from pycoin.encoding import wif_to_tuple_of_secret_exponent_compressed, public_pair_to_sec
            private_key_wif = rpc('dumpprivkey', [source])
            secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(
                private_key_wif)
            public_pair = public_pair_for_secret_exponent(
                generator_secp256k1, secret_exponent)
            source_pubkey = public_pair_to_sec(public_pair,
                                               compressed=compressed)

            # Get data (fake) public key.
            pad_length = 33 - 1 - len(data_chunk)
            assert pad_length >= 0
            data_pubkey = bytes([len(data_chunk)
                                 ]) + data_chunk + (pad_length * b'\x00')

            script = OP_1  # OP_1
            script += op_push(
                len(source_pubkey))  # Push bytes of source public key
            script += source_pubkey  # Source public key
            script += op_push(
                len(data_pubkey))  # Push bytes of data chunk (fake) public key
            script += data_pubkey  # Data chunk (fake) public key
            script += OP_2  # OP_2
            script += OP_CHECKMULTISIG  # OP_CHECKMULTISIG
        else:
            script = OP_RETURN  # OP_RETURN
            script += op_push(len(
                data_chunk))  # Push bytes of data chunk (NOTE: OP_SMALLDATA?)
            script += data_chunk  # Data chunk
        s += var_int(int(len(script)))  # Script length
        s += script

    # Change output.
    if change_output:
        address, value = change_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')  # Value
        script = OP_DUP  # OP_DUP
        script += OP_HASH160  # OP_HASH160
        script += op_push(20)  # Push 0x14 bytes
        script += pubkeyhash  # pubKeyHash
        script += OP_EQUALVERIFY  # OP_EQUALVERIFY
        script += OP_CHECKSIG  # OP_CHECKSIG
        s += var_int(int(len(script)))  # Script length
        s += script

    s += (0).to_bytes(4, byteorder='little')  # LockTime
    return s
Exemplo n.º 46
0
def coinbase_tx(secret_exponent):
    public_pair = ecdsa.public_pair_for_secret_exponent(
        ecdsa.secp256k1.generator_secp256k1, secret_exponent)
    public_key_sec = public_pair_to_sec(public_pair)
    return Tx.coinbase_tx(public_key_sec, 2500000000)
Exemplo n.º 47
0
def serialise (inputs, destination_output=None, data_output=None, change_output=None, multisig=False, source=None):
    s  = (1).to_bytes(4, byteorder='little')                # Version

    # Number of inputs.
    s += var_int(int(len(inputs)))

    # List of Inputs.
    for i in range(len(inputs)):
        txin = inputs[i]
        s += binascii.unhexlify(bytes(txin['txid'], 'utf-8'))[::-1]         # TxOutHash
        s += txin['vout'].to_bytes(4, byteorder='little')   # TxOutIndex

        # No signature.
        script = b''
        s += var_int(int(len(script)))                      # Script length
        s += script                                         # Script
        s += b'\xff' * 4                                    # Sequence

    # Number of outputs.
    n = 0
    if destination_output: n += 1
    if data_output:
        data_array, value = data_output
        for data_chunk in data_array: n += 1
    else:
        data_array = []
    if change_output: n += 1
    s += var_int(n)

    # Destination output.
    if destination_output:
        address, value = destination_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    # Data output.
    for data_chunk in data_array:
        data_array, value = data_output # DUPE
        s += (value).to_bytes(8, byteorder='little')        # Value

        if multisig:
            # Get source public key.
            from pycoin.ecdsa import generator_secp256k1, public_pair_for_secret_exponent
            from pycoin.encoding import wif_to_tuple_of_secret_exponent_compressed, public_pair_to_sec
            private_key_wif = rpc('dumpprivkey', [source])
            secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif)
            public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
            source_pubkey = public_pair_to_sec(public_pair, compressed=compressed)

            # Get data (fake) public key.
            pad_length = 33 - 1 - len(data_chunk)
            assert pad_length >= 0
            data_pubkey = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00')

            script = OP_1                                   # OP_1
            script += op_push(len(source_pubkey))           # Push bytes of source public key
            script += source_pubkey                         # Source public key
            script += op_push(len(data_pubkey))             # Push bytes of data chunk (fake) public key
            script += data_pubkey                           # Data chunk (fake) public key
            script += OP_2                                  # OP_2
            script += OP_CHECKMULTISIG                      # OP_CHECKMULTISIG
        else:
            script = OP_RETURN                              # OP_RETURN
            script += op_push(len(data_chunk))              # Push bytes of data chunk (NOTE: OP_SMALLDATA?)
            script += data_chunk                            # Data chunk
        s += var_int(int(len(script)))                      # Script length
        s += script

    # Change output.
    if change_output:
        address, value = change_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    s += (0).to_bytes(4, byteorder='little')                # LockTime
    return s
Exemplo n.º 48
0
def serialise (inputs, destination_output=None, data_output=None, change_output=None, multisig=False, source=None, unsigned=False):
    assert not (multisig and unsigned is True)
    s  = (1).to_bytes(4, byteorder='little')                # Version

    # Number of inputs.
    s += var_int(int(len(inputs)))

    # List of Inputs.
    for i in range(len(inputs)):
        txin = inputs[i]
        s += binascii.unhexlify(bytes(txin['txid'], 'utf-8'))[::-1]         # TxOutHash
        s += txin['vout'].to_bytes(4, byteorder='little')   # TxOutIndex

        if not unsigned:
            # No signature.
            script = b''
        else:
            #pubkeyhash = base58_decode(source, config.ADDRESSVERSION)
            #script = OP_DUP                                     # OP_DUP
            #script += OP_HASH160                                # OP_HASH160
            #script += op_push(20)                               # Push 0x14 bytes
            #script += pubkeyhash                                # pubKeyHash
            #script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
            #script += OP_CHECKSIG                               # OP_CHECKSIG
            script = str.encode(txin['scriptPubKey'])

        s += var_int(int(len(script)))                      # Script length
        s += script                                         # Script
        s += b'\xff' * 4                                    # Sequence

    # Number of outputs.
    n = 0
    if destination_output: n += 1
    if data_output:
        data_array, value = data_output
        for data_chunk in data_array: n += 1
    else:
        data_array = []
    if change_output: n += 1
    s += var_int(n)

    # Destination output.
    if destination_output:
        address, value = destination_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    # Data output.
    for data_chunk in data_array:
        data_array, value = data_output # DUPE
        s += (value).to_bytes(8, byteorder='little')        # Value

        if multisig:
            # Get source public key.
            if unsigned:
                assert isinstance(unsigned, str)
                pubkeypair = bitcoin_utils.parse_as_public_pair(unsigned)
                source_pubkey = public_pair_to_sec(pubkeypair, compressed=True)
            else:
                if config.PREFIX == config.UNITTEST_PREFIX:
                    private_key_wif = 'cPdUqd5EbBWsjcG9xiL1hz8bEyGFiz4SW99maU9JgpL9TEcxUf3j'
                else:
                    private_key_wif = rpc('dumpprivkey', [source])
                if private_key_wif[0] == 'c': testnet = True
                else: testnet = False
                secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif, is_test=testnet)
                public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
                source_pubkey = public_pair_to_sec(public_pair, compressed=compressed)

            # Get data (fake) public key.
            pad_length = 33 - 1 - len(data_chunk)
            assert pad_length >= 0
            data_pubkey = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00')

            script = OP_1                                   # OP_1
            script += op_push(len(source_pubkey))           # Push bytes of source public key
            script += source_pubkey                         # Source public key
            script += op_push(len(data_pubkey))             # Push bytes of data chunk (fake) public key
            script += data_pubkey                           # Data chunk (fake) public key
            script += OP_2                                  # OP_2
            script += OP_CHECKMULTISIG                      # OP_CHECKMULTISIG
        else:
            script = OP_RETURN                              # OP_RETURN
            script += op_push(len(data_chunk))              # Push bytes of data chunk (NOTE: OP_SMALLDATA?)
            script += data_chunk                            # Data chunk
        s += var_int(int(len(script)))                      # Script length
        s += script

    # Change output.
    if change_output:
        address, value = change_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    s += (0).to_bytes(4, byteorder='little')                # LockTime
    return s
def get_compressed_pubkey_format(pubkey):
    public_pair=encoding.sec_to_public_pair(encoding.binascii.unhexlify(pubkey))
    return encoding.binascii.hexlify(encoding.public_pair_to_sec(public_pair))
Exemplo n.º 50
0
def main():
    parser = argparse.ArgumentParser(description="Bitcoin utilities.")

    parser.add_argument("-a", "--address", help="show as Bitcoin address", action="store_true")
    parser.add_argument("-1", "--hash160", help="show as hash 160", action="store_true")
    parser.add_argument("-v", "--verbose", help="dump all information available", action="store_true")
    parser.add_argument("-w", "--wif", help="show as Bitcoin WIF", action="store_true")
    parser.add_argument("-n", "--uncompressed", help="show in uncompressed form", action="store_true")
    parser.add_argument("-j", "--json", help="output in JSON format", action="store_true")
    parser.add_argument("-t", help="interpret fields as test values", action="store_true")
    parser.add_argument("-ltc", help="generate LTC address", action="store_true")
    parser.add_argument("-doge", help="generate DOGE address", action="store_true")
    parser.add_argument(
        "item",
        help="a WIF, secret exponent, X/Y public pair, SEC (as hex), hash160 (as hex), Bitcoin address",
        nargs="+",
    )
    args = parser.parse_args()

    if args.ltc:
        args.t = "litecoin"
    else:
        if args.doge:
            if args.t:
                args.t = "dogetest"
            else:
                args.t = "doge"

    if args.json:
        print("{")
        argcount = len(args.item)
        i = 0
        for c in args.item:
            i = i + 1
            print('  "%s" : { ' % c)
            secret_exponent = parse_as_private_key(c)
            if secret_exponent:
                public_pair = ecdsa.public_pair_for_secret_exponent(secp256k1.generator_secp256k1, secret_exponent)
                print('    "secret_exponent" : "%d",' % secret_exponent)
                print('    "secret_exponent_hex" : "%x",' % secret_exponent)
                print(
                    '    "wif" : "%s",'
                    % encoding.secret_exponent_to_wif(secret_exponent, compressed=True, is_test=args.t)
                )
                print(
                    '    "wif_uncompressed" : "%s",'
                    % encoding.secret_exponent_to_wif(secret_exponent, compressed=False, is_test=args.t)
                )
            else:
                public_pair = parse_as_public_pair(c)
            if public_pair:
                bitcoin_address_uncompressed = encoding.public_pair_to_bitcoin_address(
                    public_pair, compressed=False, is_test=args.t
                )
                bitcoin_address_compressed = encoding.public_pair_to_bitcoin_address(
                    public_pair, compressed=True, is_test=args.t
                )
                print('    "public_pair_x" : "%d",' % public_pair[0])
                print('    "public_pair_y" : "%d",' % public_pair[1])
                print('    "x_as_hex" : "%x",' % public_pair[0])
                print('    "y_as_hex" : "%x",' % public_pair[1])
                if public_pair[1] & 1:
                    print('    "y_parity" : "odd",')
                else:
                    print('    "y_parity" : "even",')
                print('    "key_pair_as_sec" : "%s",' % b2h(encoding.public_pair_to_sec(public_pair, compressed=True)))
                hash160 = encoding.public_pair_to_hash160_sec(public_pair, compressed=True)
                hash160_unc = encoding.public_pair_to_hash160_sec(public_pair, compressed=False)
            else:
                hash160 = parse_as_address(c)
                hash160_unc = None
            if not hash160:
                print('  "error" : "cannot decode input %s",' % c)
            print('    "hash160" : "%s",' % b2h(hash160))
            if hash160_unc:
                print('    "hash160_uncompressed" : "%s",' % b2h(hash160_unc))
            if hash160_unc:
                # print('    "bitcoind_addr_uncompressed" : "%s",' % encoding.hash160_sec_to_bitcoin_address(hash160_unc))
                print('    "bitcoind_addr_uncompressed" : "%s",' % bitcoin_address_uncompressed)
            # print('    "bitcoin_addr" : "%s"' % encoding.hash160_sec_to_bitcoin_address(hash160))
            print('    "bitcoin_addr" : "%s"' % bitcoin_address_compressed)
            if i == argcount:
                print("  }")
            else:
                print("  },")
        print("}")
    else:
        for c in args.item:
            # figure out what it is:
            #  - secret exponent
            #  - WIF
            #  - X/Y public key (base 10 or hex)
            #  - sec
            #  - hash160
            #  - Bitcoin address
            secret_exponent = parse_as_private_key(c)
            if secret_exponent:
                public_pair = ecdsa.public_pair_for_secret_exponent(secp256k1.generator_secp256k1, secret_exponent)
                print("secret exponent: %d" % secret_exponent)
                print("  hex:           %x" % secret_exponent)
                print("WIF:             %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=True))
                print("  uncompressed:  %s" % encoding.secret_exponent_to_wif(secret_exponent, compressed=False))
            else:
                public_pair = parse_as_public_pair(c)
            if public_pair:
                bitcoin_address_uncompressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=False)
                bitcoin_address_compressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=True)
                print("public pair x:   %d" % public_pair[0])
                print("public pair y:   %d" % public_pair[1])
                print("  x as hex:      %x" % public_pair[0])
                print("  y as hex:      %x" % public_pair[1])
                print("y parity:        %s" % "odd" if (public_pair[1] & 1) else "even")
                print("key pair as sec: %s" % b2h(encoding.public_pair_to_sec(public_pair, compressed=True)))
                s = b2h(encoding.public_pair_to_sec(public_pair, compressed=False))
                print("  uncompressed:  %s\\\n                   %s" % (s[:66], s[66:]))
                hash160 = encoding.public_pair_to_hash160_sec(public_pair, compressed=True)
                hash160_unc = encoding.public_pair_to_hash160_sec(public_pair, compressed=False)
            else:
                hash160 = parse_as_address(c)
                hash160_unc = None
            if not hash160:
                sys.stderr.write("can't decode input %s\n" % c)
                sys.exit(1)
            print("hash160:         %s" % b2h(hash160))
            if hash160_unc:
                print("  uncompressed:  %s" % b2h(hash160_unc))
            print("Bitcoin address: %s" % encoding.hash160_sec_to_bitcoin_address(hash160))
            if hash160_unc:
                print("  uncompressed:  %s" % encoding.hash160_sec_to_bitcoin_address(hash160_unc))
Exemplo n.º 51
0
def private_key_to_public_key (private_key_wif):
    secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif, is_test=config.TESTNET)
    public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
    public_key = public_pair_to_sec(public_pair, compressed=compressed)
    public_key_hex = binascii.hexlify(public_key).decode('utf-8')
    return public_key_hex
Exemplo n.º 52
0
    def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum,
                  change_satoshi, prevtx_keynums, prevtx_outputs,
                  prevtx_inputs):
        """
        Performs a tx signing test, comparing Polly's signed tx against the reference wallet.
    
        Basic tx signing parameters:
        
        keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to 
                          use as tx inputs. Funding above out_satoshi + change_satoshi will be fees.
        out_addr        - output address in bitcoin address format. 
        out_satoshi     - output amount in satoshis.
        change_keynum   - change key index in the wallet, use None for no change.
        change_satoshi  - change amount in satoshis, use 0 for no change. 
        
        
        Supporting (previous) txs will be created to fund keynums and are controlled by these parameters:
        
        prevtx_keynums  - keynums will show up as outputs of previous txs. A number randomly picked 
                          from this list controls how many keynums are chosen to include per prev tx.
        prevtx_outputs  - in addition to previous tx outputs funding keynums, other outputs may 
                          be present. A number randomly picked from this list controls how many 
                          ignored outputs are injected per keynum. 
        prevtx_inputs   - previous txs need inputs too. A number randomly picked from this list 
                          controls how many inputs are chosen per previous tx.
        """

        total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi)
        fee_satoshi = total_in_satoshi - out_satoshi - change_satoshi
        chain0 = self.wallet.subkey(0, is_hardened=True).subkey(0)
        chain1 = self.wallet.subkey(0, is_hardened=True).subkey(1)

        assert total_in_satoshi >= out_satoshi + change_satoshi
        assert len(keynums_satoshi) <= 32

        #
        # Step 1: send the inputs and outputs to use in the signed tx
        #

        # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now.
        keys = [
            (keynum,
             encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair))
            for (keynum, _) in keynums_satoshi
        ]

        # Convert base58 address to raw hex address
        out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr)

        print()
        print("Sign tx parameters:", "")
        for i, (keynum, satoshi) in enumerate(keynums_satoshi):
            print("{:<10}{:16.8f} btc < key {}".format(
                " inputs" if 0 == i else "", satoshi / 100000000, keynum))
        print("{:<10}{:16.8f} btc > {}".format(" output",
                                               out_satoshi / 100000000,
                                               self.hexstr(out_addr_160)))
        print("{:<10}{:16.8f} btc > key {}".format(" change",
                                                   change_satoshi / 100000000,
                                                   change_keynum))
        print("{:<10}{:16.8f} btc".format(" fee", fee_satoshi / 100000000))
        print("{:<10}{:16.8f} btc".format(" total",
                                          total_in_satoshi / 100000000))

        print()
        print(self.PAD.format("Send tx parameters"), end='')

        # ---> send to Polly
        self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum,
                                change_satoshi)

        print(self.__outok())

        #
        # Step 2: send previous txs to fund the inputs
        #

        print()

        cur = 0
        prevtx_info = []

        while cur < len(keynums_satoshi):

            prevtx_outputs_satoshi = []

            # Calculate how many keynums will be associated with this prev tx
            end = min(cur + random.choice(prevtx_keynums),
                      len(keynums_satoshi))

            # Create the prev tx output list
            for keynum, satoshi in keynums_satoshi[cur:end]:

                # Inject a random number of outputs not associated with tx input keynums
                for _ in range(0, random.choice(prevtx_outputs)):
                    prevtx_outputs_satoshi.append(
                        (random.randint(0, 0x7FFFFFFF),
                         random.randint(0, 2099999997690000)))

                # Add the outputs funding the tx input keynums
                prevtx_outputs_satoshi.append((keynum, satoshi))

                # Create output script
                addr = chain0.subkey(keynum, as_private=True).bitcoin_address()
                script = standard_tx_out_script(addr)

                # Capture some info we'll use later to verify the signed tx
                prevtx_info.append((
                    keynum,
                    satoshi,
                    script,
                    0,  # This is the hash and will be replaced later
                    len(prevtx_outputs_satoshi) -
                    1))  # Index of the valid output

            print("{:30}{}".format(
                "Make prev tx for keys", " ".join(
                    str(keynum)
                    for (keynum, _, _, _, _) in prevtx_info[cur:])))

            # Create the prev tx
            prevtx = self.create_prev_tx(
                win=Wallet.from_master_secret(
                    bytes(0)),  # create a dummy wallet 
                in_keynum=list(range(0, random.choice(prevtx_inputs))),
                sources_per_input=1,
                wout=chain0,
                out_keynum_satoshi=prevtx_outputs_satoshi,
                fees_satoshi=random.randint(100, 1000))

            # We have built the prev tx, calculate its hash (and reverse the bytes)
            prevtx_hash = encoding.double_sha256(prevtx)[::-1]

            # Update the hashes now that we have a full prev tx
            for i, (keynum, satoshi, script, _,
                    outidx) in enumerate(prevtx_info[cur:]):
                prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash,
                                        outidx)

            # Create the index table that matches a keynum index with an ouput index in this prev tx
            idx_table = [
                (keynum_idx + cur, outidx)
                for keynum_idx, (_, _, _, _,
                                 outidx) in enumerate(prevtx_info[cur:])
            ]

            print(self.PAD.format("Send prev tx "), end='')

            # ---> send to Polly
            self.polly.send_prev_tx(idx_table, prevtx)

            print(self.__outok())

            cur = end

        #
        # Step 3: generate a signed tx with the reference wallet and compare against Polly's
        #

        spendables = []
        wifs = []

        # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing
        for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info:
            spendables.append(Spendable(satoshi, script, prevtx_hash, outidx))
            wifs.append(chain0.subkey(keynum, as_private=True).wif())

        change_addr = chain1.subkey(change_keynum).bitcoin_address()

        payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)]

        print()
        print(self.PAD.format("Make reference signature"))

        signed_tx = create_signed_tx(spendables, payables, wifs, fee_satoshi)
        signed_tx = self.get_tx_bytes(signed_tx)

        print(self.PAD.format("Get signed tx"), end='', flush=True)

        # <--- get the signed tx from Polly
        polly_signed_tx = self.polly.send_get_signed_tx()

        #print(self.txstr(polly_signed_tx))
        #print(self.txstr(signed_tx))

        print(self.__outok())

        # Compare reference wallet signed tx with polly's
        assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr(
            signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
Exemplo n.º 53
0
def transaction (tx_info, encoding, unittest=False, public_key_hex=None, allow_unconfirmed_inputs=False):

    if len(tx_info) == 3:
        source, destination_outputs, data = tx_info
        fee_provided = 0
    else:
        source, destination_outputs, data, fee_provided = tx_info
    if not isinstance(fee_provided, int):
        raise exceptions.TransactionError('Fee provided must be in satoshis')
    if encoding not in ('pubkeyhash', 'multisig', 'opreturn'):
        raise exceptions.TransactionError('Unknown encoding‐scheme.')

    # If public key is necessary for construction of (unsigned) transaction,
    # either use the public key provided, or derive it from a private key
    # retrieved from wallet.
    public_key = None
    if encoding in ('multisig', 'pubkeyhash'):
        # If no public key was provided, derive from private key.
        if not public_key_hex:
            # Get private key.
            if unittest:
                private_key_wif = 'cPdUqd5EbBWsjcG9xiL1hz8bEyGFiz4SW99maU9JgpL9TEcxUf3j'
            else:
                private_key_wif = rpc('dumpprivkey', [source])

            # Derive public key.
            public_key_hex = private_key_to_public_key(private_key_wif)
            
        pubkeypair = bitcoin_utils.parse_as_public_pair(public_key_hex)
        public_key = public_pair_to_sec(pubkeypair, compressed=True)

    # Protocol change.
    if encoding == 'pubkeyhash' and get_block_count() < 293000 and not config.TESTNET:
        raise exceptions.TransactionError('pubkeyhash encoding unsupported before block 293000')
    
    if config.PREFIX == config.UNITTEST_PREFIX: unittest = True

    # Validate source and all destination addresses.
    destinations = [address for address, value in destination_outputs]
    for address in destinations + [source]:
        if address:
            try:
                base58_decode(address, config.ADDRESSVERSION)
            except Exception:   # TODO
                raise exceptions.AddressError('Invalid Bitcoin address:', address)

    # Check that the source is in wallet.
    if not unittest and encoding in ('multisig') and not public_key:
        if not rpc('validateaddress', [source])['ismine']:
            raise exceptions.AddressError('Not one of your Bitcoin addresses:', source)

    # Check that the destination output isn't a dust output.
    # Set null values to dust size.
    new_destination_outputs = []
    for address, value in destination_outputs:
        if encoding == 'multisig':
            if value == None: value = config.MULTISIG_DUST_SIZE
            if not value >= config.MULTISIG_DUST_SIZE:
                raise exceptions.TransactionError('Destination output is below the dust target value.')
        else:
            if value == None: value = config.REGULAR_DUST_SIZE
            if not value >= config.REGULAR_DUST_SIZE:
                raise exceptions.TransactionError('Destination output is below the dust target value.')
        new_destination_outputs.append((address, value))
    destination_outputs = new_destination_outputs

    # Divide data into chunks.
    if data:
        def chunks(l, n):
            """ Yield successive n‐sized chunks from l.
            """
            for i in range(0, len(l), n): yield l[i:i+n]
        if encoding == 'pubkeyhash':
            data_array = list(chunks(data + config.PREFIX, 20 - 1)) # Prefix is also a suffix here.
        elif encoding == 'multisig':
            data_array = list(chunks(data, 33 - 1))
        elif encoding == 'opreturn':
            data_array = list(chunks(data, 80))
            assert len(data_array) == 1 # Only one OP_RETURN output currently supported (messages should all be shorter than 80 bytes, at the moment).
    else:
        data_array = []

    # Calculate total BTC to be sent.
    btc_out = 0
    if encoding == 'multisig': data_value = config.MULTISIG_DUST_SIZE
    elif encoding == 'opreturn': data_value = config.OP_RETURN_VALUE
    else: data_value = config.REGULAR_DUST_SIZE # Pay‐to‐PubKeyHash
    btc_out = sum([data_value for data_chunk in data_array])
    btc_out += sum([value for address, value in destination_outputs])

    # Get size of outputs.
    if encoding == 'multisig': data_output_size = 81        # 71 for the data
    elif encoding == 'opreturn': data_output_size = 90      # 80 for the data
    else: data_output_size = 25 + 9                         # Pay‐to‐PubKeyHash (25 for the data?)
    outputs_size = ((25 + 9) * len(destination_outputs)) + (len(data_array) * data_output_size)

    # Get inputs.
    unspent = get_unspent_txouts(source, normalize=True, unittest=unittest, allow_unconfirmed_inputs=allow_unconfirmed_inputs)

    inputs, btc_in = [], 0
    change_quantity = 0
    sufficient_funds = False
    final_fee = config.FEE_PER_KB
    for coin in sorted(unspent,key=lambda x:input_value_weight(x['amount'])):
        inputs.append(coin)
        btc_in += round(coin['amount'] * config.UNIT)
        size = 181 * len(inputs) + outputs_size + 10
        necessary_fee = (int(size / 10000) + 1) * config.FEE_PER_KB
        final_fee = max(fee_provided, necessary_fee)
        change_quantity = btc_in - (btc_out + final_fee)
        if change_quantity == 0 or change_quantity >= config.REGULAR_DUST_SIZE: # If change is necessary, must not be a dust output.
            sufficient_funds = True
            break
    if not sufficient_funds:
        # Approximate needed change, fee by with most recently calculated quantities.
        total_btc_out = btc_out + max(change_quantity, 0) + final_fee
        raise exceptions.BalanceError('Insufficient bitcoins at address {}. (Need approximately {} BTC.)'.format(source, total_btc_out / config.UNIT))

    # Construct outputs.
    if data: data_output = (data_array, data_value)
    else: data_output = None
    if change_quantity: change_output = (source, change_quantity)
    else: change_output = None

    # Serialise inputs and outputs.
    transaction = serialise(encoding, inputs, destination_outputs, data_output, change_output, source=source, public_key=public_key)
    unsigned_tx_hex = binascii.hexlify(transaction).decode('utf-8')
    return unsigned_tx_hex
Exemplo n.º 54
0
 def sec(self):
     """Take a point on the curve and encode it into sec format (33 bytes)
     """
     return public_pair_to_sec((self.x(), self.y()))
Exemplo n.º 55
0
def serialise (encoding, inputs, destination_outputs, data_output=None, change_output=None, source=None, pubkey=None):
    s  = (1).to_bytes(4, byteorder='little')                # Version

    # Number of inputs.
    s += var_int(int(len(inputs)))

    # List of Inputs.
    for i in range(len(inputs)):
        txin = inputs[i]
        s += binascii.unhexlify(bytes(txin['txid'], 'utf-8'))[::-1]         # TxOutHash
        s += txin['vout'].to_bytes(4, byteorder='little')   # TxOutIndex

        script = binascii.unhexlify(bytes(txin['scriptPubKey'], 'utf-8'))
        s += var_int(int(len(script)))                      # Script length
        s += script                                         # Script
        s += b'\xff' * 4                                    # Sequence

    # Number of outputs.
    n = 0
    n += len(destination_outputs)
    if data_output:
        data_array, value = data_output
        for data_chunk in data_array: n += 1
    else:
        data_array = []
    if change_output: n += 1
    s += var_int(n)

    # Destination output.
    for address, value in destination_outputs:
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    # Data output.
    for data_chunk in data_array:
        data_array, value = data_output # DUPE
        s += value.to_bytes(8, byteorder='little')        # Value

        # Get source public key (either provided as a string or derived from a private key in the wallet).
        if encoding in ('multisig', 'pubkeyhash'):
            if pubkey:
                pubkeypair = bitcoin_utils.parse_as_public_pair(pubkey)
                source_pubkey = public_pair_to_sec(pubkeypair, compressed=True)
            else:
                if config.PREFIX == config.UNITTEST_PREFIX:
                    private_key_wif = 'cPdUqd5EbBWsjcG9xiL1hz8bEyGFiz4SW99maU9JgpL9TEcxUf3j'
                else:
                    private_key_wif = rpc('dumpprivkey', [source])
                if private_key_wif[0] == 'c': testnet = True
                else: testnet = False
                secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed(private_key_wif, is_test=testnet)
                public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent)
                source_pubkey = public_pair_to_sec(public_pair, compressed=compressed)

        if encoding == 'multisig':
            # Get data (fake) public key.
            pad_length = 33 - 1 - len(data_chunk)
            assert pad_length >= 0
            data_pubkey = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00')
            # Construct script.
            script = OP_1                                   # OP_1
            script += op_push(len(source_pubkey))           # Push bytes of source public key
            script += source_pubkey                         # Source public key
            script += op_push(len(data_pubkey))             # Push bytes of data chunk (fake) public key
            script += data_pubkey                           # Data chunk (fake) public key
            script += OP_2                                  # OP_2
            script += OP_CHECKMULTISIG                      # OP_CHECKMULTISIG
        elif encoding == 'opreturn':
            script = OP_RETURN                              # OP_RETURN
            script += op_push(len(data_chunk))              # Push bytes of data chunk (NOTE: OP_SMALLDATA?)
            script += data_chunk                            # Data chunk
        elif encoding == 'pubkeyhash':
            pad_length = 20 - 1 - len(data_chunk)
            assert pad_length >= 0
            obj1 = ARC4.new(binascii.unhexlify(inputs[0]['txid']))  # Arbitrary, easy‐to‐find, unique key.
            pubkeyhash = bytes([len(data_chunk)]) + data_chunk + (pad_length * b'\x00')
            pubkeyhash_encrypted = obj1.encrypt(pubkeyhash)
            # Construct script.
            script = OP_DUP                                     # OP_DUP
            script += OP_HASH160                                # OP_HASH160
            script += op_push(20)                               # Push 0x14 bytes
            script += pubkeyhash_encrypted                      # pubKeyHash
            script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
            script += OP_CHECKSIG                               # OP_CHECKSIG
        else:
            raise exceptions.TransactionError('Unknown encoding‐scheme.')

        s += var_int(int(len(script)))                      # Script length
        s += script

    # Change output.
    if change_output:
        address, value = change_output
        pubkeyhash = base58_decode(address, config.ADDRESSVERSION)
        s += value.to_bytes(8, byteorder='little')          # Value
        script = OP_DUP                                     # OP_DUP
        script += OP_HASH160                                # OP_HASH160
        script += op_push(20)                               # Push 0x14 bytes
        script += pubkeyhash                                # pubKeyHash
        script += OP_EQUALVERIFY                            # OP_EQUALVERIFY
        script += OP_CHECKSIG                               # OP_CHECKSIG
        s += var_int(int(len(script)))                      # Script length
        s += script

    s += (0).to_bytes(4, byteorder='little')                # LockTime
    return s