def set_tx(self, tx): """Reset the model to reflect tx.""" self.beginResetModel() self.vin = [] for i in tx.vin: self.vin.append(CMutableTxIn.from_txin(i)) self.endResetModel()
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 set_tx(self, tx): """Reset the model to reflect tx.""" self.beginResetModel() self.vin = [] for i in tx.vin: self.vin.append(CMutableTxIn.from_txin(i)) self.endResetModel()
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 bump_feerate(bitcoind, tx, feerate_add, prevouts_amount=None): """Bump the feerate of a CTransaction. :param bitcoind: The bitcoind RPC connection, to access the wallet. :param tx: The CTransaction which is to be bumped. :param feerate_add: How much to increase the feerate, in sat/vbyte. :param prevouts_amount: The sum of the value of all the consumed outputs. :return: (CTransaction) The modified transaction. """ # Work on a copy vin = [CMutableTxIn.from_txin(txin) for txin in tx.vin] vout = [CMutableTxOut.from_txout(txout) for txout in tx.vout] # FIXME: Add this to python-bitcoinlib wit = CTxWitness([ CTxInWitness.from_txinwitness(txinwit) for txinwit in tx.wit.vtxinwit ]) mut_tx = CMutableTransaction(vin, vout, witness=wit, nLockTime=tx.nLockTime, nVersion=tx.nVersion) fees = fees_to_add(bitcoind, mut_tx, feerate_add, prevouts_amount) if bitcoind.getbalance() * COIN > fees: return add_input(bitcoind, mut_tx, fees) raise Exception("Could not bump fees, no suitable utxo available!")
def add_input(self, tx_input=None, input_index=None): """Add an input at input_index, or append one if input_index is None.""" if tx_input is None: tx_input = CMutableTxIn() elif tx_input.__class__ == CTxIn: tx_input = CMutableTxIn.from_txin(tx_input) if input_index is None: input_index = len(self.vin) self.beginInsertRows(QModelIndex(), input_index, input_index) self.vin.insert(input_index, tx_input) self.endInsertRows()
def add_input(self, tx_input=None, input_index=None): """Add an input at input_index, or append one if input_index is None.""" if tx_input is None: tx_input = CMutableTxIn() elif tx_input.__class__ == CTxIn: tx_input = CMutableTxIn.from_txin(tx_input) if input_index is None: input_index = len(self.vin) self.beginInsertRows(QModelIndex(), input_index, input_index) self.vin.insert(input_index, tx_input) self.endInsertRows()
def from_tx(cls, tx): if not issubclass(tx.__class__, Transaction): return super(Transaction, cls).from_tx(tx) else: kwfields = {} for attr, _, _, default in transaction_fields: if attr in ['vin', 'vout']: continue if hasattr(tx, attr): kwfields[attr] = getattr(tx, attr) vin = [CMutableTxIn.from_txin(txin) for txin in tx.vin] vout = [CMutableTxOut.from_txout(txout) for txout in tx.vout] kwfields['vin'] = vin kwfields['vout'] = vout return cls(kwfields=kwfields)
def bump_feerate(bitcoind, tx, feerate_add, prevouts_amount=None): """Bump the feerate of a CTransaction. :param bitcoind: The bitcoind RPC connection, to access the wallet. :param tx: The CTransaction which is to be bumped. :param feerate_add: How much to increase the feerate, in sat/vbyte. :param prevouts_amount: The sum of the value of all the consumed outputs. :return: (CTransaction) The modified transaction. """ # Work on a copy vin = [CMutableTxIn.from_txin(txin) for txin in tx.vin] vout = [CMutableTxOut.from_txout(txout) for txout in tx.vout] wit = CTxWitness([CTxInWitness.from_txinwitness(txinwit) for txinwit in tx.wit.vtxinwit]) mut_tx = CMutableTransaction(vin, vout, witness=wit, nLockTime=tx.nLockTime, nVersion=tx.nVersion) fees = fees_to_add(bitcoind, mut_tx, feerate_add, prevouts_amount) # No smart coin selection here, this is a demo for coin in bitcoind.listunspent(): if coin["amount"] * Decimal(COIN) > fees and coin["spendable"]: return add_input_output(bitcoind, mut_tx, coin, fees) raise Exception("Could not bump fees, no suitable utxo!")