def create_signed_transaction_multi(txin, txout, txin_scriptPubKey, txin_scriptSig): tx = CMutableTransaction(txin, txout) txin.scriptSig = CScript(txin_scriptSig) VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey), tx, 0, (SCRIPT_VERIFY_P2SH,)) return tx
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 refund_tx(self, payer_sig, serial_tx, redeem_script): ''' Sends a transaction refunding the funder of the P2SH address. ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Set script sig txin.scriptSig = CScript([payer_sig + '\x01', OP_FALSE, redeem_script]) # Verify script redeem_script = CScript(redeem_script) VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("refund_tx: TXID is %s", txid) self.logger.info("refund_tx: RAW TX is %s", b2x(serial_tx)) return serial_tx
def spend_escrow(self, payer_sig, redeemer_sig, serial_tx, redeem_script): ''' Sends a transaction fulfilling the redeem script of escrow tx ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Set script sig txin.scriptSig = CScript([ OP_FALSE, payer_sig + '\x01', redeemer_sig + '\x01', OP_TRUE, redeem_script ]) # Verify script redeem_script = CScript(redeem_script) serial_tx = tx.serialize() VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("spend_escrow: TXID is %s", txid) self.logger.info("spend_escrow: RAW TX is %s", b2x(serial_tx)) return serial_tx
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 spend_p2sh_mediator(redeemScript, txins_str, amounts, daddrs, sig, rein): txin_redeemScript = CScript(x(redeemScript)) txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() txins_obj = [] for txin_str in txins_str.split(): txin_list = txin_str.split("-") txins_obj.append( CMutableTxIn(COutPoint(lx(txin_list[0]), int(txin_list[1])))) txouts = [] len_amounts = len(amounts) for i in range(0, len_amounts): txouts.append( CMutableTxOut( round(amounts[i], 8) * COIN, CBitcoinAddress(daddrs[i]).to_scriptPubKey())) tx = CMutableTransaction(txins_obj, txouts) seckey = CBitcoinSecret(rein.user.dkey) ntxins = len(txins_obj) sig_list = [] for s in sig.split(): sig_list.append(x(s)) sig2_str = "" for i in range(0, ntxins): sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL) sig2 = seckey.sign(sighash) + x("01") sig2_str += " " + b2x(sig2) txins_obj[i].scriptSig = CScript( [OP_0, sig2, sig_list[i], txin_redeemScript]) VerifyScript(txins_obj[i].scriptSig, txin_scriptPubKey, tx, i, (SCRIPT_VERIFY_P2SH, )) tx_bytes = tx.serialize() hash = sha256(sha256(tx_bytes).digest()).digest() txid = b2x(hash[::-1]) txid_causeway = broadcast_tx(b2x(tx_bytes), rein) return (txid, sig2_str[1:])
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 sign(self, default_wallet: BitcoinWallet = None): """Signing transaction using the wallet object.""" for tx_index, tx_in in enumerate(self.tx.vin): utxo = self.solvable_utxo[tx_index] wallet = utxo.wallet or default_wallet if wallet is None: raise RuntimeError('Cannot sign transaction without a wallet.') tx_script = utxo.parsed_script if utxo.contract: sig_hash = script.SignatureHash( script.CScript.fromhex(utxo.contract), self.tx, tx_index, script.SIGHASH_ALL) else: sig_hash = script.SignatureHash(tx_script, self.tx, tx_index, script.SIGHASH_ALL) sig = wallet.private_key.sign(sig_hash) + struct.pack( '<B', script.SIGHASH_ALL) script_sig = [sig, wallet.private_key.pub ] + utxo.unsigned_script_sig tx_in.scriptSig = script.CScript(script_sig) VerifyScript(tx_in.scriptSig, tx_script, self.tx, tx_index, (SCRIPT_VERIFY_P2SH, )) self.signed = True
def complete_return_tx(return_coins_tx, txin_scriptPubKey, bob_signature_BTC): alice_signature_BTC = sign_BTC(return_coins_tx, txin_scriptPubKey) txin = return_coins_tx.vin[0] txin.scriptSig = CScript(coinExchangeScriptSig2(alice_signature_BTC, bob_signature_BTC)) VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey), return_coins_tx, 0, (SCRIPT_VERIFY_P2SH,)) print('Alice return coins tx (BTC) created successfully!') return return_coins_tx
def sign(self, transaction): """Sign a transaction.""" sig = self.signature(transaction) anchor_sig = AnchorScriptSig(self.anchor_index, self.their_sig, self.anchor_redeem) transaction.vin[0].scriptSig = anchor_sig.to_script(sig) # verify signing worked VerifyScript(transaction.vin[0].scriptSig, CScript(self.anchor_redeem).to_p2sh_scriptPubKey(), transaction, 0, (SCRIPT_VERIFY_P2SH, )) return transaction
def complete_return_tx(return_coins_tx, txin_scriptPubKey, alice_signature_BCY): bob_signature_BCY = sign_BCY(return_coins_tx, txin_scriptPubKey) txin = return_coins_tx.vin[0] txin.scriptSig = CScript( coinExchangeScriptSig2(bob_signature_BCY, alice_signature_BCY)) VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey), return_coins_tx, 0, (SCRIPT_VERIFY_P2SH, )) print('Bob return coins (BCY) tx created successfully!') return return_coins_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 _computeTransaction(signature, tx, script_pubkey, pubkey): txin = tx.vin[0] txin.scriptSig = bc.core.script.CScript([signature, pubkey]) try: VerifyScript(txin.scriptSig, script_pubkey, tx, 0, (bc.core.scripteval.SCRIPT_VERIFY_P2SH, )) except BaseException as e: log.error(str(e)) raise RuntimeError('signing_failed') transaction_serialized = bc.core.b2x(tx.serialize()) return transaction_serialized
def signed_settlement(self, their_sig): """Return the fully signed settlement transaction.""" transaction = self.unsigned_settlement() for tx_out in transaction.vout: tx_out.scriptPubKey = tx_out.scriptPubKey.to_scriptPubKey() sighash = SignatureHash(self.anchor.scriptSig.redeem, transaction, 0, SIGHASH_ALL) sig = g.seckey.sign(sighash) + bytes([SIGHASH_ALL]) transaction.vin[0].scriptSig.sig = their_sig transaction.vin[0].scriptSig = transaction.vin[0].scriptSig.to_script(sig) VerifyScript(transaction.vin[0].scriptSig, self.anchor.scriptSig.redeem.to_p2sh_scriptPubKey(), transaction, 0, (SCRIPT_VERIFY_P2SH,)) return transaction
def sign(self, privkey): """ Sign each of the inputs with the private key. Inputs should all be sent to the same scriptPubkey so we should only need one key. """ seckey = CBitcoinSecret.from_secret_bytes(x(bitcointools.encode_privkey(privkey, "hex"))) for i in range(len(self.tx.vin)): txin_scriptPubKey = self.tx.vin[i].scriptSig sighash = SignatureHash(txin_scriptPubKey, self.tx, i, SIGHASH_ALL) sig = seckey.sign(sighash) + struct.pack('<B', SIGHASH_ALL) self.tx.vin[i].scriptSig = CScript([sig, seckey.pub]) VerifyScript(self.tx.vin[i].scriptSig, txin_scriptPubKey, self.tx, i, (SCRIPT_VERIFY_P2SH,))
def split_coins(amount_to_send, txid_to_spend, utxo_index, n, network): txin_scriptPubKey = address.to_scriptPubKey() txin = create_txin(txid_to_spend, utxo_index) txout_scriptPubKey = address.to_scriptPubKey() txout = create_txout(amount_to_send / n, txout_scriptPubKey) tx = CMutableTransaction([txin], [txout] * n) sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) txin.scriptSig = CScript( [private_key.sign(sighash) + bytes([SIGHASH_ALL]), public_key]) VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, )) response = broadcast_transaction(tx, network) print(response.status_code, response.reason) print(response.text)
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 signed_commitment(self): """Return the fully signed commitment transaction.""" transaction = CMutableTransaction([self.anchor], [self.our, self.their]) transaction = CMutableTransaction.from_tx(transaction) for tx_out in transaction.vout: tx_out.scriptPubKey = tx_out.scriptPubKey.to_scriptPubKey() sighash = SignatureHash(self.anchor.scriptSig.redeem, transaction, 0, SIGHASH_ALL) sig = g.seckey.sign(sighash) + bytes([SIGHASH_ALL]) transaction.vin[0].scriptSig = transaction.vin[0].scriptSig.to_script(sig) # verify signing worked VerifyScript(transaction.vin[0].scriptSig, self.anchor.scriptSig.redeem.to_p2sh_scriptPubKey(), transaction, 0, (SCRIPT_VERIFY_P2SH,)) return transaction
def test_tx_invalid(self): for prevouts, tx, enforceP2SH in load_test_vectors('tx_invalid.json'): try: CheckTransaction(tx) except CheckTransactionError: continue with self.assertRaises(ValidationError): for i in range(len(tx.vin)): flags = set() if enforceP2SH: flags.add(SCRIPT_VERIFY_P2SH) VerifyScript(tx.vin[i].scriptSig, prevouts[tx.vin[i].prevout], tx, i, flags=flags)
def redeem_swap(amount_to_send, bob_swap_tx, txin_scriptPubKey): txout_script = P2PKH_scriptPubKey(alice_address_BCY) txout = create_txout(amount_to_send, txout_script) txin = create_txin(b2x(bob_swap_tx.GetTxid()), 0) tx = CMutableTransaction([txin], [txout]) alice_signature_BCY = sign_BCY(tx, txin_scriptPubKey) txin_scriptSig = coinExchangeScriptSig1(alice_signature_BCY, alice_secret_x) txin.scriptSig = CScript(txin_scriptSig) VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey), tx, 0, (SCRIPT_VERIFY_P2SH,)) print('Alice redeem from swap tx (BCY) created successfully!') return tx, alice_secret_x
def multisign(self, sigs, redeem_script): """ Signs a multisig transaction. Args: sigs: a `list` of `dict` with format: {"index": 0, "signatures": [sig1, sig2]} redeem_script: the redeem script in hex """ for sig in sigs: i = sig["index"] s = sig["signatures"] self.tx.vin[i].scriptSig = CScript([OP_0, x(s[0]), x(s[1]), CScript(x(redeem_script))]) VerifyScript(self.tx.vin[i].scriptSig, CScript(x(redeem_script)).to_p2sh_scriptPubKey(), self.tx, i, (SCRIPT_VERIFY_P2SH,))
def test_tx_valid(self): for prevouts, tx, enforceP2SH in load_test_vectors('tx_valid.json'): try: CheckTransaction(tx) except CheckTransactionError: self.fail('tx failed CheckTransaction(): ' + str(( prevouts, b2x(tx.serialize()), enforceP2SH))) for i in range(len(tx.vin)): flags = set() if enforceP2SH: flags.add(SCRIPT_VERIFY_P2SH) VerifyScript(tx.vin[i].scriptSig, prevouts[tx.vin[i].prevout], tx, i, flags=flags)
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 spend_preimage(redeem_script, preimages, redeemer_sig, serial_tx): """ Creates a transaction fulfilling the redeem script of the preimage P2SH. Arguements: redeem_script (bytes): The script that specifies the conditions that a tx has to fulfill to transfer funds from the `funding_tx` preimages (list): The preimages that hash into the hash values specified in the `redeem_script` redeemer_sig (bytes): The signature of the redeemer on the `serial_tx` serial_tx (bytes): The serial transaction Returns: The serial raw transaction that passes the script verification """ # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Setup preimages in reverse order script = [] for p in reversed(preimages): script += [p] # Create script sig txin.scriptSig = CScript([redeemer_sig + '\x01'] + script + [redeem_script]) # Verify script redeem_script = CScript(redeem_script) try: VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) except ValidationError: print("spend_preimage: Script failed to verify") return None serial_tx = tx.serialize() txid = b2lx(Hash(serial_tx)) print("spend_preimage: TXID is %s" % txid) print("spend_preimage: RAW TX is %s" % b2x(serial_tx)) return serial_tx
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 spend_escrow(redeem_script, payer_sig, redeemer_sig, serial_tx): """ Creates a transaction fulfilling the redeem script of the escrow P2SH. Arguements: redeem_script (bytes): The script that specifies the conditions that a tx has to fulfill to transfer funds from the `funding_tx` payer_sig (bytes): The signature of the payer on the `serial_tx` redeemer_sig (bytes): The signature of the redeemer on the `serial_tx` serial_tx (bytes): The serial transaction Returns: The serial raw transaction that passes the script verification """ # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Set script sig txin.scriptSig = CScript( [OP_0, payer_sig + '\x01', redeemer_sig + '\x01', redeem_script]) # Verify script redeem_script = CScript(redeem_script) serial_tx = tx.serialize() try: VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) except ValidationError: print("spend_escrow: Script failed to verify") return None serial_tx = tx.serialize() txid = b2lx(Hash(serial_tx)) print("spend_escrow: TXID is %s" % txid) print("spend_escrow: RAW TX is %s" % b2x(serial_tx)) return serial_tx
def make_signed_tx(ins, outs, priv): print('####### in make_signed_tx #######') print('ins: {}'.format(ins)) print('outs: {}'.format(outs)) print('priv: {}'.format(priv)) txins = [] txouts = [] txin_scriptPubKeys = [] # txin_scriptPubKeys = [] for i, inp in enumerate(ins): print('inp[tx_id]: {}'.format(inp['tx_id'])) txin = CMutableTxIn(COutPoint(lx(inp['tx_id']), inp['index'])) seckey = CBitcoinSecret.from_secret_bytes( pygcoinlib.script_to_address(inp['script']).encode('utf-8')) txin_scriptPubKeys.append( CScript([ OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG ])) # txin_scriptPubKeys.append(CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])) txins.append(txin) for o, out in enumerate(outs): # print('out[\'address\']: {}'.format(out['address'])) if 'script' in out: # txouts.append(CMutableTxOut(0, CScript([bytes(out['script'], encoding='UTF-8')]), 2)) print('song') else: txouts.append( CMutableTxOut( out['value'], CBitcoinAddress(out['address']).to_scriptPubKey(), out['color'])) # print('address: {}'.format(pygcoinlib.script_to_address(spk['script']))) tx = CMutableTransaction(txins, txouts) for i, inp in enumerate(ins): sighash = SignatureHash(txin_scriptPubKeys[i], tx, i, SIGHASH_ALL) sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) txins[i].scriptSig = CScript([sig, seckey.pub]) VerifyScript(txins[i].scriptSig, txin_scriptPubKeys[i], tx, i, (SCRIPT_VERIFY_P2SH, )) return b2x(tx.serialize())
def sign_transaction(self): """Sign the transaction.""" script, txTo, inIdx, hash_type = self.model.get_fields() if inIdx >= len(txTo.vin): self.set_result_message('Nonexistent input specified for signing.', error=True) return if not script: self.set_result_message('Invalid output script.', error=True) return privkey = self.get_private_key() if not privkey: self.set_result_message('Could not parse private key.', error=True) return sig_hash = chainparams.signature_hash(script, txTo, inIdx, hash_type) sig = privkey.sign(sig_hash) hash_type_hex = format_hex_string(hex(hash_type), with_prefix=False).decode('hex') sig = sig + hash_type_hex txTo.vin[inIdx].scriptSig = Script([sig, privkey.pub]) if self.verify_script.isChecked(): # Try verify try: VerifyScript(txTo.vin[inIdx].scriptSig, script, txTo, inIdx, (SCRIPT_VERIFY_P2SH, )) except Exception as e: self.set_result_message('Error when verifying: %s' % str(e), error=True) return self.dock.deserialize_raw(b2x(txTo.serialize())) # Deserializing a tx clears the model, so re-populate. self.model.set_fields(script=script.get_human(), inIdx=inIdx, hashType=hash_type) self.set_result_message( 'Successfully set scriptSig for input %d (SigHash type: %s).' % (inIdx, sig_hash_name(hash_type)))
def spend_preimage(self, preimages, redeemer_sig, serial_tx, redeem_script): ''' Sends a transaction fulfilling the redeem script of the preimage P2SH ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Setup preimages in reverse order script = [] for p in reversed(preimages): script += [p] # Create script sig txin.scriptSig = CScript([redeemer_sig + '\x01'] + script + [OP_TRUE, redeem_script]) # Verify script redeem_script = CScript(redeem_script) VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("spend_preimage: TXID is %s", txid) self.logger.info("spend_preimage: RAW TX is %s", b2x(serial_tx)) return serial_tx
def recover_command(args): args.fee_per_kb = int(args.fee_per_kb * COIN) addr = CBitcoinAddress(args.addr) tx = CTransaction() sum_value_in = 0 dummy_scriptSig = CScript([b'\x00'*74]) inputs = {} for outpoint, txout in tuple(args.wallet.unspent_txouts.items())[0:500]: sum_value_in += txout.nValue tx.vin.append(CTxIn(outpoint, dummy_scriptSig)) inputs[outpoint] = txout tx.vout.append(CTxOut(-1, addr.to_scriptPubKey())) fees = int((len(tx.serialize())/1000) * args.fee_per_kb) tx.vout[0].nValue = sum_value_in - fees # Sign the transaction for (i, txin) in enumerate(tx.vin): prevout_scriptPubKey = inputs[txin.prevout].scriptPubKey sighash = SignatureHash(prevout_scriptPubKey, tx, i, SIGHASH_ALL) seckey = args.wallet.keypairs[prevout_scriptPubKey] sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) if prevout_scriptPubKey[-1] == OP_CHECKMULTISIG: txin.scriptSig = CScript([OP_0, sig]) elif prevout_scriptPubKey[-1] == OP_CHECKSIG and prevout_scriptPubKey[-2] == OP_EQUALVERIFY: txin.scriptSig = CScript([sig, seckey.pub]) VerifyScript(txin.scriptSig, prevout_scriptPubKey, tx, i) print(b2x(tx.serialize()))