Change Address Heuristics

BlockSci supports a number of different heuristics for determining the change address for a given transaction. The heuristics are sometimes contradictory and thus we provide users with the ability to choose which heuristics they wish to apply. Further, we support the composibility of different change address heuristics through the various composition operators of the blocksci.heuristics.change.ChangeHeuristic class.

class blocksci.heuristics.change.ChangeHeuristic

Class representing a change heuristic

__and__(other_heuristic: blocksci.heuristics.change.ChangeHeuristic) → blocksci.heuristics.change.ChangeHeuristic

Return a new heuristic matching outputs that match both of the given heuristics

__call__(tx: blocksci.Tx) → Set[blocksci.Output]

Return all outputs matching the change heuristic

__or__(other_heuristic: blocksci.heuristics.change.ChangeHeuristic) → blocksci.heuristics.change.ChangeHeuristic

Return a new heuristic matching outputs that match either of the given heuristics

__sub__(other_heuristic: blocksci.heuristics.change.ChangeHeuristic) → blocksci.heuristics.change.ChangeHeuristic

Return a new heuristic matching outputs matched by the first heuristic unless they’re matched by the second heuristic

change(tx: blocksci.Tx) → Set[blocksci.Output]

Return all outputs matching the change heuristic

unique_change(tx: blocksci.Tx) → Optional[blocksci.Output]

If the change heuristic only matches one output return it, otherwise return none

blocksci.heuristics.change.address_reuse(*args, **kwargs)

Overloaded function.

  1. address_reuse() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the address reuse heuristic: If input addresses appear as an output address, the client might have reused addresses for change.

  1. address_reuse(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the address reuse heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.address_type(*args, **kwargs)

Overloaded function.

  1. address_type() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the address type heuristic: If all inputs are of one address type (e.g., P2PKH or P2SH), it is likely that the change output has the same type

  1. address_type(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the address type heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.client_change_address_behavior(*args, **kwargs)

Overloaded function.

  1. client_change_address_behavior() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the client change address behavior heuristic: Most clients will generate a fresh address for the change. If an output is the first to send value to an address, it is potentially the change.

  1. client_change_address_behavior(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the client change address behavior heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.legacy(*args, **kwargs)

Overloaded function.

  1. legacy() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the legacy heuristic: The original change address heuristic used in blocksci consisting of the intersection of the optimal change heuristic and the client address behavior heuristic

  1. legacy(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the legacy heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.locktime(*args, **kwargs)

Overloaded function.

  1. locktime() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the locktime heuristic: Bitcoin Core sets the locktime to the current block height to prevent fee sniping. If all outpus have been spent, and there is only one output that has been spent in a transaction that matches this transaction’s locktime behavior, it is the change.

  1. locktime(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the locktime reuse heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.optimal_change(*args, **kwargs)

Overloaded function.

  1. optimal_change() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the optimal change heuristic: If there exists an output that is smaller than any of the inputs it is likely the change. If a change output was larger than the smallest input, then the coin selection algorithm wouldn’t need to add the input in the first place.

  1. optimal_change(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the optimal change heuristic to a transaction and return the set outputs that could be the change address.

blocksci.heuristics.change.peeling_chain(*args, **kwargs)

Overloaded function.

  1. peeling_chain() -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the power of ten value heuristic: If tx is a peeling chain, returns the smaller output.

  1. peeling_chain(tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the peeling chain heuristic and return the matching output.

blocksci.heuristics.change.power_of_ten_value(*args, **kwargs)

Overloaded function.

  1. power_of_ten_value(digits: int=6) -> blocksci.heuristics.change.ChangeHeuristic

Return a ChangeHeuristic object implementing the power of ten value heuristic: Detects possible change outputs by checking for output values that are multiples of 10^digits.

  1. power_of_ten_value(digits: int=6, tx: blocksci.Tx) -> Set[blocksci.Output]

Apply the power of ten value heuristic to a transaction and return the set outputs that could be the change address.