コード例 #1
0
ファイル: coinchooser.py プロジェクト: todd1251/lbryum
    def make_tx(self,
                coins,
                outputs,
                change_addrs,
                fee_estimator,
                dust_threshold,
                abandon_txid=None):
        '''Select unspent coins to spend to pay outputs.  If the change is
        greater than dust_threshold (after adding the change output to
        the transaction) it is kept, otherwise none is sent and it is
        added to the transaction fee.'''

        # Deterministic randomness from coins
        utxos = [c['prevout_hash'] + str(c['prevout_n']) for c in coins]
        self.p = PRNG(''.join(sorted(utxos)))

        # Copy the ouputs so when adding change we don't modify "outputs"
        tx = Transaction.from_io([], outputs[:])
        # Size of the transaction with no inputs and no change
        base_size = tx.estimated_size()
        spent_amount = tx.output_value()

        claim_coin = None
        if abandon_txid is not None:
            claim_coins = [coin for coin in coins if coin['is_claim']]
            assert len(claim_coins) >= 1
            claim_coin = claim_coins[0]
            spent_amount -= claim_coin['value']
            coins = [coin for coin in coins if not coin['is_claim']]

        def sufficient_funds(buckets):
            '''Given a list of buckets, return True if it has enough
            value to pay for the transaction'''
            total_input = sum(bucket.value for bucket in buckets)
            total_size = sum(bucket.size for bucket in buckets) + base_size
            return total_input >= spent_amount + fee_estimator(total_size)

        # Collect the coins into buckets, choose a subset of the buckets
        buckets = self.bucketize_coins(coins)
        buckets = self.choose_buckets(buckets, sufficient_funds,
                                      self.penalty_func(tx))

        if claim_coin is not None:
            tx.add_inputs([claim_coin])
        tx.add_inputs([coin for b in buckets for coin in b.coins])
        tx_size = base_size + sum(bucket.size for bucket in buckets)

        # This takes a count of change outputs and returns a tx fee;
        # each pay-to-bitcoin-address output serializes as 34 bytes
        def fee(count):
            return fee_estimator(tx_size + count * 34)

        change = self.change_outputs(tx, change_addrs, fee, dust_threshold)
        tx.add_outputs(change)

        log.debug("using %i inputs", len(tx.inputs()))
        log.info("using buckets: %s", [bucket.desc for bucket in buckets])

        return tx
コード例 #2
0
ファイル: coinchooser.py プロジェクト: lbryio/lbryum
    def make_tx(self, coins, outputs, change_addrs, fee_estimator,
                dust_threshold, abandon_txid=None):
        '''Select unspent coins to spend to pay outputs.  If the change is
        greater than dust_threshold (after adding the change output to
        the transaction) it is kept, otherwise none is sent and it is
        added to the transaction fee.'''

        # Deterministic randomness from coins
        utxos = [c['prevout_hash'] + str(c['prevout_n']) for c in coins]
        self.p = PRNG(''.join(sorted(utxos)))

        # Copy the ouputs so when adding change we don't modify "outputs"
        tx = Transaction.from_io([], outputs[:])
        # Size of the transaction with no inputs and no change
        base_size = tx.estimated_size()
        spent_amount = tx.output_value()

        claim_coin = None
        if abandon_txid is not None:
            claim_coins = [coin for coin in coins if coin['is_claim']]
            assert len(claim_coins) >= 1
            claim_coin = claim_coins[0]
            spent_amount -= claim_coin['value']
            coins = [coin for coin in coins if not coin['is_claim']]

        def sufficient_funds(buckets):
            '''Given a list of buckets, return True if it has enough
            value to pay for the transaction'''
            total_input = sum(bucket.value for bucket in buckets)
            total_size = sum(bucket.size for bucket in buckets) + base_size
            return total_input >= spent_amount + fee_estimator(total_size)

        # Collect the coins into buckets, choose a subset of the buckets
        buckets = self.bucketize_coins(coins)
        buckets = self.choose_buckets(buckets, sufficient_funds,
                                      self.penalty_func(tx))

        if claim_coin is not None:
            tx.add_inputs([claim_coin])
        tx.add_inputs([coin for b in buckets for coin in b.coins])
        tx_size = base_size + sum(bucket.size for bucket in buckets)

        # This takes a count of change outputs and returns a tx fee;
        # each pay-to-bitcoin-address output serializes as 34 bytes
        def fee(count):
            return fee_estimator(tx_size + count * 34)

        change = self.change_outputs(tx, change_addrs, fee, dust_threshold)
        tx.add_outputs(change)

        log.debug("using %i inputs", len(tx.inputs()))
        log.info("using buckets: %s", [bucket.desc for bucket in buckets])

        return tx