def create(cls, sec_num): key_obj = Key(secret_exponent=sec_num) publicKey, privateKey = key_obj._public_pair key_obj = Key(public_pair=[publicKey, privateKey]) pubicAddress = key_obj.address() cert = '''-----BEGIN CERTIFICATE----- MIIDLjCCAhagAwIBAgIJAKTZkez5jH1vMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV BAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMQ0wCwYDVQQKDARUUFVCMREwDwYDVQQL DAhTZWN1cml0eTENMAsGA1UEAwwEdHB1YjEdMBsGCSqGSIb3DQEJARYOYWRtaW5A dHB1Yi5jb20wHhcNMTcwNTA4MDgxMTEwWhcNMjcwNTA2MDgxMTEwWjBvMQswCQYD VQQGEwJDTjEQMA4GA1UECAwHQmVpamluZzENMAsGA1UECgwEVFBVQjERMA8GA1UE CwwIU2VjdXJpdHkxDTALBgNVBAMMBHRwdWIxHTAbBgkqhkiG9w0BCQEWDmFkbWlu QHRwdWIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEfStTpZiZKqNHJd2tYj/E MOGYOxFrh/TTliVA3lXadzablXdB27YqBAQirbGnw+NJuvgxa7CBi/nMqahAMTnC IGFBC/MLll7T4kS/f359/BiRbs4wMiuWNIzhoRugOAmgo3sweTAJBgNVHRMEAjAA MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd BgNVHQ4EFgQUZ/QPXuhN9WaAjgAOUhOVNN1cELcwHwYDVR0jBBgwFoAUNUt6r4IA A3nI7bjzFAXN2SRaapQwDQYJKoZIhvcNAQEFBQADggEBAMlXmy0e8a+KqUKZGW6P +arugviHapt0QLUAxdFPPwbAQm7/wJYcbguAwPvxUQlHMsdvdSqEdDQeOYiOwft8 IGZ0dzNbynvhyH99tK42p5wgWRQyf4hMHrOnCdCgYUNOUVB0kPsSZ1R1ajSgfE/0 Xsi5Jbhpqpzm2G8NVqnPXeYfzQPZwzSgDs9INLs4Yw6aA8ei1IT8ESPSUtCSbFiT HDB9G7UT/ZJBG6ZeGGONsf6ZOHZz38OkonBfL/tGS6NQzTFpr4H6yKyA3GlnYLOn E+FOPdz0PSfhJOsKHY+AXFWPVrKfOimfznDYHpyQ0G6X9s31MAjF1JddRG6Xo1Vl Ftg= -----END CERTIFICATE----- ''' return cls(publicKey, pubicAddress, privateKey, cert, sec_num)
def test_segwit_create_tx(self): from pycoin.tx.tx_utils import create_tx, sign_tx from pycoin.tx.Spendable import Spendable from pycoin.tx.pay_to.ScriptPayToAddress import ScriptPayToAddress from pycoin.tx.pay_to.ScriptPayToAddressWit import ScriptPayToAddressWit from pycoin.tx.pay_to.ScriptPayToScriptWit import ScriptPayToScriptWit from pycoin.ui import address_for_pay_to_script_wit, script_obj_from_address key1 = Key(1) coin_value = 5000000 script = ScriptPayToAddressWit(b'\0', key1.hash160()).script() tx_hash = b'\ee' * 32 tx_out_index = 0 spendable = Spendable(coin_value, script, tx_hash, tx_out_index) key2 = Key(2) tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()]) self.check_signed(tx) self.assertEqual(len(tx.txs_in[0].witness), 2) s1 = ScriptPayToAddress(key1.hash160()).script() address = address_for_pay_to_script_wit(s1) spendable.script = script_obj_from_address(address).script() tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()], p2sh_lookup=build_p2sh_lookup([s1])) self.check_signed(tx)
def test_sign_verify(self): private_key = Key(secret_exponent=1) h = b"\x00" * 32 sig = private_key.sign(h) self.assertTrue(private_key.verify(h, sig)) public_key = private_key.public_copy() self.assertTrue(public_key.verify(h, sig)) h160_key = Key(hash160=private_key.hash160()) self.assertTrue(h160_key.verify(h, sig))
def main(argv=sys.argv): if len(argv) < 2: usage(argv) config_uri = argv[1] options = parse_vars(argv[2:]) setup_logging(config_uri) settings = get_appsettings(config_uri, options=options) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.create_all(engine) # initial encryption passphrase set to '' salt = os.urandom(32) password = bytes( input( "If you would like to set a password, please enter it now. Otherwise, just press enter. > " ).encode()) # initial password is the empty string enc_key = gen_key_from_salt_and_password(salt, password) f = Fernet(enc_key) secret_exponent_bytes = os.urandom(32) secret_exponent = convert_se_bytes(secret_exponent_bytes) address = Key( secret_exponent=secret_exponent, netcode=NET_CODE['bitcoin']).address(use_uncompressed=USE_COMPRESSED) with transaction.manager: model = KeyStore(name=PRIMARY, encrypted=f.encrypt(secret_exponent_bytes), salt=salt, address=address) DBSession.add(model)
def verify_dash_signature(generator, address, message, signature): compressed = False G = generator curve = G.curve() order = G.order() _a, _b, _p = curve.a(), curve.b(), curve.p() sig = base64.b64decode(signature) if len(sig) != 65: raise Exception("vmB", "Bad signature") hb = ord(sig[0]) r, s = map(str_to_long, [sig[1:33], sig[33:65]]) if hb < 27 or hb >= 35: raise Exception("vmB", "Bad first byte") if hb >= 31: compressed = True hb -= 4 recid = hb - 27 x = (r + (recid / 2) * order) % _p y2 = (pow(x, 3, _p) + _a * x + _b) % _p yomy = numbertheory.modular_sqrt(y2, _p) if (yomy - recid) % 2 == 0: y = yomy else: y = _p - yomy R = ellipticcurve.Point(curve, x, y, order) e = str_to_long(message) minus_e = -e % order inv_r = numbertheory.inverse_mod(r, order) Q = inv_r * (R * s + G * minus_e) key = Key(public_pair=(Q.x(), Q.y()), netcode='DASH') return key.address(use_uncompressed=not compressed) == address
def test_is_wif_valid(self): WIFS = [ "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH" ] for wif in WIFS: self.assertEqual(is_wif_valid(wif), "BTC") a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertEqual(is_wif_valid(a), None) NETWORK_NAMES = network_codes() for netcode in NETWORK_NAMES: for se in range(1, 10): key = Key(secret_exponent=se, netcode=netcode) for tv in [True, False]: wif = key.wif(use_uncompressed=tv) self.assertEqual( is_wif_valid(wif, allowable_netcodes=[netcode]), netcode) a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertEqual( is_wif_valid(a, allowable_netcodes=[netcode]), None)
def gen_key_pair(): key, pri_hex = _gen_pri_key() my_key = Key(secret_exponent=key, prefer_uncompressed=False, netcode=NET_CODE) return pri_hex, my_key.address()
def test_pay_to_script_file(self): the_dir = self.set_cache_dir() p2sh_file = tempfile.NamedTemporaryFile() p2sh_file.write( "52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982102c60" "47f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52102f9308a019258" "c31049344f85f89d5229b531c845836f99b08601f113bce036f953ae\n".encode("utf8")) p2sh_file.write( "53210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982102c60" "47f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52102f9308a019258" "c31049344f85f89d5229b531c845836f99b08601f113bce036f953ae\n".encode("utf8")) p2sh_file.flush() tx_source_hex = ( "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0" "0ffffffff0200f902950000000017a91415fc0754e73eb85d1cbce08786fadb7320ecb8dc8700f90295" "0000000017a914594f349df0bac3084ffea8a477bba5f03dcd45078700000000") self.launch_tool("tx -C %s" % tx_source_hex) tx_to_sign = ( "01000000020a316ea8980ef9ba02f4e6637c88229bf059f39b06238d48d06a8e" "f672aea2bb0000000000ffffffff0a316ea8980ef9ba02f4e6637c88229bf059" "f39b06238d48d06a8ef672aea2bb0100000000ffffffff01f0ca052a01000000" "1976a914751e76e8199196d454941c45d1b3a323f1433bd688ac0000000000f9" "02950000000017a91415fc0754e73eb85d1cbce08786fadb7320ecb8dc8700f9" "02950000000017a914594f349df0bac3084ffea8a477bba5f03dcd450787") wifs = ' '.join(Key(_).wif() for _ in (1, 2, 3)) signed = tempfile.mktemp(suffix=".hex") self.launch_tool("tx -a -P %s --db %s %s %s -o %s" % ( p2sh_file.name, tx_source_hex, tx_to_sign, wifs, signed), env=dict(PYCOIN_CACHE_DIR=the_dir)) tx = Tx.from_hex(open(signed).read()) self.assertEqual(tx.id(), "9d991ddccf77e33cb4584e4fc061a36da0da43589232b2e78a1aa0748ac3254b")
def _build_signature(key, tbs, network): ''' Takes a utility.ECPrivateKey() as key, tbs as rfc2459.TBSCertificate, and network as pycoin.NETWORK_NAMES ''' secret_exponent = encoding.to_long(256, encoding.byte_to_int, key[0][1].asOctets())[0] coin = Key(secret_exponent=secret_exponent, netcode=network) public_pair = coin.public_pair() coin_address = coin.address() print "building signature for %s address %s" % (network, coin_address) pubkeybitstring = (key[0].getComponentByPosition(2), key[0].getComponentByPosition(3)) tbsder = encoder.encode(tbs) hashvalue = SHA256.new(tbsder) dgst = hashvalue.digest() dgstaslong = encoding.to_long(256, encoding.byte_to_int, dgst)[0] order2 = pycoin.ecdsa.generator_secp256k1.order() ## random sign generator = pycoin.ecdsa.generator_secp256k1 rawsig2 = randomsign(generator, secret_exponent, dgstaslong) # deterministic sign ##rawsig2 = pycoin.ecdsa.sign(pycoin.ecdsa.generator_secp256k1, secret_exponent, dgstaslong) r2, s2 = rawsig2 print "signature: r: %x s: %x" % (r2, s2) if not pycoin.ecdsa.verify(generator, coin.public_pair(), dgstaslong, rawsig2): raise SignatureVerifyException( "Generated signature r: %x s: %x does not verify against public key %s" % (r2, s2, public_pair)) signature = utility.ECDSASigValue() signature.setComponentByName('r', r2) signature.setComponentByName('s', s2) dersig = encoder.encode(signature) signaturevalue = "'{0}'H".format(binascii.hexlify(dersig)) bitstring = univ.BitString(value=signaturevalue) return rfc2314.Signature(bitstring)
def test_multisig_one_at_a_time(self): N = 3 M = 3 keys = [Key(secret_exponent=i) for i in range(1, M + 2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(n=N, sec_keys=[key.sec() for key in keys[:M]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) ids = [ "403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058", "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db", "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44", "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771" ] for i in range(1, M + 1): self.assertEqual(tx2.bad_signature_count(), 1) self.assertEqual(tx2.id(), ids[i - 1]) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[i - 1:i]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_signature_count(), 0)
def test_against_myself(): """ Test code that verifies against ourselves only. Useful but not so great. """ from pycoin.contrib.msg_signing import (parse_signed_message, sign_message, verify_message) from pycoin.encoding import bitcoin_address_to_hash160_sec_with_prefix from pycoin.encoding import wif_to_tuple_of_secret_exponent_compressed for wif, right_addr in [ ('L4gXBvYrXHo59HLeyem94D9yLpRkURCHmCwQtPuWW9m6o1X8p8sp', '1LsPb3D1o1Z7CzEt1kv5QVxErfqzXxaZXv'), ('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss', '1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN'), ]: se, comp = wif_to_tuple_of_secret_exponent_compressed(wif) k = Key(secret_exponent=se, is_compressed=comp) assert k.address() == right_addr vk = Key(public_pair=k.public_pair(), is_compressed=comp) assert vk.address() == right_addr h160, pubpre = bitcoin_address_to_hash160_sec_with_prefix(right_addr) vk2 = Key(hash160=h160) assert vk2.address() == right_addr for i in range(1, 30, 10): msg = 'test message %s' % ('A' * i) sig = sign_message(k, msg, verbose=1) assert right_addr in sig # check parsing works m, a, s = parse_signed_message(sig) assert m == msg, m assert a == right_addr, a sig2 = sign_message(k, msg, verbose=0) assert sig2 in sig, (sig, sig2) assert s == sig2, s ok = verify_message(k, sig2, msg) assert ok ok = verify_message(k, sig2.encode('ascii'), msg) assert ok
def show_address(args): key, wif = decrypt_key() pub_key = Key(public_pair=key.public_pair()) addr = pub_key.address() data = explorer.get_address(addr) print() print('Address: ', data.addrStr) print('Balance: ', data.balanceSat)
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) keys_wif = [ Key(secret_exponent=secret_exponent), Key.from_text(wif), Key.from_text(c_wif), ] key_sec = Key.from_sec(sec) key_sec_c = Key.from_sec(c_sec) keys_sec = [key_sec, key_sec_c] for key in keys_wif: self.assertEqual(key.secret_exponent(), secret_exponent) self.assertEqual(key.public_copy().secret_exponent(), None) v = repr(key) if key._prefer_uncompressed: self.assertEqual(key.wif(), wif) else: self.assertEqual(key.wif(), c_wif) self.assertEqual(key.wif(use_uncompressed=True), wif) self.assertEqual(key.wif(use_uncompressed=False), c_wif) for key in keys_wif + keys_sec: if key._prefer_uncompressed: self.assertEqual(key.sec(), sec) else: self.assertEqual(key.sec(), c_sec) self.assertEqual(key.sec(use_uncompressed=True), sec) self.assertEqual(key.sec(use_uncompressed=False), c_sec) if key._prefer_uncompressed: self.assertEqual(key.address(), address_b58) else: self.assertEqual(key.address(), c_address_b58) self.assertEqual(key.address(use_uncompressed=False), c_address_b58) self.assertEqual(key.address(use_uncompressed=True), address_b58) key_pub = Key.from_text(address_b58, is_compressed=False) key_pub_c = Key.from_text(c_address_b58, is_compressed=True) self.assertEqual(key_pub.address(), address_b58) self.assertEqual(key_pub.address(use_uncompressed=True), address_b58) self.assertEqual(key_pub.address(use_uncompressed=False), None) self.assertEqual(key_pub_c.address(), c_address_b58) self.assertEqual(key_pub_c.address(use_uncompressed=True), None) self.assertEqual(key_pub_c.address(use_uncompressed=False), c_address_b58)
def test_script_type_pay_to_public_pair(self): for se in range(1, 100): key = Key(secret_exponent=se) for b in [True, False]: st = ScriptPayToPublicKey.from_key(key, use_uncompressed=b) addr = key.address(use_uncompressed=b) self.assertEqual(st.address(), addr) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def test_script_type_pay_to_address(self): for se in range(1, 100): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = script_obj_from_address(addr) self.assertEqual(st.address(), addr) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def parse_key(item, PREFIX_TRANSFORMS, network): key = parse_prefixes(item, PREFIX_TRANSFORMS) if key: return key secret_exponent = parse_as_secret_exponent(item) if secret_exponent: return Key(secret_exponent=secret_exponent, netcode=network) if SEC_RE.match(item): return Key.from_sec(h2b(item)) public_pair = parse_as_public_pair(item) if public_pair: return Key(public_pair=public_pair, netcode=network) if HASH160_RE.match(item): return Key(hash160=h2b(item), netcode=network) return None
def check_tx_can_be_signed(self, tx_u, tx_s, private_keys=[], p2sh_values=[]): tx_u_prime = self.unsigned_copy(tx_s) tx_u_hex = tx_u.as_hex() tx_s_hex = tx_s.as_hex() tx_u_prime.set_unspents(tx_s.unspents) tx_u_prime.sign( hash160_lookup=LazySecretExponentDB([Key(pk).wif() for pk in private_keys], {}), p2sh_lookup=build_p2sh_lookup([h2b(x) for x in p2sh_values]) ) self.check_signed(tx_u_prime) tx_hex = tx_u_prime.as_hex() self.assertEqual(tx_hex, tx_s_hex)
def gen_2of3_multisig_key_pair(): key_pairs = [] for i in range(0, 3): key, pri_hex = _gen_pri_key() my_key = Key(secret_exponent=key, prefer_uncompressed=False, netcode=NET_CODE) # return wif or hex format, use your own strategy key_pairs.append((my_key.wif(), my_key.sec_as_hex())) return get_multisig_address( 2, [binascii.unhexlify(key[1]) for key in key_pairs]), key_pairs
def test_repr(self): key = Key(secret_exponent=273, netcode='XTN') address = key.address() pub_k = Key.from_text(address) self.assertEqual(repr(pub_k), '<mhDVBkZBWLtJkpbszdjZRkH1o5RZxMwxca>') wif = key.wif() priv_k = Key.from_text(wif) self.assertEqual( repr(priv_k), 'private_for <0264e1b1969f9102977691a40431b0b672055dcf31163897d996434420e6c95dc9>' )
def parse_key(item, networks, generator): if item == 'create': return None, _create_bip32(generator) for network, key_info in key_info_from_text(item, networks=networks): return network, key_info["create_f"]() if HASH160_RE.match(item): return None, Key(hash160=h2b(item)) secret_exponent = parse_as_secret_exponent(item, generator) if secret_exponent: return None, Key(secret_exponent=secret_exponent, generator=generator) if SEC_RE.match(item): return None, Key.from_sec(h2b(item), generator) public_pair = parse_as_public_pair(item, generator) if public_pair: return None, Key(public_pair=public_pair) return None, None
def test_solve_pay_to_public_pair(self): for se in range(1, 10): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = ScriptPayToPublicKey.from_key(key, use_uncompressed=b) self.assertEqual(st.address(), addr) hl = build_hash160_lookup([se]) sv = 100 solution = st.solve(hash160_lookup=hl, sign_value=sv, signature_type=SIGHASH_ALL) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def test_repr(self): from pycoin.key import Key netcode = 'XTN' key = Key(secret_exponent=273, netcode=netcode) wallet = BIP32Node.from_master_secret(bytes(key.wif().encode('ascii')), netcode) address = wallet.address() pub_k = wallet.from_text(address) self.assertEqual(repr(pub_k), '<myb5gZNXePNf2E2ksrjnHRFCwyuvt7oEay>') wif = wallet.wif() priv_k = wallet.from_text(wif) self.assertEqual(repr(priv_k), 'private_for <03ad094b1dc9fdce5d3648ca359b4e210a89d049532fdd39d9ccdd8ca393ac82f4>')
def test_solve_pay_to_address(self): for se in range(1, 10): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = script_obj_from_address(addr) self.assertEqual(st.address(), addr) hl = build_hash160_lookup([se]) sv = 100 solution = st.solve(hash160_lookup=hl, signature_for_hash_type_f=const_f(sv), signature_type=SIGHASH_ALL) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def multisig_M_of_N(self, M, N, unsigned_id, signed_id): keys = [Key(secret_exponent=i) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_signature_count(), 0)
def sign_document(args): key, wif = decrypt_key() pub_key = Key(public_pair=key.public_pair()) addr = pub_key.address() out = get_spendable(addr) if out is None: raise Exception('Insufficient funds') signature, file_hash = file_signature(args.filename) print('Signing document: ', args.filename) print('File hash: ', file_hash.hex()) print('File signature: ', signature.hex()) tx = build_tx(signature, addr, wif) print(tx.as_hex())
def generate_key(): generator = secp256k1_generator rand = codecs.encode(os.urandom(32), 'hex').decode() secret_exponent = int('0x' + rand, 0) key = Key(secret_exponent=secret_exponent, generator=generator) print(key.wif()) #wif-format print(key.sec_as_hex()) #hex-format print(key.address()) #btc-address uncompressed print(key.public_copy()) #public key uncompressed key._prefer_uncompressed = False print(key.address()) #btc-address compressed print(key.public_copy()) #public key compressed print(secret_exponent) #for reuse purpose return key
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i) for i in range(1, N + 2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) for partial_key_list in itertools.permutations(keys[:N], M): tx2 = create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) for key in partial_key_list: self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def test_sign_pay_to_script_multisig(self): M, N = 3, 3 keys = [Key(secret_exponent=i) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() address = address_for_pay_to_script(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = standard_tx_out_script(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:N]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def subkey(self, path): """ path: of the form "K" where K is an integer index, or "K/N" where N is usually a 0 (deposit address) or 1 (change address) """ t = path.split("/") if len(t) == 2: n, for_change = t else: n, = t for_change = 0 b = (str(n) + ':' + str(for_change) + ':').encode("utf8") + self.master_public_key() offset = from_bytes_32(double_sha256(b)) if self.master_private_key(): return Key(secret_exponent=((self.master_private_key() + offset) % ORDER), prefer_uncompressed=True) p1 = offset * secp256k1_generator x, y = self.public_pair() p2 = secp256k1_generator.Point(x, y) p = p1 + p2 return Key(public_pair=p, prefer_uncompressed=True)
def test_master_public_and_private(self): # these addresses were generated by hand using electrum with a master public key # corresponding to secret exponent 1 RECEIVING_ADDRESSES = [ "1AYPdHLna6bKFUbeXoAEVbaXUxifUwCMay", "13UeuWJba5epizAKyfCfiFKY5Kbxfdxe7B", "19f6KJUTL5AGBRvLBGiL6Zpcx53QA7zaKT", "1Cm33VuSkoUETwx5nsF1wgmGqYwJZxpZdY", "14Z6ErkETixQMUeivsYbrdoUFns2J1iSct", ] CHANGE_ADDRESSES = [ "1JVYsmjrqSy1BKvo1gYpNjX7AYea74nQYe", "1Cc7itfQaDqZK3vHYphFsySujQjBNba8mw", "15wrXvrAnyv3usGeQRohnnZ8tz9XAekbag", "1MnWCEjE5YiZpZrkP8HcXEeDqwg43RxLwu", "1Fgyp3PUx9AAg8yJe1zGXHP5dVC6i1tXbs", "12XTLd4u9jeqw4egLAUhoKLxHARCdKWkty" ] k = Key(secret_exponent=1, generator=secp256k1_generator) master_public_key = k.sec(use_uncompressed=True)[1:] wallet = ElectrumWallet(generator=secp256k1_generator, master_public_key=master_public_key) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wallet = ElectrumWallet(generator=secp256k1_generator, master_private_key=1) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = key_from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = key_from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)