def _rpc(self, method, args): """ Returns the result of an rpc call to the Bitcoin Core RPC API. If the connection is permanently or unrecognizably broken, None is returned *and the reactor is shutdown* (because we consider this condition unsafe - TODO possibly create a "freeze" mode that could restart when the connection is healed, but that is tricky). Should not be called directly from outside code. """ if method not in ['importaddress', 'walletpassphrase', 'getaccount', 'gettransaction', 'getrawtransaction', 'gettxout', 'importmulti', 'listtransactions', 'getblockcount', 'scantxoutset']: log.debug('rpc: ' + method + " " + str(args)) try: res = self.jsonRpc.call(method, args) except JsonRpcConnectionError as e: # note that we only raise this in case the connection error is # a refusal, or is unrecognized/unknown by our code. So this does # NOT happen in a reset or broken pipe scenario. # It is safest to simply shut down. # Why not sys.exit? sys.exit calls do *not* work inside delayedCalls # or deferreds in twisted, since a bare exception catch prevents # an actual system exit (i.e. SystemExit is caught as a # BareException type). log.error("Failure of RPC connection to Bitcoin Core. " "Application cannot continue, shutting down.") stop_reactor() return None # note that JsonRpcError is not caught here; for some calls, we # have specific behaviour requirements depending on these errors, # so this is handled elsewhere in BitcoinCoreInterface. return res
def dummy_taker_finished(res, fromtx=False, waittime=0.0, txdetails=None): jmprint("Taker is finished") # check that the funds have arrived. mbal = mgr.daemon.services["wallet"].get_balance_by_mixdepth()[4] assert mbal == cj_amount jmprint("Funds: {} sats successfully arrived into mixdepth 4.".format(cj_amount)) stop_reactor()
def __init__(self, wallet): # The two principal member variables # are the blockchaininterface instance, # which is currently global in JM but # could be more flexible in future, and # the JM wallet object. self.bci = jm_single().bc_interface # main loop used to check for transactions, instantiated # after wallet is synced: self.monitor_loop = None self.wallet = wallet self.synced = False # used to flag RPC failure at construction of object: self.rpc_error = False # keep track of the quasi-real-time blockheight # (updated in main monitor loop) self.current_blockheight = None if self.bci is not None: if not self.update_blockheight(): # this accounts for the unusual case # where the application started up with # a functioning blockchain interface, but # that bci is now failing when we are starting # the wallet service. jlog.error("Failure of RPC connection to Bitcoin Core in " "wallet service startup. Application cannot " "continue, shutting down.") self.rpc_error = ("Failure of RPC connection to Bitcoin " "Core in wallet service startup.") # no need to call stopService as it has not yet been started. stop_reactor() else: jlog.warning("No blockchain source available, " + "wallet tools will not show correct balances.") # Dicts of registered callbacks, by type # and then by txinfo, for events # on transactions. self.callbacks = { "all": [], # note: list, not dict "unconfirmed": {}, "confirmed": {}, } self.restart_callback = None # transactions we are actively monitoring, # i.e. they are not new but we want to track: self.active_txs = {} # to ensure transactions are only processed once: self.processed_txids = set() self.set_autofreeze_warning_cb()
def critical_error(): jlog.error("Critical error updating blockheight.") # this cleanup (a) closes the wallet, removing the lock # and (b) signals to clients that the service is no longer # in a running state, both of which can be useful # post reactor shutdown. self.stopService() stop_reactor() return False
def try_to_create_my_orders(self): """Because wallet syncing is not synchronous(!), we cannot calculate our offers until we know the wallet contents, so poll until BlockchainInterface.wallet_synced is flagged as True. TODO: Use a deferred, probably. Note that create_my_orders() is defined by subclasses. """ if not self.wallet_service.synced: return self.offerlist = self.create_my_orders() self.sync_wait_loop.stop() if not self.offerlist: jlog.info("Failed to create offers, giving up.") stop_reactor() jlog.info('offerlist={}'.format(self.offerlist))