def into_transaction(self, dust_secret: CBitcoinSecret, dust_outpoint: OutPointWithTx, feerate): if dust_outpoint.prevout.scriptPubKey != pubkey_to_P2PKH_scriptPubkey( dust_secret.pub): print(b2x(dust_outpoint.prevout.scriptPubKey)) print(b2x(pubkey_to_P2PKH_scriptPubkey(dust_secret.pub))) raise Exception("Outpoint has incorrect scriptPubKey") sum_in = dust_outpoint.prevout.nValue fees = int(tx_size(1, 2) / 1000 * feerate) refund = sum_in - fees - self._life_signal_amount print('fee: %f' % fees) print('amount: %f' % (sum_in - fees)) redeemScript = self.redeemScript unsigned_tx = CTransaction([CTxIn(dust_outpoint.outpoint)], [ CTxOut(self._life_signal_amount, redeemScript.to_p2sh_scriptPubKey()), CTxOut(refund, pubkey_to_P2PKH_scriptPubkey(dust_secret.pub)) ]) # spend the dust input sighash = SignatureHash(dust_outpoint.prevout.scriptPubKey, unsigned_tx, 0, SIGHASH_ALL) sig = dust_secret.sign(sighash) + bytes([SIGHASH_ALL]) sigScript = CScript([sig, dust_secret.pub]) signed_input = [CTxIn(unsigned_tx.vin[0].prevout, sigScript)] return CTransaction(signed_input, unsigned_tx.vout, unsigned_tx.nLockTime)
def as_tx(self): sum_in = sum(prevtx.nValue for _, prevtx, _ in self.prevouts) sig_size = sum(redeemer.spendbytes for _, _, redeemer in self.prevouts) tx_size = ( 4 + # version field 2 + # # of txins len(self.prevouts) * 41 + # txins, excluding sigs sig_size + # txins, sigs only 1 + # # of txouts 34 + # txout 4 # nLockTime field ) feerate = int(self.proxy._call('estimatefee', 1) * COIN) # satoshi's per KB if feerate <= 0: feerate = 10000 fees = int(tx_size * feerate / 1000) tx = CMutableTransaction( [CTxIn(outpoint, nSequence=0) for outpoint, _, _ in self.prevouts], [CTxOut(sum_in - fees, self.payto.to_scriptPubKey())], 0) for n, (_, _, redeemer) in enumerate(self.prevouts): redeemer.mutate_spend(tx, n) unsigned_tx = CTransaction.from_tx(tx) for n, (_, _, redeemer) in enumerate(self.prevouts): txin = CMutableTxIn.from_txin(tx.vin[n]) txin.scriptSig = redeemer.sign_spend(unsigned_tx, n) tx.vin[n] = CTxIn.from_txin(txin) print(b2x(tx.serialize()))
def withdrawfromvault(self, fromvaultaddress, toaddress, amount): vault = self.getvault(fromvaultaddress) received = self.chaindb.listreceivedbyvault(fromvaultaddress) received = received.values()[0] if received['value'] < amount + 2 * utils.calculate_fees(None): self.logger.warning("Insufficient funds in vault, exiting, return") return # create transaction tx = CTransaction() # to the receiver txout = CTxOut() txout.nValue = amount txout.scriptPubKey = utils.address_to_pay_to_pubkey_hash(toaddress) tx.vout.append(txout) # from the sender nValueIn = 0 nValueOut = amount txin = CTxIn() txin.prevout = COutPoint() txin.prevout.hash = received['txhash'] txin.prevout.n = received['n'] txin.scriptSig = received['scriptPubKey'] tx.vin.append(txin) # calculate nValueIn nValueIn = received['value'] # calculate the total excess amount excessAmount = nValueIn - nValueOut # calculate the fees fees = 2 * utils.calculate_fees(tx) # create change transaction, if there is any change left if excessAmount > fees: change_txout = CTxOut() change_txout.nValue = excessAmount - fees account = self.getaccount() changeaddress = fromvaultaddress self.logger.debug("Change address: %s" % changeaddress) change_txout.scriptPubKey = \ utils.vault_address_to_pay_to_vault_script(changeaddress) tx.vout.append(change_txout) # calculate txhash tx.calc_sha256() txhash = str(tx.sha256) key = CKey() key.set_pubkey(vault['public_key']) key.set_privkey(vault['private_key']) signature = key.sign(txhash) vaultscript = utils.create_vault_script(vault['address'], \ vault['master_address'], vault['timeout'], vault['maxfees']) scriptSig = chr(OP_VAULT_WITHDRAW) + chr(len(signature)) + signature + \ chr(len(vaultscript)) + vaultscript self.logger.debug("Adding signature: %s" % binascii.hexlify(scriptSig)) txin.scriptSig = scriptSig return tx
def spend_command(args): args.addr = CBitcoinAddress(args.addr) redeemScript = hodl_redeemScript(args.privkey, args.nLockTime) scriptPubKey = redeemScript.to_p2sh_scriptPubKey() proxy = bitcoin.rpc.Proxy() prevouts = [] for prevout in args.prevouts: try: txid, n = prevout.split(':') txid = lx(txid) n = int(n) outpoint = COutPoint(txid, n) except ValueError: args.parser.error('Invalid output: %s' % prevout) try: prevout = proxy.gettxout(outpoint) except IndexError: args.parser.error('Outpoint %s not found' % outpoint) prevout = prevout['txout'] if prevout.scriptPubKey != scriptPubKey: args.parser.error('Outpoint not correct scriptPubKey') prevouts.append((outpoint, prevout)) sum_in = sum(prev_txout.nValue for outpoint, prev_txout in prevouts) tx_size = ( 4 + # version field 2 + # # of txins len(prevouts) * 153 + # txins, including sigs 1 + # # of txouts 34 + # txout 4 # nLockTime field ) feerate = int(proxy._call('estimatefee', 1) * COIN) # satoshi's per KB if feerate <= 0: feerate = 10000 fees = int(tx_size / 1000 * feerate) unsigned_tx = CTransaction( [CTxIn(outpoint, nSequence=0) for outpoint, prevout in prevouts], [CTxOut(sum_in - fees, args.addr.to_scriptPubKey())], args.nLockTime) signed_tx = CTransaction([ CTxIn(txin.prevout, spend_hodl_redeemScript(args.privkey, args.nLockTime, unsigned_tx, i), nSequence=0) for i, txin in enumerate(unsigned_tx.vin) ], unsigned_tx.vout, unsigned_tx.nLockTime) print(b2x(signed_tx.serialize()))
def overridevaulttx(self, fromvaultaddress, toaddress): vault = self.getvault(fromvaultaddress) # select the input addresses received = self.chaindb.listallreceivedbyvault(fromvaultaddress) if not received: self.logger.warning("Empty vault, exiting, return") return None, None received = received.values()[0] if received['value'] < 2 * utils.calculate_fees(None): self.logger.warning("Insufficient funds in vault, exiting, return") return None, None # calculate remaining amount amount = received['value'] - 2 * utils.calculate_fees(None) # create transaction tx = CTransaction() # to the receiver txout = CTxOut() txout.nValue = amount txout.scriptPubKey = utils.address_to_pay_to_pubkey_hash(toaddress) tx.vout.append(txout) # from the sender nValueIn = 0 nValueOut = amount txin = CTxIn() txin.prevout = COutPoint() txin.prevout.hash = received['txhash'] txin.prevout.n = received['n'] txin.scriptSig = received['scriptPubKey'] tx.vin.append(txin) # calculate nValueIn nValueIn = received['value'] # calculate the total excess amount excessAmount = nValueIn - nValueOut # calculate the fees fees = utils.calculate_fees(tx) # calculate txhash tx.calc_sha256() txhash = str(tx.sha256) key = CKey() key.set_pubkey(vault['public_key']) key.set_privkey(vault['private_key']) signature = key.sign(txhash) # get the script vaultscript = utils.create_vault_script(vault['address'], \ vault['master_address'], vault['timeout'], vault['maxfees']) scriptSig = chr(OP_VAULT_OVERRIDE) + chr(len(vault['master_public_key'])) + \ vault['master_public_key'] + chr(len(signature)) + signature + \ chr(len(vaultscript)) + vaultscript self.logger.debug("Adding signature: %s" % binascii.hexlify(scriptSig)) txin.scriptSig = scriptSig return amount, tx
def accuse(self, dust_op: OutPointWithTx, wallet_op: OutPointWithTx, user_index, secret_sgx): ls_tx = self._life_signals[user_index].into_transaction( secret_sgx, dust_op, feerate) # FIXME: hardcode zero here because life signal is always the first output in a life signal tx nOut_for_ls = 0 ls = self._life_signals[user_index] if ls_tx.vout[ nOut_for_ls].scriptPubKey != ls.redeemScript.to_p2sh_scriptPubKey( ): raise Exception("SGX can't spend the life signal") if wallet_op.prevout.scriptPubKey != self.scriptPubkey(): raise Exception("wallet utxo mismatch") print('ls value: %f' % ls_tx.vout[nOut_for_ls].nValue) sum_in = ls_tx.vout[0].nValue + wallet_op.prevout.nValue fees = int(tx_size(2, 1) / 1000 * feerate) print('fee: %f' % fees) print('amount: %f' % (sum_in - fees)) # note: nVersion=2 is required by CSV unsigned_tx = CTransaction([ CTxIn(COutPoint(ls_tx.GetTxid(), nOut_for_ls), nSequence=ls.relative_timeout), CTxIn(wallet_op.outpoint) ], [ CTxOut(wallet_op.prevout.nValue, self.scriptPubkey(exclude_indices=(user_index, ))) ], nVersion=2) # spend the life signal lifesignal_sigScript = self._life_signals[ user_index].scriptSig_by_key2(unsigned_tx, 0) # spend the wallet wallet_sigScript = self._scriptSig_by_sgx(secret_sgx, unsigned_tx, 1) # return the life signal as well as both transactions return ls, ls_tx, CTransaction([ CTxIn(unsigned_tx.vin[0].prevout, scriptSig=lifesignal_sigScript, nSequence=ls.relative_timeout), CTxIn(wallet_op.outpoint, wallet_sigScript) ], unsigned_tx.vout, unsigned_tx.nLockTime, unsigned_tx.nVersion)
def test_is_coinbase(self): tx = CTransaction() self.assertFalse(tx.is_coinbase()) tx.vin.append(CTxIn()) # IsCoinBase() in reference client doesn't check if vout is empty self.assertTrue(tx.is_coinbase()) tx.vin[0].prevout.n = 0 self.assertFalse(tx.is_coinbase()) tx.vin[0] = CTxIn() tx.vin.append(CTxIn()) self.assertFalse(tx.is_coinbase())
def submit_opreturn(rpc_connection, address, data): from bitcoin.core import CTxIn, CMutableTxOut, CScript, CMutableTransaction, COIN, CENT, b2x, b2lx from bitcoin.core.script import OP_CHECKSIG, OP_RETURN txouts = [] unspent = sorted([y for y in rpc_connection.listunspent(0) if str(y['address']) == address], key=lambda x: hash(x['amount'])) txins = [CTxIn(unspent[-1]['outpoint'])] value_in = unspent[-1]['amount'] change_pubkey = rpc_connection.validateaddress(address)['pubkey'] change_out = CMutableTxOut(int(value_in - 2*CENT), CScript([change_pubkey, OP_CHECKSIG])) digest_outs = [CMutableTxOut(CENT, CScript([OP_RETURN, data]))] txouts = [change_out] + digest_outs tx = CMutableTransaction(txins, txouts) print tx.serialize().encode('hex') r = rpc_connection.signrawtransaction(tx) assert r['complete'] tx = r['tx'] #print b2x(tx.serialize()) #print len(tx.serialize()), 'bytes' print(b2lx(rpc_connection.sendrawtransaction(tx)))
def creates_add_input(bitcoind, tx): """Creates and add an input to a CMutableTransaction, SIGHASH_ALL. :returns: The txid of the first stage fee bumping tx (for convenience) """ # First we get some coins privkey = CKey(os.urandom(32)) scriptPubKey = CScript([OP_0, Hash160(privkey.pub)]) address = CBitcoinAddress.from_scriptPubKey(scriptPubKey) # Let's say we want to increase the fees by 5000 sats amount = 5000 # Bitcoind is nice and will create the first stage transaction first_txid = bitcoind.rpc.sendtoaddress(str(address), amount / COIN) vout_index = get_output_index( bitcoind.rpc.getrawtransaction(first_txid, 1), amount) # === We don't generate a block yet ! === tx.vin.append( CTxIn(COutPoint(lx(first_txid), vout_index), nSequence=0xfffffffe)) # Sign the new input with ALL tx_hash = SignatureHash(address.to_redeemScript(), tx, 1, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0) sig = privkey.sign(tx_hash) + bytes([SIGHASH_ALL]) tx.wit.vtxinwit.append(CTxInWitness(CScriptWitness([sig, privkey.pub]))) return first_txid
def test_emergency_txout(bitcoind): """Test mostly the emergency tx locktime""" amount = Decimal("50") - Decimal("500") / Decimal(COIN) privkeys = [CKey(os.urandom(32)) for _ in range(4)] pubkeys = [k.pub for k in privkeys] txo = emergency_txout(pubkeys, COIN * amount) addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey)) # This makes a transaction with only one vout txid = bitcoind.pay_to(addr, amount) new_amount = amount - Decimal("500") / Decimal(COIN) addr = bitcoind.getnewaddress() txin = CTxIn(COutPoint(lx(txid), 0), nSequence=4464) txout = CTxOut(new_amount * COIN, CBitcoinAddress(addr).to_scriptPubKey()) tx = CMutableTransaction([txin], [txout], nVersion=2) tx_hash = SignatureHash(emergency_script(pubkeys), tx, 0, SIGHASH_ALL, int(amount * COIN), SIGVERSION_WITNESS_V0) sigs = [k.sign(tx_hash) + bytes([SIGHASH_ALL]) for k in privkeys] witness_script = [bytes(0), *sigs, emergency_script(pubkeys)] tx.wit = CTxWitness([CTxInWitness(CScriptWitness(witness_script))]) # 1 month of locktime bitcoind.generate_block(4464 - 2) with pytest.raises(VerifyRejectedError, match="non-BIP68-final"): bitcoind.send_tx(tx.serialize().hex()) bitcoind.generate_block(1) bitcoind.send_tx(tx.serialize().hex()) assert bitcoind.has_utxo(addr)
def close_tx(self, fee: int, privkey_dest: str) -> str: """Create a (mutual) close tx""" txin = CTxIn(COutPoint(bytes.fromhex(self.txid), self.output_index)) out_privkey = privkey_expand(privkey_dest) txout = CTxOut(self.amount - fee, CScript([script.OP_0, Hash160(coincurve.PublicKey.from_secret(out_privkey.secret).format())])) tx = CMutableTransaction(vin=[txin], vout=[txout]) sighash = script.SignatureHash(self.redeemscript(), tx, inIdx=0, hashtype=script.SIGHASH_ALL, amount=self.amount, sigversion=script.SIGVERSION_WITNESS_V0) sigs = [key.sign(sighash, hasher=None) for key in self.funding_privkeys_for_tx()] # BOLT #3: # ## Closing Transaction # ... # * `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>` witness = CScriptWitness([bytes(), sigs[0] + bytes([script.SIGHASH_ALL]), sigs[1] + bytes([script.SIGHASH_ALL]), self.redeemscript()]) tx.wit = CTxWitness([CTxInWitness(witness)]) return tx.serialize().hex()
def add_input(self, serial_id: int, prevtx: str, prevtx_vout: int, script_sig: str, sequence: int, privkey: str = None) -> None: # the dummy runner sends empty info, skip if len(prevtx) == 0: return # Find the txid of the transaction prev_tx = CTransaction.deserialize(bytes.fromhex(prevtx)) txin = CTxIn(COutPoint(prev_tx.GetTxid(), prevtx_vout), nSequence=sequence) # Get the previous output for its outscript + value prev_vout = prev_tx.vout[prevtx_vout] self.inputs.append({'input': txin, 'serial_id': serial_id, 'sats': prev_vout.nValue, 'prev_outscript': prev_vout.scriptPubKey.hex(), 'redeemscript': script_sig, 'privkey': privkey, })
def build_bounce_tx(self, txid_hex): #Generate p2sh script pub key. redeem_script = self.fund_redeem_script(self.my) redeem_script_hash160 = self.hash160_script(redeem_script) txin_script_pub_key = CScript( [OP_HASH160, redeem_script_hash160["bin"], OP_EQUAL]) #Generate address to receive bounce. if "bounce" not in self.key_pairs: self.key_pairs["bounce"] = self.key_pair_from_address( self.jsonrpc[self.my].getnewaddress(), self.my) #Setup tx inputs and outputs. txid = lx(txid_hex) vout = 0 txin = CTxIn(COutPoint(txid, vout), CScript(), 0) #Sequence number 0. txout = CTxOut( (self.send_amount - decimal.Decimal(coinbend.config["mining_fee"]["standard"])) * COIN, CBitcoinAddress( self.key_pairs["bounce"]["addr"]["base58"]).to_scriptPubKey()) #Locktime is unsigned int 4, unix timestamp in little endian format. #(Conversion to little endian is handled by the library already.) nlock_time = datetime.datetime.now() + datetime.timedelta( seconds=self.future_minutes * 60) nlock_time = int(nlock_time.strftime("%s")) #Create unsigned transaction. tx = CTransaction([txin], [txout], nlock_time) return b2x(tx.serialize())
def __init__(self, hash=b'\x00' * 32, vin=CTxIn(), sig=b'\x00' * 65, height=0): """Create a new transaction lock hash is the transaction id being locked vin is the masternode funding address sig is the masternodes signature for the lock height is the block the lock is effective If their contents are not already immutable, immutable copies will be made. """ if not len(hash) == 32: raise ValueError( 'CTransactionLock: hash must be exactly 32 bytes; got %d bytes' % len(hash)) # noqa object.__setattr__(self, 'hash', hash) object.__setattr__(self, 'vin', vin) if not len(sig) == 65: raise ValueError( 'CTransactionLock: sig must be exactly 65 bytes; got %d bytes' % len(sig)) # noqa object.__setattr__(self, 'sig', sig) object.__setattr__(self, 'height', height)
def as_tx(self): sum_in = sum(prevtx.nValue for _,prevtx,_ in self.prevouts) sig_size = sum(redeemer.spendbytes for _,_,redeemer in self.prevouts) tx_size = (4 + # version field 2 + # # of txins len(self.prevouts) * 41 + # txins, excluding sigs sig_size + # txins, sigs only 1 + # # of txouts 34 + # txout 4 # nLockTime field ) feerate = int(self.proxy._call('estimatefee', 1) * COIN) # satoshi's per KB if feerate <= 0: feerate = 10000 fees = int(tx_size * feerate / 1000) tx = CMutableTransaction( [CTxIn(outpoint, nSequence=0) for outpoint,_,_ in self.prevouts], [CTxOut(sum_in - fees, self.payto.to_scriptPubKey())], 0) for n,(_,_,redeemer) in enumerate(self.prevouts): redeemer.mutate_spend(tx, n) unsigned_tx = CTransaction.from_tx(tx) for n,(_,_,redeemer) in enumerate(self.prevouts): txin = CMutableTxIn.from_txin(tx.vin[n]) txin.scriptSig = redeemer.sign_spend(unsigned_tx, n) tx.vin[n] = CTxIn.from_txin(txin) print(b2x(tx.serialize()))
def native(self): tx_hex = self.output.transaction_hash # Convert a little-endian hex string to bytes txid = lx(tx_hex) vout = self.output.index outpoint = COutPoint(txid, vout) return CTxIn(outpoint)
def create_trx(op_return_val, issuing_transaction_fee, issuing_address, tx_outs, tx_inputs): """ :param op_return_val: :param issuing_transaction_fee: :param issuing_address: :param tx_outs: :param tx_input: :return: """ cert_out = CMutableTxOut(0, CScript([OP_RETURN, op_return_val])) tx_ins = [] value_in = 0 for tx_input in tx_inputs: tx_ins.append(CTxIn(COutPoint(tx_input.tx_hash, tx_input.tx_out_index))) value_in += tx_input.coin_value # send change back to our address amount = value_in - issuing_transaction_fee if amount > 0: change_out = create_transaction_output(issuing_address, amount) tx_outs = tx_outs + [change_out] tx_outs = tx_outs + [cert_out] transaction = CMutableTransaction(tx_ins, tx_outs) return transaction
def add_input(self, serial_id: int, prevtx: str, prevtx_vout: int, max_witness_len: int, script: str, sequence: int, privkey: str = None) -> None: # Find the txid of the transaction prev_tx = CTransaction.deserialize(bytes.fromhex(prevtx)) txin = CTxIn(COutPoint(prev_tx.GetTxid(), prevtx_vout), nSequence=sequence) # Get the previous output for its outscript + value prev_vout = prev_tx.vout[prevtx_vout] self.inputs.append({ 'input': txin, 'serial_id': serial_id, 'sats': prev_vout.nValue, 'prev_outscript': prev_vout.scriptPubKey.hex(), 'redeemscript': script, 'max_witness_len': max_witness_len, 'privkey': privkey, })
def appeal(self, user_index, user_secret: CBitcoinSecret, lifesignal_op: OutPointWithTx): ls = self._life_signals[user_index] if lifesignal_op.prevout.scriptPubKey != ls.redeemScript.to_p2sh_scriptPubKey( ): raise Exception("mismatch scriptPubkey") # spend the life signal into a black hole unsigned_tx = CTransaction([CTxIn(lifesignal_op.outpoint)], [CTxOut(0, CScript([True]))], nVersion=2) return CTransaction([ CTxIn(lifesignal_op.outpoint, scriptSig=ls.scriptSig_by_key1(user_secret, unsigned_tx, 0)) ], unsigned_tx.vout, nVersion=2)
def get_inputs(self): vin = [] for i in range(self.model.rowCount()): prev_hash, prev_vout = str(self.model.item(i, 0).text()).split(':') in_script = str(self.model.item(i, 1).data(RawRole).toString()) sequence = int(self.model.item(i, 2).text()) outpoint = COutPoint(lx(prev_hash), int(prev_vout)) i_input = CTxIn(outpoint, in_script.decode('hex'), sequence) vin.append(i_input) return vin
def add_input(): try: outpoint = COutPoint(lx(str(input_prev_tx.text())), input_prev_vout.get_amount()) in_script = Script.from_human(str(input_script.toPlainText())) new_input = CTxIn(outpoint, in_script.get_hex().decode('hex'), input_sequence.get_amount()) except Exception as e: self.status_message(str(e), True) return else: self.inputs_tree.add_input(new_input) rm_input_edit.setRange(0, len(self.inputs_tree.get_inputs()) - 1)
def create_unvault_spend(unvault_txid, unvault_vout, txout): """Creates a transaction spending from an unvault transaction. :param unvault_txid: The id of the unvaulting transaction. :param unvault_vout: The index of the unvault output in this transaction. :param txout: The txo (a CTxOut) to spend the coins to. :return: The unsigned transaction, a CMutableTransaction. """ txin = CTxIn(COutPoint(unvault_txid, unvault_vout)) return CMutableTransaction([txin], [txout], nVersion=2)
def create_spend_vault_txout(vault_txid, vault_vout, txout): """Creates a transaction spending a vault txout. Note that this transaction only ever has one input and one output. :param vault_txid: The id of the transaction funding the vault, as bytes. :param vault_vout: The index of the vault output in this transaction. :param txout: The CTxOut to pay to. :return: The *unsigned* transaction, a CMutableTransaction. """ tmp_txin = CTxIn(COutPoint(vault_txid, vault_vout)) return CMutableTransaction([tmp_txin], [txout], nVersion=2)
def test_init_with_field_keyword_args(self): ins = ( CTxIn(COutPoint(lx('537ecb89e5ed7e872f988447432e6791c0a58b069c4ec8647e1683a383e867a3'), 0), x('473044022043b9aee9187effd7e6c7bc444b09162570f17e36b4a9c02cf722126cc0efa3d502200b3ba14c809fa9a6f7f835cbdbbb70f2f43f6b30beaf91eec6b8b5981c80cea50121025edf500f18f9f2b3f175f823fa996fbb2ec52982a9aeb1dc2e388a651054fb0f')) ) outs = ( CTxOut(114263, x('76a91495efca2c6a6f0e0f0ce9530219b48607a962e77788ac')), CTxOut(2125893, x('76a914f28abfb465126d6772dcb4403b9e1ad2ea28a03488ac')) ) fields_data = {'Timestamp': 1432478808} tx = Transaction(ins, outs, 0, 2, peercoin_fields, fields_data) self.assertEqual(tx.fields, peercoin_fields) self.assertEqual(tx.Timestamp, 1432478808)
def __create_new_timestamp_tx_template(self, outpoint, txout_value, change_scriptPubKey): """Create a new timestamp transaction template The transaction created will have one input and two outputs, with the timestamp output set to an invalid dummy. The fee is set to zero, but nSequence is set to opt-in to transaction replacement, so you can find an appropriate fee iteratively. """ return CTransaction([CTxIn(outpoint, nSequence=0xfffffffd)], [CTxOut(txout_value, change_scriptPubKey), CTxOut(-1, CScript())])
def create_unvault_spend(unvault_txid, unvault_vout, txout, rbf=False): """Creates a transaction spending from an unvault transaction. :param unvault_txid: The id of the unvaulting transaction. :param unvault_vout: The index of the unvault output in this transaction. :param txout: The txo (a CTxOut) to spend the coins to. :param rbf: If set to True, signal RBF. :return: The unsigned transaction, a CMutableTransaction. """ sequence = 0xfffffffe if rbf else 0xffffffff txin = CTxIn(COutPoint(unvault_txid, unvault_vout), nSequence=sequence) return CMutableTransaction([txin], [txout], nVersion=2)
def bump_delay(self, tx, vin, delay): assert 0 < delay < 2**16 if tx.nVersion < 2: tx.nVersion = 2 seq = tx.vin[vin].nSequence assert seq == 0xFFFFFFFF or seq & 0x80000000 == 0 if seq == 0xFFFFFFFF: d = 0 d = seq & 0xFFFF if d < delay: d = delay otx = tx.vin[vin] tx.vin[vin] = CTxIn(otx.prevout, otx.scriptSig, d)
def main(): proxy = bitcoin.rpc.Proxy() assert len(sys.argv) > 1 digests = [] for f in sys.argv[1:]: try: with open(f, 'rb') as fd: digests.append(Hash(fd.read())) except FileNotFoundError as exp: if len(f)/2 in (20, 32): digests.append(x(f)) else: raise exp except IOError as exp: print(exp, file=sys.stderr) continue for digest in digests: unspent = sorted(proxy.listunspent(0), key=lambda _x: hash(_x['amount'])) txins = [CTxIn(unspent[-1]['outpoint'])] value_in = unspent[-1]['amount'] change_addr = proxy.getnewaddress() change_pubkey = proxy.validateaddress(change_addr)['pubkey'] change_out = CMutableTxOut(params.MAX_MONEY, CScript([change_pubkey, OP_CHECKSIG])) digest_outs = [CMutableTxOut(0, CScript([OP_RETURN, digest]))] txouts = [change_out] + digest_outs tx = CMutableTransaction(txins, txouts) FEE_PER_BYTE = 0.00025*COIN/1000 while True: tx.vout[0].nValue = int(value_in - max(len(tx.serialize()) * FEE_PER_BYTE, 0.00011*COIN)) r = proxy.signrawtransaction(tx) assert r['complete'] tx = r['tx'] if value_in - tx.vout[0].nValue >= len(tx.serialize()) * FEE_PER_BYTE: print(b2x(tx.serialize())) print(len(tx.serialize()), 'bytes', file=sys.stderr) print(b2lx(proxy.sendrawtransaction(tx))) break
def from_utxo(txid_in: str, tx_index_in: int, sats: int, privkey: str, fee: int, local_node_privkey: str, local_funding_privkey: str, remote_node_privkey: str, remote_funding_privkey: str, chain_hash: str = regtest_hash) -> Tuple['Funding', str]: """Make a funding transaction by spending this utxo using privkey: return Funding, tx.""" # Create dummy one to start: we will fill in txid at the end. funding = Funding('', 0, sats - fee, local_node_privkey, local_funding_privkey, remote_node_privkey, remote_funding_privkey, chain_hash) # input private key. inkey = privkey_expand(privkey) inkey_pub = coincurve.PublicKey.from_secret(inkey.secret) # use RBF'able input (requirement for dual-funded things) txin = CTxIn(COutPoint(bytes.fromhex(txid_in), tx_index_in), nSequence=0xFFFFFFFD) txout = CTxOut( sats - fee, CScript([script.OP_0, sha256(funding.redeemscript()).digest()])) tx = CMutableTransaction([txin], [txout], nVersion=2, nLockTime=funding.locktime) # now fill in funding txid. funding.txid = tx.GetTxid().hex() funding.tx = tx # while we're here, sign the transaction. address = P2WPKHBitcoinAddress.from_scriptPubKey( CScript([script.OP_0, Hash160(inkey_pub.format())])) sighash = script.SignatureHash(address.to_redeemScript(), tx, 0, script.SIGHASH_ALL, amount=sats, sigversion=script.SIGVERSION_WITNESS_V0) sig = inkey.sign(sighash, hasher=None) + bytes([script.SIGHASH_ALL]) tx.wit = CTxWitness( [CTxInWitness(CScriptWitness([sig, inkey_pub.format()]))]) return funding, tx.serialize().hex()
def create_trx(op_return_val, issuing_transaction_cost, issuing_address, txouts, tx_input): cert_out = CMutableTxOut(0, CScript([OP_RETURN, op_return_val])) txins = [CTxIn(tx_input.outpoint)] value_in = tx_input.amount # send change back to our address amount = value_in - issuing_transaction_cost.total if amount > 0: change_out = create_transaction_output(issuing_address, amount) txouts = txouts + [change_out] txouts = txouts + [cert_out] tx = CMutableTransaction(txins, txouts) return tx
def create_spend_vault_txout(vault_txid, vault_vout, txout, rbf=False): """Creates a transaction spending a vault txout. Note that this transaction only ever has one input and one output. :param vault_txid: The id of the transaction funding the vault, as bytes. :param vault_vout: The index of the vault output in this transaction. :param txout: The CTxOut to pay to. :param rbf: If set to true, signal for RBF. :return: The *unsigned* transaction, a CMutableTransaction. """ sequence = 0xfffffffe if rbf else 0xffffffff tmp_txin = CTxIn(COutPoint(vault_txid, vault_vout), nSequence=sequence) return CMutableTransaction([tmp_txin], [txout], nVersion=2)
import binascii from bitcoin.core import COutPoint, CTxIn, CTxOut, CTransaction, CBlock coinbase = "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73" scriptPubKeyHex = "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac" # construct previous out point previousOut = COutPoint() previousOut.hash = 0 previousOut.n = 4294967295 # construct txin txin = CTxIn() txin.coinbase = binascii.unhexlify(coinbase) txin.scriptSig = binascii.unhexlify(coinbase) txin.prevout = previousOut # construct txout txout = CTxOut() txout.nValue = 5000000000 txout.scriptPubKey = binascii.unhexlify(scriptPubKeyHex) # create transaction tx = CTransaction() tx.vin.append(txin) tx.vout.append(txout) tx.calc_sha256() print tx
import binascii import hashlib from bitcoin.key import CKey from bitcoin.core import COutPoint, CTxIn, CTxOut, CTransaction # from utils def myhash(s): return hashlib.sha256(hashlib.sha256(s).digest()).digest() previous = COutPoint() txin = CTxIn() txout = CTxOut() tx = CTransaction() # get the outpoint from which we want to spend previous.hash = 0xeccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2 previous.n = 0x01000000 txin.prevout = previous txin.scriptSig = binascii.unhexlify("76a914010966776006953d5567439e5e39f86a0d273bee88ac") # create output transaction txout.nValue = 0x605af40500000000 txout.scriptPubKey = binascii.unhexlify("76a914097072524438d003d23a2f23edb65aae1bb3e46988ac") # set inputs and outputs tx.vin.append(txin) tx.vout.append(txout) sertx = tx.serialize() + binascii.unhexlify("01000000")
def sendtoaddress(self, toaddress, amount): # select the input addresses funds = 0 subaccounts = [] accounts = self.getaccounts() for account in accounts: for address, subaccount in account.iteritems(): if subaccount['balance'] == 0: continue else: subaccounts.append(subaccount) # print "got one subaccount", subaccount # print "subaccounts: ", subaccounts funds = funds + subaccount['balance'] if funds >= amount + utils.calculate_fees(None): break # print "subaccounts 2: ", subaccounts # incase of insufficient funds, return if funds < amount + utils.calculate_fees(None): print "In sufficient funds, exiting, return" return # create transaction tx = CTransaction() # print "subaccounts 3: ", subaccounts # to the receiver txout = CTxOut() txout.nValue = amount txout.scriptPubKey = utils.address_to_pay_to_pubkey_hash(toaddress) tx.vout.append(txout) # from the sender nValueIn = 0 nValueOut = amount public_keys = [] private_keys = [] # secrets = [] # print "subaccounts 4: ", subaccounts for subaccount in subaccounts: # print "subaccount: ", subaccount # get received by from address previous_txouts = subaccount['received'] # print "Previous txouts", previous_txouts for received in previous_txouts: txin = CTxIn() txin.prevout = COutPoint() txin.prevout.hash = received['txhash'] txin.prevout.n = received['n'] txin.scriptSig = binascii.unhexlify(received['scriptPubKey']) tx.vin.append(txin) nValueIn = nValueIn + received['value'] public_keys.append(subaccount['public_key']) private_keys.append(subaccount['private_key']) # secrets.append(subaccount['secret']) if nValueIn >= amount + utils.calculate_fees(tx): break if nValueIn >= amount + utils.calculate_fees(tx): break # calculate the total excess amount excessAmount = nValueIn - nValueOut # calculate the fees fees = utils.calculate_fees(tx) # create change transaction, if there is any change left if excessAmount > fees: change_txout = CTxOut() change_txout.nValue = excessAmount - fees changeaddress = subaccounts[0]['address'] change_txout.scriptPubKey = utils.address_to_pay_to_pubkey_hash(changeaddress) tx.vout.append(change_txout) # calculate txhash tx.calc_sha256() txhash = str(tx.sha256) # sign the transaction for public_key, private_key, txin in zip(public_keys, private_keys, tx.vin): key = CKey() key.set_pubkey(public_key) key.set_privkey(private_key) signature = key.sign(txhash) # scriptSig = chr(len(signature)) + hash_type + signature + chr(len(public_key)) + public_key scriptSig = chr(len(signature)) + signature + chr(len(public_key)) + public_key print "Adding signature: ", binascii.hexlify(scriptSig) txin.scriptSig = scriptSig print "Tx Validity: ", tx.is_valid() return tx
# You'll need to send some funds to it to create a txout to spend. txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey) print('Pay to:',str(txin_p2sh_address)) # Same as the txid:vout the createrawtransaction RPC call requires # # lx() takes *little-endian* hex and converts it to bytes; in Bitcoin # transaction hashes are shown little-endian rather than the usual big-endian. # There's also a corresponding x() convenience function that takes big-endian # hex and converts it to bytes. txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae') vout = 0 # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CTxIn(COutPoint(txid, vout)) # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CTxOut(0.0005*COIN, CBitcoinAddress('323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp').to_scriptPubKey()) # Create the unsigned transaction. tx = CTransaction([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)
def stream_deserialize(cls, f): hash = ser_read(f, 32) vin = CTxIn.stream_deserialize(f) sig = BytesSerializer.stream_deserialize(f) height = struct.unpack(b"<I", ser_read(f, 4))[0] return cls(hash, vin, sig, height)
def build_refund_tx(self, setup_tx_id, refund_amount=None): #Check refund amount. if refund_amount != None: if refund_amount > self.trade.to_send: raise Exception("Invalid refund amount.") #Create redeem script. redeem_script = bond_redeem_script(self.ecdsa_us, self.ecdsa_them, self.factory.ecdsa_arbiters[0]) #Generate p2sh script pub key. redeem_script_hash160 = hash160_script(redeem_script) txin_script_pub_key = CScript([OP_HASH160, redeem_script_hash160["bin"], OP_EQUAL]) #Setup tx inputs. txid = lx(setup_tx_id) txin = CTxIn(COutPoint(txid, self.vout)) txouts = [] #Our output. our_address = deconstruct_address(self.change_address)["hash"] our_pub_key = CScript([OP_DUP, OP_HASH160, our_address, OP_EQUALVERIFY, OP_CHECKSIG]) #Their output. their_address = deconstruct_address(self.their_address)["hash"] their_pub_key = CScript([OP_DUP, OP_HASH160, their_address, OP_EQUALVERIFY, OP_CHECKSIG]) #Append outputs. if refund_amount == None: #Inital full refund. remaining = self.upload_amount txouts.append(CTxOut(remaining.as_decimal * COIN, our_pub_key)) else: """ Micro-payment channel i.e. the contract. The refund amount leaves "room" for a TX fee so you just do normal calculations and the difference constitutes the TX fee. """ remaining = self.upload_amount - refund_amount if remaining > C("0"): txouts.append(CTxOut(remaining.as_decimal * COIN, our_pub_key)) txouts.append(CTxOut(refund_amount.as_decimal * COIN, their_pub_key)) #Create unsigned transaction. if refund_amount == None: txin.nSequence = 0 #Enable ntimelocks. tx = CTransaction([txin], txouts, self.nlock_time) else: txin.nSequence = 0xffffffff #Make transaction final! tx = CTransaction([txin], txouts) #Return unsigned transaction hex. tx_hex = b2x(tx.serialize()) txid = calculate_txid(tx_hex) our_first_sig = self.sign_refund_tx(tx_hex, 1) our_second_sig = self.sign_refund_tx(tx_hex, 2) return { "tx_hex": tx_hex, "txid": txid, "first_sig": our_first_sig, "second_sig": our_second_sig }
# Create the (in)famous correct brainwallet secret key. h = hashlib.sha256(b'correct horse battery staple').digest() seckey = CBitcoinSecret.from_secret_bytes(h) # Same as the txid:vout the createrawtransaction RPC call requires # # lx() takes *little-endian* hex and converts it to bytes; in Bitcoin # transaction hashes are shown little-endian rather than the usual big-endian. # There's also a corresponding x() convenience function that takes big-endian # hex and converts it to bytes. txid = lx('7e195aa3de827814f172c362fcf838d92ba10e3f9fdd9c3ecaf79522b311b22d') vout = 0 # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CTxIn(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. 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 = CTxOut(0.001*COIN, CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey()) # Create the unsigned transaction. tx = CTransaction([txin],[txout])
#!/usr/bin/env python from bitcoin.core import CBlock from bitcoin.core import CTxIn, CTxOut, CTransaction txin = CTxIn() txout = CTxOut() txin.scriptSig = 0x04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73 txin.prevout = 0x0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF print txin, txin.is_valid() tx.vout.nValue = 5000000000 tx.vout.scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 tx = CTransaction() tx.vin = [txin] tx.vout = [txout] """ tx.vout.scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG """ block = CBlock() block.nVersion = 1 block.hashPrevBlock = 0 block.hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b block.nTime = 1231006505 block.nBits = 0x1d00ffff block.nNonce = 2083236893 block.vtx = [tx] block.sha256 = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f print block.is_valid()
def attack_command(args): #args.starting_height = 2**32-1 #scan_command(args) fd = open('sent-txs','a') for txhash in args.rpc.getrawmempool(): txhash = lx(txhash) tx = args.rpc.getrawtransaction(txhash) args.wallet.scan_tx(tx) args.fee_per_kb = int(args.fee_per_kb * COIN) # deque of transaction outputs, (COutPoint, CTxOut), that we have available # to spend. We use these outputs in order, oldest first. available_txouts = collections.deque() # gather up existing outputs total_funds = 0 for outpoint, txout in args.wallet.unspent_txouts.items(): total_funds += txout.nValue available_txouts.append((outpoint, txout)) size_sent = 0 while available_txouts: logging.info('Attacking! Sent %d bytes total, Funds left: %s in %d txouts' % (size_sent, str_money_value(total_funds), len(available_txouts))) tx = CTransaction() # Gather up txouts until we have enough funds in to pay the fees on a # target-sized tx as well as the non-dust outputs. sum_value_in = 0 # Assuming the whole tx is CTxOut's, each one is 46 bytes (1-of-1 # CHECKMULTISIG) and the value out needs to be at least 1000 satoshis. avg_txout_size = 46 #25+1+8 num_txouts = args.target_tx_size // avg_txout_size min_value_out = 10000 sum_min_value_out = num_txouts * min_value_out fees = (args.target_tx_size/1000) * args.fee_per_kb inputs = {} tx_size = len(tx.serialize()) dummy_scriptSig = CScript([b'\x00'*74]) while (sum_value_in < fees + sum_min_value_out and tx_size < args.target_tx_size/2 # don't devote more than half the tx to inputs and available_txouts): outpoint, txout = available_txouts.popleft() try: args.rpc.gettxout(outpoint) except IndexError: continue inputs[outpoint] = txout sum_value_in += txout.nValue # The CTxIn has a dummy signature so size calculations will be right txin = CTxIn(outpoint, dummy_scriptSig) tx.vin.append(txin) tx_size += len(txin.serialize()) total_funds -= sum_value_in # Recalculate number of txouts we'll have now that we've added the # txins. Of course, this will leave the actual value per txout a bit # high, but whatever. num_txouts = int(min((args.target_tx_size-len(tx.serialize())) / avg_txout_size, (sum_value_in - fees) / min_value_out)) # Split the funds out evenly among all transaction outputs. per_txout_value = (sum_value_in - fees) // num_txouts for i in range(num_txouts): scriptPubKey = args.wallet.make_multisig() txout = CTxOut(per_txout_value, scriptPubKey) tx.vout.append(txout) # 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) # Add the new txouts to the list of available txouts tx_hash = tx.get_hash() sum_value_out = 0 for i, txout in enumerate(tx.vout): outpoint = COutPoint(tx_hash, i) available_txouts.append((outpoint, txout)) sum_value_out += txout.nValue total_funds += sum_value_out actual_fees = sum_value_in - sum_value_out serialized_tx = tx.serialize() logging.debug('Sending tx %s\n' ' value in: %s, value out: %s, fees: %s, fees/KB: %s\n' ' size: %d, # of inputs: %d, # of outputs: %d, txout.nValue: %s' % (b2lx(tx_hash), str_money_value(sum_value_in), str_money_value(sum_value_out), str_money_value(actual_fees), str_money_value(actual_fees/(len(serialized_tx)/1000)), len(serialized_tx), len(tx.vin), len(tx.vout), per_txout_value)) size_sent += len(serialized_tx) #print(b2x(serialized_tx)) #args.wallet.save() try: args.rpc.sendrawtransaction(tx) fd.write(b2x(serialized_tx) + '\n') fd.flush() except bitcoin.rpc.JSONRPCException as exp: print(b2x(tx.serialize())) #import pdb; pdb.set_trace() time.sleep(random.randrange(30,60))
def sendtovault(self, vault_address, amount): # select the input addresses funds = 0 subaccounts = [] accounts = self.getaccounts() for account in accounts: for address, subaccount in account.iteritems(): if subaccount['balance'] == 0: continue else: subaccounts.append(subaccount) funds = funds + subaccount['balance'] if funds >= amount + utils.calculate_fees(None): break # incase of insufficient funds, return if funds < amount + utils.calculate_fees(None): self.logger.warning("Insufficient funds, exiting, return") raise exceptions.InsufficientBalanceException # create transaction tx = CTransaction() # to the receiver txout = CTxOut() txout.nValue = amount txout.scriptPubKey = utils.vault_address_to_pay_to_vault_script(vault_address) tx.vout.append(txout) # from the sender nValueIn = 0 nValueOut = amount public_keys = [] private_keys = [] for subaccount in subaccounts: # get received by from address previous_txouts = subaccount['received'] for received in previous_txouts: txin = CTxIn() txin.prevout = COutPoint() txin.prevout.hash = received['txhash'] txin.prevout.n = received['n'] txin.scriptSig = received['scriptPubKey'] tx.vin.append(txin) nValueIn = nValueIn + received['value'] public_keys.append(subaccount['public_key']) private_keys.append(subaccount['private_key']) if nValueIn >= amount + utils.calculate_fees(tx): break if nValueIn >= amount + utils.calculate_fees(tx): break # calculate the total excess amount excessAmount = nValueIn - nValueOut # calculate the fees fees = utils.calculate_fees(tx) # create change transaction, if there is any change left if excessAmount > fees: change_txout = CTxOut() change_txout.nValue = excessAmount - fees changeaddress = self.getnewaddress()[1] change_txout.scriptPubKey = utils.address_to_pay_to_pubkey_hash(changeaddress) tx.vout.append(change_txout) # calculate txhash tx.calc_sha256() txhash = str(tx.sha256) self.logger.debug("Sending to vault %064x" % tx.sha256) # sign the transaction for public_key, private_key, txin in zip(public_keys, private_keys, tx.vin): key = CKey() key.set_pubkey(public_key) key.set_privkey(private_key) signature = key.sign(txhash) # scriptSig = chr(len(signature)) + hash_type + signature + chr(len(public_key)) + public_key scriptSig = chr(len(signature)) + signature + chr(len(public_key)) + public_key self.logger.debug("Adding signature: %s" % binascii.hexlify(scriptSig)) txin.scriptSig = scriptSig self.logger.debug("Tx Validity: %064x" % tx.is_valid()) # push data to vault tx.calc_sha256() self.set(str("vault:" + vault_address), {'txhash': tx.sha256}) return (vault_address, tx)