def refund(proxy, refundGuy, contract): redeemScript = CScript(x(contract['redeemScript'])) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, refundGuy['addr'].to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) txin.nSequence = 0 tx.nLockTime = contract['redeemblocknum'] sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) sig = refundGuy['key'].sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, refundGuy['key'].pub, OP_FALSE, redeemScript]) txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey() print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize()))) res = VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) print("Script verified, sending raw transaction... (NOT)", res) txid = proxy.sendrawtransaction(tx) refund_tx = b2x(lx(b2x(txid))) fund_tx = str(fundtx['outpoint']) return {"refund_tx": refund_tx, "fund_tx": fund_tx}
def make_unsigned(cls, outpoints, output_address, tx_fee=TRANSACTION_FEE, testnet=False, out_value=None): """ Build an unsigned transaction. Args: outpoints: A `list` of `dict` objects which contain a txid, vout, value, and scriptPubkey. output_address: The address to send the full value (minus the tx fee) of the inputs to. tx_fee: The Bitcoin network fee to be paid on this transaction. testnet: Should this transaction be built for testnet? out_value: used if you want to specify a specific output value otherwise the full value of the inputs (minus the tx fee) will be used. """ # build the inputs from the outpoints object SelectParams("testnet" if testnet else "mainnet") txins = [] in_value = 0 for outpoint in outpoints: in_value += outpoint["value"] txin = CMutableTxIn(COutPoint(lx(outpoint["txid"]), outpoint["vout"])) txin.scriptSig = CScript(x(outpoint["scriptPubKey"])) txins.append(txin) # build the output value = out_value if out_value is not None else (in_value - tx_fee) txout = CMutableTxOut(value, CBitcoinAddress(output_address).to_scriptPubKey()) # make the transaction tx = CMutableTransaction(txins, [txout]) return BitcoinTransaction(tx)
def main(): ''' Our main function. ''' SelectParams('mainnet') decoded_transaction = eval(open('transaction_to_sign.txt').read()) # pylint: disable=eval-used txin_txid = lx(decoded_transaction['vin'][0]['txid']) txin_vout = 0 tx_in = CMutableTxIn(COutPoint(txin_txid, txin_vout)) tx_out = [] for idx in range(len(decoded_transaction['vout'])): satoshis = int(COIN * decoded_transaction['vout'][idx]['value']) script_pub_key = CScript(bytes.fromhex(decoded_transaction['vout'][idx]['scriptPubKey']['hex'])) tx_out.append(CMutableTxOut(satoshis, script_pub_key)) tx_to_spend = CMutableTransaction([tx_in], tx_out) priv_1 = CBitcoinSecret.from_secret_bytes(bytes.fromhex(PRIV_HEX_1)) priv_2 = CBitcoinSecret.from_secret_bytes(bytes.fromhex(PRIV_HEX_2)) txin_redeem_script = CScript(bytes.fromhex(decoded_transaction['vin'][0]['scriptSig']['hex'])) # Input 0 is fixed. sighash = SignatureHash(txin_redeem_script, tx_to_spend, 0, SIGHASH_ALL) signatures = [] for priv in [priv_1, priv_2]: signatures.append(priv.sign(sighash) + bytes([SIGHASH_ALL])) tx_in.scriptSig = CScript([CScriptOp(0x00), signatures[0], signatures[1], txin_redeem_script]) # script_pub_key Defined in cycle. VerifyScript(tx_in.scriptSig, txin_redeem_script, tx_to_spend, 0, (SCRIPT_VERIFY_P2SH,)) print(b2x(tx_to_spend.serialize()))
def refund(self, contract): fundtx = self.find_transaction_to_address(contract.p2sh) print("Fund tx found in refund: ", fundtx) refundPubKey = self.find_refundAddr(contract) print('refundPubKey: {0}'.format(refundPubKey)) redeemScript = CScript(x(contract.redeemScript)) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, refundPubKey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) # Set nSequence and nLockTime txin.nSequence = 0 tx.nLockTime = contract.redeemblocknum sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) privkey = self.bitcoind.dumpprivkey(refundPubKey) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) # Sign without secret txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript]) # txin.nSequence = 2185 txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey() print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize()))) res = VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) print("Script verified, sending raw transaction... (NOT)", res) txid = self.bitcoind.sendrawtransaction(tx) refund_tx = b2x(lx(b2x(txid))) fund_tx = str(fundtx['outpoint']) return {"refund_tx": refund_tx, "fund_tx": fund_tx}
def redeem(proxy, redeemerGuy, contract, fundtx, secret): print('redeemPubKey', redeemerGuy['addr']) # TODO: Compare with script on blockchain? redeemScript = CScript(x(contract['redeemScript'])) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, redeemerGuy['addr'].to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) # TODO: protect privkey better, separate signing from rawtx creation #privkey = self.bitcoind.dumpprivkey(self.redeemPubKey) sig = redeemerGuy['key'].sign(sighash) + bytes([SIGHASH_ALL]) preimage = secret.encode('utf-8') # preimage = x(secret) txin.scriptSig = CScript([sig, redeemerGuy['key'].pub, preimage, OP_TRUE, redeemScript]) # print("txin.scriptSig", b2x(txin.scriptSig)) txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey() print('Raw redeem transaction hex: ', b2x(tx.serialize())) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) print("Script verified, sending raw transaction...") txid = proxy.sendrawtransaction(tx) fund_tx = str(fundtx['outpoint']) redeem_tx = b2x(lx(b2x(txid))) return {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
def build_crediting_tx(script_pubkey): tx = Transaction(version=1, locktime=0) txin = CMutableTxIn() txin.scriptSig = Script.from_human('0x00 0x00') tx.vin = [txin] txout = CMutableTxOut(0, script_pubkey) tx.vout = [txout] return tx
def redeem_contract(self, contract, secret): print("Parsing script for redeem_contract...") scriptarray = self.parse_script(contract.redeemScript) redeemblocknum = scriptarray[8] redeemPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[6])) refundPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[13])) p2sh = contract.p2sh #checking there are funds in the address amount = self.check_funds(p2sh) if(amount == 0): print("address ", p2sh, " not funded") quit() fundtx = self.find_transaction_to_address(p2sh) amount = fundtx['amount'] / COIN # print("Found fund_tx: ", fundtx) p2sh = P2SHBitcoinAddress(p2sh) if fundtx['address'] == p2sh: print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) blockcount = self.bitcoind.getblockcount() print("\nCurrent blocknum at time of redeem on Zcash:", blockcount) if blockcount < int(redeemblocknum): print('redeemPubKey', redeemPubKey) zec_redeemScript = CScript(x(contract.redeemScript)) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL) # TODO: protect privkey better, separate signing from rawtx creation privkey = self.bitcoind.dumpprivkey(redeemPubKey) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) preimage = secret.encode('utf-8') txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript]) # print("txin.scriptSig", b2x(txin.scriptSig)) txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey() print('Raw redeem transaction hex: ', b2x(tx.serialize())) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) print("Script verified, sending raw transaction...") txid = self.bitcoind.sendrawtransaction(tx) fund_tx = str(fundtx['outpoint']) redeem_tx = b2x(lx(b2x(txid))) return {"redeem_tx": redeem_tx, "fund_tx": fund_tx} else: print("nLocktime exceeded, refunding") print('refundPubKey', refundPubKey) txid = self.bitcoind.sendtoaddress(refundPubKey, fundtx['amount'] - FEE) fund_tx = str(fundtx['outpoint']) refund_tx = b2x(lx(b2x(txid))) return {"refund_tx": refund_tx, "fund_tx": fund_tx} else: print("No contract for this p2sh found in database", p2sh)
def redeem_after_timelock(contract): p2sh = contract.p2sh fundtx = find_transaction_to_address(p2sh) amount = fundtx['amount'] / COIN if (fundtx['address'].__str__() != p2sh): print("no fund transaction found to the contract p2sh address ", p2sh) quit() print("Found fundtx:", fundtx) # Parsing redeemblocknum from the redeemscript of the p2sh redeemblocknum = find_redeemblocknum(contract) blockcount = bitcoind.getblockcount() print("Current block:", blockcount, "Can redeem from block:", redeemblocknum) if (still_locked(contract)): print("too early for redeeming with timelock try again at block", redeemblocknum, "or later") return 0 print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) redeemPubKey = find_refundAddr(contract) print('refundPubKey', redeemPubKey) redeemScript = CScript(x(contract.redeemScript)) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey()) # Create the unsigned raw transaction. txin.nSequence = 0 tx = CMutableTransaction([txin], [txout]) tx.nLockTime = redeemblocknum sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) # TODO: figure out how to better protect privkey privkey = bitcoind.dumpprivkey(redeemPubKey) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript]) # exit() # print("txin.scriptSig", b2x(txin.scriptSig)) txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey() # print('Redeem txhex', b2x(tx.serialize())) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) print("script verified, sending raw tx") txid = bitcoind.sendrawtransaction(tx) print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid)))) return b2x(lx(b2x(txid)))
def make_unsigned(cls, outpoints, outputs, tx_fee=TRANSACTION_FEE, testnet=False, out_value=None): """ Build an unsigned transaction. Args: outpoints: A `list` of `dict` objects which contain a txid, vout, value, and scriptPubkey. outputs: If a single address the full value of the inputs (minus the tx fee) will be sent there. Otherwise it should be a `list` of `dict` objects containing address and value. tx_fee: The Bitcoin network fee to be paid on this transaction. testnet: Should this transaction be built for testnet? out_value: used if you want to specify a specific output value otherwise the full value of the inputs (minus the tx fee) will be used. """ # build the inputs from the outpoints object SelectParams("testnet" if testnet else "mainnet") txins = [] in_value = 0 for outpoint in outpoints: in_value += outpoint["value"] txin = CMutableTxIn( COutPoint(lx(outpoint["txid"]), outpoint["vout"])) txin.scriptSig = CScript(x(outpoint["scriptPubKey"])) txins.append(txin) # build the outputs txouts = [] if isinstance(outputs, list): for output in outputs: value = output["value"] address = output["address"] txouts.append( CMutableTxOut(value, CBitcoinAddress(address).to_scriptPubKey())) else: value = out_value if out_value is not None else (in_value - tx_fee) txouts.append( CMutableTxOut(value, CBitcoinAddress(outputs).to_scriptPubKey())) # make the transaction tx = CMutableTransaction(txins, txouts) return BitcoinTransaction(tx)
def redeem_with_secret(contract, secret): # How to find redeemScript and redeemblocknum from blockchain? print("Redeeming contract using secret", contract.__dict__) p2sh = contract.p2sh minamount = float(contract.amount) #checking there are funds in the address amount = check_funds(p2sh) if (amount < minamount): print("address ", p2sh, " not sufficiently funded") return false fundtx = find_transaction_to_address(p2sh) amount = fundtx['amount'] / COIN p2sh = P2SHBitcoinAddress(p2sh) if fundtx['address'] == p2sh: print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) redeemPubKey = find_redeemAddr(contract) print('redeemPubKey', redeemPubKey) redeemScript = CScript(x(contract.redeemScript)) txin = CMutableTxIn(fundtx['outpoint']) txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) # TODO: figure out how to better protect privkey privkey = bitcoind.dumpprivkey(redeemPubKey) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) print("SECRET", secret) preimage = secret.encode('utf-8') txin.scriptSig = CScript( [sig, privkey.pub, preimage, OP_TRUE, redeemScript]) # exit() # print("txin.scriptSig", b2x(txin.scriptSig)) txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey() # print('Redeem txhex', b2x(tx.serialize())) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) print("script verified, sending raw tx") txid = bitcoind.sendrawtransaction(tx) print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid)))) return b2x(lx(b2x(txid))) else: print("No contract for this p2sh found in database", p2sh)
def maketx(tx): #txid from blockr. bitcoind does not support tx index! txid = lx(tx) vout = 0 outp = COutPoint(txid, vout) print("output: %s" % outp) # Create the txin structure, which includes the outpoint txin = CMutableTxIn(outp) print(txin) txin_scriptPubKey = CScript( [OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]) print(txin_scriptPubKey) amount = 0.001 * COIN txout = CMutableTxOut(amount, CBitcoinAddress(a).to_scriptPubKey()) print(txout) # Create the unsigned transaction. newtx = CMutableTransaction([txin], [txout]) print(newtx) sighash = SignatureHash(txin_scriptPubKey, newtx, 0, SIGHASH_ALL) print(sighash) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) print(sig) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub]) try: VerifyScript(txin.scriptSig, txin_scriptPubKey, newtx, 0, (SCRIPT_VERIFY_P2SH, )) except: pass print('*' * 20) print(b2x(newtx.serialize())) """
def maketx(tx): #txid from blockr. bitcoind does not support tx index! txid = lx(tx) vout = 0 outp = COutPoint(txid, vout) print ("output: %s"%outp) # Create the txin structure, which includes the outpoint txin = CMutableTxIn(outp) print (txin) txin_scriptPubKey = CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]) print (txin_scriptPubKey) amount = 0.001*COIN txout = CMutableTxOut(amount, CBitcoinAddress(a).to_scriptPubKey()) print (txout) # Create the unsigned transaction. newtx = CMutableTransaction([txin], [txout]) print (newtx) sighash = SignatureHash(txin_scriptPubKey, newtx, 0, SIGHASH_ALL) print (sighash) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) print (sig) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub]) try: VerifyScript(txin.scriptSig, txin_scriptPubKey, newtx, 0, (SCRIPT_VERIFY_P2SH,)) except: pass print ('*'*20) print(b2x(newtx.serialize())) """
txin_scriptPubKey = CScript( [OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]) # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut( 0.001 * COIN, CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) # Calculate the signature hash for that transaction. sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub]) # Verify the signature worked. This calls EvalScript() and actually executes # the opcodes in the scripts to see if everything worked out. If it doesn't an # exception will be raised. VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) # Done! Print the transaction to standard output with the bytes-to-hex # function. print(b2x(tx.serialize()))
# Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut(0.0005*COIN, CBitcoinAddress('323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp').to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) # Calculate the signature hash for that transaction. Note how the script we use # is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG # operation happens EvalScript() will be evaluating the redeemScript, so the # corresponding SignatureHash() function will use that same script when it # replaces the scriptSig in the transaction being hashed with the script being # executed. sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, txin_redeemScript]) # Verify the signature worked. This calls EvalScript() and actually executes # the opcodes in the scripts to see if everything worked out. If it doesn't an # exception will be raised. VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) # Done! Print the transaction to standard output with the bytes-to-hex # function. print(b2x(tx.serialize()))
dest_addr = bitcoin_rpc.getnewaddress() coinbase_amount = coinbase["vout"][0]["value"] fee = 10000 # in satoshi out_amount = coinbase_amount * COIN + burn_amount * COIN - fee txout = CMutableTxOut(out_amount, CBitcoinAddress(dest_addr).to_scriptPubKey()) # Create the transaction tx = CMutableTransaction([txin, txin2], [txout]) # Sign inputs. Start with the coinbase input. coinbase_address = coinbase["vout"][0]["scriptPubKey"]["addresses"][0] seckey_coinbase = CBitcoinSecret(bitcoin_rpc.dumpprivkey(coinbase_address)) sighash = SignatureHash(CScript(x(coinbase["vout"][0]["scriptPubKey"]["hex"])), tx, 0, SIGHASH_ALL) sig = seckey_coinbase.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig]) # Sign "burn" address input. sighash = SignatureHash(CScript(multisig_script), tx, 1, SIGHASH_ALL) sig = seckey_multisig.sign(sighash) + bytes([SIGHASH_ALL]) txin2.scriptSig = CScript([OP_0, sig, redeemScript]) scriptPubKey = redeemScript.to_p2sh_scriptPubKey() # Submit transaction to bitcoind, create a block and check received amount. txid = bitcoin_rpc.sendrawtransaction(b2x(tx.serialize())) bitcoin_rpc.generate(1) print("Sent coins from \"burn\" address to own address (txid: %s)" % txid) assert (int(bitcoin_rpc.getreceivedbyaddress(str(dest_addr)) * COIN) == out_amount) print("Received %.8f (coinbase) + %.8f coins (\"burned\") - %.8f (fee)" % (coinbase_amount, burn_amount, float(fee) / COIN))
#print("raw unsigned transaction: " + b2x(tx.serialize())) for index, txin in enumerate(txins): # Calculate the signature hash for that transaction. Note how the script we use # is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG # operation happens EvalScript() will be evaluating the redeemScript, so the # corresponding SignatureHash() function will use that same script when it # replaces the scriptSig in the transaction being hashed with the script being # executed. sighash = SignatureHash(redeem_script, tx, index, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = secret.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, redeem_script]) # Verify the signature worked. This calls EvalScript() and actually executes # the opcodes in the scripts to see if everything worked out. If it doesn't an # exception will be raised. # this is commented out so that locktime requirement error is not hidden when this script is run before locktime requirement is satisfied # VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, index, (SCRIPT_VERIFY_P2SH,)) # Done setting up the transaction. Display it. # print('transaction: ' + b2x(tx.serialize())) # actually execute the transaction transactionid = proxy.sendrawtransaction(tx) # decode and print the resulting transaction id. Using bytes to little-endian hex function. print('transaction id: ' + b2lx(transactionid))
def build_bitcoin_tx(utxos, receiver_addr, amount, fee, key_file, change_addr=None): sorted_utxos = utxos.sort_values(by=['block_height', 'value'], ascending=[True, False]) total_balance = 0 utxos_to_spend = [] for i, utxo in sorted_utxos.iterrows(): if total_balance >= amount + fee: break balance = utxo['value'] utxos_to_spend.append({ 'address': utxo['address'], 'txHash': utxo['tx_hash'], 'blockHeight': int(utxo['block_height']), 'outputIdx': int(utxo['tx_output_n']), 'value': int(utxo['value']), 'sigScript': utxo['script'] }) total_balance += balance if total_balance < amount + fee: raise ( f"Not enough balance to send! total balance: {total_balance}, required: {amount + fee}, amount to send: {amount}, fee: {fee}" ) if not change_addr: change_addr = utxos_to_spend[0]['address'] txins = [] for utxo in utxos_to_spend: txin = CMutableTxIn(COutPoint(lx(utxo['txHash']), utxo['outputIdx'])) txins.append(txin) txouts = [] txout = CMutableTxOut(amount, CBitcoinAddress(receiver_addr).to_scriptPubKey()) txouts.append(txout) outs = [{'address': receiver_addr, 'value': amount}] if total_balance > amount + fee: change = total_balance - amount - fee txout = CMutableTxOut(change, CBitcoinAddress(change_addr).to_scriptPubKey()) txouts.append(txout) outs.append({'address': change_addr, 'value': change}) tx = CMutableTransaction(txins, txouts) sig_data = [] for i, utxo in enumerate(utxos_to_spend): sighash = SignatureHash(CScript(x(utxo['sigScript'])), tx, i, SIGHASH_ALL) seckey = fetch_key_for_address(key_file, utxo['address']) if not seckey: raise ( f"Could not find private key for address: {utxo['address']}") sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) sig_data.append([sig, seckey.pub]) for i, txin in enumerate(txins): txin.scriptSig = CScript(sig_data[i]) tx_hash = b2lx( hashlib.sha256(hashlib.sha256(tx.serialize()).digest()).digest()) return utxos_to_spend, outs, fee, b2x(tx.serialize()), tx_hash
# Create the txout. Pays out to recipient, so uses recipient's pubkey # Withdraw full amount minus fee default_fee = 0.001 * COIN txout = CMutableTxOut(amount - default_fee, senderpubkey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) # nLockTime needs to be at least as large as parameter of CHECKLOCKTIMEVERIFY for script to verify tx.nLockTime = redeemblocknum # Calculate the signature hash for that transaction. Note how the script we use # is the redeemScript, not the scriptPubKey. EvalScript() will be evaluating the redeemScript sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub, OP_FALSE, txin_redeemScript]) print("Redeem tx hex:", b2x(tx.serialize())) # Verify the signature worked. VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) print("Now sending redeem transaction.......") txid = proxy.sendrawtransaction(tx) print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid))))
# # Here we'll create that scriptPubKey from scratch using the pubkey that # corresponds to the secret key we generated above. txin_scriptPubKey = CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]) # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut(0.001*COIN, CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) # Calculate the signature hash for that transaction. sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub]) # Verify the signature worked. This calls EvalScript() and actually executes # the opcodes in the scripts to see if everything worked out. If it doesn't an # exception will be raised. VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) # Done! Print the transaction to standard output with the bytes-to-hex # function. print(b2x(tx.serialize()))
txinfo = proxy.gettransaction(fund_tx) txin = CMutableTxIn(COutPoint(fund_tx, txinfo['details'][0]['vout'])) # By default, python-bitcoinlib disables locktime via nSequence, so we must enable txin.nSequence = 0xfffffffe default_fee = 0.001*COIN txout = CMutableTxOut(amount - default_fee, senderpubkey.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) tx.nLockTime = redeemblocknum # Sign the redeem script with Alice's private key ( for whose address the first payment path # is set up exclusively for ) sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL) sig = sender_seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Load the script sig of Bob's redemption transaction with the appropriate values txin.scriptSig = CScript([sig, sender_seckey.pub, 0, txin_redeemScript]) from ptpdb import set_trace set_trace() # Verify VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) # Fast forward time proxy.generatetoaddress(lockduration, proxy.getnewaddress()) # Send txid = proxy.sendrawtransaction(tx) # Confirm proxy.generatetoaddress(1, proxy.getnewaddress())
tx.append({ 'txid': t['txid'], 'vout': t['vout'], 'scriptPubKey': t['scriptPubKey'], 'amount': t['amount'] }) # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CMutableTxIn(COutPoint(lx(txid), vout)) # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut( 0.0005 * COIN, CBitcoinAddress('mmGK3hECmbsCZyAsyH4Dyg9bxir5Ggiid3').to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) print "This" print b2x(tx.serialize()) sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL) sig = toddkeys[0].sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, toddkeys[0].pub]) print "" print(b2x(tx.serialize()))
print( "Bob -- Alice did not redeem within the timeout period, so refunding your bitcoin....... " ) txin = CMutableTxIn(COutPoint(fund_tx, fund_vout)) # The default nSequence of FFFFFFFF won't let you redeem when there's a CHECKTIMELOCKVERIFY txin.nSequence = 0 txout = CMutableTxOut(send_amount - FEE, bobpubkey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout]) # nLockTime needs to be at least as large as parameter of CHECKLOCKTIMEVERIFY for script to verify tx.nLockTime = redeemblocknum # Calculate the signature hash for that transaction. Note how the script we use # is the redeemScript, not the scriptPubKey. EvalScript() will be evaluating the redeemScript sighash = SignatureHash(btc_redeemScript, tx, 0, SIGHASH_ALL) sig = bob_seckey.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, bob_seckey.pub, OP_FALSE, btc_redeemScript]) print("Time lock has passed, Bob redeeming his own tx:") print("Refund tx hex:", b2x(tx.serialize())) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) txid = bitcoind.sendrawtransaction(tx) print("Txid of submitted refund tx: ", b2x(lx(b2x(txid)))) quit() # ========================= BITCOIN REDEEM CONDITION ========================= # BEFORE 24 HRS (by blocknum): Alice redeems bitcoin tx bob funded print("Alice -- Redeeming tx.....") txin = CMutableTxIn(COutPoint(fund_tx, fund_vout)) txout = CMutableTxOut(send_amount - FEE, alicepubkey.to_scriptPubKey()) # Create the unsigned raw transaction. tx = CMutableTransaction([txin], [txout])
def make_transaction(sum_inputs, input_hashes, output_addr, seckey, mining_fee=0.00005): #TODO add change address? """all values in btc. input_hashes is a list of tuples (tx_hash, vout). output_addr is P2PKHBitcoinAddress""" # key = CBitcoinSecret("L4vB5fomsK8L95wQ7GFzvErYGht49JsCPJyJMHpB4xGM6xgi2jvG") # print(type(address), address) # print(address) # print (CBitcoinAddress(address).to_scriptPubKey()) # print(dir(seckey)) # print("Secret key: ", seckey) # print("Public key: ", base58.encode(seckey.pub)) # print(base58.encode(Hash160(seckey.pub))) # print('~',type(our_keys), our_keys) # print('~',type(seckey), seckey) # print('~',type(seckey.pub), seckey.pub) src_money = [] sum_of_src_money = 0 for tx_tup in input_hashes: # takes a transaction hash, like you would see on blockchain.info txid = lx(tx_tup[0]) # vout points at which address we are using, 0 for the first and 1 for the second vout = tx_tup[1] # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CMutableTxIn(COutPoint(txid, vout)) # print(COutPoint(txid, vout)) # print(dir(txin)) # print(txin) # print(txin.prevout) src_money.append(txin) # TODO add queries to blockcypher to get the sum_of_src_money #LOCKING SCRIPT # We also need the scriptPubKey of the output we're spending because # SignatureHash() replaces the transaction scriptSig's with it. # # Here we'll create that scriptPubKey from scratch using the pubkey that # corresponds to the secret key we generated above. txin_scriptPubKey = CScript([OP_DUP, OP_HASH160, output_addr, OP_EQUALVERIFY, OP_CHECKSIG]) # print(b2x(txin_scriptPubKey)) # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut((sum_inputs - mining_fee) * COIN,output_addr.to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction(src_money, [txout]) i = 0 while i < len(src_money): # Calculate the signature hash for that transaction. sighash = SignatureHash(txin_scriptPubKey, tx, i, SIGHASH_ALL) # print sighash in hex (2 ways) # import binascii # print('~', binascii.hexlify(sighash)) # import codecs # print(codecs.encode(sighash, 'hex')) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # print(sig) # print(b2x(sig)) # for txin in src_money: # Set the scriptSig of our transaction input appropriately. txin = src_money[i] txin.scriptSig = CScript([sig, seckey.pub]) # Verify the signature worked. This calls EvalScript() and actually executes # the opcodes in the scripts to see if everything worked out. If it doesn't an # exception will be raised. VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, i, (SCRIPT_VERIFY_P2SH,)) i += 1 # Done! Print the transaction to standard output with the bytes-to-hex # function. # send the message printed out to other nodes and they will receive the transaction # print("Raw TX: ", b2x(tx.serialize())) # print("TX hash: ", b2lx(tx.GetHash())) return tx
def demo(): """Start: A: d | B: y BCH End: A: y BCH | B: d """ d = b'This is a test string' hash_d = hashlib.sha256(d).digest() y = 0.001 proxy = bitcoin.rpc.Proxy( service_url='http://*****:*****@47.105.119.12:18332') block = proxy.getblock(proxy.getblockhash(1)) print(block) # test rpc balance = proxy.getbalance() print(balance) # print(proxy.listunspent()) # step 1 h_a = hashlib.sha256(b'a').digest() sk_a = CBitcoinSecret.from_secret_bytes(h_a) g_sk_a = sk_a.pub h_b = hashlib.sha256(b'b').digest() sk_b = CBitcoinSecret.from_secret_bytes(h_b) g_sk_b = sk_b.pub sig_d = sk_a.sign(hash_d) print('A\'s Pub: {}'.format(g_sk_a)) print('B\'s Pub: {}'.format(g_sk_b)) #addr_a = proxy.getnewaddress('testa') #addr_b = proxy.getnewaddress('testb') addr_a = P2PKHBitcoinAddress.from_pubkey(sk_a.pub) addr_b = P2PKHBitcoinAddress.from_pubkey(sk_b.pub) #print(type(sk_a.pub)) #print(type(sk_a)) print('A\'s Address: {}'.format(addr_a)) print('B\'s Address: {}'.format(addr_b)) # step 2 sk_c = sk_a + sk_b sk_c = CBitcoinSecret.from_secret_bytes(sk_c) g_sk_c = g_sk_a + g_sk_b addr_c = P2PKHBitcoinAddress.from_pubkey(sk_c.pub) print('C\'s Private: {}'.format(sk_c)) print('C\'s Pub: {}'.format(g_sk_c)) # step 3 # convert little-endian hex to bytes # tx from last block (202) #txid = b2lx(proxy.getblock(proxy.getblockhash(proxy.getblockcount())).hashPrevBlock) txid = lx( '6b3ff20a952d3406606646f56f26b93d96245d63244d647ef7f8ca8932d1bd0f') vout = 0 # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CMutableTxIn(COutPoint(txid, vout)) # We also need the scriptPubKey of the output we're spending because # SignatureHash() replaces the transaction scriptSig's with it. # # Here we'll create that scriptPubKey from scratch using the pubkey that # corresponds to the secret key we generated above. hash_c = hashlib.sha256(str(g_sk_b).encode()).digest() #payload = bytearray([d, hash_d, sig_d, txid, g_sk_a, hash_c]) payload = b''.join([d, hash_d, sig_d, txid, g_sk_a, hash_c]) txin_scriptPubKey = CScript( [OP_RETURN, addr_c, str(y).encode(), payload, True]) # Create the txout. This time we create the scriptPubKey from shared peer c's address txout = CMutableTxOut(y * COIN, addr_c.to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) # Calculate the signature hash for that transaction. sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = sk_a.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, sk_a.pub]) # Done! Print the transaction to standard output with the bytes-to-hex # function. print('STEP3') print('=' * 10 + 'TRANSACTION OUTPUT' + '=' * 10) print(b2x(tx.serialize())) #step 4 # b sends CLTV # if it reaches nLockTime the cancel, if not then A can take d away #txid = b2lx(proxy.getblock(proxy.getblockhash(proxy.getblockcount())).hashPrevBlock) txid = lx( '36e54fb7b87eb5a0cf56845909699677da9706c081c66331291adc1b3c72d28d') vout = 0 txin = CMutableTxIn(COutPoint(txid, vout)) txin_scriptPubKey = CScript([ OP_IF, proxy.getblockcount() + 10, OP_CHECKLOCKTIMEVERIFY, OP_DROP, g_sk_b, OP_CHECKSIG ] + [ OP_ELSE, OP_HASH160, Hash160(sk_a), OP_EQUALVERIFY, g_sk_a, OP_CHECKSIG, OP_ENDIF ]) txout = CMutableTxOut(y * COIN, addr_c.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) sig = sk_a.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, sk_a.pub]) #VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) print('=' * 10 + 'TRANSACTION OUTPUT' + '=' * 10) print(b2x(tx.serialize())) # step 5 # a gets y BCH by sk_a #txid = b2lx(proxy.getblock(proxy.getblockhash(proxy.getblockcount())).hashPrevBlock) txid = lx( '63d4c26dcc89fab7a7591efa872f9f3d8a97dc6c97328c1ec1982f2d42841bf8') vout = 0 txin = CMutableTxIn(COutPoint(txid, vout)) txin_scriptPubKey = CScript( [OP_DUP, OP_HASH160, Hash160(sk_a.pub), OP_EQUALVERIFY, OP_CHECKSIG]) txout = CMutableTxOut(y * COIN, addr_a.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) sig = sk_c.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, sk_c.pub]) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) print('=' * 10 + 'TRANSACTION OUTPUT' + '=' * 10) print(b2x(tx.serialize())) # step 6 #b gets the the ownership of sk_a, sk_b #txid = b2lx(proxy.getblock(proxy.getblockhash(proxy.getblockcount())).hashPrevBlock) txid = lx( '24713221119c95c2e7906aef2c16330f4b5bd84df430a9ab3aaef89094b1bdbc') vout = 0 txin = CMutableTxIn(COutPoint(txid, vout)) hash_b = hashlib.sha256(str(g_sk_b).encode()).digest() payload = b''.join([d, hash_d, sig_d, txid, g_sk_c, hash_b]) txin_scriptPubKey = CScript( [OP_RETURN, addr_c, str(y).encode(), payload, True]) txin_scriptPubKey = CScript( [OP_RETURN, addr_b, str(y).encode(), payload, True]) txout = CMutableTxOut(y * COIN, addr_b.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) sig = sk_c.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, sk_c.pub]) print('=' * 10 + 'TRANSACTION OUTPUT' + '=' * 10) print(b2x(tx.serialize())) # step 7 # convert little-endian hex to bytes # tx from last block (202) #txid = proxy.getblockhash(proxy.getblockcount()) #txid = lx(txid.decode()) #txid = b2lx(proxy.getblock(proxy.getblockhash(proxy.getblockcount())).hashPrevBlock) txid = lx( '6433f9ff3cc54c6f4b034c8560243b4ac4926ee071389296bd32db31103ddeee') vout = 0 txin = CMutableTxIn(COutPoint(txid, vout)) txin_scriptPubKey = CScript([OP_RETURN, addr_b, str(y).encode(), d, True]) txout = CMutableTxOut(y * COIN, addr_b.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) sig = sk_c.sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, sk_c.pub]) print('=' * 10 + 'TRANSACTION OUTPUT' + '=' * 10) print(b2x(tx.serialize()))
fund_tx = proxy.sendtoaddress(txin_p2sh_address, amount) # Construct the transaction which will redeem the htlc via the first payment route txinfo = proxy.gettransaction(fund_tx) txin = CMutableTxIn(COutPoint(fund_tx, txinfo['details'][0]['vout'])) default_fee = 0.001 * COIN txout = CMutableTxOut(amount - default_fee, recipientpubkey.to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) # Sign the redeem script with Bob's private key ( for whose address the first payment path # is set up exclusively for ) sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL) sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Load the script sig of Bob's redemption transaction with the appropriate values txin.scriptSig = CScript( [sig, seckey.pub, preimage, preimage, txin_redeemScript]) # Verify VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) # Fast forward time proxy.generatetoaddress(lockduration, proxy.getnewaddress()) # Send txid = proxy.sendrawtransaction(tx) # Confirm from ptpdb import set_trace set_trace() proxy.generatetoaddress(1, proxy.getnewaddress())