def test_confirm_input(self): FEE = 10000 # create a fake Spendable COIN_VALUE = 100000000 spendables = [ Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0) ] tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1]) spendables = tx_1.tx_outs_as_spendable() tx_db = dict((tx.hash(), tx) for tx in [tx_1]) tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db) tx_2 = create_signed_tx([s.as_dict() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db) tx_2 = create_signed_tx([s.as_text() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db)
def test_confirm_input_raises(self): # create a fake Spendable COIN_VALUE = 100000000 spendables = [Spendable(COIN_VALUE, script_for_address(BITCOIN_ADDRESSES[0]), FAKE_HASH, 0)] tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1]) spendables = tx_1.tx_outs_as_spendable() spendables[0].coin_value += 100 tx_db = dict((tx.hash(), tx) for tx in [tx_1]) tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) self.assertRaises(BadSpendableError, tx_2.validate_unspents, tx_db)
def test_confirm_input_raises(self): FEE = 10000 # create a fake Spendable COIN_VALUE = 100000000 spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)] tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1]) spendables = tx_1.tx_outs_as_spendable() spendables[0].coin_value += 100 tx_db = dict((tx.hash(), tx) for tx in [tx_1]) tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) self.assertRaises(BadSpendableError, tx_2.validate_unspents, tx_db)
def test_simple_spend(self): FEE = 10000 # create a fake Spendable COIN_VALUE = 100000000 spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)] EXPECTED_IDS = [ "d28bff6c4a8a0f9e7d5b7df0670d07b43c5613d8c9b14e84707b1e2c0154a978", "7afbe63b00171b18f806ebd48190ebc1c68cadf286a85489c06ebe43d146489e", "2b90c150ba1d080a0816952f5d9c2642d408989cbc4d4c540591c8c9241294bd", "17b0b5b22887081595c1a9ad153e903f63bb8682ae59d6082df018dc617e5e67", "dff1b34c243becb096ad2a2d6119973067a8137cc8bf95615e742bbf6f0944c1", "206bbfbb759a8f91901d86b62390d7587f6097a32994ece7752d143fc8a02cee", "7841412716ad35cbc9954e547ba85be89e5ed0b34ed5fb8d7594517318dc10d6", "8b7e643bf47db46ada7a75b8498990b111fe20917b5610ca6759b8b0078ccd5e", "5756f0a6d5a2bbb93a07f0729d3773aaafd21393ede3ec0e20b0b5219ca45548", "32dcbb34965ea72d2caa59eb1e907aa28bac2afea43214c1809f5d8ed360f30e", ] for count in range(1, 11): tx = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:count+1], wifs=WIFS[:1]) self.assertEqual(tx.bad_signature_count(), 0) self.assertEqual(tx.fee(), FEE) self.assertEqual(tx.id(), EXPECTED_IDS[count-1]) for idx in range(1, count+1): self.assertEqual(tx.txs_out[idx-1].bitcoin_address(), BITCOIN_ADDRESSES[idx]) # TODO: add check that s + s < generator for each signature for i in range(count): extra = (1 if i < ((COIN_VALUE - FEE) % count) else 0) self.assertEqual(tx.txs_out[i].coin_value, (COIN_VALUE - FEE)//count + extra)
def createTX(payment): (content,(addrToSend,amountToSend)) = payment if content is None: pass # it should include a reason for the error.... # raise an exception return None # actually instead of returning it should raise an exception.... else: (utxos,retAddr) = content keys = [] spendings = [] for ((txid,index),amount,key) in utxos: keys += [key.wif()] spendings += [ Spendable( amount , ScriptPayToAddress( key.hash160()).script() , h2b_rev(txid) , index ) ] print "########################################################################################" print ('spendings :',spendings) print ('addr to send :',addrToSend) print ('amountToSend :',amountToSend) print ('retAddr :',retAddr) print ('wif list :',keys) print ('transaction :',create_signed_tx(spendings,[(addrToSend,amountToSend),retAddr],wifs=keys, fee="standard").as_hex()) print "########################################################################################"
def send(self, payables, fee, change_address=None): """ Send coins list of payees with a fee and return the remaining coins to the change address (defaults to sender address) Payables should have their coin value in satoshis """ spendables = self.get_unspents() # calculate leftover coins total_in = sum([s.coin_value for s in spendables]) total_out = sum([p.value for p in payables]) leftover = total_in - (total_out + fee) if leftover > 0: payables.append(Payable(change_address or self.address, leftover)) # create a signed transaction signed_tx = create_signed_tx(spendables, payables, [ self.key.wif(), ], netcode=self.netcode) # broadcast transaction to bitcoin network for network_api in self.network_apis: try: return network_api.send(signed_tx) except NetworkAPIError: continue raise NetworkAPIError("All network calls for this method failed!")
def test_simple_spend(self): FEE = 10000 # create a fake Spendable COIN_VALUE = 100000000 spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)] EXPECTED_IDS = [ "d28bff6c4a8a0f9e7d5b7df0670d07b43c5613d8c9b14e84707b1e2c0154a978", "7afbe63b00171b18f806ebd48190ebc1c68cadf286a85489c06ebe43d146489e", "2b90c150ba1d080a0816952f5d9c2642d408989cbc4d4c540591c8c9241294bd", "17b0b5b22887081595c1a9ad153e903f63bb8682ae59d6082df018dc617e5e67", "dff1b34c243becb096ad2a2d6119973067a8137cc8bf95615e742bbf6f0944c1", "206bbfbb759a8f91901d86b62390d7587f6097a32994ece7752d143fc8a02cee", "7841412716ad35cbc9954e547ba85be89e5ed0b34ed5fb8d7594517318dc10d6", "8b7e643bf47db46ada7a75b8498990b111fe20917b5610ca6759b8b0078ccd5e", "5756f0a6d5a2bbb93a07f0729d3773aaafd21393ede3ec0e20b0b5219ca45548", "32dcbb34965ea72d2caa59eb1e907aa28bac2afea43214c1809f5d8ed360f30e", ] for count in range(1, 11): tx = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:count+1], wifs=WIFS[:1]) self.assertEqual(tx.bad_signature_count(), 0) self.assertEqual(tx.fee(), FEE) self.assertEqual(tx.id(), EXPECTED_IDS[count-1]) # TODO: add check that s + s < generator for each signature for i in range(count): extra = (1 if i < ((COIN_VALUE - FEE) % count) else 0) self.assertEqual(tx.txs_out[i].coin_value, (COIN_VALUE - FEE)//count + extra)
def createTX(payment): (content, (addrToSend, amountToSend)) = payment if content is None: pass # it should include a reason for the error.... # raise an exception return None # actually instead of returning it should raise an exception.... else: (utxos, retAddr) = content keys = [] spendings = [] for ((txid, index), amount, key) in utxos: keys += [key.wif()] spendings += [Spendable(amount, ScriptPayToAddress(key.hash160()).script(), h2b_rev(txid), index)] print "########################################################################################" print ("spendings :", spendings) print ("addr to send :", addrToSend) print ("amountToSend :", amountToSend) print ("retAddr :", retAddr) print ("wif list :", keys) print ( "transaction :", create_signed_tx(spendings, [(addrToSend, amountToSend), retAddr], wifs=keys, fee="standard").as_hex(), ) print "########################################################################################"
def test_confirm_input(self): FEE = 10000 # create a fake Spendable COIN_VALUE = 100000000 spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)] tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1]) spendables = tx_1.tx_outs_as_spendable() tx_db = dict((tx.hash(), tx) for tx in [tx_1]) tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db) tx_2 = create_signed_tx([s.as_dict() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db) tx_2 = create_signed_tx([s.as_text() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3]) tx_2.validate_unspents(tx_db)
def processSendBitcoin(fromPrivateKey, toPublicKey, amountOfBitcoin): bcip = BlockchainInfoProvider("BTC") amountOfSatoshi = int(amountOfBitcoin * 100000000) spendables = spendables_for_address(wif2address(fromPrivateKey), "BTC") try: tx = create_signed_tx(spendables, [(toPublicKey, amountOfSatoshi), wif2address(fromPrivateKey)], [fromPrivateKey], tx_fee.TX_FEE_PER_THOUSAND_BYTES) except Exception as e: print "could not build transaction." print e return False try: bcip.broadcast_tx(tx) print "tx broadcasted: ", tx.id() return tx.id() except: print "tx failed to be broadcasted" return False
def createTx(self): # address = self.fromaddress.text() # destination = self.sendto.text() address = "mti8znMQPkP9LnPcce7i3LQRuSGZ38PVPV" destination = "ms4cSWpPGb6tBzbBXNuBwsarg1SNYvkjxg" #あらかじめ送信元アドレスに対応する秘密鍵を入力しておく wif = "cNJm4inEA9xreDHntBB9gAFj8V6aSn9sqdVgDdJJGrN9Ys8b8vzD" sndtx = BlockchainInfoProvider('blockr.io') print("before") assert is_valid_wif(wif) print("after") spendables = spendables_for_address(address, "BTC") tx = create_signed_tx(spendables, payables=[destination], wifs=[wif]) sndtx.broadcast_tx(tx) self.transaction.setText(tx.as_hex())
def _make_tx(self, input_script, other_scripts=[]): from pycoin.tx.tx_utils import create_signed_tx from pycoin.solve.utils import build_p2sh_lookup cv = int(50 * 1e8) key = self._key sec = key.sec() wif = key.wif() address = key.address() p2sh_lookup = build_p2sh_lookup(other_scripts) coinbase_tx = Tx.coinbase_tx(public_key_sec=sec, coin_value=cv) coinbase_tx.txs_out[0].script = input_script spendable = coinbase_tx.tx_outs_as_spendable()[0] payables = [(address, cv)] tx = create_signed_tx(spendables=[spendable], payables=payables, wifs=[wif], p2sh_lookup=p2sh_lookup) tx.unspents = [spendable] print(tx.as_hex(include_unspents=True)) return tx
while 1: print("enter the %s => " % which, end='') netcode = input() if netcode: print(netcode) return netcode print("invalid netcode, please try again") src_address = get_address("source") netcode = get_net_code("netcode") spendables = spendables_for_address(src_address, netcode) print(spendables) while 1: print("enter the WIF for %s=> " % src_address, end='') wif = input() is_valid = is_wif_valid(wif) if is_valid: break print("invalid wif, please try again") key = Key.from_text(wif) if src_address not in (key.address(use_uncompressed=False), key.address(use_uncompressed=True)): print("** WIF doesn't correspond to %s" % src_address) print("The secret exponent is %d" % key.secret_exponent()) dst_address = get_address("destination") tx = create_signed_tx(spendables, payables=[dst_address], wifs=[wif]) print("here is the signed output transaction") print(tx.as_hex())
def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum, change_satoshi, prevtx_keynums, prevtx_outputs, prevtx_inputs): """ Performs a tx signing test, comparing Polly's signed tx against the reference wallet. Basic tx signing parameters: keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to use as tx inputs. Funding above out_satoshi + change_satoshi will be fees. out_addr - output address in bitcoin address format. out_satoshi - output amount in satoshis. change_keynum - change key index in the wallet, use None for no change. change_satoshi - change amount in satoshis, use 0 for no change. Supporting (previous) txs will be created to fund keynums and are controlled by these parameters: prevtx_keynums - keynums will show up as outputs of previous txs. A number randomly picked from this list controls how many keynums are chosen to include per prev tx. prevtx_outputs - in addition to previous tx outputs funding keynums, other outputs may be present. A number randomly picked from this list controls how many ignored outputs are injected per keynum. prevtx_inputs - previous txs need inputs too. A number randomly picked from this list controls how many inputs are chosen per previous tx. """ total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi) fee_satoshi = total_in_satoshi - out_satoshi - change_satoshi chain0 = self.wallet.subkey(0, is_hardened=True).subkey(0) chain1 = self.wallet.subkey(0, is_hardened=True).subkey(1) assert total_in_satoshi >= out_satoshi + change_satoshi assert len(keynums_satoshi) <= 32 # # Step 1: send the inputs and outputs to use in the signed tx # # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now. keys = [ (keynum, encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair)) for (keynum, _) in keynums_satoshi ] # Convert base58 address to raw hex address out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr) print() print("Sign tx parameters:", "") for i, (keynum, satoshi) in enumerate(keynums_satoshi): print("{:<10}{:16.8f} btc < key {}".format( " inputs" if 0 == i else "", satoshi / 100000000, keynum)) print("{:<10}{:16.8f} btc > {}".format(" output", out_satoshi / 100000000, self.hexstr(out_addr_160))) print("{:<10}{:16.8f} btc > key {}".format(" change", change_satoshi / 100000000, change_keynum)) print("{:<10}{:16.8f} btc".format(" fee", fee_satoshi / 100000000)) print("{:<10}{:16.8f} btc".format(" total", total_in_satoshi / 100000000)) print() print(self.PAD.format("Send tx parameters"), end='') # ---> send to Polly self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum, change_satoshi) print(self.__outok()) # # Step 2: send previous txs to fund the inputs # print() cur = 0 prevtx_info = [] while cur < len(keynums_satoshi): prevtx_outputs_satoshi = [] # Calculate how many keynums will be associated with this prev tx end = min(cur + random.choice(prevtx_keynums), len(keynums_satoshi)) # Create the prev tx output list for keynum, satoshi in keynums_satoshi[cur:end]: # Inject a random number of outputs not associated with tx input keynums for _ in range(0, random.choice(prevtx_outputs)): prevtx_outputs_satoshi.append( (random.randint(0, 0x7FFFFFFF), random.randint(0, 2099999997690000))) # Add the outputs funding the tx input keynums prevtx_outputs_satoshi.append((keynum, satoshi)) # Create output script addr = chain0.subkey(keynum, as_private=True).bitcoin_address() script = standard_tx_out_script(addr) # Capture some info we'll use later to verify the signed tx prevtx_info.append(( keynum, satoshi, script, 0, # This is the hash and will be replaced later len(prevtx_outputs_satoshi) - 1)) # Index of the valid output print("{:30}{}".format( "Make prev tx for keys", " ".join( str(keynum) for (keynum, _, _, _, _) in prevtx_info[cur:]))) # Create the prev tx prevtx = self.create_prev_tx( win=Wallet.from_master_secret( bytes(0)), # create a dummy wallet in_keynum=list(range(0, random.choice(prevtx_inputs))), sources_per_input=1, wout=chain0, out_keynum_satoshi=prevtx_outputs_satoshi, fees_satoshi=random.randint(100, 1000)) # We have built the prev tx, calculate its hash (and reverse the bytes) prevtx_hash = encoding.double_sha256(prevtx)[::-1] # Update the hashes now that we have a full prev tx for i, (keynum, satoshi, script, _, outidx) in enumerate(prevtx_info[cur:]): prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash, outidx) # Create the index table that matches a keynum index with an ouput index in this prev tx idx_table = [ (keynum_idx + cur, outidx) for keynum_idx, (_, _, _, _, outidx) in enumerate(prevtx_info[cur:]) ] print(self.PAD.format("Send prev tx "), end='') # ---> send to Polly self.polly.send_prev_tx(idx_table, prevtx) print(self.__outok()) cur = end # # Step 3: generate a signed tx with the reference wallet and compare against Polly's # spendables = [] wifs = [] # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info: spendables.append(Spendable(satoshi, script, prevtx_hash, outidx)) wifs.append(chain0.subkey(keynum, as_private=True).wif()) change_addr = chain1.subkey(change_keynum).bitcoin_address() payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)] print() print(self.PAD.format("Make reference signature")) signed_tx = create_signed_tx(spendables, payables, wifs, fee_satoshi) signed_tx = self.get_tx_bytes(signed_tx) print(self.PAD.format("Get signed tx"), end='', flush=True) # <--- get the signed tx from Polly polly_signed_tx = self.polly.send_get_signed_tx() #print(self.txstr(polly_signed_tx)) #print(self.txstr(signed_tx)) print(self.__outok()) # Compare reference wallet signed tx with polly's assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr( signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
print "enter the %s address=>"%which, address=input(); is_valid=is_address_valid(address) if is_valid: return address print 'invalid address, please try again' src_address=get_address("source") spendables=spendables_for_address(src_address) print spendables while 1: print "enter the WIF for %s" %src_address, wif=input() is_valid=is_wif_valid(wif) if is_valid: break print("invalid wif, please try again") key = key.from_text(wif) if src_address not in (key.address(use_uncompressed=False), key.address(use_uncompressed=True)): print("**WIF doesn't correspond to %s" %src_address) print("The secret exponent is %d"%key.secret_exponent()) dst_address=get_address("destination") tx=create_signed_tx(spendables, payables=[dst_address], wifs=[wif]) print 'here is the signed output transaction' print(tx.as_hex())
utxos = json.loads(urlopen(URL).read().decode("utf8")) utxo = utxos[0] return Spendable(utxo['amount'], h2b(utxo.get("scriptPubKey")), h2b_rev(utxo.get("txid")), utxo.get("vout")) amount, script_hex = get_spendable(from_address) spendable = Spendable(amount, script_hex) ################## # TODO: 设计amount计算 tx = create_signed_tx([spendable], [(to_address, btc_to_satoshi("0.00005")), (btc_withdraw_address, btc_to_satoshi("0.0015"))], fee=btc_to_satoshi("0.00005"), wifs=[master_key.wif()], netcode=args.netcode) tx_as_hex = tx.as_hex() print tx_as_hex # TODO 节点选取 # url = "https://test-insight.bitpay.com/api/tx/send" # data = urlencode(dict(rawtx=tx_as_hex)).encode("utf8") # AGENT = 'pycoin/%s' % version #req = request.Request(url, data=data) #r = request.urlopen(req).read() #print r
def process(request): if request.method == 'POST': # auto deposit function if request.POST.get('VERY_LONG_RANDOM_STRING'): account_record = AccountModel.objects.create( return_address=chikun_address) account_record.save() deposit_address = master_public_key.subkey( account_record.id).address() return HttpResponse(deposit_address) response = system('ping -c 1 -w 3 %s > /dev/null 2>&1' % hostname) if request.POST.get('v_key') == v_key and response == 0: # check balance stats for all balance 0's zero_list = AccountModel.objects.filter(balance=0) if zero_list.exists(): for i in zero_list: address = master_public_key.subkey(i.id).address() try: balance = Decimal( urlopen( 'https://%s/q/addressbalance/%s?confirmations=%s&api_code=%s' % (hostname, address, confirmations, api_code)).read()) / 100000000 # REMOTE except Exception as e: lf = open('logFile', 'a') print('try one: ', end='') print(e, file=lf) lf.close() return HttpResponse(status=204) if balance >= Decimal('0.001'): i.balance = balance i.checked += 1 i.save() # match valid accounts and make payments nonzero_list = AccountModel.objects.filter( balance__gt=0).order_by('?') if len(nonzero_list) > 1: v = True limit = len(nonzero_list) / 2 if not len( nonzero_list) % 2 else (len(nonzero_list) - 1) / 2 nonzero_list = nonzero_list[:limit * 2] else: v = False if v: slice_one = nonzero_list[:limit] slice_two = nonzero_list[limit:] c = 0 while c < limit: if not slice_one[c].balance == slice_two[c].balance: (winner, loser) = ( slice_one[c], slice_two[c] ) if slice_one[c].balance > slice_two[c].balance else ( slice_two[c], slice_one[c]) winner_key = Key.from_text( request.POST['private_key']).subkey(winner.id) loser_key = Key.from_text( request.POST['private_key']).subkey(loser.id) try: spendables = spendables_for_address( '%s&api_code=%s' % (winner_key.address(), api_code)) + spendables_for_address( '%s&api_code=%s' % (loser_key.address(), api_code)) signed_tx = create_signed_tx( spendables, [(chikun_address, int((loser.balance * vig) * 100000000)), winner.return_address], wifs=[winner_key.wif(), loser_key.wif()], fee="standard") pushtx(signed_tx.as_hex()) ResultModel.objects.create( winning_address=winner_key.address(), winning_deposit=str(winner.balance), losing_address=loser_key.address(), losing_deposit=str(loser.balance), txid=signed_tx.id()).save() for i in (winner, loser): ArchiveModel.objects.create( **AccountModel.objects.filter( id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() except Exception as e: lf = open('logFile', 'a') print('try two: ', end='') print(e, file=lf) lf.close() for i in (winner, loser): BrokenModel.objects.create( **AccountModel.objects.filter( id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() c += 1 # remove invalid accounts invalid_accounts = AccountModel.objects.filter( checked__gt=24).filter(balance=0) # four hours if invalid_accounts.exists(): for i in invalid_accounts: InvalidModel.objects.create(**AccountModel.objects.filter( id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() return HttpResponse(status=204) return HttpResponse( '<h1>Not Found</h1><p>The requested URL /with was not found on this server.</p>', status=404)
def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum, change_satoshi, prevtx_keynums, prevtx_outputs, prevtx_inputs): """ Performs a tx signing test, comparing Polly's signed tx against the reference wallet. Basic tx signing parameters: keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to use as tx inputs. Funding above out_satoshi + change_satoshi will be fees. out_addr - output address in bitcoin address format. out_satoshi - output amount in satoshis. change_keynum - change key index in the wallet, use None for no change. change_satoshi - change amount in satoshis, use 0 for no change. Supporting (previous) txs will be created to fund keynums and are controlled by these parameters: prevtx_keynums - keynums will show up as outputs of previous txs. A number randomly picked from this list controls how many keynums are chosen to include per prev tx. prevtx_outputs - in addition to previous tx outputs funding keynums, other outputs may be present. A number randomly picked from this list controls how many ignored outputs are injected per keynum. prevtx_inputs - previous txs need inputs too. A number randomly picked from this list controls how many inputs are chosen per previous tx. """ total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi) fee_satoshi = total_in_satoshi - out_satoshi - change_satoshi chain0 = self.wallet.subkey(0, is_hardened = True).subkey(0) chain1 = self.wallet.subkey(0, is_hardened = True).subkey(1) assert total_in_satoshi >= out_satoshi + change_satoshi assert len(keynums_satoshi) <= 32 # # Step 1: send the inputs and outputs to use in the signed tx # # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now. keys = [(keynum, encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair)) for (keynum, _) in keynums_satoshi] # Convert base58 address to raw hex address out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr) print() print("Sign tx parameters:", "") for i, (keynum, satoshi) in enumerate(keynums_satoshi): print("{:<10}{:16.8f} btc < key {}".format (" inputs" if 0 == i else "", satoshi / 100000000, keynum)) print("{:<10}{:16.8f} btc > {}".format (" output", out_satoshi / 100000000, self.hexstr(out_addr_160))) print("{:<10}{:16.8f} btc > key {}".format (" change", change_satoshi / 100000000, change_keynum)) print("{:<10}{:16.8f} btc".format (" fee", fee_satoshi / 100000000)) print("{:<10}{:16.8f} btc".format (" total", total_in_satoshi / 100000000)) print() print(self.PAD.format("Send tx parameters"), end='') # ---> send to Polly self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum, change_satoshi) print(self.__outok()) # # Step 2: send previous txs to fund the inputs # print() cur = 0 prevtx_info = [] while cur < len(keynums_satoshi) : prevtx_outputs_satoshi = [] # Calculate how many keynums will be associated with this prev tx end = min(cur + random.choice(prevtx_keynums), len(keynums_satoshi)) # Create the prev tx output list for keynum, satoshi in keynums_satoshi[cur:end] : # Inject a random number of outputs not associated with tx input keynums for _ in range(0, random.choice(prevtx_outputs)) : prevtx_outputs_satoshi.append((random.randint(0, 0x7FFFFFFF), random.randint(0, 2099999997690000))) # Add the outputs funding the tx input keynums prevtx_outputs_satoshi.append((keynum, satoshi)) # Create output script addr = chain0.subkey(keynum, as_private = True).bitcoin_address() script = standard_tx_out_script(addr) # Capture some info we'll use later to verify the signed tx prevtx_info.append((keynum, satoshi, script, 0, # This is the hash and will be replaced later len(prevtx_outputs_satoshi) - 1)) # Index of the valid output print("{:30}{}".format("Make prev tx for keys", " ".join(str(keynum) for (keynum, _, _, _, _) in prevtx_info[cur:]))) # Create the prev tx prevtx = self.create_prev_tx(win = Wallet.from_master_secret(bytes(0)), # create a dummy wallet in_keynum = list(range(0, random.choice(prevtx_inputs))), sources_per_input = 1, wout = chain0, out_keynum_satoshi = prevtx_outputs_satoshi, fees_satoshi = random.randint(100, 1000)) # We have built the prev tx, calculate its hash (and reverse the bytes) prevtx_hash = encoding.double_sha256(prevtx)[::-1] # Update the hashes now that we have a full prev tx for i, (keynum, satoshi, script, _, outidx) in enumerate(prevtx_info[cur:]) : prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash, outidx) # Create the index table that matches a keynum index with an ouput index in this prev tx idx_table = [(keynum_idx + cur, outidx) for keynum_idx, (_, _, _, _, outidx) in enumerate(prevtx_info[cur:])] print(self.PAD.format("Send prev tx "), end='') # ---> send to Polly self.polly.send_prev_tx(idx_table, prevtx) print(self.__outok()) cur = end # # Step 3: generate a signed tx with the reference wallet and compare against Polly's # spendables = [] wifs = [] # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info: spendables.append(Spendable(satoshi, script, prevtx_hash, outidx)) wifs.append(chain0.subkey(keynum, as_private = True).wif()) change_addr = chain1.subkey(change_keynum).bitcoin_address() payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)] print() print(self.PAD.format("Make reference signature")) signed_tx = create_signed_tx(spendables, payables, wifs, fee_satoshi) signed_tx = self.get_tx_bytes(signed_tx) print(self.PAD.format("Get signed tx"), end='', flush = True) # <--- get the signed tx from Polly polly_signed_tx = self.polly.send_get_signed_tx() #print(self.txstr(polly_signed_tx)) #print(self.txstr(signed_tx)) print(self.__outok()) # Compare reference wallet signed tx with polly's assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr(signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
def process(request): if request.method == 'POST': # auto deposit function if request.POST.get('VERY_LONG_RANDOM_STRING'): account_record = AccountModel.objects.create(return_address=chikun_address) account_record.save() deposit_address = master_public_key.subkey(account_record.id).address() return HttpResponse(deposit_address) response = system('ping -c 1 -w 3 %s > /dev/null 2>&1' % hostname) if request.POST.get('v_key') == v_key and response == 0: # check balance stats for all balance 0's zero_list = AccountModel.objects.filter(balance=0) if zero_list.exists(): for i in zero_list: address = master_public_key.subkey(i.id).address() try: balance = Decimal(urlopen('https://%s/q/addressbalance/%s?confirmations=%s&api_code=%s' % (hostname, address, confirmations, api_code)).read()) / 100000000 # REMOTE except Exception as e: lf = open('logFile', 'a') print('try one: ', end='') print(e, file=lf) lf.close() return HttpResponse(status=204) if balance >= Decimal('0.001'): i.balance = balance i.checked += 1 i.save() # match valid accounts and make payments nonzero_list = AccountModel.objects.filter(balance__gt=0).order_by('?') if len(nonzero_list) > 1: v = True limit = len(nonzero_list) / 2 if not len(nonzero_list) % 2 else (len(nonzero_list) - 1) / 2 nonzero_list = nonzero_list[:limit * 2] else: v = False if v: slice_one = nonzero_list[:limit] slice_two = nonzero_list[limit:] c = 0 while c < limit: if not slice_one[c].balance == slice_two[c].balance: (winner, loser) = (slice_one[c], slice_two[c]) if slice_one[c].balance > slice_two[c].balance else (slice_two[c], slice_one[c]) winner_key = Key.from_text(request.POST['private_key']).subkey(winner.id) loser_key = Key.from_text(request.POST['private_key']).subkey(loser.id) try: spendables = spendables_for_address('%s&api_code=%s' % (winner_key.address(), api_code)) + spendables_for_address('%s&api_code=%s' % (loser_key.address(), api_code)) signed_tx = create_signed_tx(spendables, [(chikun_address, int((loser.balance * vig) * 100000000)), winner.return_address], wifs=[winner_key.wif(), loser_key.wif()], fee="standard") pushtx(signed_tx.as_hex()) ResultModel.objects.create(winning_address=winner_key.address(), winning_deposit=str(winner.balance), losing_address=loser_key.address(), losing_deposit=str(loser.balance), txid=signed_tx.id()).save() for i in (winner, loser): ArchiveModel.objects.create(**AccountModel.objects.filter(id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() except Exception as e: lf = open('logFile', 'a') print('try two: ', end='') print(e, file=lf) lf.close() for i in (winner, loser): BrokenModel.objects.create(**AccountModel.objects.filter(id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() c += 1 # remove invalid accounts invalid_accounts = AccountModel.objects.filter(checked__gt=24).filter(balance=0) # four hours if invalid_accounts.exists(): for i in invalid_accounts: InvalidModel.objects.create(**AccountModel.objects.filter(id=i.id).values()[0]).save() AccountModel.objects.filter(id=i.id).delete() return HttpResponse(status=204) return HttpResponse('<h1>Not Found</h1><p>The requested URL /with was not found on this server.</p>', status=404)