Skip to content

Commit

Permalink
[iOS] Updated to Python 3.6.6, plus small tweaks
Browse files Browse the repository at this point in the history
- Updated the 'make_ios_project' system to use Python 3.6+.  Python 3.5
is going to be phased out, but still unofficially works.

- iOS app has a much shorter reconnect interval on connection down; this
is necessary because mobile connections are quite spotty.

- iOS app has a hardcoded "preferred server only" setting internally for
now.  This is a security measure.  Users were getting intermittent
problems due to the phishers so we block them altogether on iOS.

- Refactored some stuff in network.py to allow iOS to specify its own
reconnect interval more easily.

- On iOS we always display the TOTAL balance (confirmed + unconfirmed
added together).  This is less confusing to newbie users and on BCH with
our reliable 0-conf, unconfirmed is not such a big deal.  Unconfirmed
balances are highlighted in BLUE to alert users that it's not confirmed
yet, but otherwise the UI shows the total balance (conf + unconf).
  • Loading branch information
cculianu committed Apr 7, 2019
1 parent 423785e commit 0820be7
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 28 deletions.
5 changes: 5 additions & 0 deletions ios/ElectronCash/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
#
# MIT License
#
import os
# Disable google protobuf C++ implementation since we don't have the .so files
# anyway on iOS. this call isn't strictly necessary but we may as well
# do it just to be sure.
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'

# The below line needs to be here becasue the iOS main.m evaluates this script and looks for a
# Python class (that is bridged to ObjC) named "PythonAppDelegate", which gets the
Expand Down
28 changes: 24 additions & 4 deletions ios/ElectronCash/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
from electroncash_gui.ios_native.monkeypatches import MonkeyPatches
from electroncash.util import set_verbosity
from electroncash_gui.ios_native import ElectrumGui
from electroncash_gui.ios_native.utils import call_later, get_user_dir, cleanup_tmp_dir, is_debug_build, NSLogSuppress
from electroncash_gui.ios_native.utils import call_later, get_user_dir, cleanup_tmp_dir, is_debug_build, NSLogSuppress, NSLog
from electroncash.simple_config import SimpleConfig

# NB: This is called from appdelegate.py "application_didFinishLaunchingWithOptions_"
def main():
cleanup_tmp_dir()

Expand All @@ -19,19 +20,38 @@ def main():
'cmd': 'gui',
'gui': 'ios_native',
'cwd': os.getcwd(),
'whitelist_servers_only' : True, # on iOS we force only the whitelist ('preferred') servers only for now as a security measure
}

set_verbosity(config_options.get('verbose'), timestamps=False, thread_id=False)
NSLogSuppress(not config_options.get('verbose'))

MonkeyPatches.patch()

#for k,v in config_options.items():
# print("config[%s] = %s"%(str(k),str(v)))

config = SimpleConfig(config_options, read_user_dir_function = get_user_dir)

gui = ElectrumGui(config)
call_later(0.010, gui.main) # this is required for the activity indicator to actually animate. Switch to a direct call if not using activity indicator on Splash2

_printStats(config_options) # Prints some startup/debug stats such as Python version and SSL version (this is done in another thread to hopefully not impact startup overhead too much, as importing ssl may be a bit heavy)

return "Bitcoin Cash FTW!"

def _printStats(config_options):
import threading
def thrdfunc(config_options):
# lazy init of SSL
import ssl, sys
from electroncash import version
NSLog("Electron Cash lib version: %s (using server protocol: %s)", version.PACKAGE_VERSION, version.PROTOCOL_VERSION)
NSLog("Python version: %s", ' '.join(sys.version.split('\n')))
NSLog("OpenSSL version: %s", ssl.OPENSSL_VERSION)
#NSLog("Environment Vars:")
#for k,v in os.environ.copy().items():
# NSLog("%s=%s", str(k), str(v))
#NSLog("Config Vars:")
#for k,v in config_options.copy().items():
# NSLog("config[%s] = %s", str(k), str(v))
# /
# We do this from a thread so as to not delay app startup by importing more stuff we don't strictly need.
threading.Thread(target=thrdfunc, args=(config_options,), daemon=True).start()
17 changes: 12 additions & 5 deletions ios/ElectronCash/electroncash_gui/ios_native/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ def register_network_callbacks(self):
# methods of this class only, and specifically not be
# partials, lambdas or methods of subobjects. Hence...
self.daemon.network.register_callback(self.on_network, interests)
# Set the node and server retry interval to more reasonable valus for iOS
# This is because on mobile we really may have a spotty connection so
# it pays to retry often
self.daemon.network.NODES_RETRY_INTERVAL = 20 # seconds
self.daemon.network.SERVER_RETRY_INTERVAL = 3 # seconds
utils.NSLog("REGISTERED NETWORK CALLBACKS")

def unregister_network_callbacks(self):
Expand Down Expand Up @@ -644,20 +649,22 @@ def on_status_update(self):
walletStatus = wallets.StatusOnline
networkStatusText = _("Online")
c, u, x = self.wallet.get_balance()
walletBalanceTxt = self.format_amount(c)
walletBalanceTxt = self.format_amount(c+u+x)
walletUnitTxt = self.base_unit()
text = _("Balance" ) + ": %s "%(self.format_amount_and_units(c))
text = _("Balance" ) + ": %s "%(self.format_amount_and_units(c+u+x))
ux = 0
adjective = 'unconf.'
if u:
s = " [%s unconfirmed]"%(self.format_amount(u, True).strip())
s = " [%s unconfirmed]"%(self.format_amount(u, u < 0).strip())
text += s
ux += u
if x:
s = " [%s unmatured]"%(self.format_amount(x, True).strip())
s = " [%s unmatured]"%(self.format_amount(x, x < 0).strip())
text += s
ux += x
adjective = 'unavail.'
if ux:
walletUnconfTxt += "[%s unconf.]"%(self.format_amount(ux, True)).strip()
walletUnconfTxt += "[%s %s]"%(self.format_amount(ux, ux < 0).strip(), adjective) # [134 unconf.]

