Пример #1
0
 def _transaction_from_explorer_transaction(
         self,
         etxn,
         endpoint="/?",
         resp=None):  # keyword parameters for error handling purposes only
     if resp == None:
         resp = jsobj.new_dict()
     # parse the transactions
     transaction = transactions.from_json(obj=etxn['rawtransaction'],
                                          id=etxn['id'])
     # add the parent (coin) outputs
     coininputoutputs = etxn.get_or('coininputoutputs', None) or []
     if len(transaction.coin_inputs) != len(coininputoutputs):
         raise tferrors.ExplorerInvalidResponse(
             "amount of coin inputs and parent outputs are not matching: {} != {}"
             .format(len(transaction.coin_inputs),
                     len(coininputoutputs)), endpoint, resp)
     for (idx, co) in enumerate(coininputoutputs):
         co = CoinOutput.from_json(obj=co)
         co.id = transaction.coin_inputs[idx].parentid
         transaction.coin_inputs[idx].parent_output = co
     # add the coin output ids
     coinoutputids = etxn.get_or('coinoutputids', None) or []
     if len(transaction.coin_outputs) != len(coinoutputids):
         raise tferrors.ExplorerInvalidResponse(
             "amount of coin outputs and output identifiers are not matching: {} != {}"
             .format(len(transaction.coin_outputs),
                     len(coinoutputids)), endpoint, resp)
     for (idx, id) in enumerate(coinoutputids):
         transaction.coin_outputs[idx].id = Hash.from_json(obj=id)
     # add the parent (blockstake) outputs
     blockstakeinputoutputs = etxn.get_or('blockstakeinputoutputs',
                                          None) or []
     if len(transaction.blockstake_inputs) != len(blockstakeinputoutputs):
         raise tferrors.ExplorerInvalidResponse(
             "amount of blockstake inputs and parent outputs are not matching: {} != {}"
             .format(len(transaction.blockstake_inputs),
                     len(blockstakeinputoutputs)), endpoint, resp)
     for (idx, bso) in enumerate(blockstakeinputoutputs):
         bso = BlockstakeOutput.from_json(obj=bso)
         bso.id = transaction.blockstake_inputs[idx].parentid
         transaction.blockstake_inputs[idx].parent_output = bso
     # add the blockstake output ids
     blockstakeoutputids = etxn.get_or('blockstakeoutputids', None) or []
     if len(transaction.blockstake_outputs) != len(blockstakeoutputids):
         raise tferrors.ExplorerInvalidResponse(
             "amount of blokstake outputs and output identifiers are not matching: {} != {}"
             .format(len(transaction.blockstake_inputs),
                     len(blockstakeoutputids)), endpoint, resp)
     for (idx, id) in enumerate(blockstakeoutputids):
         transaction.blockstake_outputs[idx].id = Hash.from_json(obj=id)
     # set the unconfirmed state
     transaction.unconfirmed = etxn.get_or('unconfirmed', False)
     # set the blockid and height of the transaction only if confirmed
     if not transaction.unconfirmed:
         transaction.height = int(etxn.get_or('height', -1))
         transaction.blockid = etxn.get_or('parent', None)
     # return the transaction
     return transaction
Пример #2
0
 def _block_get_parse_cb(self, result):
     endpoint, block = result
     try:
         # parse the transactions
         transactions = []
         for etxn in block['transactions']:
             # parse the explorer transaction
             transaction = self._transaction_from_explorer_transaction(
                 etxn, endpoint=endpoint, resp=block)
             # append the transaction to the list of transactions
             transactions.append(transaction)
         rawblock = block['rawblock']
         # parse the parent id
         parentid = Hash.from_json(obj=rawblock['parentid'])
         # parse the miner payouts
         miner_payouts = []
         minerpayoutids = block.get_or('minerpayoutids', None) or []
         eminerpayouts = rawblock.get_or('minerpayouts', None) or []
         if len(eminerpayouts) != len(minerpayoutids):
             raise tferrors.ExplorerInvalidResponse(
                 "amount of miner payouts and payout ids are not matching: {} != {}"
                 .format(len(eminerpayouts),
                         len(minerpayoutids)), endpoint, block)
         for idx, mp in enumerate(eminerpayouts):
             id = Hash.from_json(minerpayoutids[idx])
             value = Currency.from_json(mp['value'])
             unlockhash = UnlockHash.from_json(mp['unlockhash'])
             miner_payouts.append(
                 ExplorerMinerPayout(id=id,
                                     value=value,
                                     unlockhash=unlockhash))
         # get the timestamp and height
         height = int(block['height'])
         timestamp = int(rawblock['timestamp'])
         # get the block's identifier
         blockid = Hash.from_json(block['blockid'])
         # for all transactions assign these properties
         for transaction in transactions:
             _assign_block_properties_to_transacton(transaction, block)
             transaction.height = height
             transaction.blockid = blockid
         # return the block, as reported by the explorer
         return ExplorerBlock(id=blockid,
                              parentid=parentid,
                              height=height,
                              timestamp=timestamp,
                              transactions=transactions,
                              miner_payouts=miner_payouts)
     except KeyError as exc:
         raise tferrors.ExplorerInvalidResponse(str(exc), endpoint,
                                                block) from exc
