def Check1000k_address(start_private_key,Num): global guessNum private_key = deepcopy(start_private_key) # private_key=26563230048437957592232553826663696440606756685920117476832299673293013768870 startkey = deepcopy(start_private_key) while private_key < 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141: random_private_key=Generate_random_private_key() random_addresss = from_private_key_to_address(random_private_key) private_key += 1 guessNum += 1 PrivateKey_WIF = bitcoin.encode_privkey(private_key,'wif') compressed_private_key = bitcoin.encode_privkey(private_key,'hex') + '01' PrivateKey_WIF_Compressed = bitcoin.encode_privkey(bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif') bitcoin_address = bitcoin.privkey_to_address(PrivateKey_WIF) compressed_bitcoin_address = bitcoin.privkey_to_address(PrivateKey_WIF_Compressed) addresss = [bitcoin_address,compressed_bitcoin_address,random_addresss[0],random_addresss[1]] for address in addresss: try: balance = querybalainceV3(address) except: print 'failed to query private_key %s ,address %s' % (private_key,address) add_unquery_address_to_log(private_key,address) continue time.sleep(0.5) #balance = querybalance('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa') if int(balance) >0 : print 'private_key %s has %s BTC' % (private_key,balance) add_query_address_has_btc(private_key,address) linestring = 'private_key %s has %s BTC !' % (private_key,balance) smtp.send_BTCmail(linestring) print "Check %s private_key %s " % (str(guessNum),private_key) if private_key==startkey + Num: add_query_address_has_btc(private_key,Num) break
def deploy(self): if self.contract.network.name in ['RSK_MAINNET', 'RSK_TESTNET' ] and self.btc_key is None: priv = os.urandom(32) if self.contract.network.name == 'RSK_MAINNET': address = bitcoin.privkey_to_address(priv, magicbyte=0) else: address = bitcoin.privkey_to_address(priv, magicbyte=0x6F) btc_key = BtcKey4RSK(private_key=binascii.hexlify(priv).decode(), btc_address=address) btc_key.save() self.btc_key = btc_key self.save() super().deploy()
def test_direct_send(setup_regtest, wallet_structures, mean_amt, mixdepth, amount, valid): log = get_log() wallets = make_wallets(1, wallet_structures=wallet_structures, mean_amt=mean_amt) wallet = wallets[0]['wallet'] sync_wallet(wallet) destaddr = btc.privkey_to_address( os.urandom(32), #TODO deterministic-ise from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg if not valid: with pytest.raises(Exception) as e_info: sendpayment.direct_send(wallet, amount, mixdepth, destaddr, answeryes=True) else: sendpayment.direct_send(wallet, amount, mixdepth, destaddr, answeryes=True)
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: print 'taker seed: ' + self.wallets[6]['seed'] while True: print 'hello' time.sleep(80) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_simple_send(self, n): #start yield generator with wallet1 yigen_proc = local_command( ['python', 'yield-generator.py', str(self.wallets[1]['seed'])], redirect=self.wallets[1]['seed'], bg=True) #A significant delay is needed to wait for the yield generator to sync its wallet time.sleep(30) #run a single sendpayment call with wallet2 amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), common.get_addr_vbyte()) try: for i in range(n): sp_proc = local_command(['python','sendpayment.py','--yes','-N','1', self.wallets[2]['seed'],\ str(amt), dest_address]) except subprocess.CalledProcessError, e: if yigen_proc: yigen_proc.terminate() print e.returncode print e.message raise
def __check_valid(k): #get raw priv key: decode_private_key = bitcoin.decode_privkey(k) if decode_private_key >= bitcoin.N: return None #get compressed priv key: compressed_private_key = bitcoin.encode_privkey(decode_private_key, "hex_compressed") #get raw addr & compressed addr addr_raw = bitcoin.privkey_to_address(decode_private_key) addr_comp = bitcoin.privkey_to_address(compressed_private_key) if addr_raw == target_addr or addr_comp == target_addr: print(f"FOUND ONE!!!! PRIVATE KEY IS: {hex(decode_private_key)}") return hex(decode_private_key)
def run_send(self, bad=False): yigen_procs = [] if bad: i = 2 else: i = 0 ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([ python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[1]['seed'], str(amt), dest_address ]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def validate_utxo_data(utxo_datas, retrieve=False): """For each txid: N, privkey, first convert the privkey and convert to address, then use the blockchain instance to look up the utxo and check that its address field matches. If retrieve is True, return the set of utxos and their values. """ results = [] for u, priv in utxo_datas: print 'validating this utxo: ' + str(u) hexpriv = btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte()) addr = btc.privkey_to_address(hexpriv, magicbyte=get_p2pk_vbyte()) print 'claimed address: ' + addr res = jm_single().bc_interface.query_utxo_set([u]) print 'blockchain shows this data: ' + str(res) if len(res) != 1: print "utxo not found on blockchain: " + str(u) return False if res[0]['address'] != addr: print "privkey corresponds to the wrong address for utxo: " + str(u) print "blockchain returned address: " + res[0]['address'] print "your privkey gave this address: " + addr return False if retrieve: results.append((u, res[0]['value'])) print 'all utxos validated OK' if retrieve: return results return True
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: print 'taker seed: '+self.wallets[6]['seed'] while True: print 'hello' time.sleep(80) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_send(self, bad=False): yigen_procs = [] if bad: i = 2 else: i = 0 ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[1]['seed'], str( amt), dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def cmdImportPrivs(args): for l in stdin: ls = l.split() for x in ls: try: privkey = bitcoin.b58check_to_hex(x) addr = bitcoin.privkey_to_address(privkey) tokenval.db["PRIVKEY_" + addr] = privkey except: pass
def create_pair(b58_magic_byte, address_magic_byte, seed=None): """Function create private key and address""" if seed is None: seed = KeyGenerator.random_seed() hash = sha256(seed) private_key = int(hash, base=16) private_key_wif = bin_to_b58check(encode(private_key, 256, 32), b58_magic_byte) address = privkey_to_address(private_key, address_magic_byte) return private_key_wif, address
def Check1000k_address(start_private_key, Num): global guessNum private_key = deepcopy(start_private_key) # private_key=26563230048437957592232553826663696440606756685920117476832299673293013768870 startkey = deepcopy(start_private_key) while private_key < 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141: random_private_key = Generate_random_private_key() random_addresss = from_private_key_to_address(random_private_key) private_key += 1 guessNum += 1 PrivateKey_WIF = bitcoin.encode_privkey(private_key, 'wif') compressed_private_key = bitcoin.encode_privkey(private_key, 'hex') + '01' PrivateKey_WIF_Compressed = bitcoin.encode_privkey( bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif') bitcoin_address = bitcoin.privkey_to_address(PrivateKey_WIF) compressed_bitcoin_address = bitcoin.privkey_to_address( PrivateKey_WIF_Compressed) addresss = [ bitcoin_address, compressed_bitcoin_address, random_addresss[0], random_addresss[1] ] for address in addresss: try: balance = querybalainceV3(address) except: print 'failed to query private_key %s ,address %s' % ( private_key, address) add_unquery_address_to_log(private_key, address) continue time.sleep(0.5) #balance = querybalance('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa') if int(balance) > 0: print 'private_key %s has %s BTC' % (private_key, balance) add_query_address_has_btc(private_key, address) linestring = 'private_key %s has %s BTC !' % (private_key, balance) smtp.send_BTCmail(linestring) print "Check %s private_key %s " % (str(guessNum), private_key) if private_key == startkey + Num: add_query_address_has_btc(private_key, Num) break
def makeTestMemberKeys(): member_names = ["member_%s" % x for x in "abcdefghijklmnopqrstuvwxyz"] privkeys = [ bitcoin.hex_to_b58check(bitcoin.sha256(member), 0x80) for member in member_names ] addresses = [bitcoin.privkey_to_address(priv) for priv in privkeys] return member_names, addresses, privkeys
def wif_to_address(crypto, wif): if is_py2: wif_byte = int(hexlify(b58decode_check(wif)[0]), 16) else: wif_byte = b58decode_check(wif)[0] if not wif_byte == crypto_data[crypto.lower()]['private_key_prefix']: msg = 'WIF encoded with wrong prefix byte. Are you sure this is a %s address?' % crypto.upper() raise Exception(msg) address_byte = crypto_data[crypto.lower()]['address_version_byte'] return privkey_to_address(wif, address_byte)
def wif_to_address(crypto, wif): if is_py2: wif_byte = int(hexlify(b58decode_check(wif)[0]), 16) else: wif_byte = b58decode_check(wif)[0] if not wif_byte == crypto_data[crypto.lower()]['private_key_prefix']: msg = 'WIF encoded with wrong prefix byte. Are you sure this is a %s address?' % crypto.upper( ) raise Exception(msg) address_byte = crypto_data[crypto.lower()]['address_version_byte'] return privkey_to_address(wif, address_byte)
def pattern_mine(pattern="dft", startWith=False): secret_key = "" address = "" while 1: # generate the secret private key secret_key = bitcoin.random_key() # generate the address derived from private key address = bitcoin.privkey_to_address(secret_key) if bool(startWith): if address.startswith("1" + pattern): break else: if pattern in address: break print("Vanity address found: ", address) print("HEX private key: ", secret_key)
def print_the_secrets(my_256_bit_secret): print ("\n\n========== 128-bit digests (12 BIP39 words): ==========") print ("\n\nThe two 128-bit digests are created by cutting the 256-bit digest.") print_128_bit_secret("FIRST",my_256_bit_secret[0:16]) print_128_bit_secret("SECOND",my_256_bit_secret[16:32]) print ("\n\nFor better security use only the 256-bit digest (24 BIP39 words).") print ("Don't forget that the two 128-bit digests were created by cutting the 256-bit digest in half.") print ("\n\n========== The same 256-bit digest in different formats: ==========") # we need it also for bitcoin.encode_privkey() my_256_bit_secret_HEX = binascii.b2a_hex(my_256_bit_secret).decode("utf-8") print ("\n\nThe 256-bit digest in hex format:", my_256_bit_secret_HEX) print ("\nThe 256-bit digest in base64 format:", binascii.b2a_base64(my_256_bit_secret).decode("utf-8")) print ("\nThe 256-bit digest in BIP39 mnemonic format:\n\n", mnemonic.Mnemonic('english').to_mnemonic(my_256_bit_secret)) print ("\n\nThe 256-bit digest in RFC1751 mnemonic format:\n\n", key_to_english(my_256_bit_secret)) CURVE_ORDER = 115792089237316195423570985008687907852837564279074904382605163141518161494337 my_256_bit_secret_decimal = string_to_number(my_256_bit_secret) print ("\n\nThe 256-bit digest in decimal format:\n\n", my_256_bit_secret_decimal) if my_256_bit_secret_decimal < ( CURVE_ORDER - 1000000000 ): if my_256_bit_secret_decimal > 1000000000: print ("Looks ok for a SECP256k1 private key.") else: print ("Looks too small for a private key.") else: print ("Looks too big for a SECP256k1 private key.") my_256_bit_secret_WIF = bitcoin.encode_privkey(my_256_bit_secret_HEX,"wif_compressed") print ("\n\nThe 256-bit digest in compressed WIF format:\n\n", my_256_bit_secret_WIF) print ("\nThe address derived from the above WIF key:",bitcoin.privkey_to_address(my_256_bit_secret_WIF))
def run_simple_send(self, n): #start yield generator with wallet1 yigen_proc = local_command(['python','yield-generator.py', str(self.wallets[1]['seed'])],redirect=self.wallets[1]['seed'],bg=True) #A significant delay is needed to wait for the yield generator to sync its wallet time.sleep(30) #run a single sendpayment call with wallet2 amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), common.get_addr_vbyte()) try: for i in range(n): sp_proc = local_command(['python','sendpayment.py','--yes','-N','1', self.wallets[2]['seed'],\ str(amt), dest_address]) except subprocess.CalledProcessError, e: if yigen_proc: yigen_proc.terminate() print e.returncode print e.message raise
def __init__(self, token_addr, mints, outputs, privs=None, linked_onchain_txn=None, signatures=[]): self.token_addr = token_addr self.mints = mints self.outputs = outputs self.privs = privs self.linked_onchain_txn = linked_onchain_txn self.signatures = signatures msg = self.txn_part() log.info("Token transaction part hash: %s", hexlify(bitcoin.electrum_sig_hash(msg))) if self.privs is None: assert (len(self.signatures)) self.signed_addresses = [] for sig in self.signatures: addr_reconstructed = bitcoin.pubtoaddr( bitcoin.ecdsa_recover(msg, sig)) self.signed_addresses.append(addr_reconstructed) else: self.signed_addresses = [ bitcoin.privkey_to_address(priv) for priv in privs ] import io b = io.BytesIO() self.write(b) self.hsh = bitcoin.sha256( bytes(b.getbuffer())[:-1] ) # TOTAL hash, including signatures, but excluding final \n byte self.handle = "TOK_" + self.hsh log.info("Token transaction overall hash: %s", self.hsh)
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command(['python','yield-generator.py',\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(60) #start a tumbler amt = amt*1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), common.get_addr_vbyte()) try: #default mixdepth source is zero, so will take coins from m 0. #see tumbler.py --h for details expected = ['tumble with these tx'] test_in = ['y'] p = pexpect.spawn('python',['tumbler.py', '-N', '1', '0', '-a', '0', '-M', '5', self.wallets[6]['seed'], dest_address]) interact(p, test_in, expected) p.expect(pexpect.EOF, timeout=100000) p.close() if p.exitstatus != 0: print 'failed due to exit status: '+str(p.exitstatus) return False #print('use seed: '+self.wallets[6]['seed']) #print('use dest addr: '+dest_address) #ret = raw_input('quit?') except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_sweep(self): #currently broken due to flooding; to make it work #change the 60 loop for the bad wallet to 20 yigen_procs = [] ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[3]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[2][ 'seed'], '0', dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def check_priv_key(priv_key): try: address = privkey_to_address(priv_key) print("try priv key {}".format(priv_key)) print("generated public key {}".format(address)) addr_overview = get_address_overview(address) #getting address data for key, value in addr_overview.items( ): #getting info from address overview #check past transactions if key == 'final_n_tx': #check for any transactions in the past if value > 0: #if exist, then address has been used print("Address has been used {0} times in the past".format( value)) print(priv_key) print(address) #check balance if key == 'final_balance': #check for funds in the address if value > 0: #if any btc left on address, print details print("Address has balance of {0}".format( from_satoshis(value, 'btc'))) except: #this happens if string doesn't generate valid key return None
def run_nparty_join(self): yigen_procs = [] for i in range(self.n): ygp = local_command(['python','yield-generator.py',\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(60) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), common.get_addr_vbyte()) try: sp_proc = local_command(['python','sendpayment.py','--yes','-N', str(self.n),\ self.wallets[self.n]['seed'], str(amt), dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_nparty_join(self): yigen_procs = [] for i in range(self.n): ygp = local_command(['python','yield-generator.py',\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(60) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), common.get_addr_vbyte()) try: sp_proc = local_command(['python','sendpayment.py','-N', str(self.n),\ self.wallets[self.n]['seed'], str(amt), dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(60) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: #default mixdepth source is zero, so will take coins from m 0. #see tumbler.py --h for details expected = ['tumble with these tx'] test_in = ['y'] p = pexpect.spawn(python_cmd, ['tumbler.py', '-N', '2', '0', '-a', '0', '-M', '5', '-w', '10', '-l', '0.2', '-s', '1000000', '-q', '5', self.wallets[6]['seed'], dest_address]) interact(p, test_in, expected) p.expect(pexpect.EOF, timeout=100000) p.close() if p.exitstatus != 0: print 'failed due to exit status: ' + str(p.exitstatus) return False except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_sweep(self): #currently broken due to flooding; to make it work #change the 60 loop for the bad wallet to 20 yigen_procs = [] ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[3]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([ python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[2]['seed'], '0', dest_address ]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def from_private_key_to_address(private_key): compressed_private_key = private_key + '01' bitcoin_address = bitcoin.privkey_to_address(private_key) compressed_bitcoin_address = bitcoin.privkey_to_address( compressed_private_key) return bitcoin_address, compressed_bitcoin_address
def from_private_key_to_address(private_key): compressed_private_key = private_key + '01' bitcoin_address = bitcoin.privkey_to_address(private_key) compressed_bitcoin_address = bitcoin.privkey_to_address(compressed_private_key) return bitcoin_address,compressed_bitcoin_address
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt, ygcfs, fails, donate, rpcwallet): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list if not rpcwallet: wallet = wallets[makercount]['wallet'] else: wallet = BitcoinCoreWallet(fromaccount="") yigen_procs = [] if ygcfs: assert makercount == len(ygcfs) for i in range(makercount): if ygcfs: #back up default config, overwrite before start os.rename("joinmarket.cfg", "joinmarket.cfg.bak") shutil.copy2(ygcfs[i], "joinmarket.cfg") ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) if ygcfs: #Note: in case of using multiple configs, #the starting config is what is used by sendpayment os.rename("joinmarket.cfg.bak", "joinmarket.cfg") #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if donate: destaddr = None else: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #hack fix for #356 if multiple orders per counterparty #removed for now. #if amount==0: makercount=2 taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, makercount-2, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting message channels') mcc.run(failures=fails) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) if not donate: received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
sig = ls[1] sigs.append(sig) l = infile.readline().decode("ascii") ls = l.split() tt = TokenTransaction(token_addr, mints, outputs, signatures=sigs) log.info("Read transaction %s.", tt.handle) for addr in tt.signed_addresses: log.info("Signed with key for address: %s", addr) yield tt elif ls[0] == "BCH": # on chain transaction hex string yield OnchainTransaction(ls[1]) # FIXME: replace this garbage with unit tests if __name__ == "__main__": priv = bitcoin.sha256("0") priv2 = bitcoin.sha256("1") addr = bitcoin.privkey_to_address(priv) mints = [("txid1", 0, 50), ("txid1", 1, 100)] ctxn = TokenTransaction("TOK", addr, mints, [], [priv]) ctxn.write(sys.stdout.buffer) #inputs = [("txid2", 0), ("txid3", 1)] outputs = [30, 50] mtxn = TokenTransaction("TOK", addr, [], outputs, [priv2, bitcoin.sha256("2")]) mtxn.write(sys.stdout.buffer)
def test_external_commitment_used(setup_podle): tries = jm_single().config.getint("POLICY", "taker_utxo_retries") #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 50000000 wallets = make_wallets(3, wallet_structures=[[1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 0, 0, 0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(10) destaddr = btc.privkey_to_address(binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #create a new utxo, notionally from an external source; to make life a little #easier we'll pay to another mixdepth, but this is OK because #taker does not source from here currently, only from the utxos chosen #for the transaction, not the whole wallet. So we can treat it as if #external (don't access its privkey). utxos = wallet.get_utxos_by_mixdepth()[1] ecs = {} for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) ecs[u] = {} ecs[u]['reveal'] = {} for j in range(tries): P, P2, s, e, commit = generate_single_podle_sig( binascii.unhexlify(priv), j) if 'P' not in ecs[u]: ecs[u]['P'] = P ecs[u]['reveal'][j] = {'P2': P2, 's': s, 'e': e} btc.update_commitments(external_to_add=ecs) #Now the conditions described above hold. We do a normal single #sendpayment. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #Cleanup - remove the external commitments added btc.update_commitments(external_to_remove=ecs)
def test_tumbler(setup_tumbler, num_ygs, wallet_structures, mean_amt, sdev_amt, yg_excess): """Test of tumbler code, with yield generators in background. """ log = get_log() options = Options() options.mixdepthsrc = 0 options.mixdepthcount = 4 options.minmakercount = 2 options.makercountrange = (num_ygs, 0) options.maxcjfee = (0.01, 10000) options.txfee = 5000 options.addrcount = 3 options.donateamount = 0.5 options.txcountparams = (4, 1) options.mintxcount = 1 options.amountpower = 100 options.timelambda = 0.2 options.waittime = 10 options.mincjamount = 1000000 options.liquiditywait = 5 options.maxbroadcasts = 4 options.maxcreatetx = 9 options = vars(options) wallets = make_wallets(num_ygs + 1, wallet_structures=wallet_structures, mean_amt=mean_amt, sdev_amt=sdev_amt) #need to make sure that at least some ygs have substantially #more coins for last stages of sweep/spend in tumble: for i in range(num_ygs): jm_single().bc_interface.grab_coins( wallets[i]['wallet'].get_external_addr(0), yg_excess) #the tumbler bot uses the last wallet in the list wallet = wallets[num_ygs]['wallet'] yigen_procs = [] for i in range(num_ygs): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddrs = [] for i in range(3): destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg destaddrs.append(destaddr) tx_list = tumbler.generate_tumbler_tx(destaddrs, options) pprint(tx_list) if options['addrcount'] + 1 > options['mixdepthcount']: print( 'not enough mixing depths to pay to all destination addresses, ' 'increasing mixdepthcount') options['mixdepthcount'] = options['addrcount'] + 1 tx_list2 = copy.deepcopy(tx_list) tx_dict = {} for tx in tx_list2: srcmixdepth = tx['srcmixdepth'] tx.pop('srcmixdepth') if srcmixdepth not in tx_dict: tx_dict[srcmixdepth] = [] tx_dict[srcmixdepth].append(tx) dbg_tx_list = [] for srcmixdepth, txlist in tx_dict.iteritems(): dbg_tx_list.append({'srcmixdepth': srcmixdepth, 'tx': txlist}) log.debug('tumbler transaction list') pprint(dbg_tx_list) total_wait = sum([tx['wait'] for tx in tx_list]) print('creates ' + str(len(tx_list)) + ' transactions in total') print('waits in total for ' + str(len(tx_list)) + ' blocks and ' + str(total_wait) + ' minutes') total_block_and_wait = len(tx_list) * 10 + total_wait print('estimated time taken ' + str(total_block_and_wait) + ' minutes or ' + str(round(total_block_and_wait / 60.0, 2)) + ' hours') jm_single().nickname = random_nick() log.debug('starting tumbler') jm_single().bc_interface.sync_wallet(wallet) jm_single().bc_interface.pushtx_failure_prob = 0.4 mcs = [ IRCMessageChannel(c, jm_single().nickname) for c in get_irc_mchannels() ] mcc = MessageChannelCollection(mcs) tumbler_bot = tumbler.Tumbler(mcc, wallet, tx_list, options) try: log.debug('starting message channels') mcc.run() except: log.debug('CRASHING, DUMPING EVERYTHING') debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed']) debug_dump_object(tumbler_bot) import traceback log.debug(traceback.format_exc()) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received != 0 """TODO: figure out a sensible assertion check for the destination
def test_tx_commitments_used(setup_podle, consume_tx, age_required, cmt_age): tries = jm_single().config.getint("POLICY","taker_utxo_retries") #remember and reset at the end taker_utxo_age = jm_single().config.getint("POLICY", "taker_utxo_age") jm_single().config.set("POLICY", "taker_utxo_age", str(age_required)) #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(3, wallet_structures=[[1,2,1,0,0],[1,2,0,0,0],[2,2,1,0,0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] #make_wallets calls grab_coins which mines 1 block per individual payout, #so the age of the coins depends on where they are in that list. The sendpayment #is the last wallet in the list, and we choose the non-tx utxos which are in #mixdepth 1 and 2 (2 and 1 utxos in each respectively). We filter for those #that have sufficient age, so to get 1 which is old enough, it will be the oldest, #which will have an age of 2 + 1 (the first utxo spent to that wallet). #So if we need an age of 6, we need to mine 3 more blocks. blocks_reqd = cmt_age - 3 jm_single().bc_interface.tick_forward_chain(blocks_reqd) yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) time.sleep(5) destaddr = btc.privkey_to_address( binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) log.debug("Here is the whole wallet: \n" + str(wallet.unspent)) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) if consume_tx: #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #Now test a sendpayment from mixdepth 0 with all the depth 0 utxos #used up, so that the other utxos in the wallet get used. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] jm_single().config.set("POLICY", "taker_utxo_age", str(taker_utxo_age)) if cmt_age < age_required: assert received == 0, "Coins arrived but shouldn't" else: assert received != 0, "sendpayment failed - coins not arrived, " +\ "received: " + str(received)
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if btc.secp_present: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address( os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose jm_single().nickname = random_nick() log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 irc = IRCMessageChannel(jm_single().nickname) taker = sendpayment.SendPayment(irc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting irc') irc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
def test_failed_sendpayment(setup_podle, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of initiating joins, but failing to complete, to see commitment usage. YGs in background as per test_regtest. Use sweeps to avoid recover_from_nonrespondants without intruding into sendpayment code. """ makercount = num_ygs answeryes = True txfee = 5000 waittime = 3 #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #Allow taker more retries than makers allow, so as to trigger #blacklist failure case jm_single().config.set("POLICY", "taker_utxo_retries", "4") #override ioauth receipt with a dummy do-nothing callback: def on_ioauth(*args): log.debug("Taker received: " + ','.join([str(x) for x in args])) class DummySendPayment(sendpayment.SendPayment): def __init__(self, msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth): self.on_ioauth = on_ioauth self.podle_fails = 0 self.podle_allowed_fails = 3 #arbitrary; but do it more than once self.retries = 0 super(DummySendPayment, self).__init__(msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) def on_welcome(self): Taker.on_welcome(self) DummyPaymentThread(self).start() class DummyPaymentThread(sendpayment.PaymentThread): def finishcallback(self, coinjointx): #Don't ignore makers and just re-start self.taker.retries += 1 if self.taker.podle_fails == self.taker.podle_allowed_fails: self.taker.msgchan.shutdown() return self.create_tx() def create_tx(self): try: super(DummyPaymentThread, self).create_tx() except btc.PoDLEError: log.debug("Got one commit failure, continuing") self.taker.podle_fails += 1 taker = DummySendPayment(mcc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #We should have been able to try (tur -1) + podle_allowed_fails times assert taker.retries == jm_single().config.getint( "POLICY", "taker_utxo_retries") + taker.podle_allowed_fails #wait for block generation time.sleep(2) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] #Sanity check no transaction succeeded assert received == 0
def test_external_commitment_used(setup_podle): tries = jm_single().config.getint("POLICY","taker_utxo_retries") #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 50000000 wallets = make_wallets(3, wallet_structures=[[1,0,0,0,0],[1,0,0,0,0],[1,1,0,0,0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(10) destaddr = btc.privkey_to_address( binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #create a new utxo, notionally from an external source; to make life a little #easier we'll pay to another mixdepth, but this is OK because #taker does not source from here currently, only from the utxos chosen #for the transaction, not the whole wallet. So we can treat it as if #external (don't access its privkey). utxos = wallet.get_utxos_by_mixdepth()[1] ecs = {} for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) ecs[u] = {} ecs[u]['reveal']={} for j in range(tries): P, P2, s, e, commit = generate_single_podle_sig( binascii.unhexlify(priv), j) if 'P' not in ecs[u]: ecs[u]['P'] = P ecs[u]['reveal'][j] = {'P2':P2, 's':s, 'e':e} btc.update_commitments(external_to_add=ecs) #Now the conditions described above hold. We do a normal single #sendpayment. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #Cleanup - remove the external commitments added btc.update_commitments(external_to_remove=ecs)
def test_failed_sendpayment(setup_podle, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of initiating joins, but failing to complete, to see commitment usage. YGs in background as per test_regtest. Use sweeps to avoid recover_from_nonrespondants without intruding into sendpayment code. """ makercount = num_ygs answeryes = True txfee = 5000 waittime = 3 #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #Allow taker more retries than makers allow, so as to trigger #blacklist failure case jm_single().config.set("POLICY", "taker_utxo_retries", "4") #override ioauth receipt with a dummy do-nothing callback: def on_ioauth(*args): log.debug("Taker received: " + ','.join([str(x) for x in args])) class DummySendPayment(sendpayment.SendPayment): def __init__(self, msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth): self.on_ioauth = on_ioauth self.podle_fails = 0 self.podle_allowed_fails = 3 #arbitrary; but do it more than once self.retries = 0 super(DummySendPayment, self).__init__(msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) def on_welcome(self): Taker.on_welcome(self) DummyPaymentThread(self).start() class DummyPaymentThread(sendpayment.PaymentThread): def finishcallback(self, coinjointx): #Don't ignore makers and just re-start self.taker.retries += 1 if self.taker.podle_fails == self.taker.podle_allowed_fails: self.taker.msgchan.shutdown() return self.create_tx() def create_tx(self): try: super(DummyPaymentThread, self).create_tx() except btc.PoDLEError: log.debug("Got one commit failure, continuing") self.taker.podle_fails += 1 taker = DummySendPayment(mcc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #We should have been able to try (tur -1) + podle_allowed_fails times assert taker.retries == jm_single().config.getint( "POLICY", "taker_utxo_retries") + taker.podle_allowed_fails #wait for block generation time.sleep(2) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] #Sanity check no transaction succeeded assert received == 0
def wif_to_address(crypto, wif): try: return privkey_to_address(wif, crypto_data[crypto]['address_version_byte']) except KeyError: raise CurrencyNotSupported("Currency not yet supported")
#Vanity miner (searching for an address containing a certain string) import bitcoin import os import codecs search = '1kid' while True: secret = os.urandom(32) address = bitcoin.privkey_to_address(secret) if search in address: break print('Found vanity address! ', address) print('Secret: ', codecs.encode(secret, 'hex').decode())
def main(): args = parse_args() # Set DEBUG variable for testing purposes (changing styling) # If true, prints the SCAD to the terminal and then breaks after first generation DEBUG = False # Generate the addresses if args.copies < 1: print("Please enter a valid number of copies (-co flag), and try again.") sys.exit() else: # Use an else statement here just in case we add the option to import a CSV file with the keys (generated somewhere else) walletDataList = [] for i in range(args.copies): thisData = {} # Generate the addresses with keys thisData["privateKey"] = bitcoin.main.random_key() # Secure: uses random library, time library and proprietary function thisData["wif"] = bitcoin.encode_privkey(thisData["privateKey"], "wif", args.versionByte) thisData["address"] = bitcoin.privkey_to_address(thisData["privateKey"], args.versionByte) # Generate the QR codes if args.errorCorrection.upper() not in ["L","M","Q","H"]: print("Please select a valid QR Error Correction value (L, M, Q, or H).") sys.exit() thisData["wifQR"] = qrTools.getQRArray(thisData["wif"], args.errorCorrection.upper()) thisData["addressQR"] = qrTools.getQRArray(thisData["address"], args.errorCorrection.upper()) # Reverse them or else they appear backwards (unknown reason) thisData["wifQR"] = list(reversed(thisData["wifQR"])) thisData["addressQR"] = list(reversed(thisData["addressQR"])) # Append ALL the wallet information, just in case we want to do something with it later walletDataList.append(thisData) # Validate other args and set some constants walletWidth = args.walletWidth walletHeight = args.walletHeight if args.layoutStyle == 1 or args.layoutStyle == 2 or args.layoutStyle == 3: walletLength = walletWidth*1.6 # Approximately the same ratio as a credit card else: print("Please choose a valid layout style option.") sys.exit() if args.blackOffset < -90.0: print("Please ensure that --black-offset (-bo flag) is set correctly, and is greater than -90.") sys.exit() textDepth = (args.blackOffset/100) * walletHeight # Check the openscad command scadExe = args.scadExe if args.scadExe == "openscad" and not distutils.spawn.find_executable("openscad"): if os.path.isfile("/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD"): print("Info: OpenSCAD found in Applications folder on Mac") scadExe = "/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD" elif os.path.isfile("%PROGRAMFILES%\OpenSCAD\openscad.exe"): print("Info: OpenSCAD found in Program Files on Windows") scadExe = "%PROGRAMFILES%\OpenSCAD\openscad.exe" elif os.path.isfile("%PROGRAMFILES(x86)%\OpenSCAD\openscad.exe"): print("Info: OpenSCAD found in Program Files (x86) on Windows") scadExe = "%PROGRAMFILES(x86)%\OpenSCAD\openscad.exe" if not distutils.spawn.find_executable(scadExe): print("Please install OpenSCAD or specify the location of it with --openscad-exe.") sys.exit() # Set the master SCAD variable masterSCAD = "// SCAD Code Generated By 3DGen.py - 3D Wallet Generator\n\n" # The beginning of the wallet are identical scadOutputs = [] # Generated from loop for each wallet (different addresses) # Include some modules at the beginning masterSCAD += "// Import some modules\n" masterSCAD += """ $fn=100; module createMeniscus(h,radius)difference(){translate([radius/2+0.1,radius/2+0.1,0]){cube([radius+0.2,radius+0.1,h+0.2],center=true);}cylinder(h=h+0.2,r=radius,center=true);} module roundCornersCube(x,y,z)translate([x/2,y/2,z/2]){difference(){r=((x+y)/2)*0.052;cube([x,y,z],center=true);translate([x/2-r,y/2-r]){rotate(0){createMeniscus(z,r);}}translate([-x/2+r,y/2-r]){rotate(90){createMeniscus(z,r);}}translate([-x/2+r,-y/2+r]){rotate(180){createMeniscus(z,r);}}translate([x/2-r,-y/2+r]){rotate(270){createMeniscus(z,r);}}}} """ # The rounding corners modules for creating a rounded rectangle masterSCAD += "\n" # Draw the main prism if args.roundCorners: mainCube = "roundCornersCube(" + str(walletLength) + "," + str(walletWidth) + "," + str(walletHeight) + ");" else: mainCube = "cube([" + str(walletLength) + "," + str(walletWidth) + "," + str(walletHeight) + "]);" mainCube += "\n\n" # Init a variable to keep all the additive/subtractive parts finalParts = [] # Init variables to keep the CSV output data in addressOut = [] privkeyOut = [] APOut = [] PAOut = [] # Set a counter for naming the files filenameCounter = 1 # Break into the loop for each wallet for data in walletDataList: # 'data' = wif, address, wifQR, addressQR # Generate the texts addressLine1 = data["address"][:math.ceil(len(data["address"])/2.0)] addressLine2 = data["address"][math.ceil(len(data["address"])/2.0):] wifLine1 = data["wif"][:17] wifLine2 = data["wif"][17:34] wifLine3 = data["wif"][34:] addressLine1Dots = textGen.getArray(addressLine1) addressLine2Dots = textGen.getArray(addressLine2) privkeyLine1Dots = textGen.getArray(wifLine1) privkeyLine2Dots = textGen.getArray(wifLine2) privkeyLine3Dots = textGen.getArray(wifLine3) bigTitle = textGen.getArray("3D " + args.coinTitle + " Wallet") addressTitle = textGen.getArray("Address") privkeyTitle = textGen.getArray("Private Key") # Create the big title union so that it can be sized and moved bigTitleUnion = "" for rowIndex in range(len(bigTitle)): row = bigTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth bigTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) # Translate the title to where it goes bigTitleFinal = "translate([(1/17)*length,(14/17)*width,0]){resize([(15/17)*length,0,0],auto=[true,true,false]){bigTitleUnion}}".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('bigTitleUnion',bigTitleUnion) finalParts.append(bigTitleFinal+"\n\n") if args.layoutStyle == 1: # Need to copy it on to the backside as well - rotate then move it, and then create a union of the two titles (front and back) bigTitle2 = "translate([length,0,height]){rotate(180,v=[0,1,0]){bigTitleFinal}}".replace('length',str(walletLength)).replace('height',str(walletHeight)).replace('bigTitleFinal',bigTitleFinal).replace('translateHeight',str(translateHeight)) finalParts.append(bigTitle2+"\n\n") # Draw the word "Address" on the front, and draw on the actual address if args.layoutStyle == 1 or args.layoutStyle == 3: # Draw the address on the front addressParts = [] # Create the address title union and size/move it addressTitleUnion = "union(){" for rowIndex in range(len(addressTitle)): row = addressTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressTitleUnion += "}" addressTitleFinal = "translate([(10/17)*length,(6/11)*width,0]){resize([0,(4/55)*width,0],auto=[true,true,false]){addressTitleUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressTitleUnion',addressTitleUnion) addressParts.append(addressTitleFinal) # Create the first line of the address addressLine1Union = "union(){" for rowIndex in range(len(addressLine1Dots)): row = addressLine1Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressLine1Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressLine1Union += "}" addressLine1Final = "translate([(8.2/17)*length,(5/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){addressLine1Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressLine1Union',addressLine1Union) addressParts.append(addressLine1Final) # Create the second line of the address addressLine2Union = "union(){" for rowIndex in range(len(addressLine2Dots)): row = addressLine2Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressLine2Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressLine2Union += "}" addressLine2Final = "translate([(8.2/17)*length,(4.1/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){addressLine2Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressLine2Union',addressLine2Union) addressParts.append(addressLine2Final) # Create the QR code addressQRUnion = "union(){" for rowIndex in range(len(data["addressQR"])): row = data["addressQR"][rowIndex] for colIndex in range(len(row)): if row[colIndex] == 0: translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressQRUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressQRUnion += "}" addressQRFinal = "translate([(0.6/17)*length,(0.6/11)*width,0]){resize([0,(8/12)*width,0],auto=[true,true,false]){addressQRUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressQRUnion',addressQRUnion) addressParts.append(addressQRFinal) finalParts.extend(addressParts) # Draw all the things having to do with the private key if args.layoutStyle == 1 or args.layoutStyle == 2: privkeyParts = [] # Create the privkey title union and size/move it privkeyTitleUnion = "union(){" for rowIndex in range(len(privkeyTitle)): row = privkeyTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyTitleUnion += "}" privkeyTitleFinal = "translate([(8.7/17)*length,(7/11)*width,0]){resize([0,(4/55)*width,0],auto=[true,true,false]){privkeyTitleUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyTitleUnion',privkeyTitleUnion) privkeyParts.append(privkeyTitleFinal) # Create the first line of the privkey privkeyLine1Union = "union(){" for rowIndex in range(len(privkeyLine1Dots)): row = privkeyLine1Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine1Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine1Union += "}" privkeyLine1Final = "translate([(8.2/17)*length,(6/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine1Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine1Union',privkeyLine1Union) privkeyParts.append(privkeyLine1Final) # Create the second line of the privkey privkeyLine2Union = "union(){" for rowIndex in range(len(privkeyLine2Dots)): row = privkeyLine2Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine2Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine2Union += "}" privkeyLine2Final = "translate([(8.2/17)*length,(5.1/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine2Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine2Union',privkeyLine2Union) privkeyParts.append(privkeyLine2Final) # Create the third line of the privkey privkeyLine3Union = "union(){" for rowIndex in range(len(privkeyLine3Dots)): row = privkeyLine3Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine3Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine3Union += "}" privkeyLine3Final = "translate([(8.2/17)*length,(4.2/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine3Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine3Union',privkeyLine3Union) privkeyParts.append(privkeyLine3Final) # Create the QR code privkeyQRUnion = "union(){" for rowIndex in range(len(data["wifQR"])): row = data["wifQR"][rowIndex] for colIndex in range(len(row)): if row[colIndex] == 0: translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyQRUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyQRUnion += "}" privkeyQRFinal = "translate([(0.6/17)*length,(0.6/11)*width,0]){resize([0,(8/12)*width,0],auto=[true,true,false]){privkeyQRUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyQRUnion',privkeyQRUnion) privkeyParts.append(privkeyQRFinal) if args.layoutStyle == 2: # Just add it all to the finalParts finalParts.extend(privkeyParts) elif args.layoutStyle == 1: # Rotate it all and then add it to the finalParts privkeyPartsNew = [] for part in privkeyParts: privkeyPartsNew.append("translate([length,0,height]){rotate(180,v=[0,1,0]){part}}".replace('length',str(walletLength)).replace('height',str(walletHeight)).replace('part',part).replace('translateHeight',str(translateHeight))) finalParts.extend(privkeyPartsNew) # Put it all together finalSCAD = masterSCAD if textDepth < 0: finalSCAD += "difference() {\n\n" else: finalSCAD += "union() {\n\n" finalSCAD += mainCube finalSCAD += "".join(finalParts) finalSCAD += "}" if DEBUG: print(finalSCAD) break if args.outputSCADFolder: try: os.makedirs(args.outputSCADFolder) except FileExistsError: pass scadOutFile = open(args.outputSCADFolder + '/wallet' + str(filenameCounter) + '.scad','w') scadOutFile.write(finalSCAD) scadOutFile.close() # Log some info print("Status: Done generating data for wallet #" + str(filenameCounter) + "...Starting generating STL file") if args.outputSTLFolder: try: os.makedirs(args.outputSTLFolder) except FileExistsError: pass scadOutFile = open('temp.scad','w') scadOutFile.write(finalSCAD) scadOutFile.close() os.system(scadExe + " -o " + args.outputSTLFolder + "/wallet" + str(filenameCounter) + ".stl temp.scad") try: os.remove('temp.scad') except: pass else: print("Please provide a folder to output the STL files.") # Update the CSV file variables addressOut.append(data["address"]) privkeyOut.append(data["wif"]) APOut.append(data["address"] + "," + data["wif"]) PAOut.append(data["wif"] + "," + data["address"]) # Print some more stats print("Status: Done generating STL file (" + str(round(filenameCounter/args.copies*100)) + "% done)") filenameCounter += 1 # Export the CSV files if args.exportAddressCSV: csvFile = open(args.exportAddressCSV,'a') csvFile.write(','.join(addressOut)) csvFile.close() if args.exportPrivkeyCSV: csvFile = open(args.exportPrivkeyCSV,'a') csvFile.write(','.join(privkeyOut)) csvFile.close() if args.exportAPCSV: csvFile = open(args.exportAPCSV,'a') csvFile.write('\n'.join(exportAPCSV)) csvFile.close() if args.exportPACSV: csvFile = open(args.exportPACSV,'a') csvFile.write('\n'.join(exportPACSV)) csvFile.close()
def test_tumbler(setup_tumbler, num_ygs, wallet_structures, mean_amt, sdev_amt, yg_excess): """Test of tumbler code, with yield generators in background. """ log = get_log() options = Options() options.mixdepthsrc = 0 options.mixdepthcount = 4 options.minmakercount = 2 options.makercountrange = (num_ygs, 0) options.maxcjfee = (0.01, 10000) options.txfee = 5000 options.addrcount = 3 options.donateamount = 0.5 options.txcountparams = (4, 1) options.mintxcount = 1 options.amountpower = 100 options.timelambda = 0.2 options.waittime = 10 options.mincjamount = 1000000 options.liquiditywait = 5 options.maxbroadcasts = 4 options.maxcreatetx = 9 options = vars(options) wallets = make_wallets(num_ygs + 1, wallet_structures=wallet_structures, mean_amt=mean_amt, sdev_amt=sdev_amt) #need to make sure that at least some ygs have substantially #more coins for last stages of sweep/spend in tumble: for i in range(num_ygs): jm_single().bc_interface.grab_coins( wallets[i]['wallet'].get_external_addr(0), yg_excess) #the tumbler bot uses the last wallet in the list wallet = wallets[num_ygs]['wallet'] yigen_procs = [] for i in range(num_ygs): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddrs = [] for i in range(3): if btc.secp_present: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address( os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg destaddrs.append(destaddr) tx_list = tumbler.generate_tumbler_tx(destaddrs, options) pprint(tx_list) if options['addrcount'] + 1 > options['mixdepthcount']: print('not enough mixing depths to pay to all destination addresses, ' 'increasing mixdepthcount') options['mixdepthcount'] = options['addrcount'] + 1 tx_list2 = copy.deepcopy(tx_list) tx_dict = {} for tx in tx_list2: srcmixdepth = tx['srcmixdepth'] tx.pop('srcmixdepth') if srcmixdepth not in tx_dict: tx_dict[srcmixdepth] = [] tx_dict[srcmixdepth].append(tx) dbg_tx_list = [] for srcmixdepth, txlist in tx_dict.iteritems(): dbg_tx_list.append({'srcmixdepth': srcmixdepth, 'tx': txlist}) log.debug('tumbler transaction list') pprint(dbg_tx_list) total_wait = sum([tx['wait'] for tx in tx_list]) print('creates ' + str(len(tx_list)) + ' transactions in total') print('waits in total for ' + str(len(tx_list)) + ' blocks and ' + str( total_wait) + ' minutes') total_block_and_wait = len(tx_list) * 10 + total_wait print('estimated time taken ' + str(total_block_and_wait) + ' minutes or ' + str(round(total_block_and_wait / 60.0, 2)) + ' hours') jm_single().nickname = random_nick() log.debug('starting tumbler') jm_single().bc_interface.sync_wallet(wallet) jm_single().bc_interface.pushtx_failure_prob = 0.4 irc = IRCMessageChannel(jm_single().nickname) tumbler_bot = tumbler.Tumbler(irc, wallet, tx_list, options) try: log.debug('starting irc') irc.run() except: log.debug('CRASHING, DUMPING EVERYTHING') debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed']) debug_dump_object(tumbler_bot) import traceback log.debug(traceback.format_exc()) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received != 0 """TODO: figure out a sensible assertion check for the destination
# If true, prints the SCAD to the terminal and then breaks after first generation DEBUG = False # Generate the addresses if args.copies < 1: print("Please enter a valid number of copies (-co flag), and try again.") sys.exit() else: # Use an else statement here just in case we add the option to import a CSV file with the keys (generated somewhere else) walletDataList = [] for i in range(args.copies): thisData = {} # Generate the addresses with keys thisData["privateKey"] = bitcoin.main.random_key() # Secure: uses random library, time library and proprietary function thisData["wif"] = bitcoin.encode_privkey(thisData["privateKey"], "wif", args.versionByte) thisData["address"] = bitcoin.privkey_to_address(thisData["privateKey"], args.versionByte) # Generate the QR codes if args.errorCorrection.upper() not in ["L","M","Q","H"]: print("Please select a valid QR Error Correction value (L, M, Q, or H).") sys.exit() thisData["wifQR"] = qrTools.getQRArray(thisData["wif"], args.errorCorrection.upper()) thisData["addressQR"] = qrTools.getQRArray(thisData["address"], args.errorCorrection.upper()) # Reverse them or else they appear backwards (unknown reason) thisData["wifQR"] = list(reversed(thisData["wifQR"])) thisData["addressQR"] = list(reversed(thisData["addressQR"])) # Append ALL the wallet information, just in case we want to do something with it later walletDataList.append(thisData)
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if btc.secp_present: destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address(os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose jm_single().nickname = random_nick() log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 irc = IRCMessageChannel(jm_single().nickname) taker = sendpayment.SendPayment(irc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting irc') irc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
def test_tx_commitments_used(setup_podle, consume_tx, age_required, cmt_age): tries = jm_single().config.getint("POLICY", "taker_utxo_retries") #remember and reset at the end taker_utxo_age = jm_single().config.getint("POLICY", "taker_utxo_age") jm_single().config.set("POLICY", "taker_utxo_age", str(age_required)) #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(3, wallet_structures=[[1, 2, 1, 0, 0], [1, 2, 0, 0, 0], [2, 2, 1, 0, 0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] #make_wallets calls grab_coins which mines 1 block per individual payout, #so the age of the coins depends on where they are in that list. The sendpayment #is the last wallet in the list, and we choose the non-tx utxos which are in #mixdepth 1 and 2 (2 and 1 utxos in each respectively). We filter for those #that have sufficient age, so to get 1 which is old enough, it will be the oldest, #which will have an age of 2 + 1 (the first utxo spent to that wallet). #So if we need an age of 6, we need to mine 3 more blocks. blocks_reqd = cmt_age - 3 jm_single().bc_interface.tick_forward_chain(blocks_reqd) yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) time.sleep(5) destaddr = btc.privkey_to_address(binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) log.debug("Here is the whole wallet: \n" + str(wallet.unspent)) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) if consume_tx: #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #Now test a sendpayment from mixdepth 0 with all the depth 0 utxos #used up, so that the other utxos in the wallet get used. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] jm_single().config.set("POLICY", "taker_utxo_age", str(taker_utxo_age)) if cmt_age < age_required: assert received == 0, "Coins arrived but shouldn't" else: assert received != 0, "sendpayment failed - coins not arrived, " +\ "received: " + str(received)
elif key_type == 'P-256': sec = the_key.export_key(format='PEM') pub = the_key._export_public_pem(compress=0) #PEM decoded_keys_temp_list.append({'secret': sec, 'public': pub}) elif key_type == 'RSA': sec = the_key.export_key().decode() pub = the_key.publickey().export_key().decode() decoded_keys_temp_list.append({'secret': sec, 'public': pub}) elif key_type == 'bitcoin': from bitcoin import encode_privkey, privkey_to_address print('the_key', the_key) sec = encode_privkey(the_key[:64], 'wif_compressed') print('sec', sec) addr = privkey_to_address(the_key[:64]) print('addr', addr) decoded_keys_temp_list.append({'secret': sec, 'address': addr}) if file_type == 'json': jsoned(decoded_keys_temp_list, key_type) elif file_type == 'separated': separated(decoded_keys_temp_list, key_type) else: printed('Wrong file type. You can only use "json" and "separated" types') clear_screen() print(logo) printed('\nDone.\n') printed( '\nMAKE SURE YOU INSTANTLY PUT YOUR PRIVATE KEY IN A SAFE PLACE AS IT\'S NOT ENCRYPTED!\n'
def main(): args = parse_args() if args.layoutStyle == 4 and args.blackOffset>0: print("Unable to generate a breakaway protected wallet with inverted depth") sys.exit() # Set DEBUG variable for testing purposes (changing styling) # If true, prints the SCAD to the terminal and then breaks after first generation DEBUG = False # Generate the addresses if args.copies < 1: print("Please enter a valid number of copies (-co flag), and try again.") sys.exit() else: # Use an else statement here just in case we add the option to import a CSV file with the keys (generated somewhere else) walletDataList = [] for i in range(args.copies): thisData = {} # Generate the addresses with keys thisData["privateKey"] = bitcoin.main.random_key() # Secure: uses random library, time library and proprietary function thisData["wif"] = bitcoin.encode_privkey(thisData["privateKey"], "wif", args.versionByte) thisData["address"] = bitcoin.privkey_to_address(thisData["privateKey"], args.versionByte) # Generate the QR codes if args.errorCorrection.upper() not in ["L","M","Q","H"]: print("Please select a valid QR Error Correction value (L, M, Q, or H).") sys.exit() thisData["wifQR"] = qrTools.getQRArray(thisData["wif"], args.errorCorrection.upper()) thisData["addressQR"] = qrTools.getQRArray(thisData["address"], args.errorCorrection.upper()) # Reverse them or else they appear backwards (unknown reason) thisData["wifQR"] = list(reversed(thisData["wifQR"])) thisData["addressQR"] = list(reversed(thisData["addressQR"])) # Append ALL the wallet information, just in case we want to do something with it later walletDataList.append(thisData) # Validate other args and set some constants walletWidth = args.walletWidth walletHeight = args.walletHeight if args.layoutStyle == 1 or args.layoutStyle == 2 or args.layoutStyle == 3 or args.layoutStyle == 4: walletLength = walletWidth*1.6 # Approximately the same ratio as a credit card else: print("Please choose a valid layout style option.") sys.exit() if args.blackOffset < -90.0: print("Please ensure that --black-offset (-bo flag) is set correctly, and is greater than -90.") sys.exit() textDepth = (args.blackOffset/100) * walletHeight # Check the openscad command scadExe = args.scadExe if args.scadExe == "openscad" and not distutils.spawn.find_executable("openscad"): if os.path.isfile("/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD"): print("Info: OpenSCAD found in Applications folder on Mac") scadExe = "/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD" elif os.path.isfile("%PROGRAMFILES%\OpenSCAD\openscad.exe"): print("Info: OpenSCAD found in Program Files on Windows") scadExe = "%PROGRAMFILES%\OpenSCAD\openscad.exe" elif os.path.isfile("%PROGRAMFILES(x86)%\OpenSCAD\openscad.exe"): print("Info: OpenSCAD found in Program Files (x86) on Windows") scadExe = "%PROGRAMFILES(x86)%\OpenSCAD\openscad.exe" if not distutils.spawn.find_executable(scadExe): print("Please install OpenSCAD or specify the location of it with --openscad-exe.") sys.exit() # Set the master SCAD variable masterSCAD = "// SCAD Code Generated By 3DGen.py - 3D Wallet Generator\n\n" # The beginning of the wallet are identical scadOutputs = [] # Generated from loop for each wallet (different addresses) # Include some modules at the beginning masterSCAD += "// Import some modules\n" masterSCAD += """ $fn=100; module createMeniscus(h,radius)difference(){translate([radius/2+0.1,radius/2+0.1,0]){cube([radius+0.2,radius+0.1,h+0.2],center=true);}cylinder(h=h+0.2,r=radius,center=true);} module roundCornersCube(x,y,z)translate([x/2,y/2,z/2]){difference(){r=((x+y)/2)*0.052;cube([x,y,z],center=true);translate([x/2-r,y/2-r]){rotate(0){createMeniscus(z,r);}}translate([-x/2+r,y/2-r]){rotate(90){createMeniscus(z,r);}}translate([-x/2+r,-y/2+r]){rotate(180){createMeniscus(z,r);}}translate([x/2-r,-y/2+r]){rotate(270){createMeniscus(z,r);}}}} """ # The rounding corners modules for creating a rounded rectangle masterSCAD += "\n" # Draw the main prism mainCube = "" adjHeight = walletHeight if args.layoutStyle == 4: adjHeight += 2 mainCube ="translate([0,0,-2]) " if args.roundCorners: mainCube += "roundCornersCube(" + str(walletLength) + "," + str(walletWidth) + "," + str(adjHeight) + ");" else: mainCube += "cube([" + str(walletLength) + "," + str(walletWidth) + "," + str(adjHeight) + "]);" mainCube += "\n\n" if args.layoutStyle == 4: # Create a slice in the wallet with breakaway stubs mainCube += """ difference () { cube([86.4,54.0,0.2]); for (x=[0:20]) { translate([((x+2)/24)*86.4,(1/20)*54.0,-1]) cube([86.4/200,54.0/100,2]); translate([((x+2)/24)*86.4,(19/20)*54.0,-1]) cube([86.4/200,54.0/100,2]); translate([(1/30)*86.4,((x+2)/24)*54.0,-1]) cube([86.4/200,54.0/100,2]); translate([(29/30)*86.4,((x+2)/24)*54.0,-1]) cube([86.4/200,54.0/100,2]); } } """ # Init a variable to keep all the additive/subtractive parts finalParts = [] # Init variables to keep the CSV output data in addressOut = [] privkeyOut = [] APOut = [] PAOut = [] # Set a counter for naming the files filenameCounter = 1 # Break into the loop for each wallet for data in walletDataList: # 'data' = wif, address, wifQR, addressQR # Generate the texts addressLine1 = data["address"][:math.ceil(len(data["address"])/2.0)] addressLine2 = data["address"][math.ceil(len(data["address"])/2.0):] wifLine1 = data["wif"][:17] wifLine2 = data["wif"][17:34] wifLine3 = data["wif"][34:] addressLine1Dots = textGen.getArray(addressLine1) addressLine2Dots = textGen.getArray(addressLine2) privkeyLine1Dots = textGen.getArray(wifLine1) privkeyLine2Dots = textGen.getArray(wifLine2) privkeyLine3Dots = textGen.getArray(wifLine3) bigTitle = textGen.getArray("3D " + args.coinTitle + " Wallet") addressTitle = textGen.getArray("Address") privkeyTitle = textGen.getArray("Private Key") # Create the big title union so that it can be sized and moved bigTitleUnion = "" for rowIndex in range(len(bigTitle)): row = bigTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth bigTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) # Translate the title to where it goes bigTitleFinal = "translate([(1/17)*length,(14/17)*width,0]){resize([(15/17)*length,0,0],auto=[true,true,false]){bigTitleUnion}}".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('bigTitleUnion',bigTitleUnion) finalParts.append(bigTitleFinal+"\n\n") if args.layoutStyle == 1 or args.layoutStyle == 4: # Need to copy it on to the backside as well - rotate then move it, and then create a union of the two titles (front and back) bigTitle2 = "translate([length,0,height]){rotate(180,v=[0,1,0]){bigTitleFinal}}".replace('length',str(walletLength)).replace('height',str(walletHeight)).replace('bigTitleFinal',bigTitleFinal).replace('translateHeight',str(translateHeight)) finalParts.append(bigTitle2+"\n\n") # Draw the word "Address" on the front, and draw on the actual address if args.layoutStyle == 1 or args.layoutStyle == 3 or args.layoutStyle == 4: # Draw the address on the front addressParts = [] # Create the address title union and size/move it addressTitleUnion = "union(){" for rowIndex in range(len(addressTitle)): row = addressTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressTitleUnion += "}" addressTitleFinal = "translate([(10/17)*length,(6/11)*width,0]){resize([0,(4/55)*width,0],auto=[true,true,false]){addressTitleUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressTitleUnion',addressTitleUnion) addressParts.append(addressTitleFinal) # Create the first line of the address addressLine1Union = "union(){" for rowIndex in range(len(addressLine1Dots)): row = addressLine1Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressLine1Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressLine1Union += "}" addressLine1Final = "translate([(8.2/17)*length,(5/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){addressLine1Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressLine1Union',addressLine1Union) addressParts.append(addressLine1Final) # Create the second line of the address addressLine2Union = "union(){" for rowIndex in range(len(addressLine2Dots)): row = addressLine2Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressLine2Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressLine2Union += "}" addressLine2Final = "translate([(8.2/17)*length,(4.1/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){addressLine2Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressLine2Union',addressLine2Union) addressParts.append(addressLine2Final) # Create the QR code addressQRUnion = "union(){" for rowIndex in range(len(data["addressQR"])): row = data["addressQR"][rowIndex] for colIndex in range(len(row)): if row[colIndex] == 0: translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth addressQRUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) addressQRUnion += "}" addressQRFinal = "translate([(0.6/17)*length,(0.6/11)*width,0]){resize([0,(8/12)*width,0],auto=[true,true,false]){addressQRUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('addressQRUnion',addressQRUnion) addressParts.append(addressQRFinal) finalParts.extend(addressParts) # Draw all the things having to do with the private key if args.layoutStyle == 1 or args.layoutStyle == 2 or args.layoutStyle == 4: privkeyParts = [] # Create the privkey title union and size/move it privkeyTitleUnion = "union(){" for rowIndex in range(len(privkeyTitle)): row = privkeyTitle[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyTitleUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyTitleUnion += "}" privkeyTitleFinal = "translate([(8.7/17)*length,(7/11)*width,0]){resize([0,(4/55)*width,0],auto=[true,true,false]){privkeyTitleUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyTitleUnion',privkeyTitleUnion) privkeyParts.append(privkeyTitleFinal) # Create the first line of the privkey privkeyLine1Union = "union(){" for rowIndex in range(len(privkeyLine1Dots)): row = privkeyLine1Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine1Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine1Union += "}" privkeyLine1Final = "translate([(8.2/17)*length,(6/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine1Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine1Union',privkeyLine1Union) privkeyParts.append(privkeyLine1Final) # Create the second line of the privkey privkeyLine2Union = "union(){" for rowIndex in range(len(privkeyLine2Dots)): row = privkeyLine2Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine2Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine2Union += "}" privkeyLine2Final = "translate([(8.2/17)*length,(5.1/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine2Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine2Union',privkeyLine2Union) privkeyParts.append(privkeyLine2Final) # Create the third line of the privkey privkeyLine3Union = "union(){" for rowIndex in range(len(privkeyLine3Dots)): row = privkeyLine3Dots[rowIndex] for colIndex in range(len(row)): if row[colIndex] == '1': translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyLine3Union += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyLine3Union += "}" privkeyLine3Final = "translate([(8.2/17)*length,(4.2/11)*width,0]){resize([0,(3/55)*width,0],auto=[true,true,false]){privkeyLine3Union}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyLine3Union',privkeyLine3Union) privkeyParts.append(privkeyLine3Final) # Create the QR code privkeyQRUnion = "union(){" for rowIndex in range(len(data["wifQR"])): row = data["wifQR"][rowIndex] for colIndex in range(len(row)): if row[colIndex] == 0: translateHeight = walletHeight if textDepth>0 else walletHeight+textDepth privkeyQRUnion += "translate([colIndex,rowIndex,translateHeight]){cube([1,1,textDepth]);}".replace('colIndex',str(colIndex)).replace('rowIndex',str(rowIndex)).replace('textDepth',str(abs(textDepth))).replace('translateHeight',str(translateHeight)) privkeyQRUnion += "}" privkeyQRFinal = "translate([(0.6/17)*length,(0.6/11)*width,0]){resize([0,(8/12)*width,0],auto=[true,true,false]){privkeyQRUnion}}\n\n".replace('length',str(walletLength)).replace('width',str(walletWidth)).replace('privkeyQRUnion',privkeyQRUnion) privkeyParts.append(privkeyQRFinal) if args.layoutStyle == 2: # Just add it all to the finalParts finalParts.extend(privkeyParts) elif args.layoutStyle == 1 or args.layoutStyle == 4: # Rotate it all and then add it to the finalParts privkeyPartsNew = [] for part in privkeyParts: privkeyPartsNew.append("translate([length,0,height]){rotate(180,v=[0,1,0]){part}}".replace('length',str(walletLength)).replace('height',str(walletHeight)).replace('part',part).replace('translateHeight',str(translateHeight))) finalParts.extend(privkeyPartsNew) # Put it all together finalSCAD = masterSCAD if textDepth < 0: finalSCAD += "difference() {\n\n" else: finalSCAD += "union() {\n\n" finalSCAD += mainCube finalSCAD += "".join(finalParts) finalSCAD += "}" if DEBUG: print(finalSCAD) break if args.outputSCADFolder: try: os.makedirs(args.outputSCADFolder) except FileExistsError: pass scadOutFile = open(args.outputSCADFolder + '/wallet' + str(filenameCounter) + '.scad','w') scadOutFile.write(finalSCAD) scadOutFile.close() # Log some info print("Status: Done generating data for wallet #" + str(filenameCounter) + "...Starting generating STL file") if args.outputSTLFolder: try: os.makedirs(args.outputSTLFolder) except FileExistsError: pass scadOutFile = open('temp.scad','w') scadOutFile.write(finalSCAD) scadOutFile.close() os.system(scadExe + " -o " + args.outputSTLFolder + "/wallet" + str(filenameCounter) + ".stl temp.scad") try: os.remove('temp.scad') except: pass else: print("Please provide a folder to output the STL files.") # Update the CSV file variables addressOut.append(data["address"]) privkeyOut.append(data["wif"]) APOut.append(data["address"] + "," + data["wif"]) PAOut.append(data["wif"] + "," + data["address"]) # Print some more stats print("Status: Done generating STL file (" + str(round(filenameCounter/args.copies*100)) + "% done)") filenameCounter += 1 # Export the CSV files if args.exportAddressCSV: csvFile = open(args.exportAddressCSV,'a') csvFile.write(','.join(addressOut)) csvFile.close() if args.exportPrivkeyCSV: csvFile = open(args.exportPrivkeyCSV,'a') csvFile.write(','.join(privkeyOut)) csvFile.close() if args.exportAPCSV: csvFile = open(args.exportAPCSV,'a') csvFile.write('\n'.join(exportAPCSV)) csvFile.close() if args.exportPACSV: csvFile = open(args.exportPACSV,'a') csvFile.write('\n'.join(exportPACSV)) csvFile.close()