# append fiat balance and price
if self.daemon.fx.is_enabled():
Expand Down
21 changes: 13 additions & 8 deletions ios/ElectronCash/electroncash_gui/ios_native/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,25 @@ def setStatus_(self, mode : int) -> None:

@objc_method
def setAmount_andUnits_unconf_(self, amt, units, unconf) -> None:
#ats = NSMutableAttributedString.alloc().initWithString_(units).autorelease()
ats = None
if unconf:
unconf = " " + unconf.strip()
'''ats.appendAttributedString_(NSAttributedString.alloc().initWithString_attributes_(
unconf,
ats = NSAttributedString.alloc().initWithString_attributes_(
amt,
{
NSFontAttributeName: UIFont.systemFontOfSize_(11.0)
NSForegroundColorAttributeName: utils.uicolor_custom('nav')
}
).autorelease())
'''
).autorelease()
else:
unconf = ''
self.walletAmount.text = amt
#self.walletUnits.attributedText = ats
if ats:
# User has unconfired balance -- show blue text
self.walletAmount.text = None
self.walletAmount.attributedText = ats
else:
# User has regular balance -- show regular text
self.walletAmount.attributedText = None
self.walletAmount.text = amt
self.walletUnits.text = units+unconf
if self.modalDrawerVC:
self.modalDrawerVC.amount.text = amt
Expand Down
6 changes: 3 additions & 3 deletions ios/make_ios_project.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

. ./common.sh

/usr/bin/env python3 --version | grep -q " 3.5"
/usr/bin/env python3 --version | grep -q " 3.[6789]"
if [ "$?" != "0" ]; then
if /usr/bin/env python3 --version; then
echo "WARNING:: Creating the Briefcase-based Xcode project for iOS requires Python 3.5."
echo "We will proceed anyway -- but if you get errors, try switching to Python 3.5."
echo "WARNING:: Creating the Briefcase-based Xcode project for iOS requires Python 3.6+."
echo "We will proceed anyway -- but if you get errors, try switching to Python 3.6+."
else
echo "ERROR: Python3+ is required"
exit 1
Expand Down
4 changes: 2 additions & 2 deletions ios/recompile_python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ elif [ -n "$1" ]; then
else
originaldir=`pwd`
cd "$dir1"
python3.5 -O -m compileall . || exit 1
python3 -O -m compileall . || exit 1
cd "$originaldir"
cd "$dir2"
python3.5 -O -m compileall . || exit 1
python3 -O -m compileall . || exit 1
cd "$originaldir"
fi

Expand Down
15 changes: 9 additions & 6 deletions lib/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@


DEFAULT_AUTO_CONNECT = True
NODES_RETRY_INTERVAL = 60
SERVER_RETRY_INTERVAL = 10

DEFAULT_WHITELIST_SERVERS_ONLY = True

def parse_servers(result):
""" parse servers list into dict format"""
Expand Down Expand Up @@ -200,6 +198,11 @@ class Network(util.DaemonThread):

INSTANCE = None # Only 1 Network instance is ever alive during app lifetime (it's a singleton)

# These defaults are decent for the desktop app. Other platforms may
# override these at any time (iOS sets these to lower values).
NODES_RETRY_INTERVAL = 60 # How often to retry a node we know about in secs, if we are connected to less than 10 nodes
SERVER_RETRY_INTERVAL = 10 # How often to reconnect when server down in secs

def __init__(self, config=None):
if config is None:
config = {} # Do not use mutables as default values!
Expand Down Expand Up @@ -957,7 +960,7 @@ def maintain_sockets(self):
server_count = len(self.interfaces) + len(self.connecting)
if server_count < self.num_server:
self.start_random_interface()
if now - self.nodes_retry_time > NODES_RETRY_INTERVAL:
if now - self.nodes_retry_time > self.NODES_RETRY_INTERVAL:
self.print_error('network: retrying connections')
self.disconnected_servers = set([])
self.nodes_retry_time = now
Expand All @@ -970,7 +973,7 @@ def maintain_sockets(self):
self.switch_to_random_interface()
else:
if self.default_server in self.disconnected_servers:
if now - self.server_retry_time > SERVER_RETRY_INTERVAL:
if now - self.server_retry_time > self.SERVER_RETRY_INTERVAL:
self.disconnected_servers.remove(self.default_server)
self.server_retry_time = now
else:
Expand Down Expand Up @@ -1858,7 +1861,7 @@ def _compute_whitelist(self):
ret -= set(self.config.get('server_whitelist_removed', [])) # this key is all the servers that were hardcoded in the whitelist that the user explicitly removed
return ret, servers_to_hostmap(ret)

def is_whitelist_only(self): return bool(self.config.get('whitelist_servers_only', True))
def is_whitelist_only(self): return bool(self.config.get('whitelist_servers_only', DEFAULT_WHITELIST_SERVERS_ONLY))

def set_whitelist_only(self, b):
if bool(b) == self.is_whitelist_only():
Expand Down

0 comments on commit 0820be7

Please sign in to comment.