Пример #3
0
        def get_block(result):
            used_addr, raw_block = result
            address = used_addr

            def get_block_with_tag(result):
                return ('b', (address, result))

            blockid = Hash.from_json(obj=raw_block['blockid'])
            return jsasync.chain(self.block_get(blockid), get_block_with_tag)
Пример #4
0
 def blockchain_info_get(self):
     """
     Get the current blockchain info, using the last known block, as reported by an explorer.
     """
     resp = self.explorer_get(endpoint="/explorer")
     resp = json_loads(resp)
     blockid = Hash.from_json(obj=resp['blockid'])
     last_block = self.block_get(blockid)
     return ExplorerBlockchainInfo(last_block=last_block)
Пример #5
0
 def from_json(cls, obj):
     if not obj:
         return cls()
     if not isinstance(obj, str):
         raise TypeError(
             "expected JSON-encoded PublicKey to be a string, not {}".
             format(type(obj)))
     parts = jsstr.split(obj, ':', 2)
     if len(parts) != 2:
         raise ValueError("invalid JSON-encoded PublicKey: {}".format(obj))
     pk = cls()
     pk._specifier = PublicKeySpecifier.from_json(parts[0])
     pk._hash = Hash.from_json(parts[1])
     return pk
Пример #6
0
 def from_json(cls, obj):
     return cls(
         parentid=Hash.from_json(obj['parentid']),
         fulfillment=FulfillmentTypes.from_json(obj['fulfillment']))
Пример #7
0
 def block_get(self, value):
     """
     Get a block from an available explorer Node.
     
     @param value: the identifier or height that points to the desired block
     """
     endpoint = "/explorer/?"
     resp = {}
     try:
         # get the explorer block
         if isinstance(value, int):
             endpoint = "/explorer/blocks/{}".format(int(value))
             resp = self.explorer_get(endpoint=endpoint)
             resp = json_loads(resp)
             resp = resp['block']
         else:
             blockid = self._normalize_id(value)
             endpoint = "/explorer/hashes/" + blockid
             resp = self.explorer_get(endpoint=endpoint)
             resp = json_loads(resp)
             if resp['hashtype'] != 'blockid':
                 raise tfchain.errors.ExplorerInvalidResponse(
                     "expected hash type 'blockid' not '{}'".format(
                         resp['hashtype']), endpoint, resp)
             resp = resp['block']
             if resp['blockid'] != blockid:
                 raise tfchain.errors.ExplorerInvalidResponse(
                     "expected block ID '{}' not '{}'".format(
                         blockid, resp['blockid']), endpoint, resp)
         # parse the transactions
         transactions = []
         for etxn in resp['transactions']:
             # parse the explorer transaction
             transaction = self._transaction_from_explorer_transaction(
                 etxn, endpoint=endpoint, resp=resp)
             # append the transaction to the list of transactions
             transactions.append(transaction)
         rawblock = resp['rawblock']
         # parse the parent id
         parentid = Hash.from_json(obj=rawblock['parentid'])
         # parse the miner payouts
         miner_payouts = []
         minerpayoutids = resp.get('minerpayoutids', None) or []
         eminerpayouts = rawblock.get('minerpayouts', None) or []
         if len(eminerpayouts) != len(minerpayoutids):
             raise tfchain.errors.ExplorerInvalidResponse(
                 "amount of miner payouts and payout ids are not matching: {} != {}"
                 .format(len(eminerpayouts),
                         len(minerpayoutids)), endpoint, resp)
         for idx, mp in enumerate(eminerpayouts):
             id = Hash.from_json(minerpayoutids[idx])
             value = Currency.from_json(mp['value'])
             unlockhash = UnlockHash.from_json(mp['unlockhash'])
             miner_payouts.append(
                 ExplorerMinerPayout(id=id,
                                     value=value,
                                     unlockhash=unlockhash))
         # get the timestamp and height
         height = int(resp['height'])
         timestamp = int(rawblock['timestamp'])
         # get the block's identifier
         blockid = Hash.from_json(resp['blockid'])
         # return the block, as reported by the explorer
         return ExplorerBlock(id=blockid,
                              parentid=parentid,
                              height=height,
                              timestamp=timestamp,
                              transactions=transactions,
                              miner_payouts=miner_payouts)
     except KeyError as exc:
         # return a KeyError as an invalid Explorer Response
         raise tfchain.errors.ExplorerInvalidResponse(
             str(exc), endpoint, resp) from exc