From 0c3ce79ea47c594b56e363296804829e013e0abd Mon Sep 17 00:00:00 2001
From: Biryuzovye Kleshni <kleshni@protonmail.ch>
Date: Sat, 30 Jun 2018 08:57:31 +0000
Subject: [PATCH] Wrap "bitmessagemain.py" for use with "multiprocessing"

---
 src/api.py            |  50 +++++++++++
 src/bitmessagemain.py | 197 +++++++++++++++++-------------------------
 2 files changed, 128 insertions(+), 119 deletions(-)

diff --git a/src/api.py b/src/api.py
index a32519e4..bc6514e7 100644
--- a/src/api.py
+++ b/src/api.py
@@ -10,8 +10,11 @@ This is not what you run to run the Bitmessage API. Instead, enable the API
 import base64
 import hashlib
 import json
+import socket
+import threading
 import time
 from binascii import hexlify, unhexlify
+from random import randint
 from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
 from struct import pack
 
@@ -23,6 +26,7 @@ from bmconfigparser import BMConfigParser
 import defaults
 import helper_inbox
 import helper_sent
+import helper_threading
 
 import state
 import queues
@@ -1297,3 +1301,49 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
             logger.exception(e)
 
             return "API Error 0021: Unexpected API Failure - %s" % e
+
+# This thread, of which there is only one, runs the API.
+class singleAPI(threading.Thread, helper_threading.StoppableThread):
+    def __init__(self):
+        threading.Thread.__init__(self, name="singleAPI")
+        self.initStop()
+
+    def stopThread(self):
+        super(singleAPI, self).stopThread()
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        try:
+            s.connect((
+                BMConfigParser().get('bitmessagesettings', 'apiinterface'),
+                BMConfigParser().getint('bitmessagesettings', 'apiport')
+            ))
+            s.shutdown(socket.SHUT_RDWR)
+            s.close()
+        except:
+            pass
+
+    def run(self):
+        port = BMConfigParser().getint('bitmessagesettings', 'apiport')
+        try:
+            from errno import WSAEADDRINUSE
+        except (ImportError, AttributeError):
+            errno.WSAEADDRINUSE = errno.EADDRINUSE
+        for attempt in range(50):
+            try:
+                if attempt > 0:
+                    port = randint(32767, 65535)
+                se = StoppableXMLRPCServer(
+                    (BMConfigParser().get(
+                        'bitmessagesettings', 'apiinterface'),
+                     port),
+                    MySimpleXMLRPCRequestHandler, True, True)
+            except socket.error as e:
+                if e.errno in (errno.EADDRINUSE, errno.WSAEADDRINUSE):
+                    continue
+            else:
+                if attempt > 0:
+                    BMConfigParser().set(
+                        "bitmessagesettings", "apiport", str(port))
+                    BMConfigParser().save()
+                break
+        se.register_introspection_functions()
+        se.serve_forever()
diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py
index 31a475dd..456d870f 100755
--- a/src/bitmessagemain.py
+++ b/src/bitmessagemain.py
@@ -9,67 +9,6 @@
 
 # The software version variable is now held in shared.py
 
-import os
-import sys
-
-app_dir = os.path.dirname(os.path.abspath(__file__))
-os.chdir(app_dir)
-sys.path.insert(0, app_dir)
-
-
-import depends
-depends.check_dependencies()
-
-# Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
-import signal
-# The next 3 are used for the API
-from singleinstance import singleinstance
-import errno
-import socket
-import ctypes
-from struct import pack
-from subprocess import call
-from time import sleep
-from random import randint
-import getopt
-
-from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
-from helper_startup import (
-    isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
-)
-
-import defaults
-import shared
-import knownnodes
-import state
-import shutdown
-import threading
-
-# Classes
-from class_sqlThread import sqlThread
-from class_singleCleaner import singleCleaner
-from class_objectProcessor import objectProcessor
-from class_singleWorker import singleWorker
-from class_addressGenerator import addressGenerator
-from bmconfigparser import BMConfigParser
-
-from inventory import Inventory
-
-from network.connectionpool import BMConnectionPool
-from network.dandelion import Dandelion
-from network.networkthread import BMNetworkThread
-from network.receivequeuethread import ReceiveQueueThread
-from network.announcethread import AnnounceThread
-from network.invthread import InvThread
-from network.addrthread import AddrThread
-from network.downloadthread import DownloadThread
-
-# Helper Functions
-import helper_bootstrap
-import helper_generic
-import helper_threading
-
-
 def connectToStream(streamNumber):
     state.streamsInWhichIAmParticipating.append(streamNumber)
     selfInitiatedConnections[streamNumber] = {}
@@ -156,63 +95,6 @@ def _fixSocket():
         socket.IPV6_V6ONLY = 27
 
 
