def listunspent(self, minconf=0, maxconf=9999999, addrs=None): """Return unspent transaction outputs in wallet Outputs will have between minconf and maxconf (inclusive) confirmations, optionally filtered to only include txouts paid to addresses in addrs. """ r = None if addrs is None: r = self._call('listunspent', minconf, maxconf) else: addrs = [str(addr) for addr in addrs] r = self._call('listunspent', minconf, maxconf, addrs) r2 = [] for unspent in r: unspent['outpoint'] = COutPoint(lx(unspent['txid']), unspent['vout']) del unspent['txid'] del unspent['vout'] # address isn't always available as Bitcoin Core allows scripts w/o # an address type to be imported into the wallet, e.g. non-p2sh # segwit try: unspent['address'] = CBitcoinAddress(unspent['address']) except KeyError: pass unspent['scriptPubKey'] = CScript( unhexlify(unspent['scriptPubKey'])) unspent['amount'] = int(unspent['amount'] * COIN) r2.append(unspent) return r2
def listunspent(self, minconf=0, maxconf=9999999, addrs=None): """Return unspent transaction outputs in wallet Outputs will have between minconf and maxconf (inclusive) confirmations, optionally filtered to only include txouts paid to addresses in addrs. """ r = None if addrs is None: r = self._call('listunspent', minconf, maxconf) else: addrs = [str(addr) for addr in addrs] r = self._call('listunspent', minconf, maxconf, addrs) r2 = [] for unspent in r: unspent['outpoint'] = COutPoint(lx(unspent['txid']), unspent['vout']) del unspent['txid'] del unspent['vout'] unspent['address'] = CBitcoinAddress(unspent['address']) unspent['scriptPubKey'] = CScript( unhexlify(unspent['scriptPubKey'])) unspent['amount'] = int(unspent['amount'] * COIN) r2.append(unspent) return r2
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 __init__(self, my_index=0, sig=b'', redeem=b''): if my_index == b'': my_index = 0 if my_index not in [0, 1]: raise Exception("Unknown index", my_index) self.my_index = my_index self.sig = sig self.redeem = CScript(redeem)
def vault_script(pubkeys): """The locking script of the funding transaction (not the P2WSH!). :param pubkeys: A list containing the pubkey of each stakeholder, as bytes. :return: A CScript representing a 4of4. """ return CScript([OP_4, *pubkeys, OP_4, OP_CHECKMULTISIG])
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 script(self): if self.revoke_side == "pay": # ((revoke|secret) & pay) | (csv & cltv & refund) return CScript([ OP_HASH160, OP_DUP, self.secret, OP_EQUAL, OP_SWAP, self.revoke, OP_EQUAL, OP_BOOLOR, OP_IF, self.paypubkey, OP_ELSE, self.delay, OP_CSV, self.timeout, OP_CLTV, OP_2DROP, self.refundpubkey, OP_ENDIF, OP_CHECKSIG ]) else: # (csv & secret & pay) | ((revoke | cltv) & refund) return CScript([ OP_HASH160, OP_DUP, self.secret, OP_EQUAL, OP_IF, self.delay, OP_CSV, OP_2DROP, self.paypubkey, OP_ELSE, self.revoke, OP_EQUAL, OP_NOTIF, self.timeout, OP_CLTV, OP_DROP, OP_ENDIF, self.refundpubkey, OP_ENDIF, OP_CHECKSIG ])
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 T(hex_scriptpubkey, expected_str_address): scriptPubKey = CScript(x(hex_scriptpubkey)) addr = P2PKHBitcoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) # now test that CBitcoinAddressError is raised with accept_non_canonical_pushdata=False with self.assertRaises(CBitcoinAddressError): P2PKHBitcoinAddress.from_scriptPubKey(scriptPubKey, accept_bare_checksig=False)
def add_private_key(self): seckey_str = input('\nInsert private key (WIF-compressed format):') if len(seckey_str) != 52 or (seckey_str[0] != 'K' and seckey_str[0] != 'L'): print("The key format is not valid!") return seckey = CBitcoinSecret(seckey_str) ''' Calculate and store each data element of the scriptPubKey/scriptSig related to this private key. These data elements will be used in the Bloom Filters. From BIP 37: For each output, test each data element of the output script. This means each hash and key in the output script is tested independently. For each input, test each data element of the input script (note: input scripts only ever contain data elements). The default scriptPubKey/scriptSig used by Bitcoin Core 0.16.0 are: - scriptPubKey: OP_HASH160 [20-byte-hash of {OP_0 hash160[pubkey]}] OP_EQUAL - scriptSig: 0x16 OP_0 hash160[pubkey] Note: 0x16 => The next opcode bytes is data to be pushed onto the stack The data element of the scriptSig should be only hash160[pubkey]. Using only that data element the bloom filter doesn't work properly. Instead the filter works well using OP_0 hash160[pubkey]. ''' scriptPubKey_data_element = bitcoin.core.Hash160( CScript([OP_0, bitcoin.core.Hash160(seckey.pub)])) scriptSig_data_element = CScript( [OP_0, bitcoin.core.Hash160(seckey.pub)]) # Calculate and store also scriptPubKey/scriptSig scriptSig = CScript( [CScriptOp(0x16), OP_0, bitcoin.core.Hash160(seckey.pub)]) scriptPubKey = CScript([OP_0, bitcoin.core.Hash160(seckey.pub) ]).to_p2sh_scriptPubKey() self.keys[seckey_str] = { "data_elements": [b2x(scriptPubKey_data_element), b2x(scriptSig_data_element)], "scriptSig": b2x(scriptSig), "scriptPubKey": b2x(scriptPubKey) } self.save_to_file()
def make_p2sh_encoding_redeemscript(datachunk, n, pubKey=None, multisig_pubkeys=None, multisig_pubkeys_required=None): _logger = logger.getChild('p2sh_encoding') assert len(datachunk) <= bitcoinlib.core.script.MAX_SCRIPT_ELEMENT_SIZE dataDropScript = [bitcoinlib.core.script.OP_DROP] # just drop the data chunk cleanupScript = [n, bitcoinlib.core.script.OP_DROP, bitcoinlib.core.script.OP_DEPTH, 0, bitcoinlib.core.script.OP_EQUAL] # unique offset + prevent scriptSig malleability if pubKey is not None: # a p2pkh script looks like this: {pubkey} OP_CHECKSIGVERIFY verifyOwnerScript = [pubKey, bitcoinlib.core.script.OP_CHECKSIGVERIFY] elif multisig_pubkeys_required is not None and multisig_pubkeys: # a 2-of-3 multisig looks like this: # 2 {pubkey1} {pubkey2} {pubkey3} 3 OP_CHECKMULTISIGVERIFY multisig_pubkeys_required = int(multisig_pubkeys_required) if multisig_pubkeys_required < 2 or multisig_pubkeys_required > 15: raise exceptions.TransactionError('invalid multisig pubkeys value') verifyOwnerScript = [multisig_pubkeys_required] for multisig_pubkey in multisig_pubkeys: verifyOwnerScript.append(multisig_pubkey) verifyOwnerScript = verifyOwnerScript + [len(multisig_pubkeys), bitcoinlib.core.script.OP_CHECKMULTISIGVERIFY] else: raise exceptions.TransactionError('Either pubKey or multisig pubKeys must be provided') redeemScript = CScript(datachunk) + CScript(dataDropScript + verifyOwnerScript + cleanupScript) _logger.debug('datachunk %s' % (binascii.hexlify(datachunk))) _logger.debug('dataDropScript %s (%s)' % (repr(CScript(dataDropScript)), binascii.hexlify(CScript(dataDropScript)))) _logger.debug('verifyOwnerScript %s (%s)' % (repr(CScript(verifyOwnerScript)), binascii.hexlify(CScript(verifyOwnerScript)))) _logger.debug('entire redeemScript %s (%s)' % (repr(redeemScript), binascii.hexlify(redeemScript))) outputScript = redeemScript.to_p2sh_scriptPubKey() #scriptSig = b''.join([CScript([datachunk, redeemScript]), outputScript]) scriptSig = b''.join([CScript([datachunk])]) print('redeemScript: ', binascii.hexlify(redeemScript)) print('outputScript: ', binascii.hexlify(outputScript)) #scriptSig = CScript([datachunk]) + redeemScript _logger.debug('scriptSig %s (%s)' % (repr(scriptSig), binascii.hexlify(scriptSig))) _logger.debug('outputScript %s (%s)' % (repr(outputScript), binascii.hexlify(outputScript))) # outputScript looks like OP_HASH160 {{ hash160([redeemScript]) }} OP_EQUALVERIFY # redeemScript looks like OP_DROP {{ pubkey }} OP_CHECKSIGVERIFY {{ n }} OP_DROP OP_DEPTH 0 OP_EQUAL # scriptSig is {{ datachunk }} OP_DROP {{ pubkey }} OP_CHECKSIGVERIFY {{ n }} OP_DROP OP_DEPTH 0 OP_EQUAL return scriptSig, redeemScript, outputScript
def spend_p2sh(redeemScript, txins_str, amounts, daddrs, sig, rein, reverse_sigs=False): 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) if reverse_sigs: txins_obj[i].scriptSig = CScript( [OP_0, sig_list[i], sig2, txin_redeemScript]) else: 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 build_2_of_3(pubkeys): txin_redeemScript = CScript( [2, x(pubkeys[0]), x(pubkeys[1]), x(pubkeys[2]), 3, OP_CHECKMULTISIG]) txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey) return (b2x(txin_redeemScript), str(txin_p2sh_address))
def to_script(self, sig=OP_PUBKEY): """Construct a CScript from an AnchorScriptSig.""" if self.my_index == 0: sig1, sig2 = sig, self.sig elif self.my_index == 1: sig1, sig2 = self.sig, sig else: raise Exception("Unknown index", self.my_index) return CScript([0, sig1, sig2, self.redeem])
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 partial_spend_p2sh_mediator_2 (redeemScript,txins_str,amount,daddr,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])))) txout = CMutableTxOut(amount*COIN,CBitcoinAddress(daddr).to_scriptPubKey()) tx = CMutableTransaction(txins_obj,[txout]) seckey = CBitcoinSecret(rein.user.dkey) ntxins = len(txins_obj) for i in range(0,ntxins): sighash = SignatureHash(txin_redeemScript,tx,i,SIGHASH_ALL) sig = seckey.sign(sighash)+x("01") txins_obj[i].scriptSig = CScript([OP_0, sig, txin_redeemScript]) #VerifyScript(txins_obj[i].scriptSig, txin_scriptPubKey, tx, i, (SCRIPT_VERIFY_P2SH,)) tx_bytes = tx.serialize() return b2x(tx_bytes)
def build_mandatory_multisig(mandatory_pubkey, other_pubkeys): txin_redeemScript = CScript([ x(mandatory_pubkey), OP_CHECKSIGVERIFY, 1, x(other_pubkeys[0]), x(other_pubkeys[1]), 2, OP_CHECKMULTISIG ]) txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey) return (b2x(txin_redeemScript), str(txin_p2sh_address))
def p2pkh(pkhash): """ Pays To PubKey Hash """ assert len(pkhash) == 20 return CScript([ s.OP_DUP, s.OP_HASH160, len(pkhash), pkhash, s.OP_EQUALVERIFY, s.OP_CHECKSIG ])
def spend_hodl_redeemScript(privkey, nLockTime, unsigned_tx, n): """Spend a hodl output Returns the complete scriptSig """ redeemScript = hodl_redeemScript(privkey, nLockTime) sighash = SignatureHash(redeemScript, unsigned_tx, n, SIGHASH_ALL) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) return CScript([sig, redeemScript])
def get_unspent_txouts(source, return_confirmed=False): """returns a list of unspent outputs for a specific address @return: A list of dicts, with each entry in the dict having the following keys: """ # Get all coins. outputs = {} if util.is_multisig(source): pubkeyhashes = util.pubkeyhash_array(source) raw_transactions = blockchain.searchrawtransactions(pubkeyhashes[1]) else: pubkeyhashes = [source] raw_transactions = blockchain.searchrawtransactions(source) canonical_address = util.canonical_address(source) for tx in raw_transactions: for vout in tx['vout']: scriptpubkey = vout['scriptPubKey'] if util.scriptpubkey_to_address(CScript(x(scriptpubkey['hex']))) == canonical_address: txid = tx['txid'] confirmations = tx['confirmations'] if 'confirmations' in tx else 0 outkey = '{}{}'.format(txid, vout['n']) if outkey not in outputs or outputs[outkey]['confirmations'] < confirmations: coin = {'amount': float(vout['value']), 'confirmations': confirmations, 'scriptPubKey': scriptpubkey['hex'], 'txid': txid, 'vout': vout['n'] } outputs[outkey] = coin outputs = outputs.values() # Prune away spent coins. unspent = [] confirmed_unspent = [] for output in outputs: spent = False confirmed_spent = False for tx in raw_transactions: for vin in tx['vin']: if 'coinbase' in vin: continue if (vin['txid'], vin['vout']) == (output['txid'], output['vout']): spent = True if 'confirmations' in tx and tx['confirmations'] > 0: confirmed_spent = True if not spent: unspent.append(output) if not confirmed_spent and output['confirmations'] > 0: confirmed_unspent.append(output) unspent = sorted(unspent, key=lambda x: x['txid']) confirmed_unspent = sorted(confirmed_unspent, key=lambda x: x['txid']) if return_confirmed: return unspent, confirmed_unspent else: return unspent
def analyze_tx(tx_hex_string): output = {} # get op_return from transaction hex = unhexlify(tx_hex_string) deserializedTransaction = CTransaction.deserialize(hex) op_return_vout = deserializedTransaction.vout[1].scriptPubKey # get redeem script redeem_script = '' for i in op_return_vout: script = bytes(i).decode('utf8') if 'REDEEM' in script: redeem_script_string = script.replace('REDEEM SCRIPT ', '') output['redeemScript'] = redeem_script_string # convert redeem script into list redeemScript = CScript(unhexlify(redeem_script_string)) redeem_script_array = [] for i in redeemScript: redeem_script_array.append(i) # get redeem script hash (hodl address) p2sh_address = P2SHBitcoinAddress.from_redeemScript(redeemScript) output['hodlAddress'] = str(p2sh_address) # get nlocktime from redeem script nlocktime_hex = b2lx(redeem_script_array[0]) nlocktime = int(nlocktime_hex, 16) output['nLockTime'] = nlocktime # get authorized key from redeem script pubkey = b2x(redeem_script_array[3]) # get address from authorized key pubkey = unhexlify(pubkey) P2PKHBitcoinAddress = bitcoin.wallet.P2PKHBitcoinAddress addr = P2PKHBitcoinAddress.from_pubkey(pubkey) output['authorizedAddress'] = str(addr) # get total sent to hodl address locked_satoshis = 0 for i in deserializedTransaction.vout: if i.nValue > 0: sPK = i.scriptPubKey amount = i.nValue try: vout_p2sh_addr = P2SHBitcoinAddress.from_scriptPubKey(sPK) # rewards only paid to really locked funds if str(p2sh_address) == str(vout_p2sh_addr): locked_satoshis += amount except: pass output["lockedSatoshis"] = locked_satoshis return (output)
async def get_listunspent_for_addr(self, addr, confirmations=1): res = await self.post('listunspent', confirmations, 9999999, [addr]) for unspent in res: coutpoint = COutPoint(lx(unspent['txid']), unspent['vout']) cscript = CScript(unhexlify(unspent['scriptPubKey'])) unspent['outpoint'] = coutpoint unspent['address'] = CBitcoinAddress(unspent['address']) unspent['scriptPubKey'] = cscript unspent['amount'] = int(D(str(unspent['amount'])) * COIN) return res
def spend_redeemScript(self, who, privkey, unsigned_tx: CTransaction, n_in): if who not in ('user', 'exch'): raise ValueError("who must be either user or exch") branch = OP_FALSE if who == 'user' else OP_TRUE redeemScript = self.deposit_redeemScript sighash = SignatureHash(redeemScript, unsigned_tx, n_in, SIGHASH_ALL) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) return CScript([sig, branch, redeemScript])
def get_address_from_pubkey(cls, pubkey): """ Get bitcoin address for a specific hrp (human readable part) bech32 encoded from a public key(secp256k1). :param string pubkey: public key :returns: string bech32 encoded address """ script_pubkey = CScript([OP_0, Hash160(pubkey)]) return str(P2WPKHBitcoinAddress.from_scriptPubKey(script_pubkey))
def build_EquihashInputHeader(args): pszTimestamp = args.pszTimestamp if args.pszTimestamp else \ build_pszTimestamp(args.coinname, args.timestamp) verb("pszTimestamp: " + pszTimestamp) pk, bits = args.pubkey, args.bits extranonce = args.extranonce if args.extranonce else bits # Input transaction scriptSig = CScript() + extranonce + b'\x04' + pszTimestamp.encode('UTF-8') txin=CMutableTxIn(scriptSig=scriptSig) # Output transaction scriptPubKey = CScript() + pk + OP_CHECKSIG txout = CMutableTxOut(nValue = args.value, scriptPubKey = scriptPubKey) tx = CMutableTransaction(vin=[txin], vout=[txout]) txhash = tx.GetTxid() verb("TX/merkle root hash: " + b2lx(txhash)) return CEquihashHeader(nTime=args.time, nBits=bits, nNonce=args.nonce, hashMerkleRoot=txhash)
def fund_redeem_script(self, person): """ Notes: * Release pub key changes depending on contract side and whether they are the buyer or seller. """ #Function can be used to create fund script for either buyer or seller. my = person their = "buyer" if my == their: their = "seller" #Begin Bitcoin Script asm code. script = CScript([ OP_DUP, 1, OP_NUMEQUAL, OP_IF, #Possible input for my bounce. OP_DROP, 2, self.key_pairs["seller"]["pub"]["bin"], self.key_pairs["buyer"]["pub"]["bin"], 2, OP_CHECKMULTISIGVERIFY, OP_ELSE, #Possible input for my refund. 2, OP_NUMEQUAL, OP_IF, 5, self.key_pairs[my]["pub"]["bin"], self.key_pairs["arbiter_1"]["pub"]["bin"], self.key_pairs["arbiter_2"]["pub"]["bin"], self.key_pairs["arbiter_3"]["pub"]["bin"], self.key_pairs["arbiter_4"]["pub"]["bin"], 5, OP_CHECKMULTISIGVERIFY, OP_ELSE, #Possible input for their claim. self.key_pairs[their]["pub"]["bin"], OP_CHECKSIGVERIFY, OP_SHA256, self.secret_info["hash"]["bin"], OP_EQUALVERIFY, OP_ENDIF, OP_ENDIF, 1, OP_DEPTH, 1, OP_NUMEQUAL, OP_IF, OP_TRUE, OP_ELSE, OP_FALSE, OP_ENDIF ]) return {"bin": script, "hex": binascii.hexlify(script).decode("ascii")}
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 generate_tx(self): tx_chain = self.get_next_tx_chain() txid = lx(tx_chain.current_unspent_tx) txins = [ CMutableTxIn(COutPoint(txid, 0)), CMutableTxIn(COutPoint(txid, 1)) ] txin_seckeys = [tx_chain.seckey, self._spent_to.seckey] amount_in = tx_chain.amount tx_chain.amount -= int(config.transaction_fee / 2) txout1 = CMutableTxOut( tx_chain.amount, CBitcoinAddress(tx_chain.address).to_scriptPubKey()) txout2 = CMutableTxOut( tx_chain.amount, CBitcoinAddress(self._spent_to.address).to_scriptPubKey()) tx = CMutableTransaction(txins, [txout1, txout2], nVersion=2) for i, txin in enumerate(txins): txin_scriptPubKey = CScript([ OP_DUP, OP_HASH160, Hash160(txin_seckeys[i].pub), OP_EQUALVERIFY, OP_CHECKSIG ]) sighash = SignatureHash(txin_scriptPubKey, tx, i, SIGHASH_ALL) sig = txin_seckeys[i].sign(sighash) + bytes([SIGHASH_ALL]) txin.scriptSig = CScript([sig, txin_seckeys[i].pub]) tx_serialized = tx.serialize() logging.debug('{} trying to sendrawtransaction' ' (in=2x{} out=2x{} fee={} bytes={})' ' using tx_chain number={}'.format( self._name, amount_in, txout1.nValue, (amount_in * 2) - (txout1.nValue * 2), len(tx_serialized), self._current_tx_chain_index)) tx_hash = self.execute_rpc('sendrawtransaction', b2x(tx_serialized)) tx_chain.current_unspent_tx = tx_hash logging.info( '{} sendrawtransaction was successful; tx got hash={}'.format( self._name, tx_hash))
def vault_txout(pubkeys, value): """The output of the funding transaction. :param pubkeys: A list containing the pubkey of each stakeholder, as bytes. :param value: The output value in satoshis. :return: A CTxOut paying to a 4of4. """ script = vault_script(pubkeys) p2wsh = CScript([OP_0, hashlib.sha256(script).digest()]) return CTxOut(value, p2wsh)
def _format_utxos(self, utxos, address, **kwargs): formattedUTXOs = [] for utxo in utxos: utxo['hash'] = utxo['tx_hash'] utxo['n'] = utxo['tx_output_n'] utxo['vout'] = self._get_utxo_vout(utxo, address) utxo['outpoint'] = COutPoint(lx(utxo['hash'])) utxo['address'] = CBitcoinAddress(address) utxo['scriptPubKey'] = CScript(binascii.unhexlify(utxo['script'])) utxo['value'] = int(utxo['value']) return utxos