Пример #1
0
def find_all_valid_decks(provider: Provider, deck_version: int,
                         prod: bool=True) -> Generator:
    '''
    Scan the blockchain for PeerAssets decks, returns list of deck objects.
    : provider - provider instance
    : version - deck protocol version (0, 1, 2, ...)
    : test True/False - test or production P2TH
    '''

    pa_params = param_query(provider.network)

    if prod:
        p2th = pa_params.P2TH_addr
    else:
        p2th = pa_params.test_P2TH_addr

    if isinstance(provider, RpcNode):
        deck_spawns = (provider.getrawtransaction(i, 1)
                       for i in find_deck_spawns(provider))

    else:
        try:
            deck_spawns = (provider.getrawtransaction(i, 1) for i in
                           provider.listtransactions(p2th))
        except TypeError as err:  # it will except if no transactions are found on this P2TH
            raise EmptyP2THDirectory(err)

    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as th:
        for result in th.map(deck_parser, ((provider, rawtx, deck_version, p2th) for rawtx in deck_spawns)):
            if result:
                yield result
Пример #2
0
def find_tx_sender(provider: Provider, raw_tx: dict) -> str:
    '''find transaction sender, vin[0] is used in this case.'''

    vin = raw_tx["vin"][0]
    txid = vin["txid"]
    index = vin["vout"]
    return provider.getrawtransaction(txid, 1)["vout"][index]["scriptPubKey"]["addresses"][0]
Пример #3
0
def find_card_bundles(provider: Provider, deck: Deck) -> Optional[Iterator]:
    '''each blockchain transaction can contain multiple cards,
       wrapped in bundles. This method finds and returns those bundles.'''

    if isinstance(provider, RpcNode):
        if deck.id is None:
            raise Exception("deck.id required to listtransactions")

        p2th_account = provider.getaccount(deck.p2th_address)
        batch_data = [('getrawtransaction', [i["txid"], 1])
                      for i in provider.listtransactions(p2th_account)]
        result = provider.batch(batch_data)

        if result is not None:
            raw_txns = [i['result'] for i in result if result]

        else:
            raise EmptyP2THDirectory({'error': 'No cards found on this deck.'})

    else:
        if deck.p2th_address is None:
            raise Exception("deck.p2th_address required to listtransactions")

        try:
            raw_txns = (provider.getrawtransaction(i, 1)
                        for i in provider.listtransactions(deck.p2th_address))
        except TypeError:
            raise EmptyP2THDirectory({'error': 'No cards found on this deck.'})

    return (card_bundler(provider, deck, i) for i in raw_txns)
Пример #4
0
def find_parent_outputs(provider: Provider, utxo: TxIn) -> TxOut:
    '''due to design of the btcpy library, TxIn object must be converted to TxOut object before signing'''

    network_params = net_query(provider.network)
    index = utxo.txout  # utxo index
    return TxOut.from_json(provider.getrawtransaction(utxo.txid,
                           1)['vout'][index],
                           network=network_params)
Пример #5
0
def get_card_transfer(provider: Provider,
                      deck: Deck,
                      txid: str,
                      debug: bool = False) -> Iterator:
    '''get a single card transfer by it's id'''

    rawtx = provider.getrawtransaction(txid, 1)

    bundle = card_bundler(provider, deck, rawtx)

    return card_bundle_parser(bundle, debug)
Пример #6
0
def find_deck(provider: Provider, key: str, version: int, prod: bool=True) -> Optional[Deck]:
    '''Find specific deck by deck id.'''

    pa_params = param_query(provider.network)
    if prod:
        p2th = pa_params.P2TH_addr
    else:
        p2th = pa_params.test_P2TH_addr

    rawtx = provider.getrawtransaction(key, 1)
    deck = deck_parser((provider, rawtx, 1, p2th))

    return deck
Пример #7
0
def find_vote_casts(provider: Provider, vote: Vote,
                    choice_index: int) -> Iterable[VoteCast]:
    '''find and verify vote_casts on this vote_choice_address'''

    vote_casts = provider.listtransactions(
        vote.vote_choice_address[choice_index])
    for tx in vote_casts:
        raw_tx = provider.getrawtransaction(tx, 1)

        sender = find_tx_sender(provider, raw_tx)
        confirmations = raw_tx["confirmations"]
        blocknum = provider.getblock(raw_tx["blockhash"])["height"]
        yield VoteCast(vote, sender, blocknum, confirmations,
                       raw_tx["blocktime"])
