def sign(self, private_keys): '''Signs the transaction. prvkeys (list of PrivateKey items)''' for i, txin in enumerate(self._inputs): prvkeys = private_keys[i] if isinstance(prvkeys, PrivateKey): assert txin['nsigs'] == 1 prvkeys = [prvkeys] elif isinstance(prvkeys, list): assert len(prvkeys) == txin['nsigs'] # Sorting keys sorted_prvkeys = [] for prvkey in prvkeys: pubkey = PublicKey.from_prvkey(prvkey) assert (pubkey in txin['pubkeys']) sorted_prvkeys += [(txin['pubkeys'].index(pubkey), prvkey)] sorted_prvkeys.sort(key=lambda x: x[0]) prvkeys = [k[1] for k in sorted_prvkeys] else: raise TransactionError('wrong type for private keys') if txin['type'] in ('p2pkh', 'p2sh'): prehash = dsha256(self.serialize_legacy_preimage(txin)) elif txin['type'] in ('p2wpkh', 'p2wsh', 'p2sh-p2wpkh', 'p2sh-p2wsh'): prehash = dsha256(self.serialize_preimage(txin)) hashtype = bytes([self.hashtype & 0xff]).hex() self._inputs[i]['signatures'] = [ prvkey.sign(prehash, alg="ecdsa", strtype=True) + hashtype for prvkey in prvkeys ]
def validate(self): pc = PublicKey.loads(self.public_key) ok = sha512(str( self.public_key).encode()).hexdigest() == self.from_addr return ok and validate_signature(pc.e, pc.n, self.get_message(), self.sign)
def parse_unlocking_script(script): # Returns type, signatures, public keys and address of the input if len(script) in [71, 72, 73]: # Pay-to-Public-Key: the unlocking script is the signature sig, script = read_data(script) assert script == bytes() return "p2pk", [sig], None, None, None elif len(script) in [105, 106, 107, 137, 138, 139]: #P2PKH # Pay-to-Public-Key-Hash: signature and public key sig, script = read_data(script) pubkey, script = read_data(script) assert script == bytes() return "p2pkh", [sig], [PublicKey.from_ser(pubkey) ], Address.from_pubkey(pubkey), None elif script[0] == OP_0: # P2SH multisig zero, script = read_bytes(script, 1, int, 'little') data = [] while script != bytes(): d, script = read_data(script) data.append(d) signatures, redeemScript = data[:-1], data[-1] # Address address = Address.from_script(redeemScript) rs = redeemScript # Parsing of redeem script m, rs = read_bytes(rs, 1, int, 'little') assert len(signatures) == (m - OP_1 + 1), "m = {:d}, len sigs = {:d}".format( m, len(signatures)) pubkeys = [] while 0 < rs[0] <= OP_PUSHDATA4: pubkey, rs = read_data(rs) pubkeys.append(PublicKey.from_ser(pubkey)) n, rs = read_bytes(rs, 1, int, 'little') assert len(pubkeys) == (n - OP_1 + 1) assert rs[0] == OP_CHECKMULTISIG return "p2sh", signatures, pubkeys, address, redeemScript else: raise ScriptError("cannot parse unlocking script")
def generate_keys(): p = generate_prime(1000, 2000) q = generate_prime(2000, 3000) assert p != q n = p * q phi = (p - 1) * (q - 1) e = 101 d = 1 while (d * e) % phi != 1: d += 1 return PublicKey(e, n), PrivateKey(d, n)
def construct_simple_transaction(wifkey, output_addr, locktime, prevout_txid, prevout_index, prevout_value): ''' Construct a Bitcoin Cash one-input / one-output transaction. wifkey (str) : private key (Wallet Import Format) output_addr (str) : recipient address (legacy or cash format) prevout_txid (str) : previous output transaction id prevout_index (int) : index of the output in the previous transaction prevout_value (int) : previous output value in satoshis''' # Private key prvkey = PrivateKey.from_wif(wifkey) # Public key and address (Public Key Hash) pubkey = PublicKey.from_prvkey(prvkey) input_address = Address.from_pubkey(pubkey) # Output address output_address = Address.from_string(output_addr) # Creation of the transaction txin = {} txin['address'] = input_address txin['txid'] = prevout_txid txin['index'] = prevout_index txin['value'] = prevout_value txin['sequence'] = Constants.SEQUENCE_NUMBER txin['pubkeys'] = [pubkey] txin['nsigs'] = 1 tx = Transaction.from_inputs([txin], locktime) txsize = (tx.estimate_size() + 32 + 2 * (output_address.kind == Constants.CASH_P2PKH)) fee = Constants.FEE_RATE * txsize txout = {} txout['address'] = output_address txout['value'] = prevout_value - fee tx.add_output(txout) prvkeys = [prvkey] tx.sign(prvkeys) rawtx = tx.serialize() fee = tx.get_fee() print("Input address", input_address.to_cash()) print("Output address", output_address.to_cash()) print("Amount sent (sat)", prevout_value - fee) print("Fee (sat)", fee) print() if tx.iscomplete: return rawtx, tx.txid(), fee else: return None
def generate_keys(): p = gen_prime(200, 300) q = gen_prime(300, 400) n = p * q e = 101 # Здесь должен быть обратный эл-т в кольце по модулю! d = 1 while (e * d) % n != 1: d += 1 return PublicKey(e, n), PrivateKey(d, n)
def get_pubkeys(self, branch, index): ''' branch (int): external (0) or internal (1) ''' assert branch in (0, 1) if isinstance(index, int): index = [index] branch_xpub = public_derivation(self.get_account_xpub(), "", "/{:d}".format(branch)) pubkeys = [] for i in index: xpub = public_derivation(branch_xpub, "", "/{:d}".format(i)) pubkey, _, _, _, _ = decode_xkey(xpub) pubkeys.append(PublicKey.from_ser(pubkey)) return pubkeys
print() ''' My addresses ''' print("ADDRESSES") print() # Claim private key # mainnet: Kz2GqdB5f5JWEYn1znS8bk2aUqg4J8WXycs6uEnwCUobRsib6N2R # testnet: cQPGJYAw68zmPzFHPCFFy4Xe74yTxacE3f1a1fFShbTbgckLz6dn # Claim address # testnet: bchtest:qrtppnj5yk7ur6u2t0tagesvlyhycddgfq630lqqkh # n12q2oecWxTmcaMmMShnqvtC4FL59LCaBE (legacy) claim_secret = 0x53a0e9e7894f4f77fba3cc62d9dcb82d61d085c34f7fa2a712e26d62ae4f42a3 claim_prvkey = PrivateKey(claim_secret) print("Claim address") print(" privkey", claim_prvkey) claim_pubkey = PublicKey.from_prvkey(claim_prvkey) claim_address = Address.from_pubkey(claim_pubkey) print(" address (cash)", claim_address.to_full_cash()) print(" address (legacy)", claim_address.to_legacy()) print(" address (hex)", claim_address.h.hex()) print() # Refund private key # mainnet: L1MK6tz8mD9WRnr9RqsbDg9BYktUkUwd6ZWQRHgdHU1m6VbUPkdz # testnet: cRiJZoyzCGqmbEKQpFgiazeFAzBtQw3KAbesXi98nafmMEgYAMDg # Refund address # testnet: bchtest:qrref365h428zh4zvwpnnfzlp2tq4w9t8qnh0pzm5q # myiEzYohqurvpghWrCaaafz5orGQinfEC9 refund_secret = 0x7b42a6f4f75cb14d701965b9da9245940837b4b3d8073bd2cf228605c1f0fe40 refund_prvkey = PrivateKey(refund_secret) print("Refund address")
wifkey1 = "L239DGsGnzuvsDQcNDrkBk5WGNhMqQRkUkFSp3bCycWwR8i7Xvod" wifkeys_multisig = [ "KzwQjFQPytv5x6w2cLdF4BSweGVCPEt8b8HbcuTi8e75LRQfw94L", "Ky4yk7uTBZ1EDbqyVfkvoZXURpWdRCxTpCERZb4gkn67fY8kK95R", "Kz3Htg8mSfC997qkBxpVCdxYhEoRcFj5ikUjE96ipVAJPou7MwRD" ] ## Bitcoin multisig the hard way - https://www.soroushjp.com/2014/12/20/bitcoin-multisig-the-hard-way-understanding-raw-multisignature-bitcoin-transactions/ #wifkeys = ["5JruagvxNLXTnkksyLMfgFgf3CagJ3Ekxu5oGxpTm5mPfTAPez3", #"5JX3qAwDEEaapvLXRfbXRMSiyRgRSW9WjgxeyJQWwBugbudCwsk", #"5JjHVMwJdjPEPQhq34WMUhzLcEd4SD7HgZktEh8WHstWcCLRceV"] # Sorted public keys involved in the multisig address pubkeys = [PublicKey.from_prvkey(wk).to_ser() for wk in wifkeys_multisig] # Number of signatures required to unlock the multisig address nsigs = 2 redeem_script = multisig_locking_script(pubkeys, nsigs) p2sh_addr = Address.from_script(redeem_script) # Transaction 1: p2pkh -> p2sh prvkey1 = PrivateKey.from_wif(wifkey1) pubkey1 = PublicKey.from_prvkey(prvkey1) input_address = Address.from_pubkey(pubkey1.to_ser()).to_string() output_address = p2sh_addr.to_cash() prevout_txid = "10e7ee10ecab3d16fcba5160792733dc2eeeb7270389d304832da3c9f5d31ef5" prevout_index = 1
parser.add_argument("--message", "-m", help="Provide a message to encrypt") # Save, load, and generate keys parser.add_argument("--keyfile", "-k", help="Generate and save keys to filename provided") parser.add_argument("--public", "-pu", help="Provide a public key file for encryption") parser.add_argument("--private", "-pr", help="Provide a private key file for decryption") args = parser.parse_args() rsa = RSA() # Encrypt and possibly save a message if args.message and args.public: message = args.message public = PublicKey.load(args.public) filename = args.save encrypt_message(rsa, message, public, filename) # Decrypt a message in a file elif args.load and args.private: filename = args.load private = PrivateKey.load(args.private) decrypt_file(rsa, filename, private) # Generate and save keys to file elif args.keyfile: filename = args.keyfile
def __str__(self): return self.to_string() def __repr__(self): return '<{} address {}>'.format(self.coin, self.to_string()) if __name__ == '__main__': bch_string = "qz954pyuatjtyrf654ud2k55ykr6n7yl9ql8cvc955" bch_string_2 = "bitcoincash:qz954pyuatjtyrf654ud2k55ykr6n7yl9ql8cvc955" btc_string = "1x6YnuBVeeE65dQRZztRWgUPwyBjHCA5g" eth_string = "0x83CbE1b588a7b1feBBF806b68Ac0c6Da9DeB69f7" eth_string_2 = "0x83cbe1b588a7b1febbf806b68ac0c6da9deb69f7" print() for string in [bch_string, bch_string_2, btc_string, eth_string, eth_string_2]: print("Original string", string) addr = Address.from_string(string) print("Address successfully created.") print("to_string result:", addr.to_string()) print() print() K = PublicKey.from_ser("0283b0c52ec1204fcd3c309c76f5a8b544f76fcac21da65612978295f4497f5831") print("Public Key", K) for coin in SUPPORTED_COINS: addr = Address.from_pubkey( K, coin ) print(addr) print()
def is_signed_correctly(self) -> bool: return PublicKey(self.input).verify(self.signature, bytes(self))
from constants import Constants if __name__ == '__main__': import sys if sys.version_info < (3, 5): sys.exit("Error: Must be using Python 3.5 or higher") wifkeys_multisig = [ "KyLxarqt64ndG3ENbLYp2922HKoasdQqd2sZS3VaQD5BF2pJLCmL", "KzqYDqNMVTPVeku7nwdFv3zPAQLwD2BnfEwgYYWeryyKbMDGTzwX", "L2wtM9x3JTvGa1YN6dpkmv4EdRsWTELJzdxsB2291KmSNe8Nof6c" ] # Sorted public keys involved in the multisig address pubkeys = [PublicKey.from_prvkey(wk) for wk in wifkeys_multisig] # Number of signatures required to unlock the multisig address nsigs = 2 redeem_script = multisig_locking_script(pubkeys, nsigs) p2sh_addr = Address.from_script(redeem_script) print("multisig addr", p2sh_addr.to_cash()) print() output_addr = Address.from_string( "qz954pyuatjtyrf654ud2k55ykr6n7yl9ql8cvc955") # Transaction 1 txin = {}
import requests from datetime import datetime from block import Transaction, Block from crypto import PublicKey, PrivateKey, sign_message b_url = 'http://localhost:5002' private_key = PrivateKey(3, 37) public_key = PublicKey(3, 37) address = '123' def add_transaction(to, amount): t = Transaction( address, to, amount, '', public_key.dumps(), ) t.sign = sign_message(private_key.d, private_key.n, t.get_message()) r = requests.post(b_url + '/add_transaction', json=t.to_dict()) print(r.text) def get_transactions(): r = requests.get(b_url + '/transaction_pool') return r.json()
def get_balance(addr): blocks = get_blocks() transactions = sum((x.transactions for x in blocks), []) amount = 0 for transaction in transactions: if transaction.from_addr == addr: amount -= transaction.amount if transaction.to_addr == addr: amount += transaction.amount return amount f = open('wallet.json', 'r') wallet = json.loads(f.read()) f.close() public_key = PublicKey.loads(wallet['public_key']) private_key = PrivateKey.loads(wallet['private_key']) address = wallet['address'] print(add_transaction('0' * 64, 1, address, public_key, private_key)) print(get_transactions()) print(mine()) print(get_transactions()) # get_blocks() print(get_balance(address))
def from_wifkey(self, wifkey): keypair = (wifkey, PublicKey.from_prvkey(wifkey, True).to_ser(strtype=True)) return self(keypair)
def from_dict(cls, data): return cls(data['from'], data['to'], data['amount'], data['sign'], PublicKey.loads(data['public_key']))