-# This thread, of which there is only one, runs the API.
-class singleAPI(threading.Thread, helper_threading.StoppableThread):
-    def __init__(self):
-        threading.Thread.__init__(self, name="singleAPI")
-        self.initStop()
-
-    def stopThread(self):
-        super(singleAPI, self).stopThread()
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        try:
-            s.connect((
-                BMConfigParser().get('bitmessagesettings', 'apiinterface'),
-                BMConfigParser().getint('bitmessagesettings', 'apiport')
-            ))
-            s.shutdown(socket.SHUT_RDWR)
-            s.close()
-        except:
-            pass
-
-    def run(self):
-        port = BMConfigParser().getint('bitmessagesettings', 'apiport')
-        try:
-            from errno import WSAEADDRINUSE
-        except (ImportError, AttributeError):
-            errno.WSAEADDRINUSE = errno.EADDRINUSE
-        for attempt in range(50):
-            try:
-                if attempt > 0:
-                    port = randint(32767, 65535)
-                se = StoppableXMLRPCServer(
-                    (BMConfigParser().get(
-                        'bitmessagesettings', 'apiinterface'),
-                     port),
-                    MySimpleXMLRPCRequestHandler, True, True)
-            except socket.error as e:
-                if e.errno in (errno.EADDRINUSE, errno.WSAEADDRINUSE):
-                    continue
-            else:
-                if attempt > 0:
-                    BMConfigParser().set(
-                        "bitmessagesettings", "apiport", str(port))
-                    BMConfigParser().save()
-                break
-        se.register_introspection_functions()
-        se.serve_forever()
-
-
-# This is a list of current connections (the thread pointers at least)
-selfInitiatedConnections = {}
-
-if shared.useVeryEasyProofOfWorkForTesting:
-    defaults.networkDefaultProofOfWorkNonceTrialsPerByte = int(
-        defaults.networkDefaultProofOfWorkNonceTrialsPerByte / 100)
-    defaults.networkDefaultPayloadLengthExtraBytes = int(
-        defaults.networkDefaultPayloadLengthExtraBytes / 100)
-
-
 class Main:
     def start(self):
         _fixSocket()
@@ -499,10 +381,87 @@ def main():
     mainprogram = Main()
     mainprogram.start()
 
+# See "workprover/Readme.md"
+
+import pyelliptic.openssl
+
+import workprover.dumbsolver
+
+workprover.dumbsolver.libcrypto = pyelliptic.openssl.OpenSSL._lib
 
 if __name__ == "__main__":
-    main()
+    import multiprocessing
 
+    multiprocessing.freeze_support()
+
+    import os
+    import sys
+
+    app_dir = os.path.dirname(os.path.abspath(__file__))
+    os.chdir(app_dir)
+    sys.path.insert(0, app_dir)
+
+
+    import depends
+    depends.check_dependencies()
+
+    # Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
+    import signal
+    # The next 3 are used for the API
+    from singleinstance import singleinstance
+    import errno
+    import socket
+    import ctypes
+    from struct import pack
+    from subprocess import call
+    from time import sleep
+    import getopt
+
+    from api import singleAPI
+    from helper_startup import (
+        isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
+    )
+
+    import defaults
+    import shared
+    import knownnodes
+    import state
+    import shutdown
+
+    # Classes
+    from class_sqlThread import sqlThread
+    from class_singleCleaner import singleCleaner
+    from class_objectProcessor import objectProcessor
+    from class_singleWorker import singleWorker
+    from class_addressGenerator import addressGenerator
+    from bmconfigparser import BMConfigParser
+
+    from inventory import Inventory
+
+    from network.connectionpool import BMConnectionPool
+    from network.dandelion import Dandelion
+    from network.networkthread import BMNetworkThread
+    from network.receivequeuethread import ReceiveQueueThread
+    from network.announcethread import AnnounceThread
+    from network.invthread import InvThread
+    from network.addrthread import AddrThread
+    from network.downloadthread import DownloadThread
+
+    # Helper Functions
+    import helper_bootstrap
+    import helper_generic
+    import helper_threading
+
+    # This is a list of current connections (the thread pointers at least)
+    selfInitiatedConnections = {}
+
+    if shared.useVeryEasyProofOfWorkForTesting:
+        defaults.networkDefaultProofOfWorkNonceTrialsPerByte = int(
+            defaults.networkDefaultProofOfWorkNonceTrialsPerByte / 100)
+        defaults.networkDefaultPayloadLengthExtraBytes = int(
+            defaults.networkDefaultPayloadLengthExtraBytes / 100)
+
+    main()
 
 # So far, the creation of and management of the Bitmessage protocol and this
 # client is a one-man operation. Bitcoin tips are quite appreciated.