Пример #8
0
def find_vote_inits(provider: Provider, deck: Deck) -> Iterable[Vote]:
    '''find vote_inits on this deck'''

    vote_ints = provider.listtransactions(deck_vote_tag(deck))

    for txid in vote_ints:
        try:
            raw_vote = provider.getrawtransaction(txid)
            vote = parse_vote_info(read_tx_opreturn(raw_vote))
            vote["vote_id"] = txid
            vote["sender"] = find_tx_sender(provider, raw_vote)
            vote["deck"] = deck
            yield Vote(**vote)
        except AssertionError:
            pass
Пример #9
0
def find_card_bundles(provider: Provider, deck: Deck) -> Optional[Iterator]:
    '''each blockchain transaction can contain multiple cards,
       wrapped in bundles. This method finds and returns those bundles.'''

    if isinstance(provider, RpcNode):
        if deck.id is None:
            raise Exception("deck.id required to listtransactions")

        batch_data = [('getrawtransaction', [i["txid"], 1]) for
                      i in provider.listtransactions(deck.id)]
        result = provider.batch(batch_data)

        if result is not None:
            raw_txns = [i['result'] for i in result if result]

        else:
            raise EmptyP2THDirectory({'error': 'No cards found on this deck.'})

    else:
        if deck.p2th_address is None:
            raise Exception("deck.p2th_address required to listtransactions")

        try:
            raw_txns = (provider.getrawtransaction(i, 1) for i in
                        provider.listtransactions(deck.p2th_address))
        except TypeError:
            raise EmptyP2THDirectory({'error': 'No cards found on this deck.'})

    return (CardBundle(deck=deck,
                       blockhash=i['blockhash'],
                       txid=i['txid'],
                       timestamp=i['time'],
                       blockseq=tx_serialization_order(provider, i["blockhash"],
                                                       i["txid"]),
                       blocknum=provider.getblock(i["blockhash"])["height"],
                       sender=find_tx_sender(provider, i),
                       vouts=i['vout'],
                       tx_confirmations=i['confirmations']
                       ) for i in raw_txns)
Пример #10
0
def get_card_transfers(provider: Provider, deck: Deck) -> Generator:
    '''get all <deck> card transfers, if cards match the protocol'''

    if isinstance(provider, RpcNode):
        if deck.id is None:
            raise Exception("deck.id required to listtransactions")
        batch_data = [('getrawtransaction', [i["txid"], 1])
                      for i in provider.listtransactions(deck.id)]
        result = provider.batch(batch_data)
        if result is not None:
            card_transfers = [i['result'] for i in result if result]
    else:
        if deck.p2th_address is None:
            raise Exception("deck.p2th_address required to listtransactions")
        if provider.listtransactions(deck.p2th_address):
            card_transfers = (provider.getrawtransaction(
                i, 1) for i in provider.listtransactions(deck.p2th_address))
        else:
            raise EmptyP2THDirectory({'error': 'No cards found on this deck.'})

    def card_parser(args: Tuple[Provider, Deck, dict]) -> list:
        '''this function wraps all the card transfer parsing'''

        provider = args[0]
        deck = args[1]
        raw_tx = args[2]

        try:
            validate_card_transfer_p2th(deck, raw_tx)  # validate P2TH first
            card_metainfo = parse_card_transfer_metainfo(
                read_tx_opreturn(raw_tx), deck.version)
            vouts = raw_tx["vout"]
            sender = find_tx_sender(provider, raw_tx)

            try:  # try to get block seq number
                blockseq = tx_serialization_order(provider,
                                                  raw_tx["blockhash"],
                                                  raw_tx["txid"])
            except KeyError:
                blockseq = 0
            try:  # try to get block number of block when this tx was written
                blocknum = provider.getblock(raw_tx["blockhash"])["height"]
            except KeyError:
                blocknum = 0
            try:  # try to get tx confirmation count
                tx_confirmations = raw_tx["confirmations"]
            except KeyError:
                tx_confirmations = 0

            cards = postprocess_card(card_metainfo, raw_tx, sender, vouts,
                                     blockseq, blocknum, tx_confirmations,
                                     deck)
            cards = [CardTransfer(**card) for card in cards]

        except (InvalidCardTransferP2TH, CardVersionMismatch,
                CardNumberOfDecimalsMismatch, InvalidVoutOrder,
                RecieverAmountMismatch, DecodeError, TypeError,
                InvalidNulldataOutput) as e:
            return []

        return cards

    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as th:
        for result in th.map(card_parser,
                             ((provider, deck, i) for i in card_transfers)):
            if result:
                yield result