def getrawtransaction(self, txid, verbose=False): """Return transaction with hash txid Raises IndexError if transaction not found. verbose - If true a dict is returned instead with additional information on the transaction. Note that if all txouts are spent and the transaction index is not enabled the transaction may not be available. """ try: r = self._call('getrawtransaction', b2lx(txid), 1 if verbose else 0) except InvalidAddressOrKeyError as ex: raise IndexError('%s.getrawtransaction(): %s (%d)' % (self.__class__.__name__, ex.error['message'], ex.error['code'])) if verbose: r['tx'] = CTransaction.deserialize(unhexlify(r['hex'])) del r['hex'] del r['txid'] del r['version'] del r['locktime'] del r['vin'] del r['vout'] r['blockhash'] = lx(r['blockhash']) if 'blockhash' in r else None else: r = CTransaction.deserialize(unhexlify(r)) return r
def lockunspent(self, unlock, outpoints): """Lock or unlock outpoints""" json_outpoints = [{ 'txid': b2lx(outpoint.hash), 'vout': outpoint.n } for outpoint in outpoints] return self._call('lockunspent', unlock, json_outpoints)
def getblockheader(self, block_hash, verbose=False): """Get block header <block_hash> verbose - If true a dict is returned with the values returned by getblockheader that are not in the block header itself (height, nextblockhash, etc.) Raises IndexError if block_hash is not valid. """ try: block_hash = b2lx(block_hash) except TypeError: raise TypeError( '%s.getblockheader(): block_hash must be bytes; got %r instance' % (self.__class__.__name__, block_hash.__class__)) try: r = self._call('getblockheader', block_hash, verbose) except InvalidAddressOrKeyError as ex: raise IndexError('%s.getblockheader(): %s (%d)' % (self.__class__.__name__, ex.error['message'], ex.error['code'])) if verbose: nextblockhash = None if 'nextblockhash' in r: nextblockhash = lx(r['nextblockhash']) return { 'confirmations': r['confirmations'], 'height': r['height'], 'mediantime': r['mediantime'], 'nextblockhash': nextblockhash, 'chainwork': x(r['chainwork']) } else: return CBlockHeader.deserialize(unhexlify(r))
def test_sendrawtransaction(self): num_outputs = 5 given_transaction = CMutableTransaction( [], [make_txout() for x in range(0, num_outputs)]) expected_txid = b2lx(given_transaction.GetHash()) given_transaction_hex = b2x(given_transaction.serialize()) proxy = FakeBitcoinProxy() resulting_txid = proxy.sendrawtransaction(given_transaction_hex) self.assertEqual(resulting_txid, expected_txid)
def getrawtransaction(self, txid, *args, **kwargs): """ Get parsed transaction. :type txid: bytes or str :rtype: dict """ if isinstance(txid, bytes): txid = b2lx(txid) return self.transactions[txid]
def sendrawtransaction(self, given_transaction): """ Pretend to broadcast and relay the transaction. Return the txid of the given transaction. """ if isinstance(given_transaction, str): given_bytes = x(given_transaction) elif isinstance(given_transaction, CMutableTransaction): given_bytes = given_transaction.serialize() else: raise FakeBitcoinProxyException("Wrong type passed to sendrawtransaction.") transaction = CMutableTransaction.deserialize(given_bytes) return b2lx(transaction.GetHash())
def gettransaction(self, txid): """Get detailed information about in-wallet transaction txid Raises IndexError if transaction not found in the wallet. FIXME: Returned data types are not yet converted. """ try: r = self._call('gettransaction', b2lx(txid)) except InvalidAddressOrKeyError as ex: raise IndexError('%s.getrawtransaction(): %s (%d)' % (self.__class__.__name__, ex.error['message'], ex.error['code'])) return r
def test_basic_rpc(self): skip_unless_enabled() loop = asyncio.get_event_loop() cli = bitcoincash.electrum.Electrum(loop=loop) loop.run_until_complete(cli.connect()) header_hex = loop.run_until_complete( cli.RPC('blockchain.block.header', 613880)) header = CBlockHeader.deserialize(x(header_hex)) self.assertEqual( "f9acfe3f0e98fc321123f787e21e17984998f46866d30244328bf7552051d57a", b2lx(header.hashMerkleRoot)) loop.run_until_complete(cli.close()) loop.close()
def getblock(self, blockhash, *args, **kwargs): """ :param blockhash: hash of the block to retrieve data for :raise IndexError: invalid blockhash """ # Note that the actual "getblock" bitcoind RPC call from # python-bitcoincashlib returns a CBlock object, not a dictionary. if isinstance(blockhash, bytes): blockhash = b2lx(blockhash) for block in self.blocks: if block["hash"] == blockhash: return block raise IndexError("no block found for blockhash {}".format(blockhash))
def gettxout(self, outpoint, includemempool=True): """Return details about an unspent transaction output. Raises IndexError if outpoint is not found or was spent. includemempool - Include mempool txouts """ r = self._call('gettxout', b2lx(outpoint.hash), outpoint.n, includemempool) if r is None: raise IndexError('%s.gettxout(): unspent txout %r not found' % (self.__class__.__name__, outpoint)) r['txout'] = CTxOut(int(r['value'] * COIN), CScript(unhexlify(r['scriptPubKey']['hex']))) del r['value'] del r['scriptPubKey'] r['bestblock'] = lx(r['bestblock']) return r
def getblock(self, block_hash): """Get block <block_hash> Raises IndexError if block_hash is not valid. """ try: block_hash = b2lx(block_hash) except TypeError: raise TypeError( '%s.getblock(): block_hash must be bytes; got %r instance' % (self.__class__.__name__, block_hash.__class__)) try: # With this change ( https://github.com/bitcoin/bitcoin/commit/96c850c20913b191cff9f66fedbb68812b1a41ea#diff-a0c8f511d90e83aa9b5857e819ced344 ), # bitcoin core's rpc takes 0/1/2 instead of true/false as the 2nd argument which specifies verbosity, since v0.15.0. # The change above is backward-compatible so far; the old "false" is taken as the new "0". r = self._call('getblock', block_hash, False) except InvalidAddressOrKeyError as ex: raise IndexError('%s.getblock(): %s (%d)' % (self.__class__.__name__, ex.error['message'], ex.error['code'])) return CBlock.deserialize(unhexlify(r))
def __repr__(self): return "CInv(type=%s hash=%s)" % (self.typemap[self.type], b2lx(self.hash))