diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1725535 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +name: CI + +on: + push: + branches: ["**"] + pull_request: + +jobs: + backend: + name: Backend checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-python@v6 + with: + python-version: "3.11" + cache: pip + cache-dependency-path: | + backend/requirements.txt + backend/conf/requirements-testing.txt + backend/conf/requirements-development.txt + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -r backend/requirements.txt + python -m pip install -r backend/conf/requirements-testing.txt + python -m pip install -r backend/conf/requirements-development.txt + python -m pip install -e backend/litecoin_scrypt + + - name: Compile-check Python sources + run: python backend/dev/python3_port_compile_check.py + + - name: Ruff fatal-error gate + run: ruff check --select E9,F63,F7,F82 backend/p2pool backend/run_p2pool.py run_p2pool.py + + - name: Unit tests + working-directory: backend + run: python -m twisted.trial p2pool.test.test_data p2pool.test.test_node p2pool.test.bitcoin.test_data + + - name: Python dependency audit + run: | + pip-audit -r backend/requirements.txt + pip-audit -r backend/conf/requirements-testing.txt + pip-audit -r backend/conf/requirements-development.txt + + - name: Bandit medium/high security gate + run: bandit -q --severity-level medium -r backend/p2pool backend/run_p2pool.py run_p2pool.py -x backend/p2pool/test + + frontend: + name: Frontend dependency audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: "22" + - name: Retire.js audit + run: npx --yes retire --path frontend/web-static --outputformat text diff --git a/.gitignore b/.gitignore index d446220..d189430 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,23 @@ *.pyc *.pyo *~ +__pycache__/ /data/ /litecoin_scrypt/build/ +/backend/litecoin_scrypt/build/ /_trial_temp* +_trial_temp*/ Makefile.local .cache/ +.pytest_cache/ +.ruff_cache/ .pkglist .pyenv/ .coverage build/ +backend/build/ ltc_scrypt.so +backend/ltc_scrypt.so -.DS_Store \ No newline at end of file +.DS_Store diff --git a/README.md b/README.md index 50e4e36..f824eec 100644 --- a/README.md +++ b/README.md @@ -1,243 +1,110 @@ -Requirements: -========================= -To use P2Pool, you must be running your own local defcoind. It takes a while to sync so get that started first. +

+ Defcoin P2Pool decentralized mining infrastructure +

-For the recommended modern Defcoin full-node wallet/source tree, see -https://github.com/defcoincore/Defcoin-Core-Nu. +# Defcoin P2Pool +Defcoin P2Pool is decentralized pool infrastructure for mining Defcoin without +routing all share accounting through one central pool database. It keeps the +classic P2Pool sharechain model, updates the runtime to Python 3, and adds the +Defcoin-specific network fixes needed by current wallets and pool operators. -Generic: -* defcoind >=1.0.0 -* Python >=2.6 -* Twisted >=10.0.0 -* python-argparse (for Python =2.6) +Run a pool node. Point miners at Stratum. Keep Defcoin mining cooperative. -NOTE: IF USING UBUNTU, USE 16 OR 18. Starting with 20 they removed some of the libs from global, and i was seeing instability with 20 (but that could have just been me). Just a note to make your life easier. +For the recommended modern Defcoin full-node wallet, use +[Defcoin Core Nu](https://github.com/defcoincore/Defcoin-Core-Nu). -Linux: -* sudo apt-get install python-zope.interface python-twisted python-twisted-web python-dev -* sudo apt-get install python-argparse # if on Python 2.6 +## What changed -Windows: -* Install [Python 2.7](http://www.python.org/getit/) -* Install [Twisted](http://twistedmatrix.com/trac/wiki/Downloads) -* Install [Zope.Interface](http://pypi.python.org/pypi/zope.interface/3.8.0) -* Install [python win32 api](http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/) -* Install [python win32 api wmi wrapper](https://pypi.python.org/pypi/WMI/#downloads) -* Unzip the files into C:\Python27\Lib\site-packages +- Python 3 runtime support with current dependency audits. +- Defcoin dual-magic parent-chain compatibility: legacy `fbc0b6db` and new + Defcoin `defc014e`, with per-peer reply magic. +- `/Defcoin` User-Agent filtering for legacy-magic parent-chain peer address + gossip. +- Defcoin P2Pool share version `36`, which removes the old lost-key P2Pool + developer donation dust output from new share templates. +- Bounded caches for repeated target, difficulty, script, and address + conversions used by the pool API and explorer-style display paths. +- A cleaner backend/frontend layout so operators can run the backend with the + bundled web UI or point it at a custom frontend. +## Screenshots -Running P2Pool: -========================= +

+ Defcoin pool overview +

-You can run a "private" node to connect your miner(s) to or a public pool. +

+ Defcoin network peers +

-Defcoin Core Nu note: -------------------------- -When running this fork against Defcoin Core Nu 26.3.x, use the new Defcoin -parent-chain magic for outbound P2P and keep legacy magic enabled only as a -transition path. The dc903 deployment uses: +## Repository layout - DEFCOIN_P2POOL_USE_NEW_MAGIC=1 python run_p2pool.py --net defcoin --allow-obsolete-bitcoind -a YOURADDR -n YOUR_PUBLIC_IP --bitcoind-p2p-port 10332 +- `backend/` - Python P2Pool backend, Defcoin network rules, tests, and helper + scripts. +- `frontend/` - bundled web UI assets and reference frontend material. +- `docs/TECHNICAL_GUIDE.md` - the single public technical guide for this fork. +- `run_p2pool.py` - compatibility launcher that keeps the historical root + command working while loading `backend/run_p2pool.py`. -`DEFCOIN_P2POOL_USE_NEW_MAGIC=1` makes P2Pool prefer Defcoin's `defc014e` -parent-chain magic while still accepting legacy `fbc0b6db` peers. Each peer is -answered with the magic it used. `--allow-obsolete-bitcoind` is currently needed -because this old Python 2 P2Pool fork has hard-coded softfork expectations that -do not line up cleanly with Defcoin Core Nu's Litecoin-derived RPC reporting. +## Quick start -Defcoin P2Pool v36 dust fix: -------------------------- -This fork removes the old P2Pool developer donation-address dust output for -newly mined Defcoin P2Pool shares. The change is a P2Pool share-template update, -not a Defcoin blockchain hard fork. +Run this pool next to a fully synced `defcoind` or Defcoin Core Nu backend. -The previous template always placed any donation weight and rounding remainder -into JP's legacy P2PK donation script, which appears on-chain as -`DQ8AwqR2XJE9G5dSEfspJYH7Spre85dj6L`. Defcoin share version `36` keeps older -shares verifiable, then switches new shares to a zero-value OP_RETURN padding -output and routes the spendable remainder to the block finder instead of the -lost-key donation address. +```bash +python3 -m venv .venv +. .venv/bin/activate +python -m pip install --upgrade pip +python -m pip install -r backend/requirements.txt +python -m pip install -e backend/litecoin_scrypt +``` -Defcoin P2Pool operators should update together. The relevant code is in: +Start a public Defcoin P2Pool node: -* `p2pool/data.py`: `DonationDustFixedShare`, `DUSTFIX_PADDING_SCRIPT`, - coinbase payout construction, and expected payout calculation. -* `p2pool/work.py`: share version 36 stops recording author-donation weight in - newly generated shares. -* `p2pool/main.py`: startup output notes the disabled developer donation output - after share version 36 activation. +```bash +DEFCOIN_P2POOL_USE_NEW_MAGIC=1 \ +python run_p2pool.py \ + --net defcoin \ + --allow-obsolete-bitcoind \ + -a YOUR_DEFCOIN_OPERATOR_ADDRESS \ + -n YOUR_PUBLIC_IP \ + --bitcoind-address 127.0.0.1 \ + --bitcoind-p2p-port 10332 \ + --fee 1.5 +``` -If coordinating with another Defcoin P2Pool operator, ask them to pull this -version and restart once both pools are ready. For the small current Defcoin -P2Pool network, operators can use a coordinated flag day instead of waiting for -normal P2Pool upgrade voting: +UPnP is disabled by default in this Defcoin fork. Use `--enable-upnp` only for +consumer NAT deployments where automatic router port mapping is explicitly +desired. - DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY=1 DEFCOIN_P2POOL_USE_NEW_MAGIC=1 python run_p2pool.py --net defcoin --allow-obsolete-bitcoind -a YOURADDR -n YOUR_PUBLIC_IP --bitcoind-p2p-port 10332 +Point miners at the configured Stratum worker port, commonly: -The parent-chain Defcoin blocks remain valid either way; incompatible old -P2Pool share-template nodes simply should not continue sharing the same P2Pool -sharechain after version 36 wins. +```text +stratum+tcp://YOUR_POOL_HOST:13372 +``` +Use the miner payout address as the Stratum username and any password. -All -------------------------- -Configuration: -Edit p2pool/networks/defcoin.py by uncommenting WORKER_PORT and BOOTSTRAP_ADDRS for the type of node you want to run. The 3 pool types are as follows. Take note that these hash ranges are an early division and may be modified (feedback welcome). -* ~~pool 0, CPU, <1mh, port 13370 --> CPU miners~~ CPU pool is for future use for slower miners when network is larger. Until then mine on USB -* pool 1, USB, <=50mh, port 13371 --> USB ASIC miners like moonlanders and gridseed (and CPUs until that pool is started) -* pool 2, ASIC, >50mh, port 13372 --> big ASIC miners like antminer L3 +## Frontend options +The backend serves `frontend/web-static` by default. To run a custom frontend, +start the backend with: -Now that it is configured, a few definitions for clarity: -* YOURADDR - the address of the wallet of the local defcoind running the pool -* USERNAME - as a miner, your defcoin payout address -* MININGPORT - port to mine to as defined when you chose your configuration -* YOUR_LOCAL_IP - IPv4 of pool computer such as 192.168.1.46 -* YOUR_PUBLIC_IP - IPv4 of pool computer such as 135.148.43.187 +```bash +python run_p2pool.py --net defcoin --web-static /path/to/custom/web-static ... +``` +See [frontend/README.md](frontend/README.md) for the frontend boundary and +[backend/README.md](backend/README.md) for backend setup and test commands. -FYI you can get defcoin addr with defcoin-cli listreceivedbyaddress 0 true +## Technical guide +For architecture, lineage, security notes, dependency policy, dual-magic +behavior, User-Agent filtering, share version `36`, performance cache evidence, +and operational details, read +[docs/TECHNICAL_GUIDE.md](docs/TECHNICAL_GUIDE.md). -Run for additional options. +## License - python run_p2pool.py --help - -FAQ: -------------------------- - -### Where is the public pool fee wallet set? - -The public worker fee is controlled by two command-line options: - - python run_p2pool.py --net defcoin -a YOURADDR --fee 1.5 ... - -`-a YOURADDR` is the node operator/default payout address. When `--fee` is -greater than zero, P2Pool occasionally assigns worker shares to that operator -address instead of the miner's username payout address. For example, `--fee 1.5` -means a 1.5% public worker fee. - -On a systemd server deployment, the live values are usually in the service file: - - systemctl cat p2pool-defcoin - -The dc903 deployment currently uses `-a DBbKV7upy41hV42dU895m4NcXn9AvHXUz9` -with `--fee 1.5`. The fee can also be checked from the pool API: - - curl http://127.0.0.1:13372/fee - -This public worker fee is separate from P2Pool's legacy developer donation -script. Changing `-a` or `--fee` does not remove the tiny legacy donation-script -dust output from old P2Pool share templates. Share version `36` removes that -spendable donation-address output for newly mined templates. - - -Example commands for running your miners: -* CPU: ./minerd -a scrypt -o stratum+tcp://IP:MININGPORT -O USERNAME:x -* USB: bfgminer.exe --scrypt -o stratum+tcp://IP:MININGPORT -u USERNAME -p 1,d=128 -S MLD:all --set MLD:clock=600 - - -Private - needs testing so might have errors -------------------------- -For standard configurations, using P2Pool should be as simple as: - - python run_p2pool.py --net defcoin -a YOURADDR -n YOUR_LOCAL_IP --bitcoind-p2p-port 10332 - -If mining from the pool computer, run your miner program, connecting to 127.0.0.1 on port MININGPORT with USERNAME and any password (x is used commonly). - -If mining from another local source, run your miner program, connecting YOUR_LOCAL_IP on port MININGPORT with USERNAME and any password (x is used commonly). Probably need to open firewall on pool computer to MININGPORT. - - -Public -------------------------- -For standard configurations, using P2Pool should be as simple as: - - python run_p2pool.py --net defcoin -a YOURADDR -n YOUR_PUBLIC_IP --bitcoind-p2p-port 10332 - -Connecting your miners to YOUR_PUBLIC_IP on port MININGPORT with USERNAME and any password (x is used commonly). - -Probably need to open firewall on pool computer to MININGPORT. - -If you are behind a NAT, you should enable TCP port forwarding on your router. Forward port MININGPORT to the host running P2Pool. - - -NOTE: Past experience showed need of opening ports MININGPORT, 1335, 1337, and 10332. Operators should open only the ports required for their deployment. - - - -Official wiki: -========================= -https://en.bitcoin.it/wiki/P2Pool - - -Alternate web frontend: -========================= - - cd .. - mv web-static web-static.old - git clone https://github.com/justino/p2pool-ui-punchy web-static - mv web-static.old web-static/legacy - cd web-static - git clone https://github.com/hardcpp/P2PoolExtendedFrontEnd ext - -There are multiple alt frontends out there to choose from. - - -Notes for Defcoin: -========================= -Requirements: -------------------------- -Prepare Defcoin core and edit the config file: - - connect=129.2.164.234:1337 - connect=107.191.119.170:1337 - connect=199.204.211.87:1337 - connect=104.37.196.137:1337 - connect=137.117.89.23:1337 - rpcuser=xxx - rpcpassword=xxx - rpcallowip=127.0.0.1 - daemon=1 - server=1 - listen=1 - maxconnections=64 - port=10332 - rpcport=1335 - -In order to run P2Pool with the Defcoin network, you would need to build and install the -dfc_scrypt module that includes the scrypt proof of work code that Defcoin uses for hashes. - -Linux: - - cd litecoin_scrypt - sudo python setup.py install - -Windows (mingw): -* Install MinGW: http://www.mingw.org/wiki/Getting_Started -* Install Python 2.7: http://www.python.org/getit/ - -In bash type this: - - cd defcoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install - -Windows (Microsoft Visual C++) -* Open visual studio console - -In bash type this: - - SET VS90COMNTOOLS=%VS110COMNTOOLS% # For visual c++ 2012 - SET VS90COMNTOOLS=%VS100COMNTOOLS% # For visual c++ 2010 - cd defcoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install - -If you run into an error with unrecognized command line option '-mno-cygwin', see this: -http://stackoverflow.com/questions/6034390/compiling-with-cython-and-mingw-produces-gcc-error-unrecognized-command-line-o - -_Tested on Ubuntu 16 and 18_ - - -License: -========================= -[Available here](COPYING) +This repository follows the inherited P2Pool license: GNU General Public +License version 3. See [COPYING](COPYING). diff --git a/SOAPpy/__init__.py b/SOAPpy/__init__.py deleted file mode 100644 index f5f5419..0000000 --- a/SOAPpy/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ - -ident = '$Id: __init__.py 541 2004-01-31 04:20:06Z warnes $' -from version import __version__ - -from Client import * -from Config import * -from Errors import * -from NS import * -from Parser import * -from SOAPBuilder import * -from Server import * -from Types import * -from Utilities import * -import wstools -import WSDL diff --git a/Makefile b/backend/Makefile similarity index 100% rename from Makefile rename to backend/Makefile diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..14a146c --- /dev/null +++ b/backend/README.md @@ -0,0 +1,48 @@ +# Defcoin P2Pool Backend + +This directory contains the Python P2Pool backend, Defcoin network parameters, +share validation, Stratum work generation, P2P protocol code, tests, and helper +scripts. + +## Install + +From the repository root: + +```bash +python3 -m venv .venv +. .venv/bin/activate +python -m pip install --upgrade pip +python -m pip install -r backend/requirements.txt +python -m pip install -e backend/litecoin_scrypt +``` + +## Run + +Use the root compatibility launcher unless you have a specific reason to call +the backend launcher directly: + +```bash +python run_p2pool.py --net defcoin --help +``` + +The default web UI is loaded from `frontend/web-static`. A custom UI can be +provided with: + +```bash +python run_p2pool.py --net defcoin --web-static /path/to/web-static ... +``` + +## Test and audit + +```bash +python backend/dev/python3_port_compile_check.py +ruff check --select E9,F63,F7,F82 backend/p2pool backend/run_p2pool.py run_p2pool.py +cd backend && python -m twisted.trial p2pool.test.test_data p2pool.test.test_node p2pool.test.bitcoin.test_data +python backend/dev/cache_benchmark.py +pip-audit -r backend/requirements.txt +pip-audit -r backend/conf/requirements-testing.txt +pip-audit -r backend/conf/requirements-development.txt +bandit --severity-level medium -r backend/p2pool backend/run_p2pool.py run_p2pool.py -x backend/p2pool/test +``` + +See `../docs/TECHNICAL_GUIDE.md` for the fuller test, audit, and deployment notes. diff --git a/SOAPpy/Client.py b/backend/SOAPpy/Client.py similarity index 89% rename from SOAPpy/Client.py rename to backend/SOAPpy/Client.py index 3749879..2563363 100644 --- a/SOAPpy/Client.py +++ b/backend/SOAPpy/Client.py @@ -1,4 +1,4 @@ -from __future__ import nested_scopes + """ ################################################################################ @@ -43,24 +43,24 @@ """ ident = '$Id: Client.py 1496 2010-03-04 23:46:17Z pooryorick $' -from version import __version__ +from .version import __version__ #import xml.sax -import urllib -from types import * +import urllib.request, urllib.parse, urllib.error +from .types import * import re import base64 -import socket, httplib -from httplib import HTTPConnection, HTTP -import Cookie +import socket, http.client +from http.client import HTTPConnection, HTTP +import http.cookies # SOAPpy modules -from Errors import * -from Config import Config -from Parser import parseSOAPRPC -from SOAPBuilder import buildSOAP -from Utilities import * -from Types import faultType, simplify +from .Errors import * +from .Config import Config +from .Parser import parseSOAPRPC +from .SOAPBuilder import buildSOAP +from .Utilities import * +from .Types import faultType, simplify ################################################################################ # Client @@ -73,7 +73,7 @@ def SOAPUserAgent(): class SOAPAddress: def __init__(self, url, config = Config): - proto, uri = urllib.splittype(url) + proto, uri = urllib.parse.splittype(url) # apply some defaults if uri[0:2] != '//': @@ -83,7 +83,7 @@ def __init__(self, url, config = Config): uri = '//' + uri proto = 'http' - host, path = urllib.splithost(uri) + host, path = urllib.parse.splithost(uri) try: int(host) @@ -95,15 +95,13 @@ def __init__(self, url, config = Config): path = '/' if proto not in ('http', 'https', 'httpg'): - raise IOError, "unsupported SOAP protocol" + raise IOError("unsupported SOAP protocol") if proto == 'httpg' and not config.GSIclient: - raise AttributeError, \ - "GSI client not supported by this Python installation" + raise AttributeError("GSI client not supported by this Python installation") if proto == 'https' and not config.SSLclient: - raise AttributeError, \ - "SSL client not supported by this Python installation" + raise AttributeError("SSL client not supported by this Python installation") - self.user,host = urllib.splituser(host) + self.user,host = urllib.parse.splituser(host) self.proto = proto self.host = host self.path = path @@ -151,14 +149,14 @@ class HTTPTransport: def __init__(self): - self.cookies = Cookie.SimpleCookie(); + self.cookies = http.cookies.SimpleCookie(); def getNS(self, original_namespace, data): """Extract the (possibly extended) namespace from the returned SOAP message.""" if type(original_namespace) == StringType: - pattern="xmlns:\w+=['\"](" + original_namespace + "[^'\"]*)['\"]" + pattern = r"xmlns:\w+=['\"](" + original_namespace + r"[^'\"]*)['\"]" match = re.search(pattern, data) if match: return match.group(1) @@ -170,7 +168,7 @@ def getNS(self, original_namespace, data): def __addcookies(self, r): '''Add cookies from self.cookies to request r ''' - for cname, morsel in self.cookies.items(): + for cname, morsel in list(self.cookies.items()): attrs = [] value = morsel.get('version', '') if value != '' and value != '0': @@ -202,7 +200,7 @@ def call(self, addr, data, namespace, soapaction = None, encoding = None, from pyGlobus.io import GSIHTTP r = GSIHTTP(real_addr, tcpAttr = config.tcpAttr) elif addr.proto == 'https': - r = httplib.HTTPS(real_addr, key_file=config.SSL.key_file, cert_file=config.SSL.cert_file) + r = http.client.HTTPS(real_addr, key_file=config.SSL.key_file, cert_file=config.SSL.cert_file) else: r = HTTPWithTimeout(real_addr, timeout=timeout) @@ -232,12 +230,12 @@ def call(self, addr, data, namespace, soapaction = None, encoding = None, if config.dumpHeadersOut: s = 'Outgoing HTTP headers' debugHeader(s) - print "POST %s %s" % (real_path, r._http_vsn_str) - print "Host:", addr.host - print "User-agent: SOAPpy " + __version__ + " (http://pywebsvcs.sf.net)" - print "Content-type:", t - print "Content-length:", len(data) - print 'SOAPAction: "%s"' % soapaction + print("POST %s %s" % (real_path, r._http_vsn_str)) + print("Host:", addr.host) + print("User-agent: SOAPpy " + __version__ + " (http://pywebsvcs.sf.net)") + print("Content-type:", t) + print("Content-length:", len(data)) + print('SOAPAction: "%s"' % soapaction) debugFooter(s) r.endheaders() @@ -245,9 +243,9 @@ def call(self, addr, data, namespace, soapaction = None, encoding = None, if config.dumpSOAPOut: s = 'Outgoing SOAP' debugHeader(s) - print data, + print(data, end=' ') if data[-1] != '\n': - print + print() debugFooter(s) # send the payload @@ -256,7 +254,7 @@ def call(self, addr, data, namespace, soapaction = None, encoding = None, # read response line code, msg, headers = r.getreply() - self.cookies = Cookie.SimpleCookie(); + self.cookies = http.cookies.SimpleCookie(); if headers: content_type = headers.get("content-type","text/xml") content_length = headers.get("Content-length") @@ -289,20 +287,20 @@ def call(self, addr, data, namespace, soapaction = None, encoding = None, data = r.getfile().read(message_len) if(config.debug): - print "code=",code - print "msg=", msg - print "headers=", headers - print "content-type=", content_type - print "data=", data + print("code=",code) + print("msg=", msg) + print("headers=", headers) + print("content-type=", content_type) + print("data=", data) if config.dumpHeadersIn: s = 'Incoming HTTP headers' debugHeader(s) if headers.headers: - print "HTTP/1.? %d %s" % (code, msg) - print "\n".join(map (lambda x: x.strip(), headers.headers)) + print("HTTP/1.? %d %s" % (code, msg)) + print("\n".join([x.strip() for x in headers.headers])) else: - print "HTTP/0.9 %d %s" % (code, msg) + print("HTTP/0.9 %d %s" % (code, msg)) debugFooter(s) def startswith(string, val): @@ -315,9 +313,9 @@ def startswith(string, val): if config.dumpSOAPIn: s = 'Incoming SOAP' debugHeader(s) - print data, + print(data, end=' ') if (len(data)>0) and (data[-1] != '\n'): - print + print() debugFooter(s) if code not in (200, 500): @@ -427,7 +425,7 @@ def __call(self, name, args, kw, ns = None, sa = None, hd = None, except socket.timeout: raise SOAPTimeoutError - except Exception, ex: + except Exception as ex: # # Call failed. # @@ -471,7 +469,7 @@ def __call(self, name, args, kw, ns = None, sa = None, hd = None, if throw_struct: if Config.debug: - print p + print(p) raise p # If unwrap_results=1 and there is only element in the struct, @@ -482,7 +480,7 @@ def __call(self, name, args, kw, ns = None, sa = None, hd = None, if self.unwrap_results: try: count = 0 - for i in p.__dict__.keys(): + for i in list(p.__dict__.keys()): if i[0] != "_": # don't count the private stuff count += 1 t = getattr(p, i) @@ -507,7 +505,7 @@ def _callWithBody(self, body): def __getattr__(self, name): # hook to catch method calls if name in ( '__del__', '__getinitargs__', '__getnewargs__', '__getstate__', '__setstate__', '__reduce__', '__reduce_ex__'): - raise AttributeError, name + raise AttributeError(name) return self.__Method(self.__call, name, config = self.config) # To handle attribute weirdness @@ -541,7 +539,7 @@ def __call__(self, *args, **kw): def __getattr__(self, name): if name == '__del__': - raise AttributeError, name + raise AttributeError(name) if self.__name[0] == "_": # Don't nest method if it is a directive return self.__class__(self.__call, name, self.__ns, diff --git a/SOAPpy/Config.py b/backend/SOAPpy/Config.py similarity index 91% rename from SOAPpy/Config.py rename to backend/SOAPpy/Config.py index deafa59..92de993 100644 --- a/SOAPpy/Config.py +++ b/backend/SOAPpy/Config.py @@ -34,12 +34,12 @@ """ ident = '$Id: Config.py 1298 2006-11-07 00:54:15Z sanxiyn $' -from version import __version__ +from .version import __version__ import socket -from types import * +from .types import * -from NS import NS +from .NS import NS ################################################################################ # Configuration class @@ -58,12 +58,11 @@ def __init__(self, config = None, **kw): if config: if not isinstance(config, SOAPConfig): - raise AttributeError, \ - "initializer must be SOAPConfig instance" + raise AttributeError("initializer must be SOAPConfig instance") s = config.__dict__ - for k, v in s.items(): + for k, v in list(s.items()): if k[0] != '_': d[k] = v else: @@ -143,13 +142,13 @@ def __init__(self, config = None, **kw): if d['SSLclient'] or d['SSLserver']: d['SSL'] = self.SSLconfig() - for k, v in kw.items(): + for k, v in list(kw.items()): if k[0] != '_': setattr(self, k, v) def __setattr__(self, name, value): if name in self.__readonly: - raise AttributeError, "readonly configuration setting" + raise AttributeError("readonly configuration setting") d = self.__dict__ @@ -162,19 +161,19 @@ def __setattr__(self, name, value): base, uri = name, 0 if type(value) == StringType: - if NS.NSMAP.has_key(value): + if value in NS.NSMAP: n = (value, NS.NSMAP[value]) - elif NS.NSMAP_R.has_key(value): + elif value in NS.NSMAP_R: n = (NS.NSMAP_R[value], value) else: - raise AttributeError, "unknown namespace" + raise AttributeError("unknown namespace") elif type(value) in (ListType, TupleType): if uri: n = (value[1], value[0]) else: n = (value[0], value[1]) else: - raise AttributeError, "unknown namespace type" + raise AttributeError("unknown namespace type") d[base], d[base + 'URI'] = n @@ -187,8 +186,8 @@ def __setattr__(self, name, value): elif name == 'namespaceStyle': value = str(value) - if not NS.STMAP.has_key(value): - raise AttributeError, "unknown namespace style" + if value not in NS.STMAP: + raise AttributeError("unknown namespace style") d[name] = value n = d['typesNamespace'] = NS.STMAP[value][0] diff --git a/SOAPpy/Errors.py b/backend/SOAPpy/Errors.py similarity index 98% rename from SOAPpy/Errors.py rename to backend/SOAPpy/Errors.py index 1a81f91..0c6ca9e 100644 --- a/SOAPpy/Errors.py +++ b/backend/SOAPpy/Errors.py @@ -41,7 +41,7 @@ """ ident = '$Id: Errors.py 921 2005-02-15 16:32:23Z warnes $' -from version import __version__ +from .version import __version__ import exceptions @@ -55,7 +55,7 @@ def __str__(self): return "" % self.msg __repr__ = __str__ def __call__(self): - return (msg,) + return (self.msg,) class RecursionError(Error): pass @@ -76,4 +76,3 @@ def __call___(self): class UnderflowError(exceptions.ArithmeticError): pass - diff --git a/SOAPpy/GSIServer.py b/backend/SOAPpy/GSIServer.py similarity index 92% rename from SOAPpy/GSIServer.py rename to backend/SOAPpy/GSIServer.py index 39f836c..ab2086f 100644 --- a/SOAPpy/GSIServer.py +++ b/backend/SOAPpy/GSIServer.py @@ -1,4 +1,4 @@ -from __future__ import nested_scopes + """ GSIServer - Contributed by Ivan R. Judson @@ -46,30 +46,30 @@ """ ident = '$Id: GSIServer.py 1468 2008-05-24 01:55:33Z warnes $' -from version import __version__ +from .version import __version__ #import xml.sax import re import socket import sys -import SocketServer -from types import * -import BaseHTTPServer +import socketserver +from .types import * +import http.server # SOAPpy modules -from Parser import parseSOAPRPC -from Config import SOAPConfig -from Types import faultType, voidType, simplify -from NS import NS -from SOAPBuilder import buildSOAP -from Utilities import debugHeader, debugFooter +from .Parser import parseSOAPRPC +from .Config import SOAPConfig +from .Types import faultType, voidType, simplify +from .NS import NS +from .SOAPBuilder import buildSOAP +from .Utilities import debugHeader, debugFooter try: from M2Crypto import SSL except: pass ##### -from Server import * +from .Server import * from pyGlobus.io import GSITCPSocketServer, ThreadingGSITCPSocketServer from pyGlobus import ioc diff --git a/SOAPpy/NS.py b/backend/SOAPpy/NS.py similarity index 96% rename from SOAPpy/NS.py rename to backend/SOAPpy/NS.py index 124dad0..a07c02c 100644 --- a/SOAPpy/NS.py +++ b/backend/SOAPpy/NS.py @@ -1,4 +1,4 @@ -from __future__ import nested_scopes + """ ################################################################################ @@ -43,7 +43,8 @@ """ ident = '$Id: NS.py 1468 2008-05-24 01:55:33Z warnes $' -from version import __version__ +from .version import __version__ +from .Errors import Error ############################################################################## # Namespace Class @@ -51,7 +52,7 @@ def invertDict(dict): d = {} - for k, v in dict.items(): + for k, v in list(dict.items()): d[v] = k return d @@ -98,7 +99,6 @@ class NS: STMAP_R = invertDict(STMAP) def __init__(self): - raise Error, "Don't instantiate this" - + raise Error("Don't instantiate this") diff --git a/SOAPpy/Parser.py b/backend/SOAPpy/Parser.py similarity index 85% rename from SOAPpy/Parser.py rename to backend/SOAPpy/Parser.py index 9e77468..b87170b 100644 --- a/SOAPpy/Parser.py +++ b/backend/SOAPpy/Parser.py @@ -1,19 +1,20 @@ # SOAPpy modules -from Config import Config -from Types import * -from NS import NS -from Utilities import * +from .Config import Config +from .Types import * +from .NS import NS +from .Utilities import * import string import fpconst import xml.sax +from defusedxml import sax as defused_sax from wstools.XMLname import fromXMLname try: from M2Crypto import SSL except: pass ident = '$Id: Parser.py 1497 2010-03-08 06:06:52Z pooryorick $' -from version import __version__ +from .version import __version__ ################################################################################ @@ -34,11 +35,11 @@ def __str__(self): class SOAPParser(xml.sax.handler.ContentHandler): class Frame: - def __init__(self, name, kind = None, attrs = {}, rules = {}): + def __init__(self, name, kind = None, attrs = None, rules = None): self.name = name self.kind = kind - self.attrs = attrs - self.rules = rules + self.attrs = {} if attrs is None else attrs + self.rules = {} if rules is None else rules self.contents = [] self.names = [] @@ -50,7 +51,7 @@ def append(self, name, data, attrs): self.contents.append(data) self.subattrs.append(attrs) - if self.namecounts.has_key(name): + if name in self.namecounts: self.namecounts[name] += 1 else: self.namecounts[name] = 1 @@ -89,7 +90,7 @@ def startElementNS(self, name, qname, attrs): def toStr( name ): prefix = name[0] tag = name[1] - if self._prem_r.has_key(prefix): + if prefix in self._prem_r: tag = self._prem_r[name[0]] + ':' + name[1] elif prefix: tag = prefix + ":" + tag @@ -105,10 +106,10 @@ def toStr( name ): if self._next == "E": if name[1] != 'Envelope': - raise Error, "expected `SOAP-ENV:Envelope', " \ - "got `%s'" % toStr( name ) + raise Error("expected `SOAP-ENV:Envelope', " \ + "got `%s'" % toStr( name )) if name[0] != NS.ENV: - raise faultType, ("%s:VersionMismatch" % NS.ENV_T, + raise faultType("%s:VersionMismatch" % NS.ENV_T, "Don't understand version `%s' Envelope" % name[0]) else: self._next = "HorB" @@ -116,18 +117,17 @@ def toStr( name ): if name[0] == NS.ENV and name[1] in ("Header", "Body"): self._next = None else: - raise Error, \ - "expected `SOAP-ENV:Header' or `SOAP-ENV:Body', " \ - "got `%s'" % toStr( name ) + raise Error("expected `SOAP-ENV:Header' or `SOAP-ENV:Body', " \ + "got `%s'" % toStr( name )) elif self._next == "B": if name == (NS.ENV, "Body"): self._next = None else: - raise Error, "expected `SOAP-ENV:Body', " \ - "got `%s'" % toStr( name ) + raise Error("expected `SOAP-ENV:Body', " \ + "got `%s'" % toStr( name )) elif self._next == "": - raise Error, "expected nothing, " \ - "got `%s'" % toStr( name ) + raise Error("expected nothing, " \ + "got `%s'" % toStr( name )) if len(self._stack) == 2: @@ -175,27 +175,27 @@ def endElementNS(self, name, qname): name = fromXMLname(name) # convert to SOAP 1.2 XML name encoding if self._next == "E": - raise Error, "didn't get SOAP-ENV:Envelope" + raise Error("didn't get SOAP-ENV:Envelope") if self._next in ("HorB", "B"): - raise Error, "didn't get SOAP-ENV:Body" + raise Error("didn't get SOAP-ENV:Body") cur = self.popFrame() attrs = cur.attrs idval = None - if attrs.has_key((None, 'id')): + if (None, 'id') in attrs: idval = attrs[(None, 'id')] - if self._ids.has_key(idval): - raise Error, "duplicate id `%s'" % idval + if idval in self._ids: + raise Error("duplicate id `%s'" % idval) del attrs[(None, 'id')] root = 1 if len(self._stack) == 3: - if attrs.has_key((NS.ENC, 'root')): + if (NS.ENC, 'root') in attrs: root = int(attrs[(NS.ENC, 'root')]) # Do some preliminary checks. First, if root="0" is present, @@ -204,9 +204,9 @@ def endElementNS(self, name, qname): if root == 0: if idval == None: - raise Error, "non-root element must have an id" + raise Error("non-root element must have an id") elif root != 1: - raise Error, "SOAP-ENC:root must be `0' or `1'" + raise Error("SOAP-ENC:root must be `0' or `1'") del attrs[(NS.ENC, 'root')] @@ -214,19 +214,19 @@ def endElementNS(self, name, qname): href = attrs.get((None, 'href')) if href: if href[0] != '#': - raise Error, "Non-local hrefs are not yet suppported." + raise Error("Non-local hrefs are not yet suppported.") if self._data != None and \ string.join(self._data, "").strip() != '': - raise Error, "hrefs can't have data" + raise Error("hrefs can't have data") href = href[1:] - if self._ids.has_key(href): + if href in self._ids: data = self._ids[href] else: data = RefHolder(name, self._stack[-1]) - if self._refs.has_key(href): + if href in self._refs: self._refs[href].append(data) else: self._refs[href] = [data] @@ -239,7 +239,7 @@ def endElementNS(self, name, qname): if attrs: for i in NS.XSI_L: - if attrs.has_key((i, 'type')): + if (i, 'type') in attrs: kind = attrs[(i, 'type')] del attrs[(i, 'type')] @@ -259,11 +259,11 @@ def endElementNS(self, name, qname): if attrs: for i in (NS.XSI, NS.XSI2): - if attrs.has_key((i, 'null')): + if (i, 'null') in attrs: null = attrs[(i, 'null')] del attrs[(i, 'null')] - if attrs.has_key((NS.XSI3, 'nil')): + if (NS.XSI3, 'nil') in attrs: null = attrs[(NS.XSI3, 'nil')] del attrs[(NS.XSI3, 'nil')] @@ -278,7 +278,7 @@ def endElementNS(self, name, qname): # check for nil=1, but watch out for string values try: null = int(null) - except ValueError, e: + except ValueError as e: if not e[0].startswith("invalid literal for int()"): raise e null = 0 @@ -286,7 +286,7 @@ def endElementNS(self, name, qname): if null: if len(cur) or \ (self._data != None and string.join(self._data, "").strip() != ''): - raise Error, "nils can't have data" + raise Error("nils can't have data") data = None @@ -431,7 +431,7 @@ def endElementNS(self, name, qname): if idval != None: self._ids[idval] = data - if self._refs.has_key(idval): + if idval in self._refs: for i in self._refs[idval]: i.parent._placeItem(i.name, data, i.pos, i.subpos, attrs) @@ -446,11 +446,9 @@ def endElementNS(self, name, qname): def endDocument(self): if len(self._refs) == 1: - raise Error, \ - "unresolved reference " + self._refs.keys()[0] + raise Error("unresolved reference " + list(self._refs.keys())[0]) elif len(self._refs) > 1: - raise Error, \ - "unresolved references " + ', '.join(self._refs.keys()) + raise Error("unresolved references " + ', '.join(list(self._refs.keys()))) def startPrefixMapping(self, prefix, uri): self._prem[prefix] = uri @@ -467,10 +465,10 @@ def characters(self, c): if self._data != None: self._data.append(c) - arrayre = '^(?:(?P[^:]*):)?' \ - '(?P[^[]+)' \ - '(?:\[(?P,*)\])?' \ - '(?:\[(?P\d+(?:,\d+)*)?\])$' + arrayre = r'^(?:(?P[^:]*):)?' \ + r'(?P[^[]+)' \ + r'(?:\[(?P,*)\])?' \ + r'(?:\[(?P\d+(?:,\d+)*)?\])$' def startArray(self, name, kind, attrs, elemsname): if type(self.arrayre) == StringType: @@ -489,7 +487,7 @@ def startArray(self, name, kind, attrs, elemsname): else: raise Exception except: - raise AttributeError, "invalid Array offset" + raise AttributeError("invalid Array offset") else: offset = 0 @@ -512,23 +510,23 @@ def startArray(self, name, kind, attrs, elemsname): return typedArrayType(None, name, (None, t), attrs, offset, m.group('rank'), m.group('asize'), elemsname) except: - raise AttributeError, "invalid Array type `%s'" % kind + raise AttributeError("invalid Array type `%s'" % kind) # Conversion class DATETIMECONSTS: - SIGNre = '(?P-?)' - CENTURYre = '(?P\d{2,})' - YEARre = '(?P\d{2})' - MONTHre = '(?P\d{2})' - DAYre = '(?P\d{2})' - HOURre = '(?P\d{2})' - MINUTEre = '(?P\d{2})' - SECONDre = '(?P\d{2}(?:\.\d*)?)' - TIMEZONEre = '(?PZ)|(?P[-+])(?P\d{2}):' \ - '(?P\d{2})' - BOSre = '^\s*' - EOSre = '\s*$' + SIGNre = r'(?P-?)' + CENTURYre = r'(?P\d{2,})' + YEARre = r'(?P\d{2})' + MONTHre = r'(?P\d{2})' + DAYre = r'(?P\d{2})' + HOURre = r'(?P\d{2})' + MINUTEre = r'(?P\d{2})' + SECONDre = r'(?P\d{2}(?:\.\d*)?)' + TIMEZONEre = r'(?PZ)|(?P[-+])(?P\d{2}):' \ + r'(?P\d{2})' + BOSre = r'^\s*' + EOSre = r'\s*$' __allres = {'sign': SIGNre, 'century': CENTURYre, 'year': YEARre, 'month': MONTHre, 'day': DAYre, 'hour': HOURre, @@ -561,14 +559,14 @@ class DATETIMECONSTS: '(%(hour)s|-):(%(minute)s|-):(%(second)s|-)' \ '(%(timezone)s)?%(e)s' % __allres - duration = '%(b)s%(sign)sP' \ - '((?P\d+)Y)?' \ - '((?P\d+)M)?' \ - '((?P\d+)D)?' \ - '((?PT)' \ - '((?P\d+)H)?' \ - '((?P\d+)M)?' \ - '((?P\d*(?:\.\d*)?)S)?)?%(e)s' % \ + duration = r'%(b)s%(sign)sP' \ + r'((?P\d+)Y)?' \ + r'((?P\d+)M)?' \ + r'((?P\d+)D)?' \ + r'((?PT)' \ + r'((?P\d+)H)?' \ + r'((?P\d+)M)?' \ + r'((?P\d*(?:\.\d*)?)S)?)?%(e)s' % \ __allres timeDuration = duration @@ -683,7 +681,7 @@ def applyZoneOffset(months, zoffs, date, minfield, posday = 1): s = float(s) else: try: s = int(s) - except ValueError: s = long(s) + except ValueError: s = int(s) if i < fn: fn = i @@ -715,7 +713,7 @@ def applyZoneOffset(months, zoffs, date, minfield, posday = 1): try: s = int(s) except ValueError: - s = long(s) + s = int(s) r.append(s) @@ -748,7 +746,7 @@ def applyZoneOffset(months, zoffs, date, minfield, posday = 1): try: s = int(s) except ValueError: - s = long(s) + s = int(s) if i < fn: fn = i @@ -781,14 +779,14 @@ def applyZoneOffset(months, zoffs, date, minfield, posday = 1): s = [] for i in range(1, len(f)): - if d.has_key(f[i]): + if f[i] in d: s.append(r[i - 1]) if len(s) == 1: return s[0] return tuple(s) - except Exception, e: - raise Error, "invalid %s value `%s' - %s" % (kind, value, e) + except Exception as e: + raise Error("invalid %s value `%s' - %s" % (kind, value, e)) intlimits = \ { @@ -796,17 +794,17 @@ def applyZoneOffset(months, zoffs, date, minfield, posday = 1): 'non-positive-integer': (0, None, 0), 'negativeInteger': (0, None, -1), 'negative-integer': (0, None, -1), - 'long': (1, -9223372036854775808L, - 9223372036854775807L), - 'int': (0, -2147483648L, 2147483647L), + 'long': (1, -9223372036854775808, + 9223372036854775807), + 'int': (0, -2147483648, 2147483647), 'short': (0, -32768, 32767), 'byte': (0, -128, 127), 'nonNegativeInteger': (0, 0, None), 'non-negative-integer': (0, 0, None), 'positiveInteger': (0, 1, None), 'positive-integer': (0, 1, None), - 'unsignedLong': (1, 0, 18446744073709551615L), - 'unsignedInt': (0, 0, 4294967295L), + 'unsignedLong': (1, 0, 18446744073709551615), + 'unsignedInt': (0, 0, 4294967295), 'unsignedShort': (0, 0, 65535), 'unsignedByte': (0, 0, 255), } @@ -832,12 +830,10 @@ def convertType(self, d, t, attrs, config=Config): if elemtype=="ur-type": return(d) else: - newarr = map( lambda(di): - self.convertToBasicTypes(d=di, + newarr = [self.convertToBasicTypes(d=di, t = ( NS.XSD, elemtype), attrs=attrs, - config=config), - d) + config=config) for di in d] return newarr else: t = (NS.XSD, t[1]) @@ -872,26 +868,26 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): try: d = int(d) if len(attrs): - d = long(d) + d = int(d) except: - d = long(d) + d = int(d) return d - if self.intlimits.has_key (t[1]): # range-bounded integer types + if t[1] in self.intlimits: # range-bounded integer types l = self.intlimits[t[1]] try: d = int(d) - except: d = long(d) + except: d = int(d) if l[1] != None and d < l[1]: - raise UnderflowError, "%s too small" % d + raise UnderflowError("%s too small" % d) if l[2] != None and d > l[2]: - raise OverflowError, "%s too large" % d + raise OverflowError("%s too large" % d) if l[0] or len(attrs): - return long(d) + return int(d) return d if t[1] == "string": if len(attrs): - return unicode(dnn) + return str(dnn) try: return str(dnn) except: @@ -902,7 +898,7 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): return False if d in ('1', 'true'): return True - raise AttributeError, "invalid boolean value" + raise AttributeError("invalid boolean value") if t[1] in ('double','float'): l = self.floatlimits[t[1]] s = d.strip().lower() @@ -920,23 +916,23 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): if config.strict_range: if fpconst.isNaN(d): if s[0:2] != 'nan': - raise ValueError, "invalid %s: %s" % (t[1], s) + raise ValueError("invalid %s: %s" % (t[1], s)) elif fpconst.isNegInf(d): if s[0:3] != '-inf': - raise UnderflowError, "%s too small: %s" % (t[1], s) + raise UnderflowError("%s too small: %s" % (t[1], s)) elif fpconst.isPosInf(d): if s[0:2] != 'inf' and s[0:3] != '+inf': - raise OverflowError, "%s too large: %s" % (t[1], s) + raise OverflowError("%s too large: %s" % (t[1], s)) elif d < 0 and d < l[1]: - raise UnderflowError, "%s too small: %s" % (t[1], s) + raise UnderflowError("%s too small: %s" % (t[1], s)) elif d > 0 and ( d < l[0] or d > l[2] ): - raise OverflowError, "%s too large: %s" % (t[1], s) + raise OverflowError("%s too large: %s" % (t[1], s)) elif d == 0: if type(self.zerofloatre) == StringType: self.zerofloatre = re.compile(self.zerofloatre) if self.zerofloatre.search(s): - raise UnderflowError, "invalid %s: %s" % (t[1], s) + raise UnderflowError("invalid %s: %s" % (t[1], s)) return d if t[1] in ("dateTime", "date", "timeInstant", "time"): @@ -961,7 +957,7 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): else: return if t[1] == "anyURI": - return urllib.unquote(collapseWhiteSpace(d)) + return urllib.parse.unquote(collapseWhiteSpace(d)) if t[1] in ("normalizedString", "token"): return collapseWhiteSpace(d) if t[0] == NS.ENC: @@ -985,14 +981,14 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): except: pass - raise Error, "unknown or missing binary encoding" + raise Error("unknown or missing binary encoding") if t[1] == "uri": - return urllib.unquote(collapseWhiteSpace(d)) + return urllib.parse.unquote(collapseWhiteSpace(d)) if t[1] == "recurringInstant": return self.convertDateTime(d, t[1]) if t[0] in (NS.XSD2, NS.ENC): if t[1] == "uriReference": - return urllib.unquote(collapseWhiteSpace(d)) + return urllib.parse.unquote(collapseWhiteSpace(d)) if t[1] == "timePeriod": return self.convertDateTime(d, t[1]) if t[1] in ("century", "year"): @@ -1002,7 +998,7 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): return self.convertDateTime(d, t[1]) if t[0] == NS.XSD3: if t[1] == "anyURI": - return urllib.unquote(collapseWhiteSpace(d)) + return urllib.parse.unquote(collapseWhiteSpace(d)) if t[1] in ("gYearMonth", "gMonthDay"): return self.convertDateTime(d, t[1]) if t[1] == "gYear": @@ -1026,7 +1022,7 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): if t[1] == "CDATA": return collapseWhiteSpace(d) - raise UnknownTypeError, "unknown type `%s'" % (str(t[0]) + ':' + t[1]) + raise UnknownTypeError("unknown type `%s'" % (str(t[0]) + ':' + t[1])) ################################################################################ @@ -1034,11 +1030,11 @@ def convertToBasicTypes(self, d, t, attrs, config=Config): ################################################################################ def _parseSOAP(xml_str, rules = None): try: - from cStringIO import StringIO + from io import StringIO except ImportError: - from StringIO import StringIO + from io import StringIO - parser = xml.sax.make_parser() + parser = defused_sax.make_parser() t = SOAPParser(rules = rules) parser.setContentHandler(t) e = xml.sax.handler.ErrorHandler() @@ -1054,7 +1050,7 @@ def _parseSOAP(xml_str, rules = None): try: parser.parse(inpsrc) - except xml.sax.SAXParseException, e: + except xml.sax.SAXParseException as e: parser._parser = None raise e @@ -1077,9 +1073,9 @@ def parseSOAPRPC(xml_str, header = 0, body = 0, attrs = 0, rules = None): p = t.body[0] # Empty string, for RPC this translates into a void - if type(p) in (type(''), type(u'')) and p in ('', u''): + if type(p) in (type(''), type('')) and p in ('', ''): name = "Response" - for k in t.body.__dict__.keys(): + for k in list(t.body.__dict__.keys()): if k[0] != "_": name = k p = structType(name) diff --git a/SOAPpy/SOAP.py b/backend/SOAPpy/SOAP.py similarity index 61% rename from SOAPpy/SOAP.py rename to backend/SOAPpy/SOAP.py index b197507..38c7030 100644 --- a/SOAPpy/SOAP.py +++ b/backend/SOAPpy/SOAP.py @@ -4,19 +4,19 @@ """ ident = '$Id: SOAP.py 541 2004-01-31 04:20:06Z warnes $' -from version import __version__ - -from Client import * -from Config import * -from Errors import * -from NS import * -from Parser import * -from SOAPBuilder import * -from Server import * -from Types import * -from Utilities import * +from .version import __version__ + +from .Client import * +from .Config import * +from .Errors import * +from .NS import * +from .Parser import * +from .SOAPBuilder import * +from .Server import * +from .Types import * +from .Utilities import * import wstools -import WSDL +from . import WSDL from warnings import warn @@ -37,4 +37,4 @@ SOAPProxy(...) instead. -""", DeprecationWarning) +""", DeprecationWarning, stacklevel=2) diff --git a/SOAPpy/SOAPBuilder.py b/backend/SOAPpy/SOAPBuilder.py similarity index 88% rename from SOAPpy/SOAPBuilder.py rename to backend/SOAPpy/SOAPBuilder.py index f2eaee2..ec843eb 100755 --- a/SOAPpy/SOAPBuilder.py +++ b/backend/SOAPpy/SOAPBuilder.py @@ -34,16 +34,16 @@ """ ident = '$Id: SOAPBuilder.py 1498 2010-03-12 02:13:19Z pooryorick $' -from version import __version__ +from .version import __version__ import cgi from wstools.XMLname import toXMLname, fromXMLname import fpconst # SOAPpy modules -from Config import Config -from NS import NS -from Types import * +from .Config import Config +from .NS import NS +from .Types import * # Test whether this Python version has Types.BooleanType # If it doesn't have it, then False and True are serialized as integers @@ -70,7 +70,7 @@ class SOAPBuilder: NS.XSD: NS.XSD_T, NS.XSD2: NS.XSD2_T, NS.XSD3: NS.XSD3_T, NS.XSI: NS.XSI_T, NS.XSI2: NS.XSI2_T, NS.XSI3: NS.XSI3_T} - def __init__(self, args = (), kw = {}, method = None, namespace = None, + def __init__(self, args = (), kw = None, method = None, namespace = None, header = None, methodattrs = None, envelope = 1, encoding = 'UTF-8', use_refs = 0, config = Config, noroot = 0): @@ -79,7 +79,7 @@ def __init__(self, args = (), kw = {}, method = None, namespace = None, ''.encode(encoding) self.args = args - self.kw = kw + self.kw = {} if kw is None else kw self.envelope = envelope self.encoding = encoding self.method = method @@ -101,7 +101,7 @@ def __init__(self, args = (), kw = {}, method = None, namespace = None, self.noroot = noroot def build(self): - if Config.debug: print "In build." + if Config.debug: print("In build.") ns_map = {} # Cache whether typing is on or not @@ -125,7 +125,7 @@ def build(self): self.depth += 1 a = '' if self.methodattrs: - for (k, v) in self.methodattrs.items(): + for (k, v) in list(self.methodattrs.items()): a += ' %s="%s"' % (k, v) if self.namespace: # Use the namespace info handed to us @@ -145,11 +145,11 @@ def build(self): for i in args: self.dump(i, typed = typed, ns_map = ns_map) - if hasattr(self.config, "argsOrdering") and self.config.argsOrdering.has_key(self.method): + if hasattr(self.config, "argsOrdering") and self.method in self.config.argsOrdering: for k in self.config.argsOrdering.get(self.method): self.dump(self.kw.get(k), k, typed = typed, ns_map = ns_map) else: - for (k, v) in self.kw.items(): + for (k, v) in list(self.kw.items()): self.dump(v, k, typed = typed, ns_map = ns_map) except RecursionError: @@ -183,8 +183,7 @@ def build(self): self.depth -= 1 if self.envelope: - e = map (lambda ns: ' xmlns:%s="%s"\n' % (ns[1], ns[0]), - self.envns.items()) + e = [' xmlns:%s="%s"\n' % (ns[1], ns[0]) for ns in list(self.envns.items())] self.out = ['<', self._env_top] + e + ['>\n'] + \ self.out + \ @@ -198,7 +197,7 @@ def build(self): return ''.join(self.out) def gentag(self): - if Config.debug: print "In gentag." + if Config.debug: print("In gentag.") self.tcounter += 1 return "v%d" % self.tcounter @@ -214,10 +213,10 @@ def genns(self, ns_map, nsURI): else: ns = None - if ns_map.has_key(nsURI): + if nsURI in ns_map: return (ns_map[nsURI] + ':', '') - if self._env_ns.has_key(nsURI): + if nsURI in self._env_ns: ns = self.envns[nsURI] = ns_map[nsURI] = self._env_ns[nsURI] return (ns + ':', '') @@ -250,7 +249,7 @@ def checkref(self, obj, tag, ns_map): if self.depth < 2: return '' - if not self.ids.has_key(id(obj)): + if id(obj) not in self.ids: n = self.ids[id(obj)] = self.icounter self.icounter = n + 1 @@ -263,7 +262,7 @@ def checkref(self, obj, tag, ns_map): self.multirefs.append((obj, tag)) else: if self.use_refs == 0: - raise RecursionError, "Cannot serialize recursive object" + raise RecursionError("Cannot serialize recursive object") n = self.ids[id(obj)] @@ -276,22 +275,24 @@ def checkref(self, obj, tag, ns_map): # dumpers - def dump(self, obj, tag = None, typed = 1, ns_map = {}): - if Config.debug: print "In dump.", "obj=", obj + def dump(self, obj, tag = None, typed = 1, ns_map = None): + if Config.debug: print("In dump.", "obj=", obj) + ns_map = {} if ns_map is None else ns_map ns_map = ns_map.copy() self.depth += 1 if type(tag) not in (NoneType, StringType, UnicodeType): - raise KeyError, "tag must be a string or None" + raise KeyError("tag must be a string or None") self.dump_dispatch(obj, tag, typed, ns_map) self.depth -= 1 # generic dumper - def dumper(self, nsURI, obj_type, obj, tag, typed = 1, ns_map = {}, + def dumper(self, nsURI, obj_type, obj, tag, typed = 1, ns_map = None, rootattr = '', id = '', xml = '<%(tag)s%(type)s%(id)s%(attrs)s%(root)s>%(data)s\n'): - if Config.debug: print "In dumper." + if Config.debug: print("In dumper.") + ns_map = {} if ns_map is None else ns_map if nsURI == None: nsURI = self.config.typesNamespaceURI @@ -321,8 +322,9 @@ def dumper(self, nsURI, obj_type, obj, tag, typed = 1, ns_map = {}, return xml % {"tag": tag, "type": t, "data": data, "root": rootattr, "id": id, "attrs": a} - def dump_float(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_float." + def dump_float(self, obj, tag, typed = 1, ns_map = None): + if Config.debug: print("In dump_float.") + ns_map = {} if ns_map is None else ns_map tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding @@ -343,18 +345,21 @@ def dump_float(self, obj, tag, typed = 1, ns_map = {}): self.out.append(self.dumper( None, "double", obj, tag, typed, ns_map, self.genroot(ns_map))) - def dump_int(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_int." + def dump_int(self, obj, tag, typed = 1, ns_map = None): + if Config.debug: print("In dump_int.") + ns_map = {} if ns_map is None else ns_map self.out.append(self.dumper(None, 'integer', obj, tag, typed, ns_map, self.genroot(ns_map))) - def dump_bool(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_bool." + def dump_bool(self, obj, tag, typed = 1, ns_map = None): + if Config.debug: print("In dump_bool.") + ns_map = {} if ns_map is None else ns_map self.out.append(self.dumper(None, 'boolean', obj, tag, typed, ns_map, self.genroot(ns_map))) - def dump_string(self, obj, tag, typed = 0, ns_map = {}): - if Config.debug: print "In dump_string." + def dump_string(self, obj, tag, typed = 0, ns_map = None): + if Config.debug: print("In dump_string.") + ns_map = {} if ns_map is None else ns_map tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding @@ -371,8 +376,9 @@ def dump_string(self, obj, tag, typed = 0, ns_map = {}): dump_str = dump_string # For Python 2.2+ dump_unicode = dump_string - def dump_None(self, obj, tag, typed = 0, ns_map = {}): - if Config.debug: print "In dump_None." + def dump_None(self, obj, tag, typed = 0, ns_map = None): + if Config.debug: print("In dump_None.") + ns_map = {} if ns_map is None else ns_map tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding ns = self.genns(ns_map, self.config.schemaNamespaceURI)[0] @@ -382,8 +388,9 @@ def dump_None(self, obj, tag, typed = 0, ns_map = {}): dump_NoneType = dump_None # For Python 2.2+ - def dump_list(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_list.", "obj=", obj + def dump_list(self, obj, tag, typed = 1, ns_map = None): + if Config.debug: print("In dump_list.", "obj=", obj) + ns_map = {} if ns_map is None else ns_map tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding @@ -502,7 +509,8 @@ def dump_list(self, obj, tag, typed = 1, ns_map = {}): dump_tuple = dump_list - def dump_exception(self, obj, tag, typed = 0, ns_map = {}): + def dump_exception(self, obj, tag, typed = 0, ns_map = None): + ns_map = {} if ns_map is None else ns_map if isinstance(obj, faultType): # Fault cns, cdecl = self.genns(ns_map, NS.ENC) vns, vdecl = self.genns(ns_map, NS.ENV) @@ -513,8 +521,9 @@ def dump_exception(self, obj, tag, typed = 0, ns_map = {}): self.dump(obj.detail, "detail", typed, ns_map) self.out.append("\n" % vns) - def dump_dictionary(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_dictionary." + def dump_dictionary(self, obj, tag, typed = 1, ns_map = None): + if Config.debug: print("In dump_dictionary.") + ns_map = {} if ns_map is None else ns_map tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding @@ -528,7 +537,7 @@ def dump_dictionary(self, obj, tag, typed = 1, ns_map = {}): self.out.append('<%s%s%s%s>\n' % (tag, id, a, self.genroot(ns_map))) - for (k, v) in obj.items(): + for (k, v) in list(obj.items()): if k[0] != "_": self.dump(v, k, 1, ns_map) @@ -536,7 +545,8 @@ def dump_dictionary(self, obj, tag, typed = 1, ns_map = {}): dump_dict = dump_dictionary # For Python 2.2+ - def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): + def dump_dispatch(self, obj, tag, typed = 1, ns_map = None): + ns_map = {} if ns_map is None else ns_map if not tag: # If it has a name use it. if isinstance(obj, anyType) and obj._name: @@ -548,11 +558,11 @@ def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): dumpmap = ( (Exception, self.dump_exception), (arrayType, self.dump_list), - (basestring, self.dump_string), + (str, self.dump_string), (NoneType, self.dump_None), (bool, self.dump_bool), (int, self.dump_int), - (long, self.dump_int), + (int, self.dump_int), (list, self.dump_list), (tuple, self.dump_list), (dict, self.dump_dictionary), @@ -585,7 +595,7 @@ def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): tag = ns + tag self.out.append("<%s%s%s%s%s>\n" % (tag, ndecl, id, a, r)) - keylist = obj.__dict__.keys() + keylist = list(obj.__dict__.keys()) # first write out items with order information if hasattr(obj, '_keyord'): @@ -639,7 +649,7 @@ def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): # SOAPBuilder's more public interface ################################################################################ -def buildSOAP(args=(), kw={}, method=None, namespace=None, +def buildSOAP(args=(), kw=None, method=None, namespace=None, header=None, methodattrs=None, envelope=1, encoding='UTF-8', config=Config, noroot = 0): t = SOAPBuilder(args=args, kw=kw, method=method, namespace=namespace, diff --git a/SOAPpy/Server.py b/backend/SOAPpy/Server.py similarity index 85% rename from SOAPpy/Server.py rename to backend/SOAPpy/Server.py index a01a105..824bec7 100644 --- a/SOAPpy/Server.py +++ b/backend/SOAPpy/Server.py @@ -1,4 +1,4 @@ -from __future__ import nested_scopes + """ ################################################################################ @@ -43,30 +43,30 @@ """ ident = '$Id: Server.py 1468 2008-05-24 01:55:33Z warnes $' -from version import __version__ +from .version import __version__ #import xml.sax import socket import sys -import SocketServer -from types import * -import BaseHTTPServer -import thread +import socketserver +from .types import * +import http.server +import _thread # SOAPpy modules -from Parser import parseSOAPRPC -from Config import Config -from Types import faultType, voidType, simplify -from NS import NS -from SOAPBuilder import buildSOAP -from Utilities import debugHeader, debugFooter +from .Parser import parseSOAPRPC +from .Config import Config +from .Types import faultType, voidType, simplify +from .NS import NS +from .SOAPBuilder import buildSOAP +from .Utilities import debugHeader, debugFooter try: from M2Crypto import SSL except: pass ident = '$Id: Server.py 1468 2008-05-24 01:55:33Z warnes $' -from version import __version__ +from .version import __version__ ################################################################################ # Call context dictionary @@ -76,7 +76,7 @@ def GetSOAPContext(): global _contexts - return _contexts[thread.get_ident()] + return _contexts[_thread.get_ident()] ################################################################################ # Server @@ -93,7 +93,7 @@ def __init__(self, func, keywords=0, context=0): self.__name__ = func.__name__ def __call__(self, *args, **kw): - return apply(self.func,args,kw) + return self.func(*args, **kw) class SOAPContext: def __init__(self, header, body, attrs, xmldata, connection, httpheaders, @@ -111,7 +111,7 @@ def __init__(self, header, body, attrs, xmldata, connection, httpheaders, class HeaderHandler: # Initially fail out if there are any problems. def __init__(self, header, attrs): - for i in header.__dict__.keys(): + for i in list(header.__dict__.keys()): if i[0] == "_": continue @@ -123,7 +123,7 @@ def __init__(self, header, attrs): fault = 0 if fault: - raise faultType, ("%s:MustUnderstand" % NS.ENV_T, + raise faultType("%s:MustUnderstand" % NS.ENV_T, "Required Header Misunderstood", "%s" % i) @@ -133,13 +133,13 @@ def __init__(self, header, attrs): class SOAPServerBase: def get_request(self): - sock, addr = SocketServer.TCPServer.get_request(self) + sock, addr = socketserver.TCPServer.get_request(self) if self.ssl_context: sock = SSL.Connection(self.ssl_context, sock) sock._setup_ssl(addr) if sock.accept_ssl() != 1: - raise socket.error, "Couldn't accept SSL connection" + raise socket.error("Couldn't accept SSL connection") return sock, addr @@ -157,7 +157,7 @@ def registerFunction(self, function, namespace = '', funcName = None, if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] - if self.funcmap.has_key(namespace): + if namespace in self.funcmap: self.funcmap[namespace][funcName] = function else: self.funcmap[namespace] = {funcName : function} @@ -189,7 +189,7 @@ def unregisterObject(self, object, namespace = '', path = ''): del self.objmap[namespace] -class SOAPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): +class SOAPRequestHandler(http.server.BaseHTTPRequestHandler): def version_string(self): return '' + \ 'SOAPpy ' + __version__ + ' (Python ' + \ @@ -197,7 +197,7 @@ def version_string(self): def date_time_string(self): self.__last_date_time_string = \ - BaseHTTPServer.BaseHTTPRequestHandler.\ + http.server.BaseHTTPRequestHandler.\ date_time_string(self) return self.__last_date_time_string @@ -210,9 +210,8 @@ def do_POST(self): if self.server.config.dumpHeadersIn: s = 'Incoming HTTP headers' debugHeader(s) - print self.raw_requestline.strip() - print "\n".join(map (lambda x: x.strip(), - self.headers.headers)) + print(self.raw_requestline.strip()) + print("\n".join([x.strip() for x in self.headers.headers])) debugFooter(s) data = self.rfile.read(int(self.headers["Content-length"])) @@ -220,9 +219,9 @@ def do_POST(self): if self.server.config.dumpSOAPIn: s = 'Incoming SOAP' debugHeader(s) - print data, + print(data, end=' ') if data[-1] != '\n': - print + print() debugFooter(s) (r, header, body, attrs) = \ @@ -254,7 +253,7 @@ def do_POST(self): if Config.specialArgs: - for (k,v) in kw.items(): + for (k,v) in list(kw.items()): if k[0]=="v": try: @@ -281,11 +280,11 @@ def do_POST(self): # authorization method a = None - keylist = ordered_args.keys() + keylist = list(ordered_args.keys()) keylist.sort() # create list in proper order w/o names - tmp = map( lambda x: ordered_args[x], keylist) + tmp = [ordered_args[x] for x in keylist] ordered_args = tmp #print '<-> Argument Matching Yielded:' @@ -302,15 +301,15 @@ def do_POST(self): try: # First look for registered functions - if self.server.funcmap.has_key(ns) and \ - self.server.funcmap[ns].has_key(method): + if ns in self.server.funcmap and \ + method in self.server.funcmap[ns]: f = self.server.funcmap[ns][method] # look for the authorization method if self.server.config.authMethod != None: authmethod = self.server.config.authMethod - if self.server.funcmap.has_key(ns) and \ - self.server.funcmap[ns].has_key(authmethod): + if ns in self.server.funcmap and \ + authmethod in self.server.funcmap[ns]: a = self.server.funcmap[ns][authmethod] else: # Now look at registered objects @@ -356,11 +355,11 @@ def do_POST(self): # and it won't be necessary here # for now we're doing both - if "SOAPAction".lower() not in self.headers.keys() or \ + if "SOAPAction".lower() not in list(self.headers.keys()) or \ self.headers["SOAPAction"] == "\"\"": self.headers["SOAPAction"] = method - thread_id = thread.get_ident() + thread_id = _thread.get_ident() _contexts[thread_id] = SOAPContext(header, body, attrs, data, self.connection, @@ -369,7 +368,7 @@ def do_POST(self): # Do an authorization check if a != None: - if not apply(a, (), {"_SOAPContext" : + if not a(*(), **{"_SOAPContext" : _contexts[thread_id] }): raise faultType("%s:Server" % NS.ENV_T, "Authorization failed.", @@ -385,28 +384,28 @@ def do_POST(self): if Config.specialArgs: if c: named_args["_SOAPContext"] = c - fr = apply(f, ordered_args, named_args) + fr = f(*ordered_args, **named_args) elif f.keywords: # This is lame, but have to de-unicode # keywords strkw = {} - for (k, v) in kw.items(): + for (k, v) in list(kw.items()): strkw[str(k)] = v if c: strkw["_SOAPContext"] = c - fr = apply(f, (), strkw) + fr = f(*(), **strkw) elif c: - fr = apply(f, args, {'_SOAPContext':c}) + fr = f(*args, **{'_SOAPContext':c}) else: - fr = apply(f, args, {}) + fr = f(*args, **{}) else: if Config.specialArgs: - fr = apply(f, ordered_args, named_args) + fr = f(*ordered_args, **named_args) else: - fr = apply(f, args, {}) + fr = f(*args, **{}) if type(fr) == type(self) and \ @@ -421,10 +420,10 @@ def do_POST(self): config = self.server.config) # Clean up _contexts - if _contexts.has_key(thread_id): + if thread_id in _contexts: del _contexts[thread_id] - except Exception, e: + except Exception as e: import traceback info = sys.exc_info() @@ -456,7 +455,7 @@ def do_POST(self): status = 500 else: status = 200 - except faultType, e: + except faultType as e: import traceback info = sys.exc_info() try: @@ -478,7 +477,7 @@ def do_POST(self): resp = buildSOAP(e, encoding = self.server.encoding, config = self.server.config) status = 500 - except Exception, e: + except Exception as e: # internal error, report as HTTP server error if self.server.config.dumpFaultInfo: @@ -500,13 +499,13 @@ def do_POST(self): self.request_version != 'HTTP/0.9': s = 'Outgoing HTTP headers' debugHeader(s) - if self.responses.has_key(status): + if status in self.responses: s = ' ' + self.responses[status][0] else: s = '' - print "%s %d%s" % (self.protocol_version, 500, s) - print "Server:", self.version_string() - print "Date:", self.__last_date_time_string + print("%s %d%s" % (self.protocol_version, 500, s)) + print("Server:", self.version_string()) + print("Date:", self.__last_date_time_string) debugFooter(s) else: # got a valid SOAP response @@ -523,23 +522,23 @@ def do_POST(self): self.request_version != 'HTTP/0.9': s = 'Outgoing HTTP headers' debugHeader(s) - if self.responses.has_key(status): + if status in self.responses: s = ' ' + self.responses[status][0] else: s = '' - print "%s %d%s" % (self.protocol_version, status, s) - print "Server:", self.version_string() - print "Date:", self.__last_date_time_string - print "Content-type:", t - print "Content-length:", len(resp) + print("%s %d%s" % (self.protocol_version, status, s)) + print("Server:", self.version_string()) + print("Date:", self.__last_date_time_string) + print("Content-type:", t) + print("Content-length:", len(resp)) debugFooter(s) if self.server.config.dumpSOAPOut: s = 'Outgoing SOAP' debugHeader(s) - print resp, + print(resp, end=' ') if resp[-1] != '\n': - print + print() debugFooter(s) self.wfile.write(resp) @@ -572,11 +571,11 @@ def do_GET(self): if path.endswith('wsdl'): method = 'wsdl' function = namespace = None - if self.server.funcmap.has_key(namespace) \ - and self.server.funcmap[namespace].has_key(method): + if namespace in self.server.funcmap \ + and method in self.server.funcmap[namespace]: function = self.server.funcmap[namespace][method] else: - if namespace in self.server.objmap.keys(): + if namespace in list(self.server.objmap.keys()): function = self.server.objmap[namespace] l = method.split(".") for i in l: @@ -586,7 +585,7 @@ def do_GET(self): self.send_response(200) self.send_header("Content-type", 'text/plain') self.end_headers() - response = apply(function, ()) + response = function(*()) self.wfile.write(str(response)) return @@ -617,12 +616,12 @@ def do_GET(self): def log_message(self, format, *args): if self.server.log: - BaseHTTPServer.BaseHTTPRequestHandler.\ + http.server.BaseHTTPRequestHandler.\ log_message (self, format, *args) -class SOAPServer(SOAPServerBase, SocketServer.TCPServer): +class SOAPServer(SOAPServerBase, socketserver.TCPServer): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', @@ -633,8 +632,7 @@ def __init__(self, addr = ('localhost', 8000), ''.encode(encoding) if ssl_context != None and not config.SSLserver: - raise AttributeError, \ - "SSL server not supported by this Python installation" + raise AttributeError("SSL server not supported by this Python installation") self.namespace = namespace self.objmap = {} @@ -646,10 +644,10 @@ def __init__(self, addr = ('localhost', 8000), self.allow_reuse_address= 1 - SocketServer.TCPServer.__init__(self, addr, RequestHandler) + socketserver.TCPServer.__init__(self, addr, RequestHandler) -class ThreadingSOAPServer(SOAPServerBase, SocketServer.ThreadingTCPServer): +class ThreadingSOAPServer(SOAPServerBase, socketserver.ThreadingTCPServer): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', @@ -660,8 +658,7 @@ def __init__(self, addr = ('localhost', 8000), ''.encode(encoding) if ssl_context != None and not config.SSLserver: - raise AttributeError, \ - "SSL server not supported by this Python installation" + raise AttributeError("SSL server not supported by this Python installation") self.namespace = namespace self.objmap = {} @@ -673,12 +670,12 @@ def __init__(self, addr = ('localhost', 8000), self.allow_reuse_address= 1 - SocketServer.ThreadingTCPServer.__init__(self, addr, RequestHandler) + socketserver.ThreadingTCPServer.__init__(self, addr, RequestHandler) # only define class if Unix domain sockets are available if hasattr(socket, "AF_UNIX"): - class SOAPUnixSocketServer(SOAPServerBase, SocketServer.UnixStreamServer): + class SOAPUnixSocketServer(SOAPServerBase, socketserver.UnixStreamServer): def __init__(self, addr = 8000, RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', @@ -689,8 +686,7 @@ def __init__(self, addr = 8000, ''.encode(encoding) if ssl_context != None and not config.SSLserver: - raise AttributeError, \ - "SSL server not supported by this Python installation" + raise AttributeError("SSL server not supported by this Python installation") self.namespace = namespace self.objmap = {} @@ -702,5 +698,5 @@ def __init__(self, addr = 8000, self.allow_reuse_address= 1 - SocketServer.UnixStreamServer.__init__(self, str(addr), RequestHandler) + socketserver.UnixStreamServer.__init__(self, str(addr), RequestHandler) diff --git a/SOAPpy/Types.py b/backend/SOAPpy/Types.py similarity index 80% rename from SOAPpy/Types.py rename to backend/SOAPpy/Types.py index 8cfee53..c6928a7 100644 --- a/SOAPpy/Types.py +++ b/backend/SOAPpy/Types.py @@ -1,4 +1,4 @@ -from __future__ import nested_scopes + """ ################################################################################ @@ -36,22 +36,22 @@ """ ident = '$Id: Types.py 1496 2010-03-04 23:46:17Z pooryorick $' -from version import __version__ +from .version import __version__ -import UserList +import collections import base64 import cgi -import urllib +import urllib.request, urllib.parse, urllib.error import copy import re import time -from types import * +from .types import * # SOAPpy modules -from Errors import * -from NS import NS -from Utilities import encodeHexString, cleanDate -from Config import Config +from .Errors import * +from .NS import NS +from .Utilities import encodeHexString, cleanDate +from .Config import Config ############################################################################### # Utility functions @@ -69,7 +69,7 @@ class anyType: def __init__(self, data = None, name = None, typed = 1, attrs = None): if self.__class__ == anyType: - raise Error, "anyType can't be instantiated directly" + raise Error("anyType can't be instantiated directly") if type(name) in (ListType, TupleType): self._ns, self._name = name @@ -104,7 +104,7 @@ def _marshalData(self): def _marshalAttrs(self, ns_map, builder): a = '' - for attr, value in self._attrs.items(): + for attr, value in list(self._attrs.items()): ns, n = builder.genns(ns_map, attr[0]) a += n + ' %s%s="%s"' % \ (ns, attr[1], cgi.escape(str(value), 1)) @@ -117,13 +117,13 @@ def _fixAttr(self, attr): elif type(attr) == ListType: attr = tuple(attr) elif type(attr) != TupleType: - raise AttributeError, "invalid attribute type" + raise AttributeError("invalid attribute type") if len(attr) != 2: - raise AttributeError, "invalid attribute length" + raise AttributeError("invalid attribute length") if type(attr[0]) not in (NoneType, StringType, UnicodeType): - raise AttributeError, "invalid attribute namespace URI type" + raise AttributeError("invalid attribute namespace URI type") return attr @@ -139,7 +139,7 @@ def _setAttr(self, attr, value): attr = self._fixAttr(attr) if type(value) is StringType: - value = unicode(value) + value = str(value) self._attrs[attr] = value @@ -156,9 +156,9 @@ def _setAttrs(self, attrs): elif isinstance(attrs, anyType): d = attrs._attrs else: - raise AttributeError, "invalid attribute type" + raise AttributeError("invalid attribute type") - for attr, value in d.items(): + for attr, value in list(d.items()): self._setAttr(attr, value) def _setMustUnderstand(self, val): @@ -183,8 +183,7 @@ def _validNamespaceURI(self, URI, strict): return URI if not strict: return self._ns - raise AttributeError, \ - "not a valid namespace for type %s" % self._type + raise AttributeError("not a valid namespace for type %s" % self._type) class voidType(anyType): pass @@ -192,10 +191,10 @@ class voidType(anyType): class stringType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type:" % self._type + raise AttributeError("invalid %s type:" % self._type) return data @@ -222,16 +221,16 @@ class tokenType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) if type(self.__invalidre) == StringType: self.__invalidre = re.compile(self.__invalidre) if self.__invalidre.search(data): - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -241,16 +240,16 @@ class normalizedStringType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) if type(self.__invalidre) == StringType: self.__invalidre = re.compile(self.__invalidre) if self.__invalidre.search(data): - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -268,33 +267,33 @@ def _marshalData(self): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if data in (0, '0', 'false', ''): return 0 if data in (1, '1', 'true'): return 1 - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) class decimalType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType, FloatType): - raise Error, "invalid %s value" % self._type + raise Error("invalid %s value" % self._type) return data class floatType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType, FloatType) or \ data < -3.4028234663852886E+38 or \ data > 3.4028234663852886E+38: - raise ValueError, "invalid %s value: %s" % (self._type, repr(data)) + raise ValueError("invalid %s value: %s" % (self._type, repr(data))) return data @@ -304,12 +303,12 @@ def _marshalData(self): class doubleType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType, FloatType) or \ data < -1.7976931348623158E+308 or \ data > 1.7976931348623157E+308: - raise ValueError, "invalid %s value: %s" % (self._type, repr(data)) + raise ValueError("invalid %s value: %s" % (self._type, repr(data))) return data @@ -321,7 +320,7 @@ class durationType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) try: # A tuple or a scalar is OK, but make them into a list @@ -332,7 +331,7 @@ def _checkValueSpace(self, data): data = [data] if len(data) > 6: - raise Exception, "too many values" + raise Exception("too many values") # Now check the types of all the components, and find # the first nonzero element along the way. @@ -346,7 +345,7 @@ def _checkValueSpace(self, data): if type(data[i]) not in \ (IntType, LongType, FloatType): - raise Exception, "element %d a bad type" % i + raise Exception("element %d a bad type" % i) if data[i] and f == -1: f = i @@ -366,13 +365,11 @@ def _checkValueSpace(self, data): for i in range(f, len(data)): if data[i]: if d != -1: - raise Exception, \ - "all except the last nonzero element must be " \ - "integers" + raise Exception("all except the last nonzero element must be " \ + "integers") if data[i] < 0 and i > f: - raise Exception, \ - "only the first nonzero element can be negative" - elif data[i] != long(data[i]): + raise Exception("only the first nonzero element can be negative") + elif data[i] != int(data[i]): d = i # Pad the list on the left if necessary. @@ -389,8 +386,8 @@ def _checkValueSpace(self, data): self.__firstnonzero = f self.__decimal = d - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -414,7 +411,7 @@ def _marshalData(self): if self.__decimal == i: s += "%g" % abs(d[i]) else: - s += "%d" % long(abs(d[i])) + s += "%d" % int(abs(d[i])) s += ['Y', 'M', 'D', 'H', 'M', 'S'][i] self._cache = s @@ -440,17 +437,17 @@ def _checkValueSpace(self, data): data[5] += f elif type(data) in (ListType, TupleType): if len(data) < 6: - raise Exception, "not enough values" + raise Exception("not enough values") if len(data) > 9: - raise Exception, "too many values" + raise Exception("too many values") data = list(data[:6]) cleanDate(data) else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -484,9 +481,9 @@ def _checkValueSpace(self, data): data[5] += f elif type(data) in (ListType, TupleType): if len(data) < 1: - raise Exception, "not enough values" + raise Exception("not enough values") if len(data) > 9: - raise Exception, "too many values" + raise Exception("too many values") data = list(data[:6]) @@ -498,17 +495,16 @@ def _checkValueSpace(self, data): for i in range(f): if data[i] == None: if f < i: - raise Exception, \ - "only leftmost elements can be none" + raise Exception("only leftmost elements can be none") else: f = i break cleanDate(data, f) else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -572,7 +568,7 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[3:6] elif len(data) > 3: - raise Exception, "too many values" + raise Exception("too many values") data = [None, None, None] + list(data) @@ -583,9 +579,9 @@ def _checkValueSpace(self, data): data = data[3:] else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -616,7 +612,7 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[0:3] elif len(data) > 3: - raise Exception, "too many values" + raise Exception("too many values") data = list(data) @@ -629,9 +625,9 @@ def _checkValueSpace(self, data): data = data[:3] else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -659,7 +655,7 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[0:2] elif len(data) > 2: - raise Exception, "too many values" + raise Exception("too many values") data = list(data) @@ -672,9 +668,9 @@ def _checkValueSpace(self, data): data = data[:2] else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -703,24 +699,24 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[0:1] elif len(data) < 1: - raise Exception, "too few values" + raise Exception("too few values") elif len(data) > 1: - raise Exception, "too many values" + raise Exception("too many values") if type(data[0]) == FloatType: try: s = int(data[0]) - except: s = long(data[0]) + except: s = int(data[0]) if s != data[0]: - raise Exception, "not integral" + raise Exception("not integral") data = [s] elif type(data[0]) not in (IntType, LongType): - raise Exception, "bad type" + raise Exception("bad type") else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return data[0] @@ -749,24 +745,24 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[0:1] / 100 elif len(data) < 1: - raise Exception, "too few values" + raise Exception("too few values") elif len(data) > 1: - raise Exception, "too many values" + raise Exception("too many values") if type(data[0]) == FloatType: try: s = int(data[0]) - except: s = long(data[0]) + except: s = int(data[0]) if s != data[0]: - raise Exception, "not integral" + raise Exception("not integral") data = [s] elif type(data[0]) not in (IntType, LongType): - raise Exception, "bad type" + raise Exception("bad type") else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return data[0] @@ -797,7 +793,7 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[0:2] elif len(data) > 2: - raise Exception, "too many values" + raise Exception("too many values") data = list(data) @@ -810,9 +806,9 @@ def _checkValueSpace(self, data): data = data[1:3] else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return tuple(data) @@ -839,27 +835,27 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[1:2] elif len(data) < 1: - raise Exception, "too few values" + raise Exception("too few values") elif len(data) > 1: - raise Exception, "too many values" + raise Exception("too many values") if type(data[0]) == FloatType: try: s = int(data[0]) - except: s = long(data[0]) + except: s = int(data[0]) if s != data[0]: - raise Exception, "not integral" + raise Exception("not integral") data = [s] elif type(data[0]) not in (IntType, LongType): - raise Exception, "bad type" + raise Exception("bad type") if data[0] < 1 or data[0] > 12: - raise Exception, "bad value" + raise Exception("bad value") else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return data[0] @@ -886,27 +882,27 @@ def _checkValueSpace(self, data): if len(data) == 9: data = data[2:3] elif len(data) < 1: - raise Exception, "too few values" + raise Exception("too few values") elif len(data) > 1: - raise Exception, "too many values" + raise Exception("too many values") if type(data[0]) == FloatType: try: s = int(data[0]) - except: s = long(data[0]) + except: s = int(data[0]) if s != data[0]: - raise Exception, "not integral" + raise Exception("not integral") data = [s] elif type(data[0]) not in (IntType, LongType): - raise Exception, "bad type" + raise Exception("bad type") if data[0] < 1 or data[0] > 31: - raise Exception, "bad value" + raise Exception("bad value") else: - raise Exception, "invalid type" - except Exception, e: - raise ValueError, "invalid %s value - %s" % (self._type, e) + raise Exception("invalid type") + except Exception as e: + raise ValueError("invalid %s value - %s" % (self._type, e)) return data[0] @@ -924,10 +920,10 @@ class hexBinaryType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) return data @@ -942,10 +938,10 @@ class base64BinaryType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) return data @@ -979,10 +975,10 @@ def _marshalData(self): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) return data @@ -991,7 +987,7 @@ def _setAttr(self, attr, value): if attr[1] == 'encoding': if attr[0] != None or value not in ('base64', 'hex'): - raise AttributeError, "invalid encoding" + raise AttributeError("invalid encoding") self._cache = None @@ -1003,16 +999,16 @@ class anyURIType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (StringType, UnicodeType): - raise AttributeError, "invalid %s type" % self._type + raise AttributeError("invalid %s type" % self._type) return data def _marshalData(self): if self._cache == None: - self._cache = urllib.quote(self._data) + self._cache = urllib.parse.quote(self._data) return self._cache @@ -1026,21 +1022,21 @@ class NOTATIONType(anyType): def __init__(self, data, name = None, typed = 1, attrs = None): if self.__class__ == NOTATIONType: - raise Error, "a NOTATION can't be instantiated directly" + raise Error("a NOTATION can't be instantiated directly") anyType.__init__(self, data, name, typed, attrs) class ENTITIESType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) in (StringType, UnicodeType): return (data,) if type(data) not in (ListType, TupleType) or \ - filter (lambda x: type(x) not in (StringType, UnicodeType), data): - raise AttributeError, "invalid %s type" % self._type + [x for x in data if type(x) not in (StringType, UnicodeType)]: + raise AttributeError("invalid %s type" % self._type) return data @@ -1053,10 +1049,10 @@ class NMTOKENSType(ENTITIESType): pass class integerType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType): - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1065,10 +1061,10 @@ class nonPositiveIntegerType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or data > 0: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1083,10 +1079,10 @@ class negativeIntegerType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or data >= 0: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1101,12 +1097,12 @@ class longType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ - data < -9223372036854775808L or \ - data > 9223372036854775807L: - raise ValueError, "invalid %s value" % self._type + data < -9223372036854775808 or \ + data > 9223372036854775807: + raise ValueError("invalid %s value" % self._type) return data @@ -1115,12 +1111,12 @@ class intType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ - data < -2147483648L or \ - data > 2147483647L: - raise ValueError, "invalid %s value" % self._type + data < -2147483648 or \ + data > 2147483647: + raise ValueError("invalid %s value" % self._type) return data @@ -1129,12 +1125,12 @@ class shortType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < -32768 or \ data > 32767: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1143,12 +1139,12 @@ class byteType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < -128 or \ data > 127: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1157,10 +1153,10 @@ class nonNegativeIntegerType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or data < 0: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1175,12 +1171,12 @@ class unsignedLongType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < 0 or \ - data > 18446744073709551615L: - raise ValueError, "invalid %s value" % self._type + data > 18446744073709551615: + raise ValueError("invalid %s value" % self._type) return data @@ -1189,12 +1185,12 @@ class unsignedIntType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < 0 or \ - data > 4294967295L: - raise ValueError, "invalid %s value" % self._type + data > 4294967295: + raise ValueError("invalid %s value" % self._type) return data @@ -1203,12 +1199,12 @@ class unsignedShortType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 65535: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1217,12 +1213,12 @@ class unsignedByteType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 255: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1231,10 +1227,10 @@ class positiveIntegerType(anyType): def _checkValueSpace(self, data): if data == None: - raise ValueError, "must supply initial %s value" % self._type + raise ValueError("must supply initial %s value" % self._type) if type(data) not in (IntType, LongType) or data <= 0: - raise ValueError, "invalid %s value" % self._type + raise ValueError("invalid %s value" % self._type) return data @@ -1249,7 +1245,7 @@ def _typeName(self): class compoundType(anyType): def __init__(self, data = None, name = None, typed = 1, attrs = None): if self.__class__ == compoundType: - raise Error, "a compound can't be instantiated directly" + raise Error("a compound can't be instantiated directly") anyType.__init__(self, data, name, typed, attrs) self._keyord = [] @@ -1261,7 +1257,7 @@ def _aslist(self, item=None): if item is not None: return self.__dict__[self._keyord[item]] else: - return map( lambda x: self.__dict__[x], self._keyord) + return [self.__dict__[x] for x in self._keyord] def _asdict(self, item=None, encoding=Config.dict_encoding): if item is not None: @@ -1273,7 +1269,7 @@ def _asdict(self, item=None, encoding=Config.dict_encoding): def fun(x): retval[x.encode(encoding)] = self.__dict__[x] if hasattr(self, '_keyord'): - map( fun, self._keyord) + list(map( fun, self._keyord)) else: for name in dir(self): if isPublic(name): @@ -1290,11 +1286,11 @@ def __getitem__(self, item): def __len__(self): return len(self._keyord) - def __nonzero__(self): + def __bool__(self): return 1 def _keys(self): - return filter(lambda x: x[0] != '_', self.__dict__.keys()) + return [x for x in list(self.__dict__.keys()) if x[0] != '_'] def _addItem(self, name, value, attrs = None): @@ -1322,7 +1318,8 @@ def _placeItem(self, name, value, pos, subpos = 0, attrs = None): self._keyord.append(name) - def _getItemAsList(self, name, default = []): + def _getItemAsList(self, name, default = None): + default = [] if default is None else default try: d = self.__dict__[name] except: @@ -1353,15 +1350,15 @@ class bodyType(structType): def __init__(self, data = None, typed = 1, attrs = None): structType.__init__(self, data, "Body", typed, attrs) -class arrayType(UserList.UserList, compoundType): +class arrayType(collections.UserList, compoundType): def __init__(self, data = None, name = None, attrs = None, offset = 0, rank = None, asize = 0, elemsname = None): if data: if type(data) not in (ListType, TupleType): - raise Error, "Data must be a sequence" + raise Error("Data must be a sequence") - UserList.UserList.__init__(self, data) + collections.UserList.__init__(self, data) compoundType.__init__(self, data, name, 0, attrs) self._elemsname = elemsname or "item" @@ -1386,7 +1383,7 @@ def __init__(self, data = None, name = None, attrs = None, if asize in ('', None): asize = '0' - self._dims = map (lambda x: int(x), str(asize).split(',')) + self._dims = [int(x) for x in str(asize).split(',')] self._dims.reverse() # It's easier to work with this way self._poss = [0] * len(self._dims) # This will end up # reversed too @@ -1394,7 +1391,7 @@ def __init__(self, data = None, name = None, attrs = None, for i in range(len(self._dims)): if self._dims[i] < 0 or \ self._dims[i] == 0 and len(self._dims) > 1: - raise TypeError, "invalid Array dimensions" + raise TypeError("invalid Array dimensions") if offset > 0: self._poss[i] = offset % self._dims[i] @@ -1403,7 +1400,7 @@ def __init__(self, data = None, name = None, attrs = None, # Don't break out of the loop if offset is 0 so we test all the # dimensions for > 0. if offset: - raise AttributeError, "invalid Array offset" + raise AttributeError("invalid Array offset") a = [None] * self._dims[0] @@ -1433,7 +1430,7 @@ def _asdict(self, item=None, encoding=Config.dict_encoding): retval = {} def fun(x): retval[str(x).encode(encoding)] = self.data[x] - map( fun, range(len(self.data)) ) + list(map( fun, list(range(len(self.data))) )) return retval def __getitem__(self, item): @@ -1445,32 +1442,31 @@ def __getitem__(self, item): def __len__(self): return len(self.data) - def __nonzero__(self): + def __bool__(self): return 1 def __str__(self): return anyType.__str__(self) + ": " + str(self._aslist()) def _keys(self): - return filter(lambda x: x[0] != '_', self.__dict__.keys()) + return [x for x in list(self.__dict__.keys()) if x[0] != '_'] def _addItem(self, name, value, attrs): if self._full: - raise ValueError, "Array is full" + raise ValueError("Array is full") pos = attrs.get((NS.ENC, 'position')) if pos != None: if self._posstate == 0: - raise AttributeError, \ - "all elements in a sparse Array must have a " \ - "position attribute" + raise AttributeError("all elements in a sparse Array must have a " \ + "position attribute") self._posstate = 1 try: if pos[0] == '[' and pos[-1] == ']': - pos = map (lambda x: int(x), pos[1:-1].split(',')) + pos = [int(x) for x in pos[1:-1].split(',')] pos.reverse() if len(pos) == 1: @@ -1498,13 +1494,11 @@ def _addItem(self, name, value, attrs): else: raise Exception except: - raise AttributeError, \ - "invalid Array element position %s" % str(pos) + raise AttributeError("invalid Array element position %s" % str(pos)) else: if self._posstate == 1: - raise AttributeError, \ - "only elements in a sparse Array may have a " \ - "position attribute" + raise AttributeError("only elements in a sparse Array may have a " \ + "position attribute") self._posstate = 0 @@ -1550,7 +1544,7 @@ def _placeItem(self, name, value, pos, subpos, attrs = None): break if self._dims[i] != 0 and pos: - raise Error, "array index out of range" + raise Error("array index out of range") a = self.data @@ -1683,12 +1677,12 @@ def simplify(object, level=0): return data elif isinstance( object, compoundType ) or isinstance(object, structType): data = object._asdict() - for k in data.keys(): + for k in list(data.keys()): if isPublic(k): data[k] = simplify(data[k], level=level+1) return data elif type(object)==DictType: - for k in object.keys(): + for k in list(object.keys()): if isPublic(k): object[k] = simplify(object[k]) return object @@ -1726,16 +1720,16 @@ def simplify_contents(object, level=0): object[k] = simplify(data[k], level=level+1) elif isinstance(object, structType): data = object._asdict() - for k in data.keys(): + for k in list(data.keys()): if isPublic(k): setattr(object, k, simplify(data[k], level=level+1)) elif isinstance( object, compoundType ) : data = object._asdict() - for k in data.keys(): + for k in list(data.keys()): if isPublic(k): object[k] = simplify(data[k], level=level+1) elif type(object)==DictType: - for k in object.keys(): + for k in list(object.keys()): if isPublic(k): object[k] = simplify(object[k]) elif type(object)==list: @@ -1744,4 +1738,3 @@ def simplify_contents(object, level=0): return object - diff --git a/SOAPpy/URLopener.py b/backend/SOAPpy/URLopener.py similarity index 82% rename from SOAPpy/URLopener.py rename to backend/SOAPpy/URLopener.py index 2c04c86..4b733a5 100644 --- a/SOAPpy/URLopener.py +++ b/backend/SOAPpy/URLopener.py @@ -2,10 +2,10 @@ authentication""" ident = '$Id: URLopener.py 541 2004-01-31 04:20:06Z warnes $' -from version import __version__ +from .version import __version__ -from Config import Config -from urllib import FancyURLopener +from .Config import Config +from urllib.request import FancyURLopener class URLopener(FancyURLopener): diff --git a/SOAPpy/Utilities.py b/backend/SOAPpy/Utilities.py similarity index 84% rename from SOAPpy/Utilities.py rename to backend/SOAPpy/Utilities.py index 1b163de..900a156 100644 --- a/SOAPpy/Utilities.py +++ b/backend/SOAPpy/Utilities.py @@ -34,21 +34,21 @@ """ ident = '$Id: Utilities.py 1298 2006-11-07 00:54:15Z sanxiyn $' -from version import __version__ +from .version import __version__ import re import string import sys -from types import * +from .types import * # SOAPpy modules -from Errors import * +from .Errors import * ################################################################################ # Utility infielders ################################################################################ def collapseWhiteSpace(s): - return re.sub('\s+', ' ', s).strip() + return re.sub(r'\s+', ' ', s).strip() def decodeHexString(data): conv = { @@ -84,8 +84,7 @@ def decodeHexString(data): try: c = conv[c] except KeyError: - raise ValueError, \ - "invalid hex string character `%s'" % c + raise ValueError("invalid hex string character `%s'" % c) if low: bin += chr(high * 16 + c) @@ -97,12 +96,11 @@ def decodeHexString(data): i += 1 if low: - raise ValueError, "invalid hex string length" + raise ValueError("invalid hex string length") while i < len(data): if data[i] not in string.whitespace: - raise ValueError, \ - "invalid hex string character `%s'" % c + raise ValueError("invalid hex string character `%s'" % c) i += 1 @@ -127,7 +125,7 @@ def cleanDate(d, first = 0): names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds') if len(d) != 6: - raise ValueError, "date must have 6 elements" + raise ValueError("date must have 6 elements") for i in range(first, 6): s = d[i] @@ -139,38 +137,38 @@ def cleanDate(d, first = 0): except OverflowError: if i > 0: raise - s = long(s) + s = int(s) if s != d[i]: - raise ValueError, "%s must be integral" % names[i] + raise ValueError("%s must be integral" % names[i]) d[i] = s elif type(s) == LongType: try: s = int(s) except: pass elif type(s) != IntType: - raise TypeError, "%s isn't a valid type" % names[i] + raise TypeError("%s isn't a valid type" % names[i]) if i == first and s < 0: continue if ranges[i] != None and \ (s < ranges[i][0] or ranges[i][1] < s): - raise ValueError, "%s out of range" % names[i] + raise ValueError("%s out of range" % names[i]) if first < 6 and d[5] >= 61: - raise ValueError, "seconds out of range" + raise ValueError("seconds out of range") if first < 2: leap = first < 1 and leapMonth(d[0], d[1]) if d[2] > months[d[1]] + leap: - raise ValueError, "day out of range" + raise ValueError("day out of range") def debugHeader(title): s = '*** ' + title + ' ' - print s + ('*' * (72 - len(s))) + print(s + ('*' * (72 - len(s)))) def debugFooter(title): - print '*' * 72 + print('*' * 72) sys.stdout.flush() diff --git a/SOAPpy/WSDL.py b/backend/SOAPpy/WSDL.py similarity index 63% rename from SOAPpy/WSDL.py rename to backend/SOAPpy/WSDL.py index 84f7d3f..47ae7ac 100644 --- a/SOAPpy/WSDL.py +++ b/backend/SOAPpy/WSDL.py @@ -3,14 +3,24 @@ Rudimentary support.""" ident = '$Id: WSDL.py 1467 2008-05-16 23:32:51Z warnes $' -from version import __version__ +from .version import __version__ import wstools import xml -from Errors import Error -from Client import SOAPProxy, SOAPAddress -from Config import Config -import urllib +from .Errors import Error +from .Client import SOAPProxy, SOAPAddress +from .Config import Config +import urllib.request, urllib.parse, urllib.error + + +def _open_http_wsdl(url, config=None): + parsed = urllib.parse.urlparse(url) + if parsed.scheme not in ('http', 'https'): + raise IOError('Unsupported WSDL URL scheme: %s' % (parsed.scheme or '')) + # Bandit B310: scheme is validated above before opening the URL. + if config is not None: + return urllib.request.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(url) # nosec B310 + return urllib.request.urlopen(url) # nosec B310 class Proxy: """WSDL Proxy. @@ -41,14 +51,14 @@ def __init__(self, wsdlsource, config=Config, **kw ): # From Mark Pilgrim's "Dive Into Python" toolkit.py--open anything. if self.wsdl is None and hasattr(wsdlsource, "read"): - print 'stream:', wsdlsource + print('stream:', wsdlsource) try: self.wsdl = reader.loadFromStream(wsdlsource) - except xml.parsers.expat.ExpatError, e: - newstream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) + except xml.parsers.expat.ExpatError as e: + newstream = _open_http_wsdl(wsdlsource, config) buf = newstream.readlines() - raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ - (wsdlsource, "\t".join(buf)) + raise Error("Unable to parse WSDL file at %s: \n\t%s" % \ + (wsdlsource, "\t".join(buf))) # NOT TESTED (as of April 17, 2003) @@ -59,29 +69,30 @@ def __init__(self, wsdlsource, config=Config, **kw ): if self.wsdl is None: try: - file(wsdlsource) + with open(wsdlsource): + pass self.wsdl = reader.loadFromFile(wsdlsource) #print 'file' except (IOError, OSError): pass - except xml.parsers.expat.ExpatError, e: - newstream = urllib.urlopen(wsdlsource) + except xml.parsers.expat.ExpatError as e: + newstream = _open_http_wsdl(wsdlsource) buf = newstream.readlines() - raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ - (wsdlsource, "\t".join(buf)) + raise Error("Unable to parse WSDL file at %s: \n\t%s" % \ + (wsdlsource, "\t".join(buf))) if self.wsdl is None: try: - stream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) + stream = _open_http_wsdl(wsdlsource, config) self.wsdl = reader.loadFromStream(stream, wsdlsource) except (IOError, OSError): pass - except xml.parsers.expat.ExpatError, e: - newstream = urllib.urlopen(wsdlsource) + except xml.parsers.expat.ExpatError as e: + newstream = _open_http_wsdl(wsdlsource) buf = newstream.readlines() - raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ - (wsdlsource, "\t".join(buf)) + raise Error("Unable to parse WSDL file at %s: \n\t%s" % \ + (wsdlsource, "\t".join(buf))) if self.wsdl is None: - import StringIO + import io self.wsdl = reader.loadFromString(str(wsdlsource)) #print 'string' @@ -102,7 +113,7 @@ def __init__(self, wsdlsource, config=Config, **kw ): def __str__(self): s = '' - for method in self.methods.values(): + for method in list(self.methods.values()): s += str(method) return s @@ -111,7 +122,7 @@ def __getattr__(self, name): Raises AttributeError is method name is not found.""" - if not self.methods.has_key(name): raise AttributeError, name + if name not in self.methods: raise AttributeError(name) callinfo = self.methods[name] self.soapproxy.proxy = SOAPAddress(callinfo.location) @@ -120,18 +131,17 @@ def __getattr__(self, name): return self.soapproxy.__getattr__(name) def show_methods(self): - for key in self.methods.keys(): + for key in list(self.methods.keys()): method = self.methods[key] - print "Method Name:", key.ljust(15) - print + print("Method Name:", key.ljust(15)) + print() inps = method.inparams for parm in range(len(inps)): details = inps[parm] - print " In #%d: %s (%s)" % (parm, details.name, details.type) - print + print(" In #%d: %s (%s)" % (parm, details.name, details.type)) + print() outps = method.outparams for parm in range(len(outps)): details = outps[parm] - print " Out #%d: %s (%s)" % (parm, details.name, details.type) - print - + print(" Out #%d: %s (%s)" % (parm, details.name, details.type)) + print() diff --git a/backend/SOAPpy/__init__.py b/backend/SOAPpy/__init__.py new file mode 100644 index 0000000..35d6d22 --- /dev/null +++ b/backend/SOAPpy/__init__.py @@ -0,0 +1,15 @@ + +ident = '$Id: __init__.py 541 2004-01-31 04:20:06Z warnes $' +from .version import __version__ + +from .Client import * +from .Config import * +from .Errors import * +from .NS import * +from .Parser import * +from .SOAPBuilder import * +from .Server import * +from .Types import * +from .Utilities import * +import wstools +from . import WSDL diff --git a/SOAPpy/version.py b/backend/SOAPpy/version.py similarity index 100% rename from SOAPpy/version.py rename to backend/SOAPpy/version.py diff --git a/backend/conf/requirements-development.txt b/backend/conf/requirements-development.txt new file mode 100644 index 0000000..450c71b --- /dev/null +++ b/backend/conf/requirements-development.txt @@ -0,0 +1,5 @@ +ipdb>=0.13.13,<1 +ipython>=9.13,<10 +ruff>=0.15.14,<1 +pip-audit>=2.10,<3 +bandit>=1.9.3,<2 diff --git a/backend/conf/requirements-testing.txt b/backend/conf/requirements-testing.txt new file mode 100644 index 0000000..8174c14 --- /dev/null +++ b/backend/conf/requirements-testing.txt @@ -0,0 +1,2 @@ +coverage>=7.14,<8 +unittest-xml-reporting>=4.0,<5 diff --git a/configure b/backend/configure similarity index 100% rename from configure rename to backend/configure diff --git a/dev/CLEAN b/backend/dev/CLEAN similarity index 100% rename from dev/CLEAN rename to backend/dev/CLEAN diff --git a/dev/COUNT b/backend/dev/COUNT similarity index 100% rename from dev/COUNT rename to backend/dev/COUNT diff --git a/dev/COVERAGE_REPORT b/backend/dev/COVERAGE_REPORT similarity index 100% rename from dev/COVERAGE_REPORT rename to backend/dev/COVERAGE_REPORT diff --git a/dev/COVERAGE_TEST b/backend/dev/COVERAGE_TEST similarity index 100% rename from dev/COVERAGE_TEST rename to backend/dev/COVERAGE_TEST diff --git a/dev/FIND b/backend/dev/FIND similarity index 100% rename from dev/FIND rename to backend/dev/FIND diff --git a/dev/LINT b/backend/dev/LINT similarity index 100% rename from dev/LINT rename to backend/dev/LINT diff --git a/dev/TEST b/backend/dev/TEST similarity index 100% rename from dev/TEST rename to backend/dev/TEST diff --git a/backend/dev/cache_benchmark.py b/backend/dev/cache_benchmark.py new file mode 100644 index 0000000..8d1f74f --- /dev/null +++ b/backend/dev/cache_benchmark.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +"""Benchmark small deterministic caches used by the Defcoin P2Pool port.""" + +from __future__ import annotations + +import statistics +import sys +import time +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + +from p2pool import data as p2pool_data +from p2pool.bitcoin import data as bitcoin_data +from p2pool.networks import defcoin + + +def _time_calls(func, values, rounds): + start = time.perf_counter() + checksum = 0 + for _ in range(rounds): + for value in values: + result = func(value) + if isinstance(result, float): + checksum ^= int(result) + else: + checksum ^= int(result) + return time.perf_counter() - start, checksum + + +def _time_tuple_calls(func, values, rounds): + start = time.perf_counter() + checksum = 0 + for _ in range(rounds): + for args in values: + result = func(*args) + if isinstance(result, (str, bytes)): + checksum ^= len(result) + elif isinstance(result, tuple): + checksum ^= int(result[0]) + elif isinstance(result, float): + checksum ^= int(result) + else: + checksum ^= int(result) + return time.perf_counter() - start, checksum + + +def _format_speedup(uncached, cached): + if cached == 0: + return "inf" + return "%.2fx" % (uncached / cached) + + +def main(): + targets = [ + 2**256 // divisor - 1 + for divisor in (2**20, 2**22, 2**24, 2**26, 2**28, 2**30, 2**32, 2**34) + ] + difficulties = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0] + address_hashes = [0x1000000000000000000000000000000000000000 + i for i in range(8)] + address_args = [(value, defcoin.PARENT.ADDRESS_VERSION, -1, defcoin.PARENT) for value in address_hashes] + addresses = [ + bitcoin_data.pubkey_hash_to_address(value, defcoin.PARENT.ADDRESS_VERSION, -1, defcoin.PARENT) + for value in address_hashes + ] + script_args = [(address, defcoin.PARENT) for address in addresses] + + cases = [ + ("target_to_average_attempts", bitcoin_data.target_to_average_attempts, targets, 20000), + ("target_to_difficulty", bitcoin_data.target_to_difficulty, targets, 20000), + ("difficulty_to_target", bitcoin_data.difficulty_to_target, difficulties, 20000), + ] + + print("cache benchmark: repeated deterministic calculations") + for name, cached_func, values, rounds in cases: + cached_func.cache_clear() + uncached_func = cached_func.__wrapped__ + uncached_times = [] + cached_times = [] + uncached_checksum = cached_checksum = None + for _ in range(5): + elapsed, uncached_checksum = _time_calls(uncached_func, values, rounds) + uncached_times.append(elapsed) + cached_func.cache_clear() + elapsed, cached_checksum = _time_calls(cached_func, values, rounds) + cached_times.append(elapsed) + assert uncached_checksum == cached_checksum + uncached = statistics.median(uncached_times) + cached = statistics.median(cached_times) + print( + f"{name} uncached={uncached:.6f}s cached={cached:.6f}s " + f"speedup={_format_speedup(uncached, cached)} cache={cached_func.cache_info()}" + ) + + tuple_cases = [ + ("pubkey_hash_to_address", bitcoin_data.pubkey_hash_to_address, address_args, 20000), + ("address_to_script2", bitcoin_data.address_to_script2, script_args, 20000), + ] + for name, cached_func, values, rounds in tuple_cases: + cached_func.cache_clear() + uncached_func = cached_func.__wrapped__ + uncached_times = [] + cached_times = [] + uncached_checksum = cached_checksum = None + for _ in range(5): + elapsed, uncached_checksum = _time_tuple_calls(uncached_func, values, rounds) + uncached_times.append(elapsed) + cached_func.cache_clear() + elapsed, cached_checksum = _time_tuple_calls(cached_func, values, rounds) + cached_times.append(elapsed) + assert uncached_checksum == cached_checksum + uncached = statistics.median(uncached_times) + cached = statistics.median(cached_times) + print( + f"{name} uncached={uncached:.6f}s cached={cached:.6f}s " + f"speedup={_format_speedup(uncached, cached)} cache={cached_func.cache_info()}" + ) + + p2pool_data.donation_script_to_address.cache_clear() + start = time.perf_counter() + for _ in range(10000): + p2pool_data.donation_script_to_address.__wrapped__(defcoin) + uncached = time.perf_counter() - start + start = time.perf_counter() + for _ in range(10000): + p2pool_data.donation_script_to_address(defcoin) + cached = time.perf_counter() - start + print( + f"donation_script_to_address uncached={uncached:.6f}s cached={cached:.6f}s " + f"speedup={_format_speedup(uncached, cached)} " + f"cache={p2pool_data.donation_script_to_address.cache_info()}" + ) + + +if __name__ == "__main__": + main() diff --git a/dev/convert_networks b/backend/dev/convert_networks similarity index 100% rename from dev/convert_networks rename to backend/dev/convert_networks diff --git a/dev/convert_networks.py b/backend/dev/convert_networks.py similarity index 100% rename from dev/convert_networks.py rename to backend/dev/convert_networks.py diff --git a/backend/dev/python3_port_compile_check.py b/backend/dev/python3_port_compile_check.py new file mode 100644 index 0000000..8d9bcc4 --- /dev/null +++ b/backend/dev/python3_port_compile_check.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Compile-check all Python sources during the Python 3 migration. + +This is a syntax gate only. Passing it does not prove runtime correctness +because p2pool still needs a byte/string audit before it can safely process +shares or network messages under Python 3. +""" + +from pathlib import Path +import py_compile + + +SKIP_DIRS = {".git", ".venv", "__pycache__"} + + +def main() -> int: + root = Path(__file__).resolve().parents[1] + failures = [] + total = 0 + for path in root.rglob("*.py"): + if SKIP_DIRS.intersection(path.parts): + continue + total += 1 + try: + py_compile.compile(str(path), doraise=True) + except Exception as exc: # pragma: no cover - diagnostic script + failures.append((path.relative_to(root), exc)) + + print(f"python_files {total}") + print(f"py3_compile_failures {len(failures)}") + for path, exc in failures: + print(f"{path}\t{type(exc).__name__}\t{str(exc).splitlines()[-1]}") + return 1 if failures else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/dev/readme b/backend/dev/readme similarity index 100% rename from dev/readme rename to backend/dev/readme diff --git a/fpconst.py b/backend/fpconst.py similarity index 99% rename from fpconst.py rename to backend/fpconst.py index d33650a..a2cd0aa 100644 --- a/fpconst.py +++ b/backend/fpconst.py @@ -40,6 +40,7 @@ ident = "$Id: fpconst.py,v 1.16 2005/02/24 17:42:03 warnes Exp $" import struct, operator +from functools import reduce # check endianess _big_endian = struct.pack('i',1)[0] != '\x01' diff --git a/backend/litecoin_scrypt/pyproject.toml b/backend/litecoin_scrypt/pyproject.toml new file mode 100644 index 0000000..642ab3c --- /dev/null +++ b/backend/litecoin_scrypt/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/litecoin_scrypt/scrypt.c b/backend/litecoin_scrypt/scrypt.c similarity index 100% rename from litecoin_scrypt/scrypt.c rename to backend/litecoin_scrypt/scrypt.c diff --git a/litecoin_scrypt/scrypt.h b/backend/litecoin_scrypt/scrypt.h similarity index 85% rename from litecoin_scrypt/scrypt.h rename to backend/litecoin_scrypt/scrypt.h index 694158d..8da945c 100644 --- a/litecoin_scrypt/scrypt.h +++ b/backend/litecoin_scrypt/scrypt.h @@ -7,7 +7,6 @@ extern "C" { void scrypt_1024_1_1_256(const char* input, char* output); void scrypt_1024_1_1_256_sp(const char* input, char* output, char* scratchpad); -const int scrypt_scratchpad_size = 131583; #ifdef __cplusplus } diff --git a/backend/litecoin_scrypt/scryptmodule.c b/backend/litecoin_scrypt/scryptmodule.c new file mode 100644 index 0000000..4d90514 --- /dev/null +++ b/backend/litecoin_scrypt/scryptmodule.c @@ -0,0 +1,64 @@ +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#define PY_SSIZE_T_CLEAN 1 +#include + +#include "scrypt.h" + +static PyObject *scrypt_getpowhash(PyObject *self, PyObject *args, PyObject* kwargs) +{ + char *input; + Py_ssize_t inputlen; + char *outbuf; + PyObject *value = NULL; + + static char *g2_kwlist[] = {"input", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y#", g2_kwlist, + &input, &inputlen)) { + return NULL; + } + + outbuf = PyMem_Malloc(32); + if (outbuf == NULL) { + return PyErr_NoMemory(); + } + + Py_BEGIN_ALLOW_THREADS; + scrypt_1024_1_1_256(input, outbuf); + Py_END_ALLOW_THREADS; + + value = Py_BuildValue("y#", outbuf, 32); + PyMem_Free(outbuf); + return value; +} + +static PyMethodDef ScryptMethods[] = { + { "getPoWHash", (PyCFunction) scrypt_getpowhash, METH_VARARGS | METH_KEYWORDS, "Returns the proof of work hash using scrypt" }, + { NULL, NULL, 0, NULL } +}; + +static struct PyModuleDef scryptmodule = { + PyModuleDef_HEAD_INIT, + "ltc_scrypt", + NULL, + -1, + ScryptMethods +}; + +PyMODINIT_FUNC PyInit_ltc_scrypt(void) { + return PyModule_Create(&scryptmodule); +} diff --git a/backend/litecoin_scrypt/setup.py b/backend/litecoin_scrypt/setup.py new file mode 100644 index 0000000..f963eea --- /dev/null +++ b/backend/litecoin_scrypt/setup.py @@ -0,0 +1,27 @@ +# Copyright (C) 2013 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from setuptools import setup, Extension + +ltc_scrypt_module = Extension('ltc_scrypt', + sources = ['scryptmodule.c', + 'scrypt.c'], + include_dirs=['.'], + extra_compile_args=['-O0', '-fwrapv', '-fno-strict-aliasing']) + +setup (name = 'ltc_scrypt', + version = '1.0.99', + description = 'Bindings for scrypt proof of work used by Litecoin', + ext_modules = [ltc_scrypt_module]) diff --git a/nattraverso/__init__.py b/backend/nattraverso/__init__.py similarity index 100% rename from nattraverso/__init__.py rename to backend/nattraverso/__init__.py diff --git a/nattraverso/ipdiscover.py b/backend/nattraverso/ipdiscover.py similarity index 97% rename from nattraverso/ipdiscover.py rename to backend/nattraverso/ipdiscover.py index 5c12ef3..15d00c8 100644 --- a/nattraverso/ipdiscover.py +++ b/backend/nattraverso/ipdiscover.py @@ -49,7 +49,7 @@ def get_local_ip(): port.stopListening() if is_bogus_ip(localip): - raise RuntimeError, "Invalid IP address returned" + raise RuntimeError("Invalid IP address returned") else: defer.returnValue((is_rfc1918_ip(localip), localip)) @@ -128,7 +128,7 @@ def _discover_multicast(): yield mcast.joinGroup('239.255.255.250', socket.INADDR_ANY) logging.debug("Sending multicast ping") - for i in xrange(3): + for i in range(3): p.transport.write(nonce, ('239.255.255.250', port)) address, = yield p.address_received.get_deferred(5) diff --git a/nattraverso/portmapper.py b/backend/nattraverso/portmapper.py similarity index 100% rename from nattraverso/portmapper.py rename to backend/nattraverso/portmapper.py diff --git a/nattraverso/pynupnp/__init__.py b/backend/nattraverso/pynupnp/__init__.py similarity index 100% rename from nattraverso/pynupnp/__init__.py rename to backend/nattraverso/pynupnp/__init__.py diff --git a/nattraverso/pynupnp/soap.py b/backend/nattraverso/pynupnp/soap.py similarity index 100% rename from nattraverso/pynupnp/soap.py rename to backend/nattraverso/pynupnp/soap.py diff --git a/nattraverso/pynupnp/upnp.py b/backend/nattraverso/pynupnp/upnp.py similarity index 99% rename from nattraverso/pynupnp/upnp.py rename to backend/nattraverso/pynupnp/upnp.py index c3bea75..54feca9 100644 --- a/nattraverso/pynupnp/upnp.py +++ b/backend/nattraverso/pynupnp/upnp.py @@ -11,7 +11,7 @@ """ __revision__ = "$id" -import socket, random, urlparse, logging +import socket, random, urllib.parse, logging from twisted.internet import reactor, defer from twisted.web import client @@ -492,7 +492,7 @@ def _on_gateway_response(self, body, loc): self._on_discovery_failed(UPnPError("upnp response showed no WANConnections")) return - control_url2 = urlparse.urljoin(urlbase, controlurl) + control_url2 = urllib.parse.urljoin(urlbase, controlurl) soap_proxy = SoapProxy(control_url2, upnpinfo.wanservice) self._on_discovery_succeeded(UPnPDevice(soap_proxy, upnpinfo.deviceinfos)) diff --git a/nattraverso/pynupnp/upnpxml.py b/backend/nattraverso/pynupnp/upnpxml.py similarity index 97% rename from nattraverso/pynupnp/upnpxml.py rename to backend/nattraverso/pynupnp/upnpxml.py index 75059dc..8b1684b 100644 --- a/nattraverso/pynupnp/upnpxml.py +++ b/backend/nattraverso/pynupnp/upnpxml.py @@ -10,7 +10,7 @@ __revision__ = "$id" -from xml.dom import minidom +from defusedxml import minidom import logging # Allowed UPnP services to use when mapping ports/external addresses @@ -54,7 +54,7 @@ def __init__(self, xml): 'manufacturer' : 'manufacturer' } device = doc.getElementsByTagName('device')[0] - for name, tag in attributes.iteritems(): + for name, tag in attributes.items(): try: self.deviceinfos[name] = device.getElementsByTagName( tag)[0].firstChild.datas.encode('utf-8') @@ -86,4 +86,3 @@ def __init__(self, xml): 'URLBase')[0].firstChild.data.encode('utf-8') except: pass - diff --git a/nattraverso/utils.py b/backend/nattraverso/utils.py similarity index 89% rename from nattraverso/utils.py rename to backend/nattraverso/utils.py index 1bfc6da..ff55dd4 100644 --- a/nattraverso/utils.py +++ b/backend/nattraverso/utils.py @@ -17,7 +17,7 @@ def is_rfc1918_ip(ip): @type ip: a string "x.x.x.x" @return: True if it's a LAN address, False otherwise """ - if isinstance(ip, basestring): + if isinstance(ip, str): ip = _ip_to_number(ip) for net, mask in _nets: @@ -46,11 +46,11 @@ def _ip_to_number(ipstr): """ net = [ int(digit) for digit in ipstr.split('.') ] + [ 0, 0, 0 ] net = net[:4] - return ((((((0L+net[0])<<8) + net[1])<<8) + net[2])<<8) +net[3] + return ((((((0+net[0])<<8) + net[1])<<8) + net[2])<<8) +net[3] # List of rfc1918 net/mask _rfc1918_networks = [('127', 8), ('192.168', 16), ('10', 8), ('172.16', 12)] # Machine readable form of the above -_nets = [(_ip_to_number(net), (2L**32 -1)^(2L**(32-mask)-1)) +_nets = [(_ip_to_number(net), (2**32 -1)^(2**(32-mask)-1)) for net, mask in _rfc1918_networks] diff --git a/backend/p2pool/__init__.py b/backend/p2pool/__init__.py new file mode 100644 index 0000000..6fa650d --- /dev/null +++ b/backend/p2pool/__init__.py @@ -0,0 +1,79 @@ +import os +import re +import shutil +import subprocess # nosec B404 + + +def _describe_from_git(root_dir): + for executable in ('git', 'git.cmd'): + command = shutil.which(executable) + if command is None: + continue + try: + return subprocess.check_output( # noqa: S603 # nosec B603 + [command, 'describe', '--always', '--dirty'], + cwd=root_dir, + stderr=subprocess.DEVNULL, + ).strip().decode('ascii') + except (OSError, subprocess.CalledProcessError, UnicodeDecodeError): + continue + + +def _read_git_head(git_dir): + if not os.path.isdir(git_dir): + return None + + with open(os.path.join(git_dir, 'HEAD'), encoding='utf-8') as head_file: + head = head_file.read().strip() + + prefix = 'ref: ' + if not head.startswith(prefix): + return head[:7] + + ref_path = head[len(prefix):] + loose_ref = os.path.join(git_dir, *ref_path.split('/')) + if os.path.exists(loose_ref): + with open(loose_ref, encoding='utf-8') as ref_file: + return ref_file.read().strip()[:7] + + packed_refs = os.path.join(git_dir, 'packed-refs') + if os.path.exists(packed_refs): + with open(packed_refs, encoding='utf-8') as packed_file: + for line in packed_file: + if line.startswith('#') or not line.strip(): + continue + sha, packed_ref = line.strip().split(' ', 1) + if packed_ref == ref_path: + return sha[:7] + + return None + + +def _get_version(): + package_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + repo_root = os.path.dirname(package_root) + root_dir = repo_root if os.path.exists(os.path.join(repo_root, '.git')) else package_root + try: + git_version = _describe_from_git(root_dir) + if git_version is not None: + return git_version + + git_dir = os.path.join(root_dir, '.git') + git_head = _read_git_head(git_dir) + if git_head is not None: + return git_head + + dir_name = os.path.split(root_dir)[1] + match = re.match('p2pool-([.0-9]+)', dir_name) + if match: + return match.groups()[0] + + except OSError as err: + return f'unknown {str(err).encode("utf-8").hex()}' + + return f'unknown {os.path.split(root_dir)[1].encode("utf-8").hex()}' + +__version__ = _get_version() + +DEBUG = True +BENCH = False diff --git a/p2pool/bitcoin/__init__.py b/backend/p2pool/bitcoin/__init__.py similarity index 100% rename from p2pool/bitcoin/__init__.py rename to backend/p2pool/bitcoin/__init__.py diff --git a/p2pool/bitcoin/data.py b/backend/p2pool/bitcoin/data.py similarity index 88% rename from p2pool/bitcoin/data.py rename to backend/p2pool/bitcoin/data.py index 73e3ef7..32e5352 100644 --- a/p2pool/bitcoin/data.py +++ b/backend/p2pool/bitcoin/data.py @@ -1,4 +1,4 @@ -from __future__ import division + import hashlib import random @@ -7,11 +7,14 @@ import p2pool from p2pool.util import math, pack, segwit_addr, cash_addr +from p2pool.util.py3 import bchr, bord, bytes_to_hex, hex_to_bytes, ensure_bytes import struct +from functools import lru_cache, reduce mask = (1<<64) - 1 def hash256(data): + data = ensure_bytes(data) return pack.IntType(256).unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest()) def pack256(data): @@ -21,14 +24,17 @@ def pack256(data): data>>192 & mask) def unpack256(data): + data = ensure_bytes(data) raw = struct.unpack("= 128: - n = '\x00' + n - bits2 = (chr(len(n)) + (n + 3*chr(0))[:3])[::-1] + if n and bord(n[0]) >= 128: + n = b'\x00' + n + bits2 = (bchr(len(n)) + (n + 3*b'\x00')[:3])[::-1] bits = pack.IntType(32).unpack(bits2) return cls(bits) @@ -173,13 +179,13 @@ def read(self, file): if marker == 0: next = self._wtx_type.read(file) witness = [None]*len(next['tx_ins']) - for i in xrange(len(next['tx_ins'])): + for i in range(len(next['tx_ins'])): witness[i] = self._witness_type.read(file) locktime = self._int_type.read(file) return dict(version=version, marker=marker, flag=next['flag'], tx_ins=next['tx_ins'], tx_outs=next['tx_outs'], witness=witness, lock_time=locktime) else: tx_ins = [None]*marker - for i in xrange(marker): + for i in range(marker): tx_ins[i] = tx_in_type.read(file) next = self._ntx_type.read(file) return dict(version=version, tx_ins=tx_ins, tx_outs=next['tx_outs'], lock_time=next['lock_time']) @@ -241,7 +247,7 @@ def write(self, file, item): ]) def make_auxpow_tree(chain_ids): - for size in (2**i for i in xrange(31)): + for size in (2**i for i in range(31)): if size < len(chain_ids): continue res = {} @@ -353,27 +359,31 @@ def calculate_merkle_link(hashes, index): def check_merkle_link(tip_hash, link): if link['index'] >= 2**len(link['branch']): raise ValueError('index too large') - return reduce(lambda c, (i, h): hash256(merkle_record_type.pack( - dict(left=h, right=c) if (link['index'] >> i) & 1 else - dict(left=c, right=h) + return reduce(lambda c, item: hash256(merkle_record_type.pack( + dict(left=item[1], right=c) if (link['index'] >> item[0]) & 1 else + dict(left=c, right=item[1]) )), enumerate(link['branch']), tip_hash) # targets +@lru_cache(maxsize=4096) def target_to_average_attempts(target): - assert 0 <= target and isinstance(target, (int, long)), target - if target >= 2**256: warnings.warn('target >= 2**256!') + assert 0 <= target and isinstance(target, int), target + if target >= 2**256: warnings.warn('target >= 2**256!', stacklevel=2) return 2**256//(target + 1) +@lru_cache(maxsize=4096) def average_attempts_to_target(average_attempts): assert average_attempts > 0 return min(int(2**256/average_attempts - 1 + 0.5), 2**256-1) +@lru_cache(maxsize=4096) def target_to_difficulty(target): - assert 0 <= target and isinstance(target, (int, long)), target - if target >= 2**256: warnings.warn('target >= 2**256!') + assert 0 <= target and isinstance(target, int), target + if target >= 2**256: warnings.warn('target >= 2**256!', stacklevel=2) return (0xffff0000 * 2**(256-64) + 1)/(target + 1) +@lru_cache(maxsize=4096) def difficulty_to_target(difficulty): assert difficulty >= 0 if difficulty == 0: return 2**256-1 @@ -384,18 +394,19 @@ def difficulty_to_target(difficulty): base58_alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' def base58_encode(bindata): - bindata2 = bindata.lstrip(chr(0)) + bindata2 = bindata.lstrip(b'\x00') return base58_alphabet[0]*(len(bindata) - len(bindata2)) + math.natural_to_string(math.string_to_natural(bindata2), base58_alphabet) def base58_decode(b58data): b58data2 = b58data.lstrip(base58_alphabet[0]) - return chr(0)*(len(b58data) - len(b58data2)) + math.natural_to_string(math.string_to_natural(b58data2, base58_alphabet)) + return b'\x00'*(len(b58data) - len(b58data2)) + math.natural_to_string(math.string_to_natural(b58data2, base58_alphabet)) human_address_type = ChecksummedType(pack.ComposedType([ ('version', pack.IntType(8)), ('pubkey_hash', pack.IntType(160)), ])) +@lru_cache(maxsize=4096) def pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net): if addr_ver == -1: if hasattr(net, 'padding_bugfix') and net.padding_bugfix: @@ -404,6 +415,8 @@ def pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net): thash = '{:x}'.format(pubkey_hash) if len(thash) % 2 == 1: thash = '0%s' % thash + if len(thash) < 40: + thash = thash.zfill(40) data = [int(x) for x in bytearray.fromhex(thash)] if net.SYMBOL.lower() in ['bch', 'tbch', 'bsv', 'tbsv']: return cash_addr.encode(net.HUMAN_READABLE_PART, bech32_ver, data) @@ -417,10 +430,12 @@ def pubkey_to_address(pubkey, net): class AddrError(Exception): __slots__ = () +@lru_cache(maxsize=4096) def address_to_script2(address, net): res = address_to_pubkey_hash(address, net) return pubkey_hash_to_script2(res[0], res[1], res[2], net) +@lru_cache(maxsize=4096) def address_to_pubkey_hash(address, net): try: return get_legacy_pubkey_hash(address, net) @@ -490,8 +505,9 @@ def get_txid(tx): return hash256(tx_id_type.pack(tx)) def pubkey_to_script2(pubkey): + pubkey = ensure_bytes(pubkey) assert len(pubkey) <= 75 - return (chr(len(pubkey)) + pubkey) + '\xac' + return bchr(len(pubkey)) + pubkey + b'\xac' def pubkey_hash_to_script2(pubkey_hash, version, bech32_version, net): if version == -1 and bech32_version >= 0: @@ -509,19 +525,20 @@ def pubkey_hash_to_script2(pubkey_hash, version, bech32_version, net): # TODO: Check the version and restrict the bytes. if bech32_version == 0: # P2KH - return '\x76\xa9%s%s\x88\xac' % (hsize, ehash) + return b'\x76\xa9' + hsize + ehash + b'\x88\xac' elif bech32_version == 1: # P2SH - return '\xa9%s%s\x87' % (hsize, ehash) + return b'\xa9' + hsize + ehash + b'\x87' else: raise NotImplementedError("Invalid cashaddr type %d" % bech32_version) else: - return '\x00%s%s' % (hsize, ehash) + return b'\x00' + hsize + ehash if version == net.ADDRESS_P2SH_VERSION: - return ('\xa9\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x87' - return '\x76\xa9' + ('\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x88\xac' + return b'\xa9\x14' + ensure_bytes(pack.IntType(160).pack(pubkey_hash)) + b'\x87' + return b'\x76\xa9\x14' + ensure_bytes(pack.IntType(160).pack(pubkey_hash)) + b'\x88\xac' def script2_to_address(script2, addr_ver, bech32_ver, net): + script2 = ensure_bytes(script2) try: return script2_to_pubkey_address(script2, net) except AddrError: @@ -532,9 +549,10 @@ def script2_to_address(script2, addr_ver, bech32_ver, net): return func(script2, addr_ver, bech32_ver, net) except AddrError: pass - raise ValueError("Invalid script2 hash %s" % binascii.hexlify(script2)) + raise ValueError("Invalid script2 hash %s" % bytes_to_hex(script2)) def script2_to_pubkey_address(script2, net): + script2 = ensure_bytes(script2) try: pubkey = script2[1:-1] res = pubkey_to_script2(pubkey) @@ -545,6 +563,7 @@ def script2_to_pubkey_address(script2, net): return pubkey_to_address(pubkey, net) def script2_to_pubkey_hash_address(script2, addr_ver, bech32_ver, net): + script2 = ensure_bytes(script2) # TODO: Check for BCH and BSV length, could be longer than 20 bytes try: pubkey_hash = pack.IntType(160).unpack(script2[3:-2]) @@ -556,6 +575,7 @@ def script2_to_pubkey_hash_address(script2, addr_ver, bech32_ver, net): return pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net) def script2_to_cashaddress(script2, addr_ver, ca_ver, net): + script2 = ensure_bytes(script2) try: if ca_ver == 0: sub_hash = script2[3:-2] @@ -563,7 +583,7 @@ def script2_to_cashaddress(script2, addr_ver, ca_ver, net): sub_hash = script2[2:-1] else: raise ValueError - pubkey_hash = int(sub_hash.encode('hex'), 16) + pubkey_hash = int.from_bytes(sub_hash, 'big') res = pubkey_hash_to_script2(pubkey_hash, addr_ver, ca_ver, net) if res != script2: raise ValueError @@ -572,8 +592,9 @@ def script2_to_cashaddress(script2, addr_ver, ca_ver, net): return pubkey_hash_to_address(pubkey_hash, addr_ver, ca_ver, net) def script2_to_bech32_address(script2, addr_ver, bech32_ver, net): + script2 = ensure_bytes(script2) try: - pubkey_hash = int(script2[2:].encode('hex'), 16) + pubkey_hash = int.from_bytes(script2[2:], 'big') res = pubkey_hash_to_script2(pubkey_hash, addr_ver, bech32_ver, net) if res != script2: raise ValueError @@ -582,6 +603,7 @@ def script2_to_bech32_address(script2, addr_ver, bech32_ver, net): return pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net) def script2_to_p2sh_address(script2, addr_ver, bech32_ver, net): + script2 = ensure_bytes(script2) # TODO: Check for BCH and BSV length, could be longer than 20 bytes try: pubkey_hash = pack.IntType(160).unpack(script2[2:-1]) @@ -611,7 +633,7 @@ def script2_to_human(script2, net): if script2_test2 == script2: return 'Address. Address: %s' % (pubkey_hash_to_address(pubkey_hash, net),) - return 'Unknown. Script: %s' % (script2.encode('hex'),) + return 'Unknown. Script: %s' % (bytes_to_hex(script2),) def is_segwit_script(script): - return script.startswith('\x00\x14') or script.startswith('\xa9\x14') + return script.startswith(b'\x00\x14') or script.startswith(b'\xa9\x14') diff --git a/p2pool/bitcoin/getwork.py b/backend/p2pool/bitcoin/getwork.py similarity index 80% rename from p2pool/bitcoin/getwork.py rename to backend/p2pool/bitcoin/getwork.py index 721b8ba..9bbc397 100644 --- a/p2pool/bitcoin/getwork.py +++ b/backend/p2pool/bitcoin/getwork.py @@ -2,16 +2,17 @@ Representation of a getwork request/reply ''' -from __future__ import division + from . import data as bitcoin_data from . import sha256 from p2pool.util import pack +from p2pool.util.py3 import bytes_to_hex, hex_to_bytes def _swap4(s): if len(s) % 4: raise ValueError() - return ''.join(s[x:x+4][::-1] for x in xrange(0, len(s), 4)) + return b''.join(s[x:x+4][::-1] for x in range(0, len(s), 4)) class BlockAttempt(object): def __init__(self, version, previous_block, merkle_root, timestamp, bits, share_target): @@ -29,7 +30,7 @@ def __ne__(self, other): return not (self == other) def __repr__(self): - return 'BlockAttempt(%s)' % (', '.join('%s=%r' % (k, v) for k, v in self.__dict__.iteritems()),) + return 'BlockAttempt(%s)' % (', '.join('%s=%r' % (k, v) for k, v in self.__dict__.items()),) def getwork(self, **extra): if 'data' in extra or 'hash1' in extra or 'target' in extra or 'midstate' in extra: @@ -45,10 +46,10 @@ def getwork(self, **extra): )) getwork = { - 'data': _swap4(block_data).encode('hex') + '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000', + 'data': bytes_to_hex(_swap4(block_data)) + '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000', 'hash1': '00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000010000', - 'target': pack.IntType(256).pack(self.share_target).encode('hex'), - 'midstate': _swap4(sha256.process(sha256.initial_state, block_data[:64])).encode('hex'), + 'target': bytes_to_hex(pack.IntType(256).pack(self.share_target)), + 'midstate': bytes_to_hex(_swap4(sha256.process(sha256.initial_state, block_data[:64]))), } getwork = dict(getwork) @@ -66,7 +67,7 @@ def from_getwork(cls, getwork): merkle_root=attrs['merkle_root'], timestamp=attrs['timestamp'], bits=attrs['bits'], - share_target=pack.IntType(256).unpack(getwork['target'].decode('hex')), + share_target=pack.IntType(256).unpack(hex_to_bytes(getwork['target'])), ) def update(self, **kwargs): @@ -75,4 +76,4 @@ def update(self, **kwargs): return self.__class__(**d) def decode_data(data): - return bitcoin_data.block_header_type.unpack(_swap4(data.decode('hex'))[:80]) + return bitcoin_data.block_header_type.unpack(_swap4(hex_to_bytes(data))[:80]) diff --git a/p2pool/bitcoin/height_tracker.py b/backend/p2pool/bitcoin/height_tracker.py similarity index 84% rename from p2pool/bitcoin/height_tracker.py rename to backend/p2pool/bitcoin/height_tracker.py index bbeae01..aeacf3f 100644 --- a/p2pool/bitcoin/height_tracker.py +++ b/backend/p2pool/bitcoin/height_tracker.py @@ -40,6 +40,12 @@ def __init__(self, best_block_func, factory, backlog_needed): self._think_task.start(15) self._think2_task = deferral.RobustLoopingCall(self._think2) self._think2_task.start(15) + + def stop(self): + self._factory.new_headers.unwatch(self._watch1) + self._factory.new_block.unwatch(self._watch2) + tasks = [self._clear_task, self._think_task, self._think2_task] + return defer.DeferredList([task.stop() for task in tasks if task.running], consumeErrors=True) def _think(self): try: @@ -68,11 +74,13 @@ def _heard_headers(self, headers): self._think() if len(self._tracker.items) >= self._last_notified_size + 100: - print 'Have %i/%i block headers' % (len(self._tracker.items), self._backlog_needed) + print('Have %i/%i block headers' % (len(self._tracker.items), self._backlog_needed)) self._last_notified_size = len(self._tracker.items) @defer.inlineCallbacks - def _request(self, last): + def _request(self, last=None): + if last is None: + last = self._best_block_func() if last in self._tracker.items: return if last in self._requested: @@ -118,8 +126,10 @@ def get_height_rel_highest(block_hash): def get_height(block_hash): this_height = height_cacher.call_now(block_hash, 0) return this_height + stop_height_tracker = lambda: None else: - get_height_rel_highest = HeightTracker(best_block_func, factory, 5*net.SHARE_PERIOD*net.CHAIN_LENGTH/net.PARENT.BLOCK_PERIOD).get_height_rel_highest - get_height = HeightTracker(best_block_func, factory, 5*net.SHARE_PERIOD*net.CHAIN_LENGTH/net.PARENT.BLOCK_PERIOD).get_height - defer.returnValue((get_height_rel_highest, get_height)) - + tracker = HeightTracker(best_block_func, factory, 5*net.SHARE_PERIOD*net.CHAIN_LENGTH/net.PARENT.BLOCK_PERIOD) + get_height_rel_highest = tracker.get_height_rel_highest + get_height = tracker.get_height + stop_height_tracker = tracker.stop + defer.returnValue((get_height_rel_highest, get_height, stop_height_tracker)) diff --git a/p2pool/bitcoin/helper.py b/backend/p2pool/bitcoin/helper.py similarity index 73% rename from p2pool/bitcoin/helper.py rename to backend/p2pool/bitcoin/helper.py index e80fef3..93047ed 100644 --- a/p2pool/bitcoin/helper.py +++ b/backend/p2pool/bitcoin/helper.py @@ -6,20 +6,21 @@ import p2pool from p2pool.bitcoin import data as bitcoin_data from p2pool.util import deferral, jsonrpc +from p2pool.util.py3 import bytes_to_hex, hex_to_bytes txlookup = {} @deferral.retry('Error while checking Bitcoin connection:', 1) @defer.inlineCallbacks def check(bitcoind, net, args): if not (yield net.PARENT.RPC_CHECK(bitcoind)): - print >>sys.stderr, " Check failed! Make sure that you're connected to the right bitcoind with --bitcoind-rpc-port, and that it has finished syncing!" + print(" Check failed! Make sure that you're connected to the right bitcoind with --bitcoind-rpc-port, and that it has finished syncing!", file=sys.stderr) raise deferral.RetrySilentlyException() version_check_result = net.VERSION_CHECK((yield bitcoind.rpc_getnetworkinfo())['version']) if version_check_result == True: version_check_result = None # deprecated if version_check_result == False: version_check_result = 'Coin daemon too old! Upgrade!' # deprecated if version_check_result is not None: - print >>sys.stderr, ' ' + version_check_result + print(' ' + version_check_result, file=sys.stderr) raise deferral.RetrySilentlyException() try: @@ -36,19 +37,24 @@ def check(bitcoind, net, args): softforks_supported = set() unsupported_forks = getattr(net, 'SOFTFORKS_REQUIRED', set()) - softforks_supported if unsupported_forks: - print "You are running a coin daemon that does not support all of the " - print "forking features that have been activated on this blockchain." - print "Consequently, your node may mine invalid blocks or may mine blocks that" - print "are not part of the Nakamoto consensus blockchain.\n" - print "Missing fork features:", ', '.join(unsupported_forks) + print("You are running a coin daemon that does not support all of the ") + print("forking features that have been activated on this blockchain.") + print("Consequently, your node may mine invalid blocks or may mine blocks that") + print("are not part of the Nakamoto consensus blockchain.\n") + print("Missing fork features:", ', '.join(unsupported_forks)) if not args.allow_obsolete_bitcoind: - print "\nIf you know what you're doing, this error may be overridden by running p2pool" - print "with the '--allow-obsolete-bitcoind' command-line option.\n\n\n" + print("\nIf you know what you're doing, this error may be overridden by running p2pool") + print("with the '--allow-obsolete-bitcoind' command-line option.\n\n\n") raise deferral.RetrySilentlyException() @deferral.retry('Error getting work from bitcoind:', 3) @defer.inlineCallbacks -def getwork(bitcoind, use_getblocktemplate=False, txidcache={}, feecache={}, feefifo=[], known_txs={}): +def getwork(bitcoind, use_getblocktemplate=False, txidcache=None, feecache=None, feefifo=None, known_txs=None): + txidcache = {} if txidcache is None else txidcache + feecache = {} if feecache is None else feecache + feefifo = [] if feefifo is None else feefifo + known_txs = {} if known_txs is None else known_txs + def go(): if use_getblocktemplate: # Defcoin Core Nu inherits modern getblocktemplate rule negotiation. @@ -68,7 +74,7 @@ def go(): work = yield go() end = time.time() except jsonrpc.Error_for_code(-32601): # Method not found - print >>sys.stderr, 'Error: Bitcoin version too old! Upgrade to v0.5 or newer!' + print('Error: Bitcoin version too old! Upgrade to v0.5 or newer!', file=sys.stderr) raise deferral.RetrySilentlyException() if not 'start' in txidcache: # we clear it every 30 min @@ -91,7 +97,7 @@ def go(): txhashes.append(txid) else: cachemisses += 1 - packed = x.decode('hex') + packed = hex_to_bytes(x) txid = bitcoin_data.hash256(packed) txidcache[x] = txid txhashes.append(txid) @@ -101,7 +107,7 @@ def go(): else: knownmisses += 1 if not packed: - packed = x.decode('hex') + packed = hex_to_bytes(x) unpacked = bitcoin_data.tx_type.unpack(packed) unpacked_transactions.append(unpacked) # The only place where we can get information on transaction fees is in GBT results, so we need to store those @@ -124,7 +130,7 @@ def go(): assert work['height'] == (yield bitcoind.rpc_getblock(work['previousblockhash']))['height'] + 1 t1 = time.time() - if p2pool.BENCH: print "%8.3f ms for helper.py:getwork(). Cache: %i hits %i misses, %i known_tx %i unknown %i cached" % ((t1 - t0)*1000., cachehits, cachemisses, knownhits, knownmisses, len(txidcache)) + if p2pool.BENCH: print("%8.3f ms for helper.py:getwork(). Cache: %i hits %i misses, %i known_tx %i unknown %i cached" % ((t1 - t0)*1000., cachehits, cachemisses, knownhits, knownmisses, len(txidcache))) defer.returnValue(dict( version=work['version'], previous_block=int(work['previousblockhash'], 16), @@ -133,8 +139,8 @@ def go(): transaction_fees=[x.get('fee', None) if isinstance(x, dict) else None for x in work['transactions']], subsidy=work['coinbasevalue'], time=work['time'] if 'time' in work else work['curtime'], - bits=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']), - coinbaseflags=work['coinbaseflags'].decode('hex') if 'coinbaseflags' in work else ''.join(x.decode('hex') for x in work['coinbaseaux'].itervalues()) if 'coinbaseaux' in work else '', + bits=bitcoin_data.FloatingIntegerType().unpack(hex_to_bytes(work['bits'])[::-1]) if isinstance(work['bits'], str) else bitcoin_data.FloatingInteger(work['bits']), + coinbaseflags=hex_to_bytes(work['coinbaseflags']) if 'coinbaseflags' in work else b''.join(hex_to_bytes(x) for x in work['coinbaseaux'].values()) if 'coinbaseaux' in work else b'', height=work['height'], rules=work.get('rules', []), last_update=time.time(), @@ -145,7 +151,7 @@ def go(): @deferral.retry('Error submitting primary block: (will retry)', 10, 10) def submit_block_p2p(block, factory, net): if factory.conn.value is None: - print >>sys.stderr, 'No bitcoind connection when block submittal attempted! %s%064x' % (net.PARENT.BLOCK_EXPLORER_URL_PREFIX, bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header']))) + print('No bitcoind connection when block submittal attempted! %s%064x' % (net.PARENT.BLOCK_EXPLORER_URL_PREFIX, bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header']))), file=sys.stderr) raise deferral.RetrySilentlyException() factory.conn.value.send_block(block=block) @@ -156,16 +162,16 @@ def submit_block_rpc(block, ignore_failure, bitcoind, bitcoind_work, net): segwit_activated = len(segwit_rules - set(bitcoind_work.value['rules'])) < len(segwit_rules) if bitcoind_work.value['use_getblocktemplate']: try: - result = yield bitcoind.rpc_submitblock((bitcoin_data.block_type if segwit_activated else bitcoin_data.stripped_block_type).pack(block).encode('hex')) + result = yield bitcoind.rpc_submitblock(bytes_to_hex((bitcoin_data.block_type if segwit_activated else bitcoin_data.stripped_block_type).pack(block))) except jsonrpc.Error_for_code(-32601): # Method not found, for older litecoin versions - result = yield bitcoind.rpc_getblocktemplate(dict(mode='submit', data=bitcoin_data.block_type.pack(block).encode('hex'))) + result = yield bitcoind.rpc_getblocktemplate(dict(mode='submit', data=bytes_to_hex(bitcoin_data.block_type.pack(block)))) success = result is None else: - result = yield bitcoind.rpc_getmemorypool(bitcoin_data.block_type.pack(block).encode('hex')) + result = yield bitcoind.rpc_getmemorypool(bytes_to_hex(bitcoin_data.block_type.pack(block))) success = result success_expected = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(block['header'])) <= block['header']['bits'].target if (not success and success_expected and not ignore_failure) or (success and not success_expected): - print >>sys.stderr, 'Block submittal result: %s (%r) Expected: %s' % (success, result, success_expected) + print('Block submittal result: %s (%r) Expected: %s' % (success, result, success_expected), file=sys.stderr) def submit_block(block, ignore_failure, node): submit_block_p2p(block, node.factory, node.net) diff --git a/backend/p2pool/bitcoin/networks/__init__.py b/backend/p2pool/bitcoin/networks/__init__.py new file mode 100644 index 0000000..cb0dee4 --- /dev/null +++ b/backend/p2pool/bitcoin/networks/__init__.py @@ -0,0 +1,7 @@ +import importlib +import pkgutil + +nets = dict((name, importlib.import_module('.' + name, __name__)) + for module_loader, name, ispkg in pkgutil.iter_modules(__path__)) +for net_name, net in nets.items(): + net.NAME = net_name diff --git a/p2pool/bitcoin/networks/bitcoin.py b/backend/p2pool/bitcoin/networks/bitcoin.py similarity index 97% rename from p2pool/bitcoin/networks/bitcoin.py rename to backend/p2pool/bitcoin/networks/bitcoin.py index 084c323..dbfe810 100644 --- a/p2pool/bitcoin/networks/bitcoin.py +++ b/backend/p2pool/bitcoin/networks/bitcoin.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'f9beb4d9'.decode('hex') +P2P_PREFIX = bytes.fromhex('f9beb4d9') P2P_PORT = 8333 ADDRESS_VERSION = 0 ADDRESS_P2SH_VERSION = 5 diff --git a/p2pool/bitcoin/networks/bitcoin_testnet.py b/backend/p2pool/bitcoin/networks/bitcoin_testnet.py similarity index 96% rename from p2pool/bitcoin/networks/bitcoin_testnet.py rename to backend/p2pool/bitcoin/networks/bitcoin_testnet.py index 2adeb8a..25fe4d6 100644 --- a/p2pool/bitcoin/networks/bitcoin_testnet.py +++ b/backend/p2pool/bitcoin/networks/bitcoin_testnet.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = '0b110907'.decode('hex') +P2P_PREFIX = bytes.fromhex('0b110907') P2P_PORT = 18333 ADDRESS_VERSION = 111 ADDRESS_P2SH_VERSION = 196 diff --git a/p2pool/bitcoin/networks/bitcoincash.py b/backend/p2pool/bitcoin/networks/bitcoincash.py similarity index 91% rename from p2pool/bitcoin/networks/bitcoincash.py rename to backend/p2pool/bitcoin/networks/bitcoincash.py index 5092b6f..a12b9a1 100644 --- a/p2pool/bitcoin/networks/bitcoincash.py +++ b/backend/p2pool/bitcoin/networks/bitcoincash.py @@ -7,8 +7,8 @@ from p2pool.util import pack -#P2P_PREFIX = 'f9beb4d9'.decode('hex') # disk magic and old net magic -P2P_PREFIX = 'e3e1f3e8'.decode('hex') # new net magic +#P2P_PREFIX = bytes.fromhex('f9beb4d9') # disk magic and old net magic +P2P_PREFIX = bytes.fromhex('e3e1f3e8') # new net magic P2P_PORT = 8333 ADDRESS_VERSION = 0 ADDRESS_P2SH_VERSION = 5 diff --git a/p2pool/bitcoin/networks/bitcoincash_testnet.py b/backend/p2pool/bitcoin/networks/bitcoincash_testnet.py similarity index 91% rename from p2pool/bitcoin/networks/bitcoincash_testnet.py rename to backend/p2pool/bitcoin/networks/bitcoincash_testnet.py index 0f1d47d..7be8ad8 100644 --- a/p2pool/bitcoin/networks/bitcoincash_testnet.py +++ b/backend/p2pool/bitcoin/networks/bitcoincash_testnet.py @@ -7,8 +7,8 @@ from p2pool.util import pack -#P2P_PREFIX = '0b110907'.decode('hex') # disk magic and old netmagic -P2P_PREFIX = 'f4e5f3f4'.decode('hex') # new net magic +#P2P_PREFIX = bytes.fromhex('0b110907') # disk magic and old netmagic +P2P_PREFIX = bytes.fromhex('f4e5f3f4') # new net magic P2P_PORT = 18333 ADDRESS_VERSION = 111 ADDRESS_P2SH_VERSION = 196 diff --git a/p2pool/bitcoin/networks/btcregtest.py b/backend/p2pool/bitcoin/networks/btcregtest.py similarity index 95% rename from p2pool/bitcoin/networks/btcregtest.py rename to backend/p2pool/bitcoin/networks/btcregtest.py index 1032cba..2237975 100644 --- a/p2pool/bitcoin/networks/btcregtest.py +++ b/backend/p2pool/bitcoin/networks/btcregtest.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'fabfb5da'.decode('hex') +P2P_PREFIX = bytes.fromhex('fabfb5da') P2P_PORT = 18444 ADDRESS_VERSION = 111 RPC_PORT = 28332 diff --git a/p2pool/bitcoin/networks/defcoin.py b/backend/p2pool/bitcoin/networks/defcoin.py similarity index 95% rename from p2pool/bitcoin/networks/defcoin.py rename to backend/p2pool/bitcoin/networks/defcoin.py index 5c70430..a965d83 100644 --- a/p2pool/bitcoin/networks/defcoin.py +++ b/backend/p2pool/bitcoin/networks/defcoin.py @@ -20,8 +20,8 @@ 'defcoin.conf') P2P_PORT = 1337 -LEGACY_P2P_PREFIX = 'fbc0b6db'.decode('hex') -NEW_P2P_PREFIX = 'defc014e'.decode('hex') +LEGACY_P2P_PREFIX = bytes.fromhex('fbc0b6db') +NEW_P2P_PREFIX = bytes.fromhex('defc014e') # MAGIC_BYTES_2026_LEGACY_KILL_SWITCH: # Keep DEFCOIN_P2POOL_USE_NEW_MAGIC unset/0 while the local defcoind service is # running legacy outbound magic. Set it to 1 when defcoind is switched to diff --git a/p2pool/bitcoin/networks/defcoin_testnet.py b/backend/p2pool/bitcoin/networks/defcoin_testnet.py similarity index 96% rename from p2pool/bitcoin/networks/defcoin_testnet.py rename to backend/p2pool/bitcoin/networks/defcoin_testnet.py index f8dc830..a2d8593 100644 --- a/p2pool/bitcoin/networks/defcoin_testnet.py +++ b/backend/p2pool/bitcoin/networks/defcoin_testnet.py @@ -20,7 +20,7 @@ 'defcoin.conf') P2P_PORT = 62456 -P2P_PREFIX = 'b6f5d3cf'.decode('hex') +P2P_PREFIX = bytes.fromhex('b6f5d3cf') RPC_PORT = 62455 RPC_CHECK = defer.inlineCallbacks(lambda bitcoind: defer.returnValue( (yield bitcoind.rpc_getblockchaininfo())['chain'] == 'test' diff --git a/p2pool/bitcoin/networks/fastcoin.py b/backend/p2pool/bitcoin/networks/fastcoin.py similarity index 96% rename from p2pool/bitcoin/networks/fastcoin.py rename to backend/p2pool/bitcoin/networks/fastcoin.py index 8c60f68..f82374c 100644 --- a/p2pool/bitcoin/networks/fastcoin.py +++ b/backend/p2pool/bitcoin/networks/fastcoin.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'fbc0b6db'.decode('hex') +P2P_PREFIX = bytes.fromhex('fbc0b6db') P2P_PORT = 9526 ADDRESS_VERSION = 96 RPC_PORT = 9527 diff --git a/p2pool/bitcoin/networks/litecoin.py b/backend/p2pool/bitcoin/networks/litecoin.py similarity index 97% rename from p2pool/bitcoin/networks/litecoin.py rename to backend/p2pool/bitcoin/networks/litecoin.py index ca010cc..b8335ae 100644 --- a/p2pool/bitcoin/networks/litecoin.py +++ b/backend/p2pool/bitcoin/networks/litecoin.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'fbc0b6db'.decode('hex') +P2P_PREFIX = bytes.fromhex('fbc0b6db') P2P_PORT = 9333 ADDRESS_VERSION = 48 ADDRESS_P2SH_VERSION = 50 diff --git a/p2pool/bitcoin/networks/litecoin_testnet.py b/backend/p2pool/bitcoin/networks/litecoin_testnet.py similarity index 96% rename from p2pool/bitcoin/networks/litecoin_testnet.py rename to backend/p2pool/bitcoin/networks/litecoin_testnet.py index f231aaf..f91287a 100644 --- a/p2pool/bitcoin/networks/litecoin_testnet.py +++ b/backend/p2pool/bitcoin/networks/litecoin_testnet.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'fdd2c8f1'.decode('hex') +P2P_PREFIX = bytes.fromhex('fdd2c8f1') P2P_PORT = 19335 ADDRESS_VERSION = 111 ADDRESS_P2SH_VERSION = 58 diff --git a/p2pool/bitcoin/networks/namecoin.py b/backend/p2pool/bitcoin/networks/namecoin.py similarity index 96% rename from p2pool/bitcoin/networks/namecoin.py rename to backend/p2pool/bitcoin/networks/namecoin.py index 605c20c..568874c 100644 --- a/p2pool/bitcoin/networks/namecoin.py +++ b/backend/p2pool/bitcoin/networks/namecoin.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'f9beb4fe'.decode('hex') +P2P_PREFIX = bytes.fromhex('f9beb4fe') P2P_PORT = 8334 ADDRESS_VERSION = 52 RPC_PORT = 8336 diff --git a/p2pool/bitcoin/networks/namecoin_testnet.py b/backend/p2pool/bitcoin/networks/namecoin_testnet.py similarity index 96% rename from p2pool/bitcoin/networks/namecoin_testnet.py rename to backend/p2pool/bitcoin/networks/namecoin_testnet.py index 0a06238..bc8da36 100644 --- a/p2pool/bitcoin/networks/namecoin_testnet.py +++ b/backend/p2pool/bitcoin/networks/namecoin_testnet.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = 'fabfb5fe'.decode('hex') +P2P_PREFIX = bytes.fromhex('fabfb5fe') P2P_PORT = 18334 ADDRESS_VERSION = 111 RPC_PORT = 18336 diff --git a/p2pool/bitcoin/networks/terracoin.py b/backend/p2pool/bitcoin/networks/terracoin.py similarity index 96% rename from p2pool/bitcoin/networks/terracoin.py rename to backend/p2pool/bitcoin/networks/terracoin.py index ba36d62..c6585ee 100644 --- a/p2pool/bitcoin/networks/terracoin.py +++ b/backend/p2pool/bitcoin/networks/terracoin.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = '42babe56'.decode('hex') +P2P_PREFIX = bytes.fromhex('42babe56') P2P_PORT = 13333 ADDRESS_VERSION = 0 RPC_PORT = 13332 diff --git a/p2pool/bitcoin/networks/terracoin_testnet.py b/backend/p2pool/bitcoin/networks/terracoin_testnet.py similarity index 96% rename from p2pool/bitcoin/networks/terracoin_testnet.py rename to backend/p2pool/bitcoin/networks/terracoin_testnet.py index 54f72cb..4ad941c 100644 --- a/p2pool/bitcoin/networks/terracoin_testnet.py +++ b/backend/p2pool/bitcoin/networks/terracoin_testnet.py @@ -7,7 +7,7 @@ from p2pool.util import pack -P2P_PREFIX = '41babe56'.decode('hex') +P2P_PREFIX = bytes.fromhex('41babe56') P2P_PORT = 23333 ADDRESS_VERSION = 111 RPC_PORT = 23332 diff --git a/p2pool/bitcoin/p2p.py b/backend/p2pool/bitcoin/p2p.py similarity index 93% rename from p2pool/bitcoin/p2p.py rename to backend/p2pool/bitcoin/p2p.py index 3135b90..eef24ba 100644 --- a/p2pool/bitcoin/p2p.py +++ b/backend/p2pool/bitcoin/p2p.py @@ -2,7 +2,7 @@ Implementation of Bitcoin's p2p protocol ''' -import random +import secrets import sys import time @@ -11,6 +11,7 @@ import p2pool from . import data as bitcoin_data from p2pool.util import deferral, p2protocol, pack, variable +from p2pool.util.py3 import ensure_bytes class Protocol(p2protocol.Protocol): def __init__(self, net): @@ -31,8 +32,8 @@ def connectionMade(self): address=self.transport.getHost().host, port=self.transport.getHost().port, ), - nonce=random.randrange(2**64), - sub_version_num='/P2Pool:%s/' % (p2pool.__version__,), + nonce=secrets.randbits(64), + sub_version_num=ensure_bytes('/P2Pool:%s/' % (p2pool.__version__,), 'ascii'), start_height=0, ) @@ -75,7 +76,7 @@ def handle_inv(self, invs): elif inv['type'] == 'block': self.factory.new_block.happened(inv['hash']) else: - print 'Unknown inv type', inv + print('Unknown inv type', inv) message_getdata = pack.ComposedType([ ('requests', pack.ListType(pack.ComposedType([ @@ -155,7 +156,7 @@ def handle_alert(self, message, signature): ]) def handle_reject(self, message, ccode, reason, data): if p2pool.DEBUG: - print >>sys.stderr, 'Received reject message (%s): %s' % (message, reason) + print('Received reject message (%s): %s' % (message, reason), file=sys.stderr) def connectionLost(self, reason): if hasattr(self.factory, 'gotConnection'): @@ -163,7 +164,7 @@ def connectionLost(self, reason): if hasattr(self, 'pinger'): self.pinger.stop() if p2pool.DEBUG: - print >>sys.stderr, 'Bitcoin connection lost. Reason:', reason.getErrorMessage() + print('Bitcoin connection lost. Reason:', reason.getErrorMessage(), file=sys.stderr) class ClientFactory(protocol.ReconnectingClientFactory): protocol = Protocol diff --git a/p2pool/bitcoin/script.py b/backend/p2pool/bitcoin/script.py similarity index 68% rename from p2pool/bitcoin/script.py rename to backend/p2pool/bitcoin/script.py index c4bdd1c..fc67a32 100644 --- a/p2pool/bitcoin/script.py +++ b/backend/p2pool/bitcoin/script.py @@ -1,31 +1,32 @@ from p2pool.util import math, pack -import cStringIO as StringIO +from p2pool.util.py3 import bord, bchr, ensure_bytes +import io def reads_nothing(f): - return None, f + return None def protoPUSH(length): return lambda f: f.read(length) def protoPUSHDATA(size_len): def _(f): length_str = f.read(size_len) - length = math.string_to_natural(length_str[::-1].lstrip(chr(0))) + length = math.string_to_natural(length_str[::-1].lstrip(b'\x00')) data = f.read(length) return data return _ opcodes = {} -for i in xrange(256): +for i in range(256): opcodes[i] = 'UNK_' + str(i), reads_nothing -opcodes[0] = 'PUSH', lambda f: ('', f) -for i in xrange(1, 76): +opcodes[0] = 'PUSH', lambda f: b'' +for i in range(1, 76): opcodes[i] = 'PUSH', protoPUSH(i) opcodes[76] = 'PUSH', protoPUSHDATA(1) opcodes[77] = 'PUSH', protoPUSHDATA(2) opcodes[78] = 'PUSH', protoPUSHDATA(4) -opcodes[79] = 'PUSH', lambda f: ('\x81', f) -for i in xrange(81, 97): - opcodes[i] = 'PUSH', lambda f, _i=i: (chr(_i - 80), f) +opcodes[79] = 'PUSH', lambda f: b'\x81' +for i in range(81, 97): + opcodes[i] = 'PUSH', lambda f, _i=i: bchr(_i - 80) opcodes[172] = 'CHECKSIG', reads_nothing opcodes[173] = 'CHECKSIGVERIFY', reads_nothing @@ -33,10 +34,10 @@ def _(f): opcodes[175] = 'CHECKMULTISIGVERIFY', reads_nothing def parse(script): - f = StringIO.StringIO(script) + f = io.BytesIO(ensure_bytes(script)) while pack.remaining(f): opcode_str = f.read(1) - opcode = ord(opcode_str) + opcode = bord(opcode_str) opcode_name, read_func = opcodes[opcode] opcode_arg = read_func(f) yield opcode_name, opcode_arg @@ -53,29 +54,31 @@ def get_sigop_count(script): def create_push_script(datums): # datums can be ints or strs res = [] for datum in datums: - if isinstance(datum, (int, long)): + if isinstance(datum, int): if datum == -1 or 1 <= datum <= 16: - res.append(chr(datum + 80)) + res.append(bchr(datum + 80)) continue negative = datum < 0 datum = math.natural_to_string(abs(datum)) - if datum and ord(datum[0]) & 128: - datum = '\x00' + datum + if datum and bord(datum[0]) & 128: + datum = b'\x00' + datum if negative: - datum = chr(ord(datum[0]) + 128) + datum[1:] + datum = bchr(bord(datum[0]) + 128) + datum[1:] datum = datum[::-1] + else: + datum = ensure_bytes(datum) if len(datum) < 76: - res.append(chr(len(datum))) + res.append(bchr(len(datum))) elif len(datum) <= 0xff: - res.append(76) - res.append(chr(len(datum))) + res.append(bchr(76)) + res.append(bchr(len(datum))) elif len(datum) <= 0xffff: - res.append(77) + res.append(bchr(77)) res.append(pack.IntType(16).pack(len(datum))) elif len(datum) <= 0xffffffff: - res.append(78) + res.append(bchr(78)) res.append(pack.IntType(32).pack(len(datum))) else: raise ValueError('string too long') res.append(datum) - return ''.join(res) + return b''.join(res) diff --git a/p2pool/bitcoin/sha256.py b/backend/p2pool/bitcoin/sha256.py similarity index 81% rename from p2pool/bitcoin/sha256.py rename to backend/p2pool/bitcoin/sha256.py index dd601e3..b713e06 100644 --- a/p2pool/bitcoin/sha256.py +++ b/backend/p2pool/bitcoin/sha256.py @@ -1,7 +1,9 @@ -from __future__ import division + import struct +from p2pool.util.py3 import bytes_to_hex, ensure_bytes + k = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -19,7 +21,7 @@ def rightrotate(x, n): return (x >> n) | (x << 32 - n) % 2**32 w = list(struct.unpack('>16I', chunk)) - for i in xrange(16, 64): + for i in range(16, 64): s0 = rightrotate(w[i-15], 7) ^ rightrotate(w[i-15], 18) ^ (w[i-15] >> 3) s1 = rightrotate(w[i-2], 17) ^ rightrotate(w[i-2], 19) ^ (w[i-2] >> 10) w.append((w[i-16] + s0 + w[i-7] + s1) % 2**32) @@ -42,15 +44,16 @@ class sha256(object): digest_size = 256//8 block_size = 512//8 - def __init__(self, data='', _=(initial_state, '', 0)): + def __init__(self, data=b'', _=(initial_state, b'', 0)): self.state, self.buf, self.length = _ self.update(data) def update(self, data): + data = ensure_bytes(data) state = self.state buf = self.buf + data - chunks = [buf[i:i + self.block_size] for i in xrange(0, len(buf) + 1, self.block_size)] + chunks = [buf[i:i + self.block_size] for i in range(0, len(buf) + 1, self.block_size)] for chunk in chunks[:-1]: state = process(state, chunk) @@ -59,17 +62,17 @@ def update(self, data): self.length += 8*len(data) - def copy(self, data=''): + def copy(self, data=b''): return self.__class__(data, (self.state, self.buf, self.length)) def digest(self): state = self.state - buf = self.buf + '\x80' + '\x00'*((self.block_size - 9 - len(self.buf)) % self.block_size) + struct.pack('>Q', self.length) + buf = self.buf + b'\x80' + b'\x00'*((self.block_size - 9 - len(self.buf)) % self.block_size) + struct.pack('>Q', self.length) - for chunk in [buf[i:i + self.block_size] for i in xrange(0, len(buf), self.block_size)]: + for chunk in [buf[i:i + self.block_size] for i in range(0, len(buf), self.block_size)]: state = process(state, chunk) return state def hexdigest(self): - return self.digest().encode('hex') + return bytes_to_hex(self.digest()) diff --git a/p2pool/bitcoin/stratum.py b/backend/p2pool/bitcoin/stratum.py similarity index 83% rename from p2pool/bitcoin/stratum.py rename to backend/p2pool/bitcoin/stratum.py index 6fe9c3b..09778fc 100644 --- a/p2pool/bitcoin/stratum.py +++ b/backend/p2pool/bitcoin/stratum.py @@ -1,4 +1,4 @@ -import random +import secrets import sys import time @@ -7,6 +7,7 @@ from p2pool.bitcoin import data as bitcoin_data, getwork from p2pool.util import expiring_dict, jsonrpc, pack +from p2pool.util.py3 import bytes_to_hex, hex_to_bytes def clip(num, bot, top): return min(top, max(bot, num)) @@ -41,7 +42,7 @@ def rpc_subscribe(self, miner_version=None, session_id=None, *args): def rpc_authorize(self, username, password): if not hasattr(self, 'authorized'): # authorize can be called many times in one connection - print '>>>Authorize: %s from %s' % (username, self.transport.getPeer().host) + print('>>>Authorize: %s from %s' % (username, self.transport.getPeer().host)) self.authorized = username self.username = username.strip() @@ -66,9 +67,9 @@ def rpc_configure(self, extensions, extensionParameters): #pool can send mining.set_version_mask at any time if the pool mask changes if 'minimum-difficulty' in extensions: - print 'Extension method minimum-difficulty not implemented' + print('Extension method minimum-difficulty not implemented') if 'subscribe-extranonce' in extensions: - print 'Extension method subscribe-extranonce not implemented' + print('Extension method subscribe-extranonce not implemented') def _send_work(self): try: @@ -84,17 +85,17 @@ def _send_work(self): else: self.fixed_target = False self.target = x['share_target'] if self.target == None else max(x['min_share_target'], self.target) - jobid = str(random.randrange(2**128)) + jobid = str(secrets.randbits(128)) self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty(self.target)*self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None) self.other.svc_mining.rpc_notify( jobid, # jobid - getwork._swap4(pack.IntType(256).pack(x['previous_block'])).encode('hex'), # prevhash - x['coinb1'].encode('hex'), # coinb1 - x['coinb2'].encode('hex'), # coinb2 - [pack.IntType(256).pack(s).encode('hex') for s in x['merkle_link']['branch']], # merkle_branch - getwork._swap4(pack.IntType(32).pack(x['version'])).encode('hex'), # version - getwork._swap4(pack.IntType(32).pack(x['bits'].bits)).encode('hex'), # nbits - getwork._swap4(pack.IntType(32).pack(x['timestamp'])).encode('hex'), # ntime + bytes_to_hex(getwork._swap4(pack.IntType(256).pack(x['previous_block']))), # prevhash + bytes_to_hex(x['coinb1']), # coinb1 + bytes_to_hex(x['coinb2']), # coinb2 + [bytes_to_hex(pack.IntType(256).pack(s)) for s in x['merkle_link']['branch']], # merkle_branch + bytes_to_hex(getwork._swap4(pack.IntType(32).pack(x['version']))), # version + bytes_to_hex(getwork._swap4(pack.IntType(32).pack(x['bits'].bits))), # nbits + bytes_to_hex(getwork._swap4(pack.IntType(32).pack(x['timestamp']))), # ntime True, # clean_jobs ).addErrback(lambda err: None) self.handler_map[jobid] = x, got_response @@ -103,11 +104,11 @@ def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce, version_bit #asicboost: version_bits is the version mask that the miner used worker_name = worker_name.strip() if job_id not in self.handler_map: - print >>sys.stderr, '''Couldn't link returned work's job id with its handler. This should only happen if this process was recently restarted!''' + print('''Couldn't link returned work's job id with its handler. This should only happen if this process was recently restarted!''', file=sys.stderr) #self.other.svc_client.rpc_reconnect().addErrback(lambda err: None) return False x, got_response = self.handler_map[job_id] - coinb_nonce = extranonce2.decode('hex') + coinb_nonce = hex_to_bytes(extranonce2) assert len(coinb_nonce) == self.wb.COINBASE_NONCE_LENGTH new_packed_gentx = x['coinb1'] + coinb_nonce + x['coinb2'] @@ -127,9 +128,9 @@ def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce, version_bit version=nversion, previous_block=x['previous_block'], merkle_root=bitcoin_data.check_merkle_link(bitcoin_data.hash256(new_packed_gentx), x['merkle_link']), # new_packed_gentx has witness data stripped - timestamp=pack.IntType(32).unpack(getwork._swap4(ntime.decode('hex'))), + timestamp=pack.IntType(32).unpack(getwork._swap4(hex_to_bytes(ntime))), bits=x['bits'], - nonce=pack.IntType(32).unpack(getwork._swap4(nonce.decode('hex'))), + nonce=pack.IntType(32).unpack(getwork._swap4(hex_to_bytes(nonce))), ) result = got_response(header, worker_name, coinb_nonce, self.target) @@ -143,7 +144,7 @@ def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce, version_bit self.target = int(self.target * clip((time.time() - old_time)/(len(self.recent_shares)*self.share_rate), 0.5, 2.) + 0.5) newtarget = clip(self.target, self.wb.net.SANE_TARGET_RANGE[0], self.wb.net.SANE_TARGET_RANGE[1]) if newtarget != self.target: - print "Clipping target from %064x to %064x" % (self.target, newtarget) + print("Clipping target from %064x to %064x" % (self.target, newtarget)) self.target = newtarget self.target = max(x['min_share_target'], self.target) self.recent_shares = [time.time()] diff --git a/p2pool/bitcoin/worker_interface.py b/backend/p2pool/bitcoin/worker_interface.py similarity index 76% rename from p2pool/bitcoin/worker_interface.py rename to backend/p2pool/bitcoin/worker_interface.py index 39dd9c2..938f99b 100644 --- a/p2pool/bitcoin/worker_interface.py +++ b/backend/p2pool/bitcoin/worker_interface.py @@ -1,6 +1,6 @@ -from __future__ import division -import StringIO + +import io import json import random import sys @@ -10,6 +10,7 @@ import p2pool from p2pool.bitcoin import data as bitcoin_data, getwork from p2pool.util import expiring_dict, jsonrpc, pack, variable +from p2pool.util.py3 import ensure_text class _Provider(object): def __init__(self, parent, long_poll): @@ -39,17 +40,20 @@ def __init__(self, worker_bridge): self.worker_bridge = worker_bridge self.worker_views = {} - + self.merkle_root_to_handler = expiring_dict.ExpiringDict(300) - + + def stop(self): + self.merkle_root_to_handler.stop() + def attach_to(self, res, get_handler=None): - res.putChild('', _GETableServer(_Provider(self, long_poll=False), get_handler)) - + res.putChild(b'', _GETableServer(_Provider(self, long_poll=False), get_handler)) + def repost(request): - request.content = StringIO.StringIO(json.dumps(dict(id=0, method='getwork'))) + request.content = io.BytesIO(json.dumps(dict(id=0, method='getwork')).encode('utf-8')) return s.render_POST(request) s = _GETableServer(_Provider(self, long_poll=True), repost) - res.putChild('long-polling', s) + res.putChild(b'long-polling', s) @defer.inlineCallbacks def _getwork(self, request, data, long_poll): @@ -62,40 +66,45 @@ def _getwork(self, request, data, long_poll): if data is not None: header = getwork.decode_data(data) if header['merkle_root'] not in self.merkle_root_to_handler: - print >>sys.stderr, '''Couldn't link returned work's merkle root with its handler. This should only happen if this process was recently restarted!''' + print('''Couldn't link returned work's merkle root with its handler. This should only happen if this process was recently restarted!''', file=sys.stderr) defer.returnValue(False) - defer.returnValue(self.merkle_root_to_handler[header['merkle_root']](header, request.getUser() if request.getUser() is not None else '', '\0'*self.worker_bridge.COINBASE_NONCE_LENGTH)) + handler, pseudoshare_target = self.merkle_root_to_handler[header['merkle_root']] + request_user = request.getUser() if request.getUser() is not None else '' + request_user = ensure_text(request_user, 'utf-8') if request_user else '' + defer.returnValue(handler(header, request_user, b'\0'*self.worker_bridge.COINBASE_NONCE_LENGTH, pseudoshare_target)) if p2pool.DEBUG: id = random.randrange(1000, 10000) - print 'POLL %i START is_long_poll=%r user_agent=%r user=%r' % (id, long_poll, request.getHeader('User-Agent'), request.getUser()) + print('POLL %i START is_long_poll=%r user_agent=%r user=%r' % (id, long_poll, request.getHeader('User-Agent'), request.getUser())) if long_poll: request_id = request.getClientIP(), request.getHeader('Authorization') if self.worker_views.get(request_id, self.worker_bridge.new_work_event.times) != self.worker_bridge.new_work_event.times: if p2pool.DEBUG: - print 'POLL %i PUSH' % (id,) + print('POLL %i PUSH' % (id,)) else: if p2pool.DEBUG: - print 'POLL %i WAITING' % (id,) + print('POLL %i WAITING' % (id,)) yield self.worker_bridge.new_work_event.get_deferred() self.worker_views[request_id] = self.worker_bridge.new_work_event.times - x, handler = self.worker_bridge.get_work(*self.worker_bridge.preprocess_request(request.getUser() if request.getUser() is not None else '')) + request_user = request.getUser() if request.getUser() is not None else '' + request_user = ensure_text(request_user, 'utf-8') if request_user else '' + x, handler = self.worker_bridge.get_work(*self.worker_bridge.preprocess_request(request_user)) res = getwork.BlockAttempt( version=x['version'], previous_block=x['previous_block'], - merkle_root=bitcoin_data.check_merkle_link(bitcoin_data.hash256(x['coinb1'] + '\0'*self.worker_bridge.COINBASE_NONCE_LENGTH + x['coinb2']), x['merkle_link']), + merkle_root=bitcoin_data.check_merkle_link(bitcoin_data.hash256(x['coinb1'] + b'\0'*self.worker_bridge.COINBASE_NONCE_LENGTH + x['coinb2']), x['merkle_link']), timestamp=x['timestamp'], bits=x['bits'], share_target=x['share_target'], ) assert res.merkle_root not in self.merkle_root_to_handler - self.merkle_root_to_handler[res.merkle_root] = handler + self.merkle_root_to_handler[res.merkle_root] = (handler, res.share_target) if p2pool.DEBUG: - print 'POLL %i END identifier=%i' % (id, self.worker_bridge.new_work_event.times) + print('POLL %i END identifier=%i' % (id, self.worker_bridge.new_work_event.times)) extra_params = {} if request.getHeader('User-Agent') == 'Jephis PIC Miner': diff --git a/p2pool/data.py b/backend/p2pool/data.py similarity index 88% rename from p2pool/data.py rename to backend/p2pool/data.py index 471da67..be95b68 100644 --- a/p2pool/data.py +++ b/backend/p2pool/data.py @@ -1,6 +1,7 @@ -from __future__ import division + import hashlib +from functools import lru_cache import os import random import sys @@ -13,11 +14,12 @@ import p2pool from p2pool.bitcoin import data as bitcoin_data, script, sha256 from p2pool.util import math, forest, pack +from p2pool.util.py3 import bord, bytes_to_hex, hex_to_bytes, ensure_bytes def parse_bip0034(coinbase): - _, opdata = script.parse(coinbase).next() + _, opdata = next(script.parse(coinbase)) bignum = pack.IntType(len(opdata)*8).unpack(opdata) - if ord(opdata[-1]) & 0x80: + if bord(opdata[-1]) & 0x80: bignum = -bignum return (bignum,) @@ -29,12 +31,16 @@ def parse_bip0034(coinbase): ('length', pack.VarIntType()), ]) -def prefix_to_hash_link(prefix, const_ending=''): +def prefix_to_hash_link(prefix, const_ending=b''): + prefix = ensure_bytes(prefix) + const_ending = ensure_bytes(const_ending) assert prefix.endswith(const_ending), (prefix, const_ending) x = sha256.sha256(prefix) return dict(state=x.state, extra_data=x.buf[:max(0, len(x.buf)-len(const_ending))], length=x.length//8) -def check_hash_link(hash_link, data, const_ending=''): +def check_hash_link(hash_link, data, const_ending=b''): + data = ensure_bytes(data) + const_ending = ensure_bytes(const_ending) extra_length = hash_link['length'] % (512//8) assert len(hash_link['extra_data']) == max(0, extra_length - len(const_ending)) extra = (hash_link['extra_data'] + const_ending)[len(hash_link['extra_data']) + len(const_ending) - extra_length:] @@ -48,6 +54,13 @@ def check_hash_link(hash_link, data, const_ending=''): ('contents', pack.VarStrType()), ]) +class TextVarStrType(pack.VarStrType): + def read(self, file): + return pack.VarStrType.read(self, file).decode('ascii') + + def write(self, file, item): + pack.VarStrType.write(self, file, ensure_bytes(item, 'ascii')) + def load_share(share, net, peer_addr): assert peer_addr is None or isinstance(peer_addr, tuple) if share['type'] in share_versions: @@ -68,18 +81,19 @@ def is_segwit_activated(version, net): # Old P2Pool Defcoin shares used JP's P2PK developer donation script. Version # 36 keeps old shares verifiable, but removes the spendable donation output from # newly mined share templates. -LEGACY_DONATION_SCRIPT = '4104ffd03de44a6e11b9917f3a29f9443283d9871c9d743ef30d5eddcd37094b64d1b3d8090496b53256786bf5c82932ec23c3b74d9f05a6f95a8b5529352656664bac'.decode('hex') +LEGACY_DONATION_SCRIPT = bytes.fromhex('4104ffd03de44a6e11b9917f3a29f9443283d9871c9d743ef30d5eddcd37094b64d1b3d8090496b53256786bf5c82932ec23c3b74d9f05a6f95a8b5529352656664bac') DONATION_SCRIPT = LEGACY_DONATION_SCRIPT -DUSTFIX_PADDING_SCRIPT = '\x6a\x40' + 'Defcoin P2Pool dustfix v36'.ljust(64, '\0') +DUSTFIX_PADDING_SCRIPT = b'\x6a\x40' + b'Defcoin P2Pool dustfix v36'.ljust(64, b'\0') def make_gentx_before_refhash(fixed_tail_script): - return pack.VarStrType().pack(fixed_tail_script) + pack.IntType(64).pack(0) + pack.VarStrType().pack('\x6a\x28' + pack.IntType(256).pack(0) + pack.IntType(64).pack(0))[:3] + return pack.VarStrType().pack(fixed_tail_script) + pack.IntType(64).pack(0) + pack.VarStrType().pack(b'\x6a\x28' + pack.IntType(256).pack(0) + pack.IntType(64).pack(0))[:3] def dustfix_flag_day_enabled(net): return getattr(net, 'NAME', None) == 'defcoin' and os.environ.get( 'DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY', '').lower() in ( '1', 'true', 'yes', 'on') +@lru_cache(maxsize=16) def donation_script_to_address(net, script=DONATION_SCRIPT): try: return bitcoin_data.script2_to_address( @@ -129,12 +143,12 @@ def get_dynamic_types(cls, net): ('previous_share_hash', pack.PossiblyNoneType(0, pack.IntType(256))), ('coinbase', pack.VarStrType()), ('nonce', pack.IntType(32)), - ] + ([('address', pack.VarStrType())] + ] + ([('address', TextVarStrType())] if cls.VERSION >= 34 else [('pubkey_hash', pack.IntType(160))]) + [ ('subsidy', pack.IntType(64)), ('donation', pack.IntType(16)), - ('stale_info', pack.EnumType(pack.IntType(8), dict((k, {0: None, 253: 'orphan', 254: 'doa'}.get(k, 'unk%i' % (k,))) for k in xrange(256)))), + ('stale_info', pack.EnumType(pack.IntType(8), dict((k, {0: None, 253: 'orphan', 254: 'doa'}.get(k, 'unk%i' % (k,))) for k in range(256)))), ('desired_version', pack.VarIntType()), ]))] + ([segwit_data] if is_segwit_activated(cls.VERSION, net) else []) + ([ ('new_transaction_hashes', pack.ListType(pack.IntType(256))), @@ -244,7 +258,7 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta t4 = time.time() if all_transaction_stripped_size and p2pool.DEBUG: - print "Generating a share with %i bytes, %i WU (new: %i B, %i WU) in %i tx (%i new), plus est gentx of %i bytes/%i WU" % ( + print("Generating a share with %i bytes, %i WU (new: %i B, %i WU) in %i tx (%i new), plus est gentx of %i bytes/%i WU" % ( all_transaction_real_size, all_transaction_weight, new_transaction_size, @@ -252,11 +266,11 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta len(other_transaction_hashes), len(new_transaction_hashes), cls.gentx_size, - cls.gentx_weight) - print "Total block stripped size=%i B, full size=%i B, weight: %i WU" % ( + cls.gentx_weight)) + print("Total block stripped size=%i B, full size=%i B, weight: %i WU" % ( 80+all_transaction_stripped_size+cls.gentx_size, 80+all_transaction_real_size+cls.gentx_size, - 3*80+all_transaction_weight+cls.gentx_weight) + 3*80+all_transaction_weight+cls.gentx_weight)) included_transactions = set(other_transaction_hashes) removed_fees = [fee for tx_hash, fee in desired_other_transaction_hashes_and_fees if tx_hash not in included_transactions] @@ -271,9 +285,9 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta max(0, min(height, net.REAL_CHAIN_LENGTH) - 1), 65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target), ) - assert total_weight == sum(weights.itervalues()) + donation_weight, (total_weight, sum(weights.itervalues()) + donation_weight) + assert total_weight == sum(weights.values()) + donation_weight, (total_weight, sum(weights.values()) + donation_weight) - amounts = dict((script, share_data['subsidy']*(199*weight)//(200*total_weight)) for script, weight in weights.iteritems()) # 99.5% goes according to weights prior to this share + amounts = dict((script, share_data['subsidy']*(199*weight)//(200*total_weight)) for script, weight in weights.items()) # 99.5% goes according to weights prior to this share if 'address' not in share_data: this_address = bitcoin_data.pubkey_hash_to_address( share_data['pubkey_hash'], net.PARENT.ADDRESS_VERSION, @@ -287,7 +301,7 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta # Old shares paid donation weight and rounding remainder to the legacy # P2PK developer donation address. New dust-fixed shares keep the same # total coinbase value but route the remainder to the block finder. - remainder = share_data['subsidy'] - sum(amounts.itervalues()) + remainder = share_data['subsidy'] - sum(amounts.values()) if cls.PAYS_LEGACY_DONATION: amounts[donation_address] = amounts.get(donation_address, 0) + remainder else: @@ -297,16 +311,16 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta this_address, net.PARENT) del(share_data['address']) - if sum(amounts.itervalues()) != share_data['subsidy'] or any(x < 0 for x in amounts.itervalues()): + if sum(amounts.values()) != share_data['subsidy'] or any(x < 0 for x in amounts.values()): raise ValueError() # block length limit, unlikely to ever be hit - dests = sorted(amounts.iterkeys(), key=lambda address: ( + dests = sorted(iter(amounts.keys()), key=lambda address: ( donation_address is not None and address == donation_address, amounts[address], address))[-4000:] if len(dests) >= 200: - print "found %i payment dests. Antminer S9s may crash when this is close to 226." % len(dests) + print("found %i payment dests. Antminer S9s may crash when this is close to 226." % len(dests)) segwit_activated = is_segwit_activated(cls.VERSION, net) if segwit_data is None and known_txs is None: @@ -317,7 +331,7 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta share_txs = [(known_txs[h], bitcoin_data.get_txid(known_txs[h]), h) for h in other_transaction_hashes] segwit_data = dict(txid_merkle_link=bitcoin_data.calculate_merkle_link([None] + [tx[1] for tx in share_txs], 0), wtxid_merkle_root=bitcoin_data.merkle_hash([0] + [bitcoin_data.get_wtxid(tx[0], tx[1], tx[2]) for tx in share_txs])) if segwit_activated and segwit_data is not None: - witness_reserved_value_str = '[P2Pool]'*4 + witness_reserved_value_str = b'[P2Pool]'*4 witness_reserved_value = pack.IntType(256).unpack(witness_reserved_value_str) witness_commitment_hash = bitcoin_data.get_witness_commitment_hash(segwit_data['wtxid_merkle_root'], witness_reserved_value) @@ -340,14 +354,14 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta share_info['transaction_hash_refs'] = transaction_hash_refs if previous_share != None and desired_timestamp > previous_share.timestamp + 180: - print "Warning: Previous share's timestamp is %i seconds old." % int(desired_timestamp - previous_share.timestamp) - print "Make sure your system clock is accurate, and ensure that you're connected to decent peers." - print "If your clock is more than 300 seconds behind, it can result in orphaned shares." - print "(It's also possible that this share is just taking a long time to mine.)" + print("Warning: Previous share's timestamp is %i seconds old." % int(desired_timestamp - previous_share.timestamp)) + print("Make sure your system clock is accurate, and ensure that you're connected to decent peers.") + print("If your clock is more than 300 seconds behind, it can result in orphaned shares.") + print("(It's also possible that this share is just taking a long time to mine.)") if previous_share != None and previous_share.timestamp > int(time.time()) + 3: - print "WARNING! Previous share's timestamp is %i seconds in the future. This is not normal." % \ - int(previous_share.timestamp - (int(time.time()))) - print "Make sure your system clock is accurate. Errors beyond 300 sec result in orphaned shares." + print("WARNING! Previous share's timestamp is %i seconds in the future. This is not normal." % \ + int(previous_share.timestamp - (int(time.time())))) + print("Make sure your system clock is accurate. Errors beyond 300 sec result in orphaned shares.") if segwit_activated: share_info['segwit_data'] = segwit_data @@ -367,12 +381,12 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta sequence=None, script=share_data['coinbase'], )], - tx_outs=([dict(value=0, script='\x6a\x24\xaa\x21\xa9\xed' \ + tx_outs=([dict(value=0, script=b'\x6a\x24\xaa\x21\xa9\xed' \ + pack.IntType(256).pack( witness_commitment_hash))] if segwit_activated else []) \ + payouts \ - + [dict(value=0, script='\x6a\x28' + cls.get_ref_hash( + + [dict(value=0, script=b'\x6a\x28' + cls.get_ref_hash( net, share_info, ref_merkle_link) \ + pack.IntType(64).pack(last_txout_nonce))], lock_time=0, @@ -395,13 +409,13 @@ def get_share(header, last_txout_nonce=last_txout_nonce): assert share.header == header # checks merkle_root return share t5 = time.time() - if p2pool.BENCH: print "%8.3f ms for data.py:generate_transaction(). Parts: %8.3f %8.3f %8.3f %8.3f %8.3f " % ( + if p2pool.BENCH: print("%8.3f ms for data.py:generate_transaction(). Parts: %8.3f %8.3f %8.3f %8.3f %8.3f " % ( (t5-t0)*1000., (t1-t0)*1000., (t2-t1)*1000., (t3-t2)*1000., (t4-t3)*1000., - (t5-t4)*1000.) + (t5-t4)*1000.)) return share_info, gentx, other_transaction_hashes, get_share @classmethod @@ -506,11 +520,11 @@ def as_share(self): def iter_transaction_hash_refs(self): try: - return zip(self.share_info['transaction_hash_refs'][::2], self.share_info['transaction_hash_refs'][1::2]) + return list(zip(self.share_info['transaction_hash_refs'][::2], self.share_info['transaction_hash_refs'][1::2])) except AttributeError: - return zip() + return list(zip()) except KeyError: - return zip() + return list(zip()) def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=None): from p2pool import p2p @@ -531,7 +545,7 @@ def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=No if not ( type(self) is DonationDustFixedShare and dustfix_flag_day_enabled(self.net) - ) and counts.get(self.VERSION, 0) < sum(counts.itervalues())*60//100: + ) and counts.get(self.VERSION, 0) < sum(counts.values())*60//100: raise p2p.PeerMisbehavingError('switch without enough hash power upgraded') else: raise p2p.PeerMisbehavingError('''%s can't follow %s''' % (type(self).__name__, type(previous_share).__name__)) @@ -543,7 +557,7 @@ def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=No else: other_tx_hashes = [] if known_txs is not None and not isinstance(known_txs, dict): - print "Performing maybe-unnecessary packing and hashing" + print("Performing maybe-unnecessary packing and hashing") known_txs = dict((bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)), tx) for tx in known_txs) share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net, @@ -563,16 +577,16 @@ def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=No self.address) if self.share_data['subsidy'] > max_subsidy: self.naughty = 1 - print "Excessive block reward in share! Naughty. " + details + print("Excessive block reward in share! Naughty. " + details) elif self.share_data['subsidy'] < max_subsidy: - print "Strange, we received a share that did not include as many coins in the block reward as was allowed. " - print "While permitted by the protocol, this causes coins to be lost forever if mined as a block, and costs us money." - print details + print("Strange, we received a share that did not include as many coins in the block reward as was allowed. ") + print("While permitted by the protocol, this causes coins to be lost forever if mined as a block, and costs us money.") + print(details) if self.share_data['previous_share_hash'] and tracker.items[self.share_data['previous_share_hash']].naughty: - print "naughty ancestor found %i generations ago" % tracker.items[self.share_data['previous_share_hash']].naughty + print("naughty ancestor found %i generations ago" % tracker.items[self.share_data['previous_share_hash']].naughty) # I am not easily angered ... - print "I will not fail to punish children and grandchildren to the third and fourth generation for the sins of their parents." + print("I will not fail to punish children and grandchildren to the third and fourth generation for the sins of their parents.") self.naughty = 1 + tracker.items[self.share_data['previous_share_hash']].naughty if self.naughty > 6: self.naughty = 0 @@ -581,8 +595,8 @@ def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=No if share_info != self.share_info: raise ValueError('share_info invalid') if bitcoin_data.get_txid(gentx) != self.gentx_hash: - print bitcoin_data.get_txid(gentx), self.gentx_hash - print gentx + print(bitcoin_data.get_txid(gentx), self.gentx_hash) + print(gentx) raise ValueError('''gentx doesn't match hash_link''') if self.VERSION < 34: if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link: # the other hash commitments are checked in the share_info assertion @@ -599,11 +613,11 @@ def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=No _diff = self.net.PARENT.DUMB_SCRYPT_DIFF*float( bitcoin_data.target_to_difficulty(self.target)) if not self.naughty: - print("Received good share: diff=%.2e hash=%064x miner=%s" % - (_diff, self.hash, self.address)) + print(("Received good share: diff=%.2e hash=%064x miner=%s" % + (_diff, self.hash, self.address))) else: - print("Received naughty=%i share: diff=%.2e hash=%064x miner=%s" % - (self.naughty, _diff, self.hash, self.address)) + print(("Received naughty=%i share: diff=%.2e hash=%064x miner=%s" % + (self.naughty, _diff, self.hash, self.address))) return gentx # only used by as_block def get_other_tx_hashes(self, tracker): @@ -708,25 +722,34 @@ def get_delta(self, element): from p2pool.bitcoin import data as bitcoin_data share = self.tracker.items[element] att = bitcoin_data.target_to_average_attempts(share.target) - return (1, {share.address: att*(65535-share.share_data['donation'])}, + payout_key = getattr(share, 'address', share.new_script) + return (1, {payout_key: att*(65535-share.share_data['donation'])}, att*65535, att*share.share_data['donation']) - def combine_deltas(self, (share_count1, weights1, total_weight1, total_donation_weight1), (share_count2, weights2, total_weight2, total_donation_weight2)): + def combine_deltas(self, xxx_todo_changeme, xxx_todo_changeme1): + (share_count1, weights1, total_weight1, total_donation_weight1) = xxx_todo_changeme + (share_count2, weights2, total_weight2, total_donation_weight2) = xxx_todo_changeme1 return share_count1 + share_count2, math.add_dicts(weights1, weights2), total_weight1 + total_weight2, total_donation_weight1 + total_donation_weight2 - def initial_solution(self, start, (max_shares, desired_weight)): + def initial_solution(self, start, xxx_todo_changeme2): + (max_shares, desired_weight) = xxx_todo_changeme2 assert desired_weight % 65535 == 0, divmod(desired_weight, 65535) return 0, None, 0, 0 - def apply_delta(self, (share_count1, weights_list, total_weight1, total_donation_weight1), (share_count2, weights2, total_weight2, total_donation_weight2), (max_shares, desired_weight)): + def apply_delta(self, xxx_todo_changeme3, xxx_todo_changeme4, xxx_todo_changeme5): + (share_count1, weights_list, total_weight1, total_donation_weight1) = xxx_todo_changeme3 + (share_count2, weights2, total_weight2, total_donation_weight2) = xxx_todo_changeme4 + (max_shares, desired_weight) = xxx_todo_changeme5 if total_weight1 + total_weight2 > desired_weight and share_count2 == 1: assert (desired_weight - total_weight1) % 65535 == 0 - script, = weights2.iterkeys() + script, = iter(weights2.keys()) new_weights = {script: (desired_weight - total_weight1)//65535*weights2[script]//(total_weight2//65535)} return share_count1 + share_count2, (weights_list, new_weights), desired_weight, total_donation_weight1 + (desired_weight - total_weight1)//65535*total_donation_weight2//(total_weight2//65535) return share_count1 + share_count2, (weights_list, weights2), total_weight1 + total_weight2, total_donation_weight1 + total_donation_weight2 - def judge(self, (share_count, weights_list, total_weight, total_donation_weight), (max_shares, desired_weight)): + def judge(self, xxx_todo_changeme6, xxx_todo_changeme7): + (share_count, weights_list, total_weight, total_donation_weight) = xxx_todo_changeme6 + (max_shares, desired_weight) = xxx_todo_changeme7 if share_count > max_shares or total_weight > desired_weight: return 1 elif share_count == max_shares or total_weight == desired_weight: @@ -734,7 +757,9 @@ def judge(self, (share_count, weights_list, total_weight, total_donation_weight) else: return -1 - def finalize(self, (share_count, weights_list, total_weight, total_donation_weight), (max_shares, desired_weight)): + def finalize(self, xxx_todo_changeme8, xxx_todo_changeme9): + (share_count, weights_list, total_weight, total_donation_weight) = xxx_todo_changeme8 + (max_shares, desired_weight) = xxx_todo_changeme9 assert share_count <= max_shares and total_weight <= desired_weight assert share_count == max_shares or total_weight == desired_weight return math.add_dicts(*math.flatten_linked_list(weights_list)), total_weight, total_donation_weight @@ -798,7 +823,7 @@ def think(self, block_rel_height_func, block_abs_height_func, previous_block, bi if bad_share.peer_addr is not None: bad_peer_addresses.add(bad_share.peer_addr) if p2pool.DEBUG: - print "BAD", bad + print("BAD", bad) try: self.remove(bad) except NotImplementedError: @@ -827,9 +852,9 @@ def think(self, block_rel_height_func, block_abs_height_func, previous_block, bi # decide best tree decorated_tails = sorted((self.score(max(self.verified.tails[tail_hash], key=self.verified.get_work), block_rel_height_func), tail_hash) for tail_hash in self.verified.tails) if p2pool.DEBUG: - print len(decorated_tails), 'tails:' + print(len(decorated_tails), 'tails:') for score, tail_hash in decorated_tails: - print format_hash(tail_hash), score + print(format_hash(tail_hash), score) best_tail_score, best_tail = decorated_tails[-1] if decorated_tails else (None, None) # decide best verified head @@ -850,12 +875,12 @@ def think(self, block_rel_height_func, block_abs_height_func, previous_block, bi punish_aggressively = traditional_sort[-1][0][2] if traditional_sort else False if p2pool.DEBUG: - print len(decorated_heads), 'heads. Top 10:' + print(len(decorated_heads), 'heads. Top 10:') for score, head_hash in decorated_heads[-10:]: - print ' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score - print "Traditional sort:" + print(' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score) + print("Traditional sort:") for score, head_hash in traditional_sort[-10:]: - print ' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score + print(' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score) best_head_score, best = decorated_heads[-1] if decorated_heads else (None, None) punish = 0 @@ -863,7 +888,7 @@ def think(self, block_rel_height_func, block_abs_height_func, previous_block, bi best_share = self.items[best] punish, punish_reason = best_share.should_punish_reason(previous_block, bits, self, known_txs) while punish > 0: - print 'Punishing share for %r! Jumping from %s to %s!' % (punish_reason, format_hash(best), format_hash(best_share.previous_hash)) + print('Punishing share for %r! Jumping from %s to %s!' % (punish_reason, format_hash(best), format_hash(best_share.previous_hash))) best = best_share.previous_hash best_share = self.items[best] punish, punish_reason = best_share.should_punish_reason(previous_block, bits, self, known_txs) @@ -876,7 +901,7 @@ def best_descendent(hsh, limit=20): return (best_kids[-1][0]+1, best_kids[-1][1]) try: gens, hsh = best_descendent(best) - if p2pool.DEBUG: print "best_descendent went %i generations for share %s from %s" % (gens, format_hash(hsh), format_hash(best)) + if p2pool.DEBUG: print("best_descendent went %i generations for share %s from %s" % (gens, format_hash(hsh), format_hash(best))) best = hsh best_share = self.items[best] except: @@ -895,9 +920,9 @@ def best_descendent(hsh, limit=20): target_cutoff = 2**256-1 if p2pool.DEBUG: - print 'Desire %i shares. Cutoff: %s old diff>%.2f' % (len(desired), math.format_dt(time.time() - timestamp_cutoff), bitcoin_data.target_to_difficulty(target_cutoff)) + print('Desire %i shares. Cutoff: %s old diff>%.2f' % (len(desired), math.format_dt(time.time() - timestamp_cutoff), bitcoin_data.target_to_difficulty(target_cutoff))) for peer_addr, hash, ts, targ in desired: - print ' ', None if peer_addr is None else '%s:%i' % peer_addr, format_hash(hash), math.format_dt(time.time() - ts), bitcoin_data.target_to_difficulty(targ), ts >= timestamp_cutoff, targ <= target_cutoff + print(' ', None if peer_addr is None else '%s:%i' % peer_addr, format_hash(hash), math.format_dt(time.time() - ts), bitcoin_data.target_to_difficulty(targ), ts >= timestamp_cutoff, targ <= target_cutoff) return best, [(peer_addr, hash) for peer_addr, hash, ts, targ in desired if ts >= timestamp_cutoff], decorated_heads, bad_peer_addresses, punish_aggressively @@ -919,9 +944,9 @@ def update_min_protocol_version(counts, share): minpver = getattr(share.net, 'MINIMUM_PROTOCOL_VERSION', 1400) newminpver = share.MINIMUM_PROTOCOL_VERSION if (counts is not None) and (minpver < newminpver): - if counts.get(share.VERSION, 0) >= sum(counts.itervalues())*95//100: + if counts.get(share.VERSION, 0) >= sum(counts.values())*95//100: share.net.MINIMUM_PROTOCOL_VERSION = newminpver # Reject peers running obsolete nodes - print 'Setting MINIMUM_PROTOCOL_VERSION = %d' % (newminpver) + print('Setting MINIMUM_PROTOCOL_VERSION = %d' % (newminpver)) def get_pool_attempts_per_second(tracker, previous_share_hash, dist, min_work=False, integer=False): assert dist >= 2 @@ -948,7 +973,7 @@ def get_stale_counts(tracker, share_hash, lookbehind, rates=False): res[s] = res.get(s, 0) + bitcoin_data.target_to_average_attempts(share.target) if rates: dt = tracker.items[share_hash].timestamp - tracker.items[tracker.get_nth_parent_hash(share_hash, lookbehind - 1)].timestamp - res = dict((k, v/dt) for k, v in res.iteritems()) + res = dict((k, v/dt) for k, v in res.items()) return res def get_user_stale_props(tracker, share_hash, lookbehind, net): @@ -967,13 +992,13 @@ def get_user_stale_props(tracker, share_hash, lookbehind, net): stale += 1 total += 1 res[key] = stale, total - return dict((pubkey_hash, stale/total) for pubkey_hash, (stale, total) in res.iteritems()) + return dict((pubkey_hash, stale/total) for pubkey_hash, (stale, total) in res.items()) def get_expected_payouts(tracker, best_share_hash, block_target, subsidy, net): weights, total_weight, donation_weight = tracker.get_cumulative_weights(best_share_hash, min(tracker.get_height(best_share_hash), net.REAL_CHAIN_LENGTH), 65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target)) - res = dict((script, subsidy*weight//total_weight) for script, weight in weights.iteritems()) + res = dict((script, subsidy*weight//total_weight) for script, weight in weights.items()) best_share = tracker.items[best_share_hash] - remainder = subsidy - sum(res.itervalues()) + remainder = subsidy - sum(res.values()) if type(best_share).PAYS_LEGACY_DONATION: donation_addr = donation_script_to_address(net) res[donation_addr] = res.get(donation_addr, 0) + remainder @@ -993,10 +1018,10 @@ def get_warnings(tracker, best_share, net, bitcoind_getinfo, bitcoind_work_value desired_version_counts = get_desired_version_counts(tracker, best_share, min(net.CHAIN_LENGTH, 60*60//net.SHARE_PERIOD, tracker.get_height(best_share))) majority_desired_version = max(desired_version_counts, key=lambda k: desired_version_counts[k]) - if majority_desired_version not in share_versions and desired_version_counts[majority_desired_version] > sum(desired_version_counts.itervalues())/2: + if majority_desired_version not in share_versions and desired_version_counts[majority_desired_version] > sum(desired_version_counts.values())/2: res.append('A MAJORITY OF SHARES CONTAIN A VOTE FOR AN UNSUPPORTED SHARE IMPLEMENTATION! (v%i with %i%% support)\n' 'An upgrade is likely necessary. Check https://github.com/jtoomim/p2pool/tree/1mb_segwit or https://forum.bitcoin.com/pools/p2pool-decentralized-dos-resistant-trustless-censorship-resistant-pool-t69932-99999.html for more information.' % ( - majority_desired_version, 100*desired_version_counts[majority_desired_version]/sum(desired_version_counts.itervalues()))) + majority_desired_version, 100*desired_version_counts[majority_desired_version]/sum(desired_version_counts.values()))) if bitcoind_getinfo['warnings'] != '': if 'This is a pre-release test build' not in bitcoind_getinfo['warnings']: @@ -1031,7 +1056,7 @@ def __init__(self, prefix, net, share_cb, verified_hash_cb): with open(filename, 'rb') as f: for line in f: try: - type_id_str, data_hex = line.strip().split(' ') + type_id_str, data_hex = line.strip().split(b' ') type_id = int(type_id_str) if type_id == 0: pass @@ -1042,7 +1067,7 @@ def __init__(self, prefix, net, share_cb, verified_hash_cb): verified_hash_cb(verified_hash) verified_hashes.add(verified_hash) elif type_id == 5: - raw_share = share_type.unpack(data_hex.decode('hex')) + raw_share = share_type.unpack(hex_to_bytes(data_hex)) if raw_share['type'] < Share.VERSION: continue share = load_share(raw_share, self.net, None) @@ -1054,9 +1079,9 @@ def __init__(self, prefix, net, share_cb, verified_hash_cb): log.err(None, "HARMLESS error while reading saved shares, continuing where left off:") self.known = known # filename -> (set of share hashes, set of verified hashes) - self.known_desired = dict((k, (set(a), set(b))) for k, (a, b) in known.iteritems()) + self.known_desired = dict((k, (set(a), set(b))) for k, (a, b) in known.items()) - print "Share loading took %.3f seconds" % (time.time() - start) + print("Share loading took %.3f seconds" % (time.time() - start)) def _add_line(self, line): filenames, next = self.get_filenames_and_next() @@ -1066,23 +1091,23 @@ def _add_line(self, line): filename = next with open(filename, 'ab') as f: - f.write(line + '\n') + f.write(ensure_bytes(line, 'ascii') + b'\n') return filename def add_share(self, share): - for filename, (share_hashes, verified_hashes) in self.known.iteritems(): + for filename, (share_hashes, verified_hashes) in self.known.items(): if share.hash in share_hashes: break else: - filename = self._add_line("%i %s" % (5, share_type.pack(share.as_share()).encode('hex'))) + filename = self._add_line("%i %s" % (5, bytes_to_hex(share_type.pack(share.as_share())))) share_hashes, verified_hashes = self.known.setdefault(filename, (set(), set())) share_hashes.add(share.hash) share_hashes, verified_hashes = self.known_desired.setdefault(filename, (set(), set())) share_hashes.add(share.hash) def add_verified_hash(self, share_hash): - for filename, (share_hashes, verified_hashes) in self.known.iteritems(): + for filename, (share_hashes, verified_hashes) in self.known.items(): if share_hash in verified_hashes: break else: @@ -1097,20 +1122,20 @@ def get_filenames_and_next(self): return [os.path.join(self.dirname, self.filename + str(suffix)) for suffix in suffixes], os.path.join(self.dirname, self.filename + (str(suffixes[-1] + 1) if suffixes else str(0))) def forget_share(self, share_hash): - for filename, (share_hashes, verified_hashes) in self.known_desired.iteritems(): + for share_hashes, verified_hashes in self.known_desired.values(): if share_hash in share_hashes: share_hashes.remove(share_hash) self.check_remove() def forget_verified_share(self, share_hash): - for filename, (share_hashes, verified_hashes) in self.known_desired.iteritems(): + for share_hashes, verified_hashes in self.known_desired.values(): if share_hash in verified_hashes: verified_hashes.remove(share_hash) self.check_remove() def check_remove(self): to_remove = set() - for filename, (share_hashes, verified_hashes) in self.known_desired.iteritems(): + for filename, (share_hashes, verified_hashes) in self.known_desired.items(): #print filename, len(share_hashes) + len(verified_hashes) if not share_hashes and not verified_hashes: to_remove.add(filename) @@ -1118,4 +1143,4 @@ def check_remove(self): self.known.pop(filename) self.known_desired.pop(filename) os.remove(filename) - print "REMOVED", filename + print("REMOVED", filename) diff --git a/p2pool/main.py b/backend/p2pool/main.py similarity index 83% rename from p2pool/main.py rename to backend/p2pool/main.py index 97534c4..1944fc6 100644 --- a/p2pool/main.py +++ b/backend/p2pool/main.py @@ -1,4 +1,4 @@ -from __future__ import division + import base64 import gc @@ -9,7 +9,7 @@ import time import signal import traceback -import urlparse +import urllib.parse if '--iocp' in sys.argv: from twisted.internet import iocpreactor @@ -19,9 +19,10 @@ from twisted.python import log from nattraverso import portmapper, ipdiscover -import bitcoin.p2p as bitcoin_p2p, bitcoin.data as bitcoin_data -from bitcoin import stratum, worker_interface, helper -from util import fixargparse, jsonrpc, variable, deferral, math, logging, switchprotocol +from .bitcoin import p2p as bitcoin_p2p, data as bitcoin_data +from .bitcoin import stratum, worker_interface, helper +from .util import fixargparse, jsonrpc, variable, deferral, math, logging, switchprotocol +from .util.py3 import ensure_bytes from . import networks, web, work import p2pool, p2pool.data as p2pool_data, p2pool.node as p2pool_node @@ -62,12 +63,12 @@ def popleft(self): def updatestamp(self, n): self.stamp = n - def paytotal(self): + def paytotal(self, node): self.payouttotal = 0.0 - print("pubkeys.keys: %s" % pubkeys.keys) - for i in range(len(pubkeys.keys)): + print(("pubkeys.keys: %s" % self.keys)) + for i in range(len(self.keys)): self.payouttotal += node.get_current_txouts().get( - pubkeys.keys[i]['address'], 0) * 1e-8 + self.keys[i]['address'], 0) * 1e-8 return self.payouttotal def getpaytotal(self): @@ -78,22 +79,22 @@ def getpaytotal(self): @defer.inlineCallbacks def main(args, net, datadir_path, merged_urls, worker_endpoint): try: - print 'p2pool (version %s)' % (p2pool.__version__,) - print + print('p2pool (version %s)' % (p2pool.__version__,)) + print() @defer.inlineCallbacks def connect_p2p(): # connect to bitcoind over bitcoin-p2p - print '''Testing bitcoind P2P connection to '%s:%s'...''' % (args.bitcoind_address, args.bitcoind_p2p_port) + print('''Testing bitcoind P2P connection to '%s:%s'...''' % (args.bitcoind_address, args.bitcoind_p2p_port)) factory = bitcoin_p2p.ClientFactory(net.PARENT) reactor.connectTCP(args.bitcoind_address, args.bitcoind_p2p_port, factory) def long(): - print ''' ...taking a while. Common reasons for this include all of bitcoind's connection slots being used...''' - long_dc = reactor.callLater(5, long) + print(''' ...taking a while. Common reasons for this include all of bitcoind's connection slots being used...''') + long_dc = reactor.callLater(5, int) yield factory.getProtocol() # waits until handshake is successful if not long_dc.called: long_dc.cancel() - print ' ...success!' - print + print(' ...success!') + print() defer.returnValue(factory) if args.testnet: # establish p2p connection first if testnet so bitcoind can work without connections @@ -101,8 +102,10 @@ def long(): # connect to bitcoind over JSON-RPC and do initial getmemorypool url = '%s://%s:%i/' % ('https' if args.bitcoind_rpc_ssl else 'http', args.bitcoind_address, args.bitcoind_rpc_port) - print '''Testing bitcoind RPC connection to '%s' with username '%s'...''' % (url, args.bitcoind_rpc_username) - bitcoind = jsonrpc.HTTPProxy(url, dict(Authorization='Basic ' + base64.b64encode(args.bitcoind_rpc_username + ':' + args.bitcoind_rpc_password)), timeout=30) + print('''Testing bitcoind RPC connection to '%s' with username '%s'...''' % (url, args.bitcoind_rpc_username)) + rpc_auth = '%s:%s' % (args.bitcoind_rpc_username, args.bitcoind_rpc_password) + rpc_auth_header = 'Basic ' + base64.b64encode(ensure_bytes(rpc_auth, 'utf-8')).decode('ascii') + bitcoind = jsonrpc.HTTPProxy(url, dict(Authorization=rpc_auth_header), timeout=30) yield helper.check(bitcoind, net, args) temp_work = yield helper.getwork(bitcoind) @@ -113,55 +116,55 @@ def poll_warnings(): yield poll_warnings() deferral.RobustLoopingCall(poll_warnings).start(20*60) - print ' ...success!' - print ' Current block hash: %x' % (temp_work['previous_block'],) - print ' Current block height: %i' % (temp_work['height'] - 1,) - print + print(' ...success!') + print(' Current block hash: %x' % (temp_work['previous_block'],)) + print(' Current block height: %i' % (temp_work['height'] - 1,)) + print() if not args.testnet: factory = yield connect_p2p() - print 'Determining payout address...' + print('Determining payout address...') pubkeys = keypool() if args.pubkey_hash is None and args.address != 'dynamic': address_path = os.path.join(datadir_path, 'cached_payout_address') if os.path.exists(address_path): - with open(address_path, 'rb') as f: - address = f.read().strip('\r\n') - print ' Loaded cached address: %s...' % (address,) + with open(address_path, encoding='utf-8') as f: + address = f.read().strip() + print(' Loaded cached address: %s...' % (address,)) else: address = None if address is not None: res = yield deferral.retry('Error validating cached address:', 5)(lambda: bitcoind.rpc_validateaddress(address))() if not res['isvalid'] or not res['ismine']: - print ' Cached address is either invalid or not controlled by local bitcoind!' + print(' Cached address is either invalid or not controlled by local bitcoind!') address = None if address is None: - print ' Getting payout address from bitcoind...' + print(' Getting payout address from bitcoind...') address = yield deferral.retry('Error getting payout address from bitcoind:', 5)(lambda: bitcoind.rpc_getaccountaddress('p2pool'))() - with open(address_path, 'wb') as f: + with open(address_path, 'w', encoding='utf-8') as f: f.write(address) my_address = address - print(' ...success! Payout address: %s' % my_address) + print((' ...success! Payout address: %s' % my_address)) print() pubkeys.addkey({'address': my_address}) elif args.address != 'dynamic': my_address = args.address - print(' ...success! Payout address: %s' % my_address) + print((' ...success! Payout address: %s' % my_address)) print() pubkeys.addkey({'address': my_address}) else: - print ' Entering dynamic address mode.' + print(' Entering dynamic address mode.') if args.numaddresses < 2: - print ' ERROR: Can not use fewer than 2 addresses in dynamic mode. Resetting to 2.' + print(' ERROR: Can not use fewer than 2 addresses in dynamic mode. Resetting to 2.') args.numaddresses = 2 for i in range(args.numaddresses): address = yield deferral.retry('Error getting a dynamic address from bitcoind:', 5)(lambda: bitcoind.rpc_getnewaddress('p2pool'))() @@ -172,25 +175,25 @@ def poll_warnings(): my_address = pubkeys.keys[0]['address'] for i in range(len(pubkeys.keys)): - print(' ...payout %d: %s' % (i, pubkeys[i]['address'])) + print((' ...payout %d: %s' % (i, pubkeys[i]['address']))) - print "Loading shares..." + print("Loading shares...") shares = {} known_verified = set() def share_cb(share): share.time_seen = 0 # XXX shares[share.hash] = share if len(shares) % 1000 == 0 and shares: - print " %i" % (len(shares),) + print(" %i" % (len(shares),)) ss = p2pool_data.ShareStore(os.path.join(datadir_path, 'shares.'), net, share_cb, known_verified.add) - print " ...done loading %i shares (%i verified)!" % (len(shares), len(known_verified)) - print + print(" ...done loading %i shares (%i verified)!" % (len(shares), len(known_verified))) + print() - print 'Initializing work...' + print('Initializing work...') global gnode - gnode = node = p2pool_node.Node(factory, bitcoind, shares.values(), known_verified, net) + gnode = node = p2pool_node.Node(factory, bitcoind, list(shares.values()), known_verified, net) yield node.start() for share_hash in shares: @@ -215,11 +218,11 @@ def save_shares(): counts = p2pool_data.get_desired_version_counts(node.tracker, node.tracker.get_nth_parent_hash(previous_share.hash, net.CHAIN_LENGTH*9//10), net.CHAIN_LENGTH//10) p2pool_data.update_min_protocol_version(counts, best_share) - print ' ...success!' - print + print(' ...success!') + print() - print 'Joining p2pool network using port %i...' % (args.p2pool_port,) + print('Joining p2pool network using port %i...' % (args.p2pool_port,)) @defer.inlineCallbacks def parse(host): @@ -232,10 +235,10 @@ def parse(host): addrs = {} if os.path.exists(os.path.join(datadir_path, 'addrs')): try: - with open(os.path.join(datadir_path, 'addrs'), 'rb') as f: + with open(os.path.join(datadir_path, 'addrs'), encoding='utf-8') as f: addrs.update(dict((tuple(k), v) for k, v in json.loads(f.read()))) except: - print >>sys.stderr, 'error parsing addrs' + print('error parsing addrs', file=sys.stderr) for addr_df in map(parse, net.BOOTSTRAP_ADDRS): try: addr = yield addr_df @@ -263,12 +266,12 @@ def parse(host): node.p2p_node.start() def save_addrs(): - with open(os.path.join(datadir_path, 'addrs'), 'wb') as f: - f.write(json.dumps(node.p2p_node.addr_store.items())) + with open(os.path.join(datadir_path, 'addrs'), 'w', encoding='utf-8') as f: + f.write(json.dumps(list(node.p2p_node.addr_store.items()))) deferral.RobustLoopingCall(save_addrs).start(60) - print ' ...success!' - print + print(' ...success!') + print() if args.upnp: @defer.inlineCallbacks @@ -289,7 +292,7 @@ def upnp_thread(): # start listening for workers with a JSON-RPC server - print 'Listening for workers on %r port %i...' % (worker_endpoint[0], worker_endpoint[1]) + print('Listening for workers on %r port %i...' % (worker_endpoint[0], worker_endpoint[1])) wb = work.WorkerBridge(node, my_address, args.donation_percentage, merged_urls, args.worker_fee, args, pubkeys, @@ -305,23 +308,23 @@ def upnp_thread(): with open(os.path.join(os.path.join(datadir_path, 'ready_flag')), 'wb') as f: pass - print ' ...success!' - print + print(' ...success!') + print() # done! - print 'Started successfully!' - print 'Go to http://127.0.0.1:%i/ to view graphs and statistics!' % (worker_endpoint[1],) + print('Started successfully!') + print('Go to http://127.0.0.1:%i/ to view graphs and statistics!' % (worker_endpoint[1],)) if getattr(p2pool_data.PaddingBugfixShare, 'SUCCESSOR', None) is p2pool_data.DonationDustFixedShare: - print '''P2Pool developer donation output is disabled after Defcoin share version 36 activation.''' + print('''P2Pool developer donation output is disabled after Defcoin share version 36 activation.''') if args.donation_percentage > 1.1: - print '''Donating %.1f%% of work towards P2Pool's development. Thanks for the tip!''' % (args.donation_percentage,) + print('''Donating %.1f%% of work towards P2Pool's development. Thanks for the tip!''' % (args.donation_percentage,)) elif args.donation_percentage < .9: - print '''Donating %.1f%% of work towards P2Pool's development. Please donate to encourage further development of P2Pool!''' % (args.donation_percentage,) + print('''Donating %.1f%% of work towards P2Pool's development. Please donate to encourage further development of P2Pool!''' % (args.donation_percentage,)) else: - print '''Donating %.1f%% of work towards P2Pool's development. Thank you!''' % (args.donation_percentage,) - print 'You can increase this amount with --give-author argument! (or decrease it, if you must)' - print + print('''Donating %.1f%% of work towards P2Pool's development. Thank you!''' % (args.donation_percentage,)) + print('You can increase this amount with --give-author argument! (or decrease it, if you must)') + print() if hasattr(signal, 'SIGALRM'): @@ -338,7 +341,7 @@ class IRCClient(irc.IRCClient): channel = net.ANNOUNCE_CHANNEL def lineReceived(self, line): if p2pool.DEBUG: - print repr(line) + print(repr(line)) irc.IRCClient.lineReceived(self, line) def signedOn(self): self.in_channel = False @@ -378,7 +381,7 @@ def privmsg(self, user, channel, message): self._remember_message(message) def connectionLost(self, reason): node.tracker.verified.added.unwatch(self.watch_id) - print 'IRC connection lost:', reason.getErrorMessage() + print('IRC connection lost:', reason.getErrorMessage()) class IRCClientFactory(protocol.ReconnectingClientFactory): protocol = IRCClient reactor.connectTCP("irc.freenode.net", 6667, IRCClientFactory(), bindAddress=(worker_endpoint[0], 0)) @@ -396,7 +399,7 @@ def status_thread(): len(node.tracker.verified.items), len(node.tracker.items), len(node.p2p_node.peers), - sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming), + sum(1 for peer in node.p2p_node.peers.values() if peer.incoming), ) + (' FDs: %i R/%i W' % (len(reactor.getReaders()), len(reactor.getWriters())) if p2pool.DEBUG else '') datums, dt = wb.local_rate_monitor.get_datums_in_last() @@ -425,7 +428,7 @@ def status_thread(): this_str += '\n Shares: %i (%i orphan, %i dead) Stale rate: %s Efficiency: %s Current payout: %s %s' % ( shares, stale_orphan_shares, stale_doa_shares, math.format_binomial_conf(stale_orphan_shares + stale_doa_shares, shares, 0.95), - math.format_binomial_conf(stale_orphan_shares + stale_doa_shares, shares, 0.95, lambda x: (1 - x)/(1 - stale_prop)), + math.format_binomial_conf(stale_orphan_shares + stale_doa_shares, shares, 0.95, lambda x, stale_prop=stale_prop: (1 - x)/(1 - stale_prop)), paystr, net.PARENT.SYMBOL, ) this_str += '\n Pool: %sH/s Stale rate: %.1f%% Expected time to block: %s' % ( @@ -435,15 +438,15 @@ def status_thread(): ) for warning in p2pool_data.get_warnings(node.tracker, node.best_share_var.value, net, bitcoind_getinfo_var.value, node.bitcoind_work.value): - print >>sys.stderr, '#'*40 - print >>sys.stderr, '>>> Warning: ' + warning - print >>sys.stderr, '#'*40 + print('#'*40, file=sys.stderr) + print('>>> Warning: ' + warning, file=sys.stderr) + print('#'*40, file=sys.stderr) if gc.garbage: - print '%i pieces of uncollectable cyclic garbage! Types: %r' % (len(gc.garbage), map(type, gc.garbage)) + print('%i pieces of uncollectable cyclic garbage! Types: %r' % (len(gc.garbage), list(map(type, gc.garbage)))) if this_str != last_str or time.time() > last_time + 15: - print this_str + print(this_str) last_str = this_str last_time = time.time() except: @@ -455,11 +458,11 @@ def status_thread(): def run(): if not hasattr(tcp.Client, 'abortConnection'): - print "Twisted doesn't have abortConnection! Upgrade to a newer version of Twisted to avoid memory leaks!" - print 'Pausing for 3 seconds...' + print("Twisted doesn't have abortConnection! Upgrade to a newer version of Twisted to avoid memory leaks!") + print('Pausing for 3 seconds...') time.sleep(3) - realnets = dict((name, net) for name, net in networks.nets.iteritems() if '_testnet' not in name) + realnets = dict((name, net) for name, net in networks.nets.items() if '_testnet' not in name) parser = fixargparse.FixedArgumentParser(description='p2pool (version %s)' % (p2pool.__version__,), fromfile_prefix_chars='@') parser.add_argument('--version', action='version', version=p2pool.__version__) @@ -512,9 +515,12 @@ def run(): parser.add_argument('--irc-announce', help='announce any blocks found on irc://irc.freenode.net/#p2pool', action='store_true', default=False, dest='irc_announce') + parser.add_argument('--enable-bugreport', + help='opt in to submitting caught exceptions to the historical upstream p2pool error endpoint', + action='store_true', default=False, dest='bugreport') parser.add_argument('--no-bugreport', - help='disable submitting caught exceptions to the author', - action='store_true', default=False, dest='no_bugreport') + help=fixargparse.argparse.SUPPRESS, + action='store_false', dest='bugreport') p2pool_group = parser.add_argument_group('p2pool interface') p2pool_group.add_argument('--p2pool-port', metavar='PORT', @@ -523,9 +529,12 @@ def run(): p2pool_group.add_argument('-n', '--p2pool-node', metavar='ADDR[:PORT]', help='connect to existing p2pool node at ADDR listening on port PORT (defaults to default p2pool P2P port) in addition to builtin addresses', type=str, action='append', default=[], dest='p2pool_nodes') + parser.add_argument('--enable-upnp', + help='''attempt to use UPnP to forward p2pool's P2P port from the Internet to this computer''', + action='store_true', default=False, dest='upnp') parser.add_argument('--disable-upnp', - help='''don't attempt to use UPnP to forward p2pool's P2P port from the Internet to this computer''', - action='store_false', default=True, dest='upnp') + help='''compatibility option; UPnP is disabled by default in this Defcoin fork''', + action='store_false', dest='upnp') p2pool_group.add_argument('--max-conns', metavar='CONNS', help='maximum incoming connections (default: 40)', type=int, action='store', default=40, dest='p2pool_conns') @@ -603,7 +612,8 @@ def run(): '''rpcpassword=%x\r\n''' '''\r\n''' '''Keep that password secret! After creating the file, restart Bitcoin.''' % (conf_path, random.randrange(2**128))) - conf = open(conf_path, 'rb').read() + with open(conf_path, encoding='utf-8') as conf_file: + conf = conf_file.read() contents = {} for line in conf.splitlines(True): if '#' in line: @@ -652,18 +662,18 @@ def run(): try: _ = bitcoin_data.address_to_pubkey_hash(args.address, net.PARENT) args.pubkey_hash = True - except Exception, e: + except Exception as e: parser.error('error parsing address: ' + repr(e)) else: args.pubkey_hash = None def separate_url(url): - s = urlparse.urlsplit(url) + s = urllib.parse.urlsplit(url) if '@' not in s.netloc: parser.error('merged url netloc must contain an "@"') userpass, new_netloc = s.netloc.rsplit('@', 1) - return urlparse.urlunsplit(s._replace(netloc=new_netloc)), userpass - merged_urls = map(separate_url, args.merged_urls) + return urllib.parse.urlunsplit(s._replace(netloc=new_netloc)), userpass + merged_urls = list(map(separate_url, args.merged_urls)) if args.logfile is None: args.logfile = os.path.join(datadir_path, 'log') @@ -674,9 +684,9 @@ def separate_url(url): sys.stderr = log.DefaultObserver.stderr = logging.AbortPipe(logging.PrefixPipe(pipe, '> ')) if hasattr(signal, "SIGUSR1"): def sigusr1(signum, frame): - print 'Caught SIGUSR1, closing %r...' % (args.logfile,) + print('Caught SIGUSR1, closing %r...' % (args.logfile,)) logfile.reopen() - print '...and reopened %r after catching SIGUSR1.' % (args.logfile,) + print('...and reopened %r after catching SIGUSR1.' % (args.logfile,)) signal.signal(signal.SIGUSR1, sigusr1) deferral.RobustLoopingCall(logfile.reopen).start(5) @@ -698,14 +708,14 @@ def emit(self, eventDict): else: text = " ".join([str(m) for m in eventDict["message"]]) + "\n" - from twisted.web import client - client.getPage( + from p2pool.util import http + http.get_page( url='http://u.forre.st/p2pool_error.cgi', - method='POST', + method=b'POST', postdata=p2pool.__version__ + ' ' + net.NAME + '\n' + text, timeout=15, ).addBoth(lambda x: None) - if not args.no_bugreport: + if args.bugreport: log.addObserver(ErrorReporter().emit) if args.rconsole: from rfoo.utils import rconsole diff --git a/backend/p2pool/networks/__init__.py b/backend/p2pool/networks/__init__.py new file mode 100644 index 0000000..cb0dee4 --- /dev/null +++ b/backend/p2pool/networks/__init__.py @@ -0,0 +1,7 @@ +import importlib +import pkgutil + +nets = dict((name, importlib.import_module('.' + name, __name__)) + for module_loader, name, ispkg in pkgutil.iter_modules(__path__)) +for net_name, net in nets.items(): + net.NAME = net_name diff --git a/p2pool/networks/bitcoin.py b/backend/p2pool/networks/bitcoin.py similarity index 93% rename from p2pool/networks/bitcoin.py rename to backend/p2pool/networks/bitcoin.py index 6ef44c1..1613e51 100644 --- a/p2pool/networks/bitcoin.py +++ b/backend/p2pool/networks/bitcoin.py @@ -12,8 +12,8 @@ REAL_CHAIN_LENGTH = 24*60*60//10 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = 'fc70035c7a81bc6f'.decode('hex') -PREFIX = '2472ef181efcd37b'.decode('hex') +IDENTIFIER = bytes.fromhex('fc70035c7a81bc6f') +PREFIX = bytes.fromhex('2472ef181efcd37b') P2P_PORT = 9333 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/networks/bitcoin_testnet.py b/backend/p2pool/networks/bitcoin_testnet.py similarity index 89% rename from p2pool/networks/bitcoin_testnet.py rename to backend/p2pool/networks/bitcoin_testnet.py index a35531e..306d028 100644 --- a/p2pool/networks/bitcoin_testnet.py +++ b/backend/p2pool/networks/bitcoin_testnet.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 60*60//10 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = '5fc2be2d4f0d6bfb'.decode('hex') -PREFIX = '3f6057a15036f441'.decode('hex') +IDENTIFIER = bytes.fromhex('5fc2be2d4f0d6bfb') +PREFIX = bytes.fromhex('3f6057a15036f441') P2P_PORT = 19333 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/networks/bitcoincash.py b/backend/p2pool/networks/bitcoincash.py similarity index 93% rename from p2pool/networks/bitcoincash.py rename to backend/p2pool/networks/bitcoincash.py index cd25f5b..6aa92c7 100644 --- a/p2pool/networks/bitcoincash.py +++ b/backend/p2pool/networks/bitcoincash.py @@ -12,8 +12,8 @@ REAL_CHAIN_LENGTH = 3*24*60 # shares -- three days TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = 'b826c0a51ddc2d2b'.decode('hex') -PREFIX = 'ac9a8fda9a911bce'.decode('hex') +IDENTIFIER = bytes.fromhex('b826c0a51ddc2d2b') +PREFIX = bytes.fromhex('ac9a8fda9a911bce') P2P_PORT = 9349 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/networks/bitcoincash_testnet.py b/backend/p2pool/networks/bitcoincash_testnet.py similarity index 89% rename from p2pool/networks/bitcoincash_testnet.py rename to backend/p2pool/networks/bitcoincash_testnet.py index b5212fa..b7d5eab 100644 --- a/p2pool/networks/bitcoincash_testnet.py +++ b/backend/p2pool/networks/bitcoincash_testnet.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 3*24*60 # shares -- three days TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = 'c9f3de8d9508faef'.decode('hex') -PREFIX = '08c5541df85a8a65'.decode('hex') +IDENTIFIER = bytes.fromhex('c9f3de8d9508faef') +PREFIX = bytes.fromhex('08c5541df85a8a65') P2P_PORT = 19339 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/networks/btcregtest.py b/backend/p2pool/networks/btcregtest.py similarity index 89% rename from p2pool/networks/btcregtest.py rename to backend/p2pool/networks/btcregtest.py index f6b828c..1350bac 100644 --- a/p2pool/networks/btcregtest.py +++ b/backend/p2pool/networks/btcregtest.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 60*60//10 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = '5ad2c6ecbd7d9372'.decode('hex') -PREFIX = '8f2c8d54b3278bc8'.decode('hex') +IDENTIFIER = bytes.fromhex('5ad2c6ecbd7d9372') +PREFIX = bytes.fromhex('8f2c8d54b3278bc8') P2P_PORT = 19444 MIN_TARGET = 0 MAX_TARGET = 2**256//2 - 1 diff --git a/p2pool/networks/defcoin.py b/backend/p2pool/networks/defcoin.py similarity index 85% rename from p2pool/networks/defcoin.py rename to backend/p2pool/networks/defcoin.py index 10dc0e6..8e26cc5 100644 --- a/p2pool/networks/defcoin.py +++ b/backend/p2pool/networks/defcoin.py @@ -31,13 +31,13 @@ SPREAD = 42 # blocks MIN_TARGET = 0 MAX_TARGET = 2**256//2**20 - 1 -VERSION_CHECK = lambda v: None if 160002 <= v else 'Litecoin Cash version out of date. Upgrade to 0.16.0.2 or newer!' #dfc version? +VERSION_CHECK = lambda v: None if 160002 <= v else 'Defcoin Core version out of date. Upgrade to a compatible Defcoin Core release.' VERSION_WARNING = lambda v: None BLOCK_MAX_SIZE = 4000000 BLOCK_MAX_WEIGHT = 4000000 ANNOUNCE_CHANNEL = '#p2pool-dfc' #irc plugin? -IDENTIFIER = 'b032d5a8c6923410'.decode('hex') -PREFIX = '1389c1ad3ef0b9b5'.decode('hex') +IDENTIFIER = bytes.fromhex('b032d5a8c6923410') +PREFIX = bytes.fromhex('1389c1ad3ef0b9b5') #PERSIST = True # SET THIS TO FALSE UNTIL THE SHARE CHAIN IS BOOTSTRAPPED PERSIST = False diff --git a/p2pool/networks/defcoin_testnet.py b/backend/p2pool/networks/defcoin_testnet.py similarity index 89% rename from p2pool/networks/defcoin_testnet.py rename to backend/p2pool/networks/defcoin_testnet.py index 345ffe7..7ac1963 100644 --- a/p2pool/networks/defcoin_testnet.py +++ b/backend/p2pool/networks/defcoin_testnet.py @@ -25,7 +25,7 @@ BOOTSTRAP_ADDRS = [] ANNOUNCE_CHANNEL = '#p2pool-dfc-alt' -IDENTIFIER = '17b751fd110a4637'.decode('hex') -PREFIX = 'fc962530dd5c11ef'.decode('hex') +IDENTIFIER = bytes.fromhex('17b751fd110a4637') +PREFIX = bytes.fromhex('fc962530dd5c11ef') PERSIST = False diff --git a/p2pool/networks/fastcoin.py b/backend/p2pool/networks/fastcoin.py similarity index 87% rename from p2pool/networks/fastcoin.py rename to backend/p2pool/networks/fastcoin.py index db27887..9607a13 100644 --- a/p2pool/networks/fastcoin.py +++ b/backend/p2pool/networks/fastcoin.py @@ -8,8 +8,8 @@ TARGET_LOOKBEHIND = 60 # shares SPREAD = 150 # blocks NEW_SPREAD = 150 # blocks -IDENTIFIER = '9f2e390aa41ffade'.decode('hex') -PREFIX = '50f713ab040dfade'.decode('hex') +IDENTIFIER = bytes.fromhex('9f2e390aa41ffade') +PREFIX = bytes.fromhex('50f713ab040dfade') P2P_PORT = 23660 MIN_TARGET = 0 MAX_TARGET = 2**256//2**20 - 1 diff --git a/p2pool/networks/litecoin.py b/backend/p2pool/networks/litecoin.py similarity index 91% rename from p2pool/networks/litecoin.py rename to backend/p2pool/networks/litecoin.py index 783a7da..edcc780 100644 --- a/p2pool/networks/litecoin.py +++ b/backend/p2pool/networks/litecoin.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 24*60*60//10 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = 'e037d5b8c6923410'.decode('hex') -PREFIX = '7208c1a53ef629b0'.decode('hex') +IDENTIFIER = bytes.fromhex('e037d5b8c6923410') +PREFIX = bytes.fromhex('7208c1a53ef629b0') P2P_PORT = 9326 MIN_TARGET = 0 MAX_TARGET = 2**256//2**20 - 1 diff --git a/p2pool/networks/litecoin_testnet.py b/backend/p2pool/networks/litecoin_testnet.py similarity index 86% rename from p2pool/networks/litecoin_testnet.py rename to backend/p2pool/networks/litecoin_testnet.py index e494b10..a953b31 100644 --- a/p2pool/networks/litecoin_testnet.py +++ b/backend/p2pool/networks/litecoin_testnet.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 20*60//3 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 3 # blocks -IDENTIFIER = 'cca5e24ec6408b1e'.decode('hex') -PREFIX = 'ad9614f6466a39cf'.decode('hex') +IDENTIFIER = bytes.fromhex('cca5e24ec6408b1e') +PREFIX = bytes.fromhex('ad9614f6466a39cf') P2P_PORT = 19338 MIN_TARGET = 0 MAX_TARGET = 2**256//20 - 1 diff --git a/p2pool/networks/terracoin.py b/backend/p2pool/networks/terracoin.py similarity index 90% rename from p2pool/networks/terracoin.py rename to backend/p2pool/networks/terracoin.py index e365e28..24fe968 100644 --- a/p2pool/networks/terracoin.py +++ b/backend/p2pool/networks/terracoin.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 24*60*60//30 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 10 # blocks -IDENTIFIER = 'a42a265ad1b6d42b'.decode('hex') -PREFIX = '56a3f62173d2a9b5'.decode('hex') +IDENTIFIER = bytes.fromhex('a42a265ad1b6d42b') +PREFIX = bytes.fromhex('56a3f62173d2a9b5') P2P_PORT = 9323 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/networks/terracoin_testnet.py b/backend/p2pool/networks/terracoin_testnet.py similarity index 87% rename from p2pool/networks/terracoin_testnet.py rename to backend/p2pool/networks/terracoin_testnet.py index 627852e..241e89a 100644 --- a/p2pool/networks/terracoin_testnet.py +++ b/backend/p2pool/networks/terracoin_testnet.py @@ -6,8 +6,8 @@ REAL_CHAIN_LENGTH = 60*60//30 # shares TARGET_LOOKBEHIND = 200 # shares SPREAD = 10 # blocks -IDENTIFIER = 'b41a282ca5b2d85a'.decode('hex') -PREFIX = '16d2b91182dab8a4'.decode('hex') +IDENTIFIER = bytes.fromhex('b41a282ca5b2d85a') +PREFIX = bytes.fromhex('16d2b91182dab8a4') P2P_PORT = 19323 MIN_TARGET = 0 MAX_TARGET = 2**256//2**32 - 1 diff --git a/p2pool/node.py b/backend/p2pool/node.py similarity index 84% rename from p2pool/node.py rename to backend/p2pool/node.py index c47dd98..45ae756 100644 --- a/p2pool/node.py +++ b/backend/p2pool/node.py @@ -23,7 +23,7 @@ def __init__(self, node, **kwargs): def handle_shares(self, shares, peer): if len(shares) > 5: - print 'Processing %i shares from %s...' % (len(shares), '%s:%i' % peer.addr if peer is not None else None) + print('Processing %i shares from %s...' % (len(shares), '%s:%i' % peer.addr if peer is not None else None)) new_count = 0 all_new_txs = {} @@ -47,7 +47,7 @@ def handle_shares(self, shares, peer): self.node.set_best_share() if len(shares) > 5: - print '... done processing %i shares. New: %i Have: %i/~%i' % (len(shares), new_count, len(self.node.tracker.items), 2*self.node.net.CHAIN_LENGTH) + print('... done processing %i shares. New: %i Have: %i/~%i' % (len(shares), new_count, len(self.node.tracker.items), 2*self.node.net.CHAIN_LENGTH)) @defer.inlineCallbacks def handle_share_hashes(self, hashes, peer): @@ -76,7 +76,7 @@ def handle_get_shares(self, hashes, parents, stops, peer): break shares.append(share) if len(shares) > 0: - print 'Sending %i shares to %s:%i' % (len(shares), peer.addr[0], peer.addr[1]) + print('Sending %i shares to %s:%i' % (len(shares), peer.addr[0], peer.addr[1])) return shares def handle_bestblock(self, header, peer): @@ -92,16 +92,16 @@ def broadcast_share(self, share_hash): self.shared_share_hashes.add(share.hash) shares.append(share) - for peer in self.peers.itervalues(): + for peer in self.peers.values(): peer.sendShares([share for share in shares if share.peer_addr != peer.addr], self.node.tracker, self.node.known_txs_var.value, include_txs_with=[share_hash]) def start(self): p2p.Node.start(self) self.shared_share_hashes = set(self.node.tracker.items) + self._spread_delayed = [] self.node.tracker.removed.watch_weakref(self, lambda self, share: self.shared_share_hashes.discard(share.hash)) - @apply @defer.inlineCallbacks def download_shares(): while True: @@ -111,9 +111,9 @@ def download_shares(): if len(self.peers) == 0: yield deferral.sleep(1) continue - peer = random.choice(self.peers.values()) + peer = random.choice(list(self.peers.values())) - print 'Requesting parent share %s from %s' % (p2pool_data.format_hash(share_hash), '%s:%i' % peer.addr) + print('Requesting parent share %s from %s' % (p2pool_data.format_hash(share_hash), '%s:%i' % peer.addr)) try: shares = yield peer.get_shares( hashes=[share_hash], @@ -123,7 +123,7 @@ def download_shares(): ))[:100], ) except defer.TimeoutError: - print 'Share request timed out!' + print('Share request timed out!') continue except: log.err(None, 'in download_shares:') @@ -134,11 +134,11 @@ def download_shares(): yield deferral.sleep(1) # sleep so we don't keep rerequesting the same share nobody has continue self.handle_shares([(share, []) for share in shares], peer) - + self._download_shares_df = download_shares() @self.node.best_block_header.changed.watch def _(header): - for peer in self.peers.itervalues(): + for peer in self.peers.values(): peer.send_bestblock(header=header) # send share when the chain changes to their chain @@ -154,7 +154,17 @@ def spread(): self.node.bitcoind_work.value['previous_block'] in [share.header['previous_block'], share.header_hash]): self.broadcast_share(share.hash) spread() - reactor.callLater(5, spread) # so get_height_rel_highest can update + self._spread_delayed.append(reactor.callLater(5, spread)) # so get_height_rel_highest can update + + @defer.inlineCallbacks + def stop(self): + if hasattr(self, '_download_shares_df') and not self._download_shares_df.called: + self._download_shares_df.cancel() + for delayed in getattr(self, '_spread_delayed', []): + if delayed.active(): + delayed.cancel() + self._spread_delayed = [] + yield p2p.Node.stop(self) class Node(object): @@ -187,7 +197,7 @@ def __init__(self, factory, bitcoind, shares, known_verified_share_hashes, net): self.p2p_node = None # overwritten externally def check_and_purge_txs(self): - if self.cur_share_ver < 34: + if (self.cur_share_ver or 0) < 34: return best_share = self.tracker.items.get( self.best_share_var.value, None) @@ -210,12 +220,19 @@ def start(self): def work_poller(): while stop_signal.times == 0: flag = self.factory.new_block.get_deferred() + timeout = deferral.sleep(15) + stopped = stop_signal.get_deferred() try: self.bitcoind_work.set((yield helper.getwork(self.bitcoind, self.bitcoind_work.value['use_getblocktemplate'], self.txidcache, self.feecache, self.feefifo, self.known_txs_var.value))) self.check_and_purge_txs() except: log.err() - yield defer.DeferredList([flag, deferral.sleep(15)], fireOnOneCallback=True) + try: + yield defer.DeferredList([flag, timeout, stopped], fireOnOneCallback=True, consumeErrors=True) + finally: + for waiter in (flag, timeout, stopped): + if not waiter.called: + waiter.cancel() work_poller() # PEER WORK @@ -248,7 +265,8 @@ def poll_header(): # BEST SHARE - self.get_height_rel_highest, self.get_height = yield height_tracker.get_height_funcs(self.bitcoind, self.factory, lambda: self.bitcoind_work.value['previous_block'], self.net) + self.get_height_rel_highest, self.get_height, stop_height_tracker = yield height_tracker.get_height_funcs(self.bitcoind, self.factory, lambda: self.bitcoind_work.value['previous_block'], self.net) + stop_signal.watch(lambda: stop_height_tracker()) self.bitcoind_work.changed.watch(lambda _: self.set_best_share()) self.set_best_share() @@ -257,8 +275,8 @@ def poll_header(): # update mining_txs according to getwork results @self.bitcoind_work.changed.run_and_watch def _(_=None): - new_mining_txs = dict(zip(self.bitcoind_work.value['transaction_hashes'], self.bitcoind_work.value['transactions'])) - added_known_txs = {hsh:tx for hsh,tx in new_mining_txs.iteritems() if not hsh in self.known_txs_var.value} + new_mining_txs = dict(list(zip(self.bitcoind_work.value['transaction_hashes'], self.bitcoind_work.value['transactions']))) + added_known_txs = {hsh:tx for hsh,tx in new_mining_txs.items() if not hsh in self.known_txs_var.value} self.mining_txs_var.set(new_mining_txs) self.known_txs_var.add(added_known_txs) # add p2p transactions from bitcoind to known_txs @@ -268,7 +286,7 @@ def _(tx): bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)): tx, }) - if self.cur_share_ver < 34: + if (self.cur_share_ver or 0) < 34: # forward transactions seen to bitcoind @self.known_txs_var.transitioned.watch @defer.inlineCallbacks @@ -285,24 +303,24 @@ def _(share): return if share.VERSION >= 34: - print 'GOT BLOCK FROM PEER! %s %s%064x' % ( + print('GOT BLOCK FROM PEER! %s %s%064x' % ( p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, - share.header_hash) + share.header_hash)) return block = share.as_block(self.tracker, self.known_txs_var.value) if block is None: - print >>sys.stderr, 'GOT INCOMPLETE BLOCK FROM PEER! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash) + print('GOT INCOMPLETE BLOCK FROM PEER! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash), file=sys.stderr) return helper.submit_block(block, True, self) - print - print 'GOT BLOCK FROM PEER! Passing to bitcoind! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash) - print + print() + print('GOT BLOCK FROM PEER! Passing to bitcoind! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash)) + print() def forget_old_txs(): new_known_txs = {} if self.p2p_node is not None: - for peer in self.p2p_node.peers.itervalues(): + for peer in self.p2p_node.peers.values(): new_known_txs.update(peer.remembered_txs) new_known_txs.update(self.mining_txs_var.value) new_known_txs.update(self.mining2_txs_var.value) @@ -313,7 +331,7 @@ def forget_old_txs(): if tx_hash in self.known_txs_var.value: new_known_txs[tx_hash] = self.known_txs_var.value[tx_hash] self.known_txs_var.set(new_known_txs) - if self.cur_share_ver < 34: + if (self.cur_share_ver or 0) < 34: t = deferral.RobustLoopingCall(forget_old_txs) t.start(10) stop_signal.watch(t.stop) @@ -337,7 +355,7 @@ def set_best_share(self): if self.p2p_node is not None: for bad_peer_address in bad_peer_addresses: # XXX O(n) - for peer in self.p2p_node.peers.itervalues(): + for peer in self.p2p_node.peers.values(): if peer.addr == bad_peer_address: peer.badPeerHappened() break @@ -350,9 +368,9 @@ def clean_tracker(self): # eat away at heads if decorated_heads: - for i in xrange(1000): + for i in range(1000): to_remove = set() - for share_hash, tail in self.tracker.heads.iteritems(): + for share_hash, tail in self.tracker.heads.items(): if share_hash in [head_hash for score, head_hash in decorated_heads[-5:]]: #print 1 continue @@ -372,9 +390,9 @@ def clean_tracker(self): #print "_________", to_remove # drop tails - for i in xrange(1000): + for i in range(1000): to_remove = set() - for tail, heads in self.tracker.tails.iteritems(): + for tail, heads in self.tracker.tails.items(): if min(self.tracker.get_height(head) for head in heads) < 2*self.tracker.net.CHAIN_LENGTH + 10: continue to_remove.update(self.tracker.reverse.get(tail, set())) @@ -384,7 +402,7 @@ def clean_tracker(self): #start = time.time() for aftertail in to_remove: if self.tracker.items[aftertail].previous_hash not in self.tracker.tails: - print "erk", aftertail, self.tracker.items[aftertail].previous_hash + print("erk", aftertail, self.tracker.items[aftertail].previous_hash) continue if aftertail in self.tracker.verified.items: self.tracker.verified.remove(aftertail) diff --git a/p2pool/p2p.py b/backend/p2pool/p2p.py similarity index 83% rename from p2pool/p2p.py rename to backend/p2pool/p2p.py index b6ad7a6..b5d059f 100644 --- a/p2pool/p2p.py +++ b/backend/p2pool/p2p.py @@ -1,7 +1,8 @@ -from __future__ import division + import math import random +import secrets import sys import time @@ -12,6 +13,7 @@ from p2pool import data as p2pool_data from p2pool.bitcoin import data as bitcoin_data from p2pool.util import deferral, p2protocol, pack, variable +from p2pool.util.py3 import ensure_bytes _HANDSHAKE_LOG_INTERVAL = 300 _HANDSHAKE_LOG_STATE = {} @@ -23,9 +25,9 @@ def _rate_limited_handshake_log(kind, host, message, interval=_HANDSHAKE_LOG_INT if now - last >= interval: if suppressed: elapsed = max(1, now - last) - print '%s (suppressed %i similar %s messages in the last %.0f seconds)' % (message, suppressed, kind, elapsed) + print('%s (suppressed %i similar %s messages in the last %.0f seconds)' % (message, suppressed, kind, elapsed)) else: - print message + print(message) _HANDSHAKE_LOG_STATE[key] = now, 0 else: _HANDSHAKE_LOG_STATE[key] = last, suppressed + 1 @@ -38,8 +40,8 @@ def fragment(f, **kwargs): try: f(**kwargs) except p2protocol.TooLong: - fragment(f, **dict((k, v[:len(v)//2]) for k, v in kwargs.iteritems())) - fragment(f, **dict((k, v[len(v)//2:]) for k, v in kwargs.iteritems())) + fragment(f, **dict((k, v[:len(v)//2]) for k, v in kwargs.items())) + fragment(f, **dict((k, v[len(v)//2:]) for k, v in kwargs.items())) class Protocol(p2protocol.Protocol): VERSION = 3501 @@ -53,6 +55,10 @@ def __init__(self, node, incoming): self.other_version = None self.connected2 = False + self.timeout_delayed = None + self._stop_thread = None + self._stop_thread2 = None + self._known_txs_cache_timers = [] def connectionMade(self): self.factory.proto_made_connection(self) @@ -75,7 +81,7 @@ def connectionMade(self): port=self.transport.getHost().port, ), nonce=self.node.nonce, - sub_version=p2pool.__version__, + sub_version=ensure_bytes(p2pool.__version__), mode=1, best_share_hash=self.node.best_share_hash_func(), ) @@ -98,7 +104,7 @@ def connectionMade(self): def _connect_timeout(self): self.timeout_delayed = None - print 'Handshake timed out, disconnecting from %s:%i' % self.addr + print('Handshake timed out, disconnecting from %s:%i' % self.addr) self.disconnect() def packetReceived(self, command, payload2): @@ -106,12 +112,12 @@ def packetReceived(self, command, payload2): if command != 'version' and not self.connected2: raise PeerMisbehavingError('first message was not version message') p2protocol.Protocol.packetReceived(self, command, payload2) - except PeerMisbehavingError, e: - print 'Peer %s:%i misbehaving, will drop and ban. Reason:' % self.addr, e.message + except PeerMisbehavingError as e: + print('Peer %s:%i misbehaving, will drop and ban. Reason:' % self.addr, e) self.badPeerHappened() def badPeerHappened(self, bantime=3600): - print "Bad peer banned:", self.addr + print("Bad peer banned:", self.addr) self.disconnect() if self.transport.getPeer().host != '127.0.0.1': # never ban localhost host = self.transport.getPeer().host @@ -123,7 +129,7 @@ def badPeerHappened(self, bantime=3600): def _timeout(self): self.timeout_delayed = None - print 'Connection timed out, disconnecting from %s:%i' % self.addr + print('Connection timed out, disconnecting from %s:%i' % self.addr) self.disconnect() def sendAdvertisement(self): @@ -135,7 +141,7 @@ def sendAdvertisement(self): host, port_str = host.split(':') port = int(port_str) if p2pool.DEBUG: - print 'Advertising for incoming connections: %s:%i' % (host, port) + print('Advertising for incoming connections: %s:%i' % (host, port)) # Advertise given external IP address, just as if there were another peer behind us, with that address, who asked us to advertise it for them self.send_addrs(addrs=[ dict( @@ -149,7 +155,7 @@ def sendAdvertisement(self): ]) else: if p2pool.DEBUG: - print 'Advertising for incoming connections' + print('Advertising for incoming connections') # Ask peer to advertise what it believes our IP address to be self.send_addrme(port=port) @@ -204,7 +210,7 @@ def handle_version(self, version, services, addr_to, addr_from, nonce, sub_versi self.disconnect() return if p2pool.DEBUG: - print "Peer %s:%s says protocol version is %s, client version %s" % (advertised_host, advertised_port, version, sub_version) + print("Peer %s:%s says protocol version is %s, client version %s" % (advertised_host, advertised_port, version, sub_version)) self.nonce = nonce self.connected2 = True @@ -250,7 +256,8 @@ def remove_from_remote_view_of_my_known_txs(removed): # cache forgotten txs here for a little while so latency of "losing_tx" packets doesn't cause problems key = max(self.known_txs_cache) + 1 if self.known_txs_cache else 0 self.known_txs_cache[key] = removed #dict((h, before[h]) for h in removed) - reactor.callLater(20, self.known_txs_cache.pop, key) + self._known_txs_cache_timers.append( + reactor.callLater(20, self.known_txs_cache.pop, key, None)) watch_id1 = self.node.known_txs_var.removed.watch(remove_from_remote_view_of_my_known_txs) self.connection_lost_event.watch(lambda: self.node.known_txs_var.removed.unwatch(watch_id1)) @@ -266,13 +273,14 @@ def update_remote_view_of_my_known_txs(before, after): # cache forgotten txs here for a little while so latency of "losing_tx" packets doesn't cause problems key = max(self.known_txs_cache) + 1 if self.known_txs_cache else 0 self.known_txs_cache[key] = dict((h, before[h]) for h in removed) - reactor.callLater(20, self.known_txs_cache.pop, key) + self._known_txs_cache_timers.append( + reactor.callLater(20, self.known_txs_cache.pop, key, None)) t1 = time.time() - if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for update_remote_view_of_my_known_txs" % ((t1-t0)*1000.) + if p2pool.BENCH and (t1-t0) > .01: print("%8.3f ms for update_remote_view_of_my_known_txs" % ((t1-t0)*1000.)) watch_id2 = self.node.known_txs_var.transitioned.watch(update_remote_view_of_my_known_txs) self.connection_lost_event.watch(lambda: self.node.known_txs_var.transitioned.unwatch(watch_id2)) - self.send_have_tx(tx_hashes=self.node.known_txs_var.value.keys()) + self.send_have_tx(tx_hashes=list(self.node.known_txs_var.value.keys())) def update_remote_view_of_my_mining_txs(before, after): t0 = time.time() @@ -286,14 +294,14 @@ def update_remote_view_of_my_mining_txs(before, after): assert self.remote_remembered_txs_size <= self.max_remembered_txs_size fragment(self.send_remember_tx, tx_hashes=[x for x in added if x in self.remote_tx_hashes], txs=[after[x] for x in added if x not in self.remote_tx_hashes]) t1 = time.time() - if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for update_remote_view_of_my_mining_txs" % ((t1-t0)*1000.) + if p2pool.BENCH and (t1-t0) > .01: print("%8.3f ms for update_remote_view_of_my_mining_txs" % ((t1-t0)*1000.)) watch_id2 = self.node.mining_txs_var.transitioned.watch(update_remote_view_of_my_mining_txs) self.connection_lost_event.watch(lambda: self.node.mining_txs_var.transitioned.unwatch(watch_id2)) - self.remote_remembered_txs_size += sum(100 + bitcoin_data.tx_type.packed_size(x) for x in self.node.mining_txs_var.value.values()) + self.remote_remembered_txs_size += sum(100 + bitcoin_data.tx_type.packed_size(x) for x in list(self.node.mining_txs_var.value.values())) assert self.remote_remembered_txs_size <= self.max_remembered_txs_size - fragment(self.send_remember_tx, tx_hashes=[], txs=self.node.mining_txs_var.value.values()) + fragment(self.send_remember_tx, tx_hashes=[], txs=list(self.node.mining_txs_var.value.values())) message_ping = pack.ComposedType([]) def handle_ping(self): @@ -307,11 +315,11 @@ def handle_addrme(self, port): #print 'addrme from', host, port if host == '127.0.0.1': if random.random() < .8 and self.node.peers: - random.choice(self.node.peers.values()).send_addrme(port=port) # services... + random.choice(list(self.node.peers.values())).send_addrme(port=port) # services... else: self.node.got_addr((self.transport.getPeer().host, port), self.other_services, int(time.time())) if random.random() < .8 and self.node.peers: - random.choice(self.node.peers.values()).send_addrs(addrs=[ + random.choice(list(self.node.peers.values())).send_addrs(addrs=[ dict( address=dict( services=self.other_services, @@ -332,7 +340,7 @@ def handle_addrs(self, addrs): for addr_record in addrs: self.node.got_addr((addr_record['address']['address'], addr_record['address']['port']), addr_record['address']['services'], min(int(time.time()), addr_record['timestamp'])) if random.random() < .8 and self.node.peers: - random.choice(self.node.peers.values()).send_addrs(addrs=[addr_record]) + random.choice(list(self.node.peers.values())).send_addrs(addrs=[addr_record]) message_getaddrs = pack.ComposedType([ ('count', pack.IntType(32)), @@ -367,14 +375,14 @@ def handle_shares(self, shares): if tx_hash in self.node.known_txs_var.value: tx = self.node.known_txs_var.value[tx_hash] else: - for cache in self.known_txs_cache.itervalues(): + for cache in self.known_txs_cache.values(): if tx_hash in cache: tx = cache[tx_hash] if p2pool.DEBUG: - print 'Transaction %064x rescued from peer latency cache!' % (tx_hash,) + print('Transaction %064x rescued from peer latency cache!' % (tx_hash,)) break else: - print >>sys.stderr, 'Peer referenced unknown transaction %064x, disconnecting' % (tx_hash,) + print('Peer referenced unknown transaction %064x, disconnecting' % (tx_hash,), file=sys.stderr) self.disconnect() return txs.append(tx) @@ -385,10 +393,11 @@ def handle_shares(self, shares): self.node.handle_shares(result, self) t1 = time.time() - if p2pool.BENCH: print "%8.3f ms for %i shares in handle_shares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares))) + if p2pool.BENCH: print("%8.3f ms for %i shares in handle_shares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares)))) - def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): + def sendShares(self, shares, tracker, known_txs, include_txs_with=None): + include_txs_with = [] if include_txs_with is None else include_txs_with t0 = time.time() tx_hashes = set() hashes_to_send = [] @@ -402,7 +411,7 @@ def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): newset = set(share.share_info['new_transaction_hashes']) ktxset = set(known_txs) missing = newset - ktxset - print "Missing %i of %i transactions for broadcast" % (len(missing), len(newset)) + print("Missing %i of %i transactions for broadcast" % (len(missing), len(newset))) assert tx_hash in known_txs, 'tried to broadcast share without knowing all its new transactions' if tx_hash not in self.remote_tx_hashes: tx_hashes.add(tx_hash) @@ -416,7 +425,7 @@ def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): all_hashes = share.share_info['new_transaction_hashes'] new_tx_size = sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in hashes_to_send) all_tx_size = sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in all_hashes) - print "Sending a share with %i txs (%i new) totaling %i msg bytes (%i new)" % (len(all_hashes), len(hashes_to_send), all_tx_size, new_tx_size) + print("Sending a share with %i txs (%i new) totaling %i msg bytes (%i new)" % (len(all_hashes), len(hashes_to_send), all_tx_size, new_tx_size)) if tx_hashes: hashes_to_send = [x for x in tx_hashes if x not in self.node.mining_txs_var.value and x in known_txs] @@ -436,7 +445,7 @@ def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): self.remote_remembered_txs_size -= new_tx_size t1 = time.time() - if p2pool.BENCH: print "%8.3f ms for %i shares in sendShares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares))) + if p2pool.BENCH: print("%8.3f ms for %i shares in sendShares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares)))) @@ -490,7 +499,7 @@ def handle_losing_tx(self, tx_hashes): #assert self.remote_tx_hashes.issuperset(tx_hashes) self.remote_tx_hashes.difference_update(tx_hashes) t1 = time.time() - if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for %i txs in handle_losing_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), (t1-t0)*1000./ max(1, len(tx_hashes))) + if p2pool.BENCH and (t1-t0) > .01: print("%8.3f ms for %i txs in handle_losing_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), (t1-t0)*1000./ max(1, len(tx_hashes)))) @@ -502,20 +511,20 @@ def handle_remember_tx(self, tx_hashes, txs): t0 = time.time() for tx_hash in tx_hashes: if tx_hash in self.remembered_txs: - print >>sys.stderr, 'Peer referenced transaction twice, disconnecting' + print('Peer referenced transaction twice, disconnecting', file=sys.stderr) self.disconnect() return if tx_hash in self.node.known_txs_var.value: tx = self.node.known_txs_var.value[tx_hash] else: - for cache in self.known_txs_cache.itervalues(): + for cache in self.known_txs_cache.values(): if tx_hash in cache: tx = cache[tx_hash] - print 'Transaction %064x rescued from peer latency cache!' % (tx_hash,) + print('Transaction %064x rescued from peer latency cache!' % (tx_hash,)) break else: - print >>sys.stderr, 'Peer referenced unknown transaction %064x, disconnecting' % (tx_hash,) + print('Peer referenced unknown transaction %064x, disconnecting' % (tx_hash,), file=sys.stderr) self.disconnect() return @@ -526,12 +535,12 @@ def handle_remember_tx(self, tx_hashes, txs): for tx in txs: tx_hash = bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)) if tx_hash in self.remembered_txs: - print >>sys.stderr, 'Peer referenced transaction twice, disconnecting' + print('Peer referenced transaction twice, disconnecting', file=sys.stderr) self.disconnect() return if tx_hash in self.node.known_txs_var.value and not warned and p2pool.DEBUG: - print 'Peer sent entire transaction %064x that was already received' % (tx_hash,) + print('Peer sent entire transaction %064x that was already received' % (tx_hash,)) warned = True self.remembered_txs[tx_hash] = tx @@ -541,7 +550,7 @@ def handle_remember_tx(self, tx_hashes, txs): if self.remembered_txs_size >= self.max_remembered_txs_size: raise PeerMisbehavingError('too much transaction data stored') t1 = time.time() - if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for %i txs in p2p.py:handle_remember_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), ((t1-t0)*1000. / max(1,len(tx_hashes)) )) + if p2pool.BENCH and (t1-t0) > .01: print("%8.3f ms for %i txs in p2p.py:handle_remember_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), ((t1-t0)*1000. / max(1,len(tx_hashes)) ))) message_forget_tx = pack.ComposedType([ ('tx_hashes', pack.ListType(pack.IntType(256))), ]) @@ -556,15 +565,23 @@ def connectionLost(self, reason): self.connection_lost_event.happened() if self.timeout_delayed is not None: self.timeout_delayed.cancel() + self.timeout_delayed = None + for timer in self._known_txs_cache_timers: + if timer.active(): + timer.cancel() + self._known_txs_cache_timers = [] if self.connected2: self.factory.proto_disconnected(self, reason) - self._stop_thread() - if self.node.advertise_ip: + if self._stop_thread is not None: + self._stop_thread() + self._stop_thread = None + if self.node.advertise_ip and self._stop_thread2 is not None: self._stop_thread2() + self._stop_thread2 = None self.connected2 = False self.factory.proto_lost_connection(self, reason) if p2pool.DEBUG: - print "Peer connection lost:", self.addr, reason + print("Peer connection lost:", self.addr, reason) self.get_shares.respond_all(reason) @defer.inlineCallbacks @@ -584,14 +601,14 @@ def __init__(self, node, max_conns): self.listen_port = None def buildProtocol(self, addr): - if sum(self.conns.itervalues()) >= self.max_conns or self.conns.get(self._host_to_ident(addr.host), 0) >= 3: + if sum(self.conns.values()) >= self.max_conns or self.conns.get(self._host_to_ident(addr.host), 0) >= 3: return None if addr.host in self.node.bans and self.node.bans[addr.host] > time.time(): return None p = Protocol(self.node, True) p.factory = self if p2pool.DEBUG: - print "Got peer connection from:", addr + print("Got peer connection from:", addr) return p def _host_to_ident(self, host): @@ -678,6 +695,8 @@ def stop(self): assert self.running self.running = False self._stop_thinking() + for proto in list(self.node.peers.values()): + proto.disconnect() def _think(self): try: @@ -717,10 +736,15 @@ def proto_disconnected(self, proto, reason): self.node.lost_conn(proto, reason) class Node(object): - def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs=set(), desired_outgoing_conns=10, max_outgoing_attempts=30, max_incoming_conns=50, preferred_storage=1000, known_txs_var=variable.VariableDict({}), mining_txs_var=variable.VariableDict({}), mining2_txs_var=variable.VariableDict({}), advertise_ip=True, external_ip=None): + def __init__(self, best_share_hash_func, port, net, addr_store=None, connect_addrs=None, desired_outgoing_conns=10, max_outgoing_attempts=30, max_incoming_conns=50, preferred_storage=1000, known_txs_var=None, mining_txs_var=None, mining2_txs_var=None, advertise_ip=True, external_ip=None): self.best_share_hash_func = best_share_hash_func self.port = port self.net = net + addr_store = {} if addr_store is None else addr_store + connect_addrs = set() if connect_addrs is None else connect_addrs + known_txs_var = variable.VariableDict({}) if known_txs_var is None else known_txs_var + mining_txs_var = variable.VariableDict({}) if mining_txs_var is None else mining_txs_var + mining2_txs_var = variable.VariableDict({}) if mining2_txs_var is None else mining2_txs_var self.addr_store = dict(addr_store) self.connect_addrs = connect_addrs self.preferred_storage = preferred_storage @@ -731,7 +755,7 @@ def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs self.external_ip = external_ip self.traffic_happened = variable.Event() - self.nonce = random.randrange(2**64) + self.nonce = secrets.randbits(64) self.peers = {} self.bans = {} # address -> end_time self.banscores = {} # address -> how naughty this peer has been recently @@ -762,7 +786,7 @@ def forgive_transgressions(self): def _think(self): try: if len(self.addr_store) < self.preferred_storage and self.peers: - random.choice(self.peers.values()).send_getaddrs(count=8) + random.choice(list(self.peers.values())).send_getaddrs(count=8) except: log.err() @@ -776,6 +800,14 @@ def stop(self): self.running = False self._stop_thinking() + if self.forgiveness_task.running: + self.forgiveness_task.stop() + peer_waiters = [peer.connection_lost_event.get_deferred(timeout=5) + for peer in list(self.peers.values())] + for peer in list(self.peers.values()): + peer.disconnect() + if peer_waiters: + yield defer.DeferredList(peer_waiters, consumeErrors=True) yield self.clientfactory.stop() yield self.serverfactory.stop() for singleclientconnector in self.singleclientconnectors: @@ -788,7 +820,7 @@ def got_conn(self, conn): raise ValueError('already have peer') self.peers[conn.nonce] = conn - print '%s peer %s:%i established. p2pool version: %i %r' % ('Incoming connection from' if conn.incoming else 'Outgoing connection to', conn.addr[0], conn.addr[1], conn.other_version, conn.other_sub_version) + print('%s peer %s:%i established. p2pool version: %i %r' % ('Incoming connection from' if conn.incoming else 'Outgoing connection to', conn.addr[0], conn.addr[1], conn.other_version, conn.other_sub_version)) def lost_conn(self, conn, reason): if conn.nonce not in self.peers: @@ -797,10 +829,11 @@ def lost_conn(self, conn, reason): raise ValueError('wrong conn') del self.peers[conn.nonce] - print 'Lost peer %s:%i - %s' % (conn.addr[0], conn.addr[1], reason.getErrorMessage()) + print('Lost peer %s:%i - %s' % (conn.addr[0], conn.addr[1], reason.getErrorMessage())) - def got_addr(self, (host, port), services, timestamp): + def got_addr(self, xxx_todo_changeme, services, timestamp): + (host, port) = xxx_todo_changeme if (host, port) in self.addr_store: old_services, old_first_seen, old_last_seen = self.addr_store[host, port] self.addr_store[host, port] = services, old_first_seen, max(old_last_seen, timestamp) @@ -809,19 +842,19 @@ def got_addr(self, (host, port), services, timestamp): self.addr_store[host, port] = services, timestamp, timestamp def handle_shares(self, shares, peer): - print 'handle_shares', (shares, peer) + print('handle_shares', (shares, peer)) def handle_share_hashes(self, hashes, peer): - print 'handle_share_hashes', (hashes, peer) + print('handle_share_hashes', (hashes, peer)) def handle_get_shares(self, hashes, parents, stops, peer): - print 'handle_get_shares', (hashes, parents, stops, peer) + print('handle_get_shares', (hashes, parents, stops, peer)) def handle_bestblock(self, header, peer): - print 'handle_bestblock', header + print('handle_bestblock', header) def get_good_peers(self, max_count): t = time.time() - return [x[0] for x in sorted(self.addr_store.iteritems(), key=lambda (k, (services, first_seen, last_seen)): - -math.log(max(3600, last_seen - first_seen))/math.log(max(3600, t - last_seen))*random.expovariate(1) + return [x[0] for x in sorted(iter(self.addr_store.items()), key=lambda k_services_first_seen_last_seen: + -math.log(max(3600, k_services_first_seen_last_seen[1][2] - k_services_first_seen_last_seen[1][1]))/math.log(max(3600, t - k_services_first_seen_last_seen[1][2]))*random.expovariate(1) )][:max_count] diff --git a/p2pool/test/__init__.py b/backend/p2pool/test/__init__.py similarity index 100% rename from p2pool/test/__init__.py rename to backend/p2pool/test/__init__.py diff --git a/p2pool/test/bitcoin/__init__.py b/backend/p2pool/test/bitcoin/__init__.py similarity index 100% rename from p2pool/test/bitcoin/__init__.py rename to backend/p2pool/test/bitcoin/__init__.py diff --git a/p2pool/test/bitcoin/test_data.py b/backend/p2pool/test/bitcoin/test_data.py similarity index 76% rename from p2pool/test/bitcoin/test_data.py rename to backend/p2pool/test/bitcoin/test_data.py index e07efbb..7624d4c 100644 --- a/p2pool/test/bitcoin/test_data.py +++ b/backend/p2pool/test/bitcoin/test_data.py @@ -1,5 +1,5 @@ import unittest -import mock +from unittest import mock from random import randint from binascii import hexlify, unhexlify @@ -39,17 +39,17 @@ def test_tx_hash(self): tx_ins=[dict( previous_output=None, sequence=None, - script='70736a0468860e1a0452389500522cfabe6d6d2b2f33cf8f6291b184f1b291d24d82229463fcec239afea0ee34b4bfc622f62401000000000000004d696e656420627920425443204775696c6420ac1eeeed88'.decode('hex'), + script=bytes.fromhex('70736a0468860e1a0452389500522cfabe6d6d2b2f33cf8f6291b184f1b291d24d82229463fcec239afea0ee34b4bfc622f62401000000000000004d696e656420627920425443204775696c6420ac1eeeed88'), )], tx_outs=[dict( value=5003880250, - script=data.pubkey_hash_to_script2(pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')), networks.nets['bitcoin'].ADDRESS_VERSION, -1, networks.nets['bitcoin']), + script=data.pubkey_hash_to_script2(pack.IntType(160).unpack(bytes.fromhex('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b')), networks.nets['bitcoin'].ADDRESS_VERSION, -1, networks.nets['bitcoin']), )], lock_time=0, )) == 0xb53802b2333e828d6532059f46ecf6b313a42d79f97925e457fbbfda45367e5c def test_address_to_pubkey_hash(self): - assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.nets['bitcoin'])[0] == pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')) + assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.nets['bitcoin'])[0] == pack.IntType(160).unpack(bytes.fromhex('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b')) def test_merkle_hash(self): assert data.merkle_hash([ @@ -451,30 +451,30 @@ def test_get_cashaddr_pubkey_hash(self, mcd): @mock.patch.object(data, 'pack', spec=data.pack) def test_pubkey_hash_to_script2(self, mp): - mp.IntType().pack.return_value = '\xde\xad\xbe\xef' - legacy_out = '\x76\xa9\x14\xde\xad\xbe\xef\x88\xac' + mp.IntType().pack.return_value = b'\xde\xad\xbe\xef' + legacy_out = b'\x76\xa9\x14\xde\xad\xbe\xef\x88\xac' self.assertEqual(legacy_out, data.pubkey_hash_to_script2(1234, 0, -1, self.btcnet)) mp.IntType().pack.assert_called_once_with(1234) mp.reset_mock() - p2sh_out = '\xa9\x14\xde\xad\xbe\xef\x87' + p2sh_out = b'\xa9\x14\xde\xad\xbe\xef\x87' self.assertEqual(p2sh_out, data.pubkey_hash_to_script2(1234, 3, -1, self.btcnet)) mp.IntType().pack.assert_called_once_with(1234) mp.reset_mock() phash = int('deadbeef', 16) - bech32_out = '\x00\x04\xde\xad\xbe\xef' + bech32_out = b'\x00\x04\xde\xad\xbe\xef' self.assertEqual(bech32_out, data.pubkey_hash_to_script2(phash, -1, 2, self.ltcnet)) self.assertEqual(0, mp.IntType().pack.call_count) # Cashaddr test version 0 (P2KH) - cashaddr_out = '\x76\xa9\x04\xde\xad\xbe\xef\x88\xac' + cashaddr_out = b'\x76\xa9\x04\xde\xad\xbe\xef\x88\xac' mp.reset_mock() self.assertEqual(cashaddr_out, data.pubkey_hash_to_script2(phash, -1, 0, self.bchnet)) self.assertEqual(0, mp.IntType().pack.call_count) # Cashaddr test version 1 (P2SH) - cashaddr_out = '\xa9\x04\xde\xad\xbe\xef\x87' + cashaddr_out = b'\xa9\x04\xde\xad\xbe\xef\x87' self.assertEqual(cashaddr_out, data.pubkey_hash_to_script2(phash, -1, 1, self.bchnet)) for i in range(2, 16): @@ -482,12 +482,12 @@ def test_pubkey_hash_to_script2(self, mp): phash, -1, i, self.bchnet) # Max cashaddr hash size. phash2 = int('deadbeef' * 16, 16) - mp.IntType().pack.return_value = '\xde\xad\xbe\xef' * 16 + mp.IntType().pack.return_value = b'\xde\xad\xbe\xef' * 16 mp.reset_mock() - cashaddr_out2 = '\x76\xa9\x40%s\x88\xac' % ('\xde\xad\xbe\xef' * 16) + cashaddr_out2 = b'\x76\xa9\x40' + (b'\xde\xad\xbe\xef' * 16) + b'\x88\xac' self.assertEqual(cashaddr_out2, data.pubkey_hash_to_script2(phash2, -1, 0, self.bchnet)) - cashaddr_out2 = '\xa9\x40%s\x87' % ('\xde\xad\xbe\xef' * 16) + cashaddr_out2 = b'\xa9\x40' + (b'\xde\xad\xbe\xef' * 16) + b'\x87' self.assertEqual(cashaddr_out2, data.pubkey_hash_to_script2(phash2, -1, 1, self.bchnet)) @@ -514,11 +514,11 @@ def test_script2_to_address(self, mstpa, mstca, mstba, mstpha, mstpka): mstpka.return_value = 'Pubkey' self.assertRaises(ValueError, data.script2_to_address, 'foobar', 1, -1, self.btcnet) - mstpa.assert_called_once_with('foobar', 1, -1, self.btcnet) - mstca.assert_called_once_with('foobar', 1, -1, self.btcnet) - mstba.assert_called_once_with('foobar', 1, -1, self.btcnet) - mstpha.assert_called_once_with('foobar', 1, -1, self.btcnet) - mstpka.assert_called_once_with('foobar', self.btcnet) + mstpa.assert_called_once_with(b'foobar', 1, -1, self.btcnet) + mstca.assert_called_once_with(b'foobar', 1, -1, self.btcnet) + mstba.assert_called_once_with(b'foobar', 1, -1, self.btcnet) + mstpha.assert_called_once_with(b'foobar', 1, -1, self.btcnet) + mstpka.assert_called_once_with(b'foobar', self.btcnet) mstpka.side_effect = None self.assertEqual('Pubkey', data.script2_to_address('foobar', 1, -1, self.btcnet)) @@ -550,8 +550,9 @@ def test_script2_to_pubkey_address(self, mpta, mpts): mpts.reset_mock() self.assertRaises(data.AddrError, data.script2_to_pubkey_address, 'foobar', self.btcnet) - mpts.assert_called_once_with('ooba') + mpts.assert_called_once_with(b'ooba') mpta.return_value = 'foo' + mpts.return_value = b'moobar' self.assertEqual('foo', data.script2_to_pubkey_address('moobar', self.btcnet)) @@ -576,8 +577,9 @@ def test_script2_to_pubkey_hash_address(self, mphta, mphts, mp): self.assertRaises(data.AddrError, data.script2_to_pubkey_hash_address, 'foobar', 1, -1, self.btcnet) mp.IntType.assert_called_once_with(160) - mp.IntType().unpack.assert_called_once_with('b') + mp.IntType().unpack.assert_called_once_with(b'b') mphts.assert_called_once_with('moo', 1, -1, self.btcnet) + mphts.return_value = b'foo' mphta.return_value = 'moobar' self.assertEqual('moobar', data.script2_to_pubkey_hash_address('foo', 1, -1, @@ -588,7 +590,7 @@ def test_script2_to_pubkey_hash_address(self, mphta, mphts, mp): @mock.patch.object(data, 'pubkey_hash_to_address', spec=data.pubkey_hash_to_address) def test_script2_to_cashaddress(self, mphta, mphts): - phash = '\xde\xad\xbe\xef' * 2 + phash = b'\xde\xad\xbe\xef' * 2 for i in range(2, 16): self.assertRaises(data.AddrError, data.script2_to_cashaddress, phash, -1, i, self.bchnet) @@ -616,7 +618,7 @@ def test_script2_to_cashaddress(self, mphta, mphts): @mock.patch.object(data, 'pubkey_hash_to_address', spec=data.pubkey_hash_to_address) def test_script2_to_bech32_address(self, mphta, mphts): - phash = '\xde\xad\xbe\xef' + phash = b'\xde\xad\xbe\xef' mphts.side_effect = ValueError self.assertRaises(data.AddrError, data.script2_to_bech32_address, phash, 1, -1, self.btcnet) @@ -651,10 +653,10 @@ def test_script2_to_p2sh_address(self, mphta, mphts, mp): mphts.reset_mock() self.assertRaises(data.AddrError, data.script2_to_p2sh_address, 'foobar', 1, -1, self.btcnet) - mp.IntType.called_once_with(160) - mp.IntType().unpack.assert_called_once_with('oba') + mp.IntType.assert_any_call(160) + mp.IntType().unpack.assert_called_with(b'oba') mphts.assert_called_once_with('moo', 1, -1, self.btcnet) - mphts.return_value = 'moo' + mphts.return_value = b'moo' mphta.return_value = 'moobar' self.assertEqual('moobar', data.script2_to_p2sh_address('moo', 1, -1, self.btcnet)) @@ -676,2867 +678,2867 @@ class IntegrationTests(unittest.TestCase): merkle_links5 = [None, 1, 2, 3, 4, 5] merkle_result5 = {'index': 0, 'branch': [1, - 94864150206590526235965722633721835315983130322594944160453736056914236592459L, - 59849171046155764382219583444308915046617550355436344310681675321029813555762L]} + 94864150206590526235965722633721835315983130322594944160453736056914236592459, + 59849171046155764382219583444308915046617550355436344310681675321029813555762]} merkle_links6 = [None, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] merkle_result6 = {'index': 0, 'branch': [1, - 94864150206590526235965722633721835315983130322594944160453736056914236592459L, - 72494757060291235084519934761016282559218743148805001002098588078214939771139L, - 18012755156996779427190686631173143337082707813254112256638152524170454035843L]} + 94864150206590526235965722633721835315983130322594944160453736056914236592459, + 72494757060291235084519934761016282559218743148805001002098588078214939771139, + 18012755156996779427190686631173143337082707813254112256638152524170454035843]} merkle_links10 = [None, - 112016540517777279124582056964762882775092635530152119738265592842063160830965L, - 56016915772221477937604398882069387632763464690103128956960662776002935411782L, - 27489797435812445852286074542232496823045696260790971196874895068817967327914L, - 29231458257536678058796531788726312001828885265742980097893645233605822098575L, - 109621318833012795682402637604567380346073503361634966798913016745742953699966L, - 24909319073749908615499772821230754597736318049326474726843859675116381978383L, - 73116838412628052670152025319686481320276280169380738966717514804364097533428L, - 80886863176958214668563050365622560907514596142176225339217204583899265998125L, - 41589402369775626260554332252036838054298791596933198958489513673258971505130L, - 90207124876116528982898796178611787615303549079587054631783065386394107105504L, - 114354507635998358018416447246810731083459038073523320387363301795032648400355L, - 3468633635759129348396311811642141059611148041398510578008184000944189646411L, - 17514043107330244526426315235805045874023023428775112862062056950974122062033L, - 53259785307043432607139655762614467196491065248189533004175348159284660172869L, - 52620393715353636218560129188772966967309800948433722877797002054186316980514L, - 81916037529722914583852010621426568426887061600075613109986180610980935124387L, - 28887865002743070237254048932842508376262793422026358600329002055567891885209L, - 26911650718246041071462711157596525307850141815199918550035772490323117482977L, - 98782771420179306759562155487949995386960639005911027478989653998061955681574L, - 21385446635146895191163854777028162803169770223985713636865070264449808450295L, - 115312282836937207946894229413241455580662549241543640118420474329115656990460L, - 8038616326053636715857944728508909614506215005454136641706259209707589435714L, - 115648774472085869829557067749566131339376972955485372286312437113097810332113L, - 89977569599113102467001097812324253681742984229238600181917861256506653234721L, - 48924912067861623118041172086475435793443440679010754712941941116717440634853L, - 36587039210909234246472793549041156245733357108593864427518986567710598392952L, - 46109624864431307857770609789747492326638809391439411091696680294058837799477L, - 16046121833973661809951046995227302935987263834895748044292415373871029012138L, - 87103134101714405379218872339020541911369109388829618784084371041796944430262L, - 71849222861024798916155067399910267006659711014200840638927330075305001351870L, - 70844616719056711586280497702324062435759674335122542937012422880906044773779L, - 9335799715313274697512042344496215317099396583298735675248312763375363020532L, - 96310452005589395003812166209756935214142758015493698798130407204945344186095L, - 81905963287417508258305936184419375724301111181318778863757865663441633463111L, - 92370163495579471744030437129029154007365623200242295216366697364220099495719L, - 36375283506059775931024155362654312316148209788950930164000462865078958359360L, - 88726230387220372332073897600804273225361892039757582601238798806528910444882L, - 6070129213356042314691499461742835393224940498627879606963066377266801299612L, - 58583931103886568102124231505465601207272863084913352879958978958829547119677L, - 57463926047214227742724634341326914848675917055176191431046747377307567352099L, - 27012546757231614922088904355562654115959540651898947136364052388242505768569L, - 99433045653889563967150006921846226712363259667263341416016685182002637504325L, - 98930772562583899742647561893951122857272411004257815634561920125860196333333L, - 50108682577013406020347739879562585417576253647642773177726545361365392252368L, - 64685183169410827677125410208853885791480988563246282885484253607919434869157L, - 63831879829294080751777051276131359248834082161927565636980809995812441758198L, - 88444488165896703625205363380828907087113537711070698319237824422865316278850L, - 72159984086399288134669843460215053409686501596375218830869388391271515007149L, - 93923006498599762246269011802512049338272400480966002367955078528607110984351L, - 56582486764232203710657643460558786621824618256032901506993654680411374403506L, - 27247248238300328134410397652427878380336360748128996791026616325378108504335L, - 49761339576008033226113121759699928068150081352868219274106736813953326265638L, - 9161675158558004739448120378002634293608802907093779336873863369459008891019L, - 93461397760483743306132919367837003785210423820141031416311717270390284637122L, - 62900762991748812547111882734991529379973619367968883782425707337170895993596L, - 32757595965065373444083144038461103402985094949819621309996011288543377384235L, - 103960048224805408775641108708179160892191001524201247681388380155314536724637L, - 53456560041009681567044041341204706503806618637681525958328705890594461717036L, - 77717709415749147611975161379861131154824772698687245241144493306107366243712L, - 74890197579975358597780466905530025112143596353512857089470046812806235935743L, - 24637040035557619748551503164358139880147695176857752327797598473320679714713L, - 12816399163497874874824956046851796108049172420116309081964631263041327964849L, - 74494961293884467664954304349698851458635838653133923701487804959710521062367L, - 90993195954149572297606851545725050698910241708435138297753626520345755984107L, - 58215138150929360293081719766024706035215643415428831405694694330692503719259L, - 89956111261673835060385930154948690999626591425223630675807002157058238821032L, - 96913445328851719786024423266233282775668924616055488595011129416530218434040L, - 112072065079699680359500521368330428382079803608836130990153785318838270149395L, - 14850098647561667617732277867245347785629166243871670796634517953513118025474L, - 52051372518516601581864957765692485097071703085140267671692394559015291978948L, - 22428334879466085092832984704566361590992480397962998571491363448424996051481L, - 83668121237531480514218115266149211167088412945398880150294279995083596674859L, - 57326589617037353335933101525368632749804298967102525145907702271743943446814L, - 88632149646179999179343911262867363834501950399527016409018248336659121987348L, - 103513396087040744916176505331390959339760897230049404623861598220178425365949L, - 59405515372488566742785411177582096185006244999302269156531451569770912827320L, - 94410488185034888630546519641288768107950043015563130381678422847498960827496L, - 92917043115324816161356018866304701890979909198500356250790217418537154937706L, - 28387412679588455802257935903781479441774758695531218575255221599977885477398L, - 45345338964765670288443753460668457262803572116668804743820613946584039806468L, - 17554385903835687117359760867293914739385241051772405021245097638788516398348L, - 146704054663283934711294565066041188709559059689193984271952431577139905378L, - 55534501706042922186966773974076149855785615244193978550637186387298665233797L, - 12402292003490764097291803996915545804946326347843103552862034174944187019226L, - 33927279023744526352720281963382595793226423508933214565592188289555773451285L, - 28674729283795803892989231482389874960373994212629043184176027814493098577767L, - 62979428877521372940895063007616268821966798956402214474988446361024679512490L, - 58059928852559648909397597332991639414174241397379900252886480855366523869880L, - 23149549033567608603378576763933536979652221515126523824297157005037634154491L, - 31331785003632325691521049665971090873036911275170678595855097146136857650528L, - 69805883028197720252962280781148286012966422594772335803511661210608982041459L, - 90136259271208036140807781305121794369112527230665007487380885920988164491980L, - 108284363538516685124971597472434350564615615957983267557967320689537268236763L, - 103872916138223246484444709027601996626359494810040925740369292169665090170821L, - 20163745130684015554427748135506154842279311229136081884933763731166339971930L, - 38861078160039252718353485169669430755389752224759618377580811463418472015059L, - 106492657875624040584059066389441241595276994256407827006904008468691816706346L, - 9776670813106470420023500205860682589193759333647761957028971310568162594911L, - 95547750627942877263332803284960121334737730663663425653187528890288840934155L, - 24595691744900522268361546496044420497232882656768597381664524102565879647753L, - 20560951005227323016094269978149633908118400347609938515652741873881000822274L, - 97538994901021840060915370027943000291340661051520734452728118980746955504134L, - 3206096951624214679035489155064291884200717537349225004749377469262758264168L, - 87213128872816361850234696481403629146111393159791555573774379367698747440969L, - 52492154392359966513135657643612646077062522044723689819581548433266475660167L, - 57874848912728677019093831563261174317645429492784161819476727716797103478980L, - 34617353845582173186339818095469634689208812124426987406603484565520843863162L, - 63352994991869902985863831141264774104112904508101336521440783817476166378616L, - 24896526347641187332629740257374236902537250311446894531290446029320129805493L, - 34763391532733369762581513657392564500863299511718590960540820980612119494337L, - 56490223225145450506626693194447650046194222302382964227296839561606036891082L, - 36970817473630539387769860171583437005195045204732265535515596613775570972383L, - 87053185231976002982248680324703214694723208963143948890114515885935043320397L, - 29847036569571379084663465808018400062560795577661654153597262068169908014170L, - 18988090895065615698635043358038852667590102293148566014706810260439102513807L, - 64469609724802831866389115122647676877222365077735069104786062834889597393919L, - 83556789821922402798488159552377663265175622639952608675121508387029580871368L, - 109936006775042091714841318781806779763941627558694342588009783709013194834414L, - 22968733154639340981140430196449031182859954403940180947419570045659083407700L, - 17789275781319118050581425161808713092125058324692136001600328252471260119734L, - 25745380119689470807209093393218039737578393498273708320349637209328821820318L, - 61641607478575128527700451527718093807683009050940235589813631356624939032595L, - 47110848145937746368414424058821501259911814303529144556069358271853914032200L, - 41533909436391753047012504052982996026827131975414910405032096368886062826129L, - 13054948048121635721506270513359775546141300282536389803702833848405874430279L, - 16080681035777294584165123624695238589201445166830763492914391196185304360703L, - 81299539459149782016401935277584722958566375743744658185491349417910196375678L, - 18945061964739542292675224703307880535444665336511089699084814584597438298960L, - 112797159538436039343555668735819394839428598748222619016939149100522384391054L, - 73300295966858556355393607143518982906893794572692795215344888739320658186069L, - 4041434409204542945242581084870345689830618454597899093695016513143642290802L, - 97508794687679881071902975234200563849411621855344235991749755970686207161839L, - 15282141413086994702794900287401256763476842815020057731420569793924926978911L, - 99728292502384296296228667181892942533052936791849702203347135028416281206377L, - 3411041873042499785540450848806342320912326049804985044239917476630471753169L, - 4048033594044406973983364298209147826637114833783700079142995185645222879854L, - 101860405294836197506128289253832975563582041161562488561533643193912164273168L, - 78905877433925568584515437130206044862818139296717285038469191868676799310061L, - 18775690530628442604546733798201529558056066835322234540392467080880913809254L, - 82947397524614988691926143062900829869324231456303333360721539341888846038725L, - 42694379073331099052172297715130893406380955641898301659263525140461504293047L, - 14442033767533181542149794383759150549978335385330888902568884429150620610599L, - 93313581709603325926029120119082923112988831425916606563484732721238387656810L, - 72801205216710264428360436666267791931111107489657889310598331480989588029387L, - 67672324229006698997429333430044401253111346908650081260433438623710584187265L, - 70772702159994604749028832792273009568408747593795621407790253945395559706842L, - 29729304049522432818646784254663965006745767318792991694212308384739446301778L, - 84627931201730893564670832781378984288443711600180448657831065852784023499012L, - 5341943877865281034686860324729716028225611069848222572406801055229289775947L, - 29363932365380673199419088786644528126811770594253361078602977419321774803891L, - 9004928131838813677658487282066233255501121930576377831608071926739686700330L, - 105136954397546093563754645032958827106234484325609968808287454474846711319990L, - 99816460821225201342714853579093969388961697645623860806505884442477625580990L, - 106681508148883422742224326307154802018855256554317516173086564531286716004164L, - 7006763686362832983859018353853556207867301220635874533560223129687398063238L, - 14321478981818480518746074874714729340600984755356898480669110575494399252101L, - 20175260458757597605277157497724495661959897504305393475703533111106974204442L, - 111769254449605230052328802781178889903176520895536759727961315714921223704351L, - 36426670645651890452930640114977419417665421141639862712468284926884279415361L, - 109432460300382670484067214653957247313416883180489696636197853559990484030609L, - 7520403297596573819592781546673822831071168643752348400012072445764927721892L, - 73196937925500377714455439113432849037994391890274802433562823511838920107695L, - 36752755571095894428029260872947166518412591768027342056659080137127900826464L, - 99995344805296217510853913486463991681280426231577702483100113184040494219000L, - 112420429371656727207370103196793504245398270791446904347278453314283313337871L, - 47191946582297313211416991922641768931234133845492807678047578621589626189485L, - 109778423006027852506893839915943588591107046052313487963867787449068930618840L, - 10345675446434556619929989818962829290520520574227315805411995298022315933978L, - 97692937909469320640194638870172745072367628197340418062076997031203937194269L, - 18683260981785212200820959138526719721818988710798906741300704329047908844217L, - 6892696773191096918392700093236074630398023141032592274451349049962035542623L, - 60564427846980699670576108199909223771359549125660413891296955825422714914983L, - 38785763103128427613833647061323411816642055799472850145381412858873101474209L, - 10266092268719998396552723710961267337810574916933175583941362520043487533883L, - 52632148605242242206734320602317136445314295285812595150816657145404960256128L, - 86430865182180102182285826479504223564509795487884784384886813129147931898614L, - 109654073516008488670419221955708597615091266827715478203469017337766287849746L, - 81026678297990230131216764193661112039622434667965493171991305981991014657474L, - 82622748792598278407144966529781092604914661332588100202486823117756878578049L, - 25507322366608129176928204743509962836694925557984874383693252038444933529306L, - 51980179894131690770292900838955321107735899831146194979127760708884582438956L, - 39893713525243360628219119209298547936570206617596529159668900841315961417217L, - 14387364924292276198604346380005369236826342347182298818726067797096427891678L, - 80725549608704072432582752894272065317134564903036018699016358034851243292524L, - 57931677269404600136349629037176710293905732342675570761221364386370582050657L, - 108241043767163664167205246362258726108503618735082308459850286665596958398812L, - 27041560631327932383266441142102307786246412560862312846135065301507337248992L, - 34625690239551233696337914812047380316989766280990608029448299992841381318556L, - 13597595180205500577632878824504131058343151112673827495505944816766119242943L, - 68657989526988390460365803072516350579228727483683299855487425203740805321173L, - 68128720652325683666418891539682215901319669332175011784422584094377594552002L, - 104041769249150650432713286188297298874807527317507734388055926579788565698935L, - 17506611583023822782703007270314878467544710450669560774683033677129500120696L, - 79876035561916781816687040564988738579362298771175915576172207704762733629456L, - 82330566824257956442496960295477270673561486600504288976568497333939224637217L, - 10998126045115673379715696210992497023523769066924127029147032066105877814739L, - 6134205546032008896024930332940593161437017366857148587377265090739938507808L, - 11583121769842881304585057168682659884964100675720338197866411629831388260593L, - 47948467738357486329944891563527055069643980603315028338968162313802724094371L, - 11215667885570749573396172846938492308466387752575072442893328939856592581070L, - 9534445050215996549574184314121246759691522074947006611864912586114253182980L, - 26960993245824579668286903301462553933094711257295314684210187284207914046917L, - 42268713249784757565602219772893477530395402041957575219491013329425037932834L, - 18253096826887824215101051821620413966925375390818892158612837687736493874269L, - 32647453224566146209026428358709030929789472415884155623819230563509430098873L, - 287767308279396009793123999269205094524894944712599136360128064711797483633L, - 34729615465854230937966579696686155883411529356665280280028584403769296316609L, - 68281051772180230242281621506957421090373838565755113033691729820708913107414L, - 99139670525431256093001603279585358199342573071415589508037259484090669834518L, - 91267441814111668449455789360877685829217853601929030146847181639079805725296L, - 112331375053079340953180040166784320778361475210237842930567257762115150453895L, - 28371709961045497162723804260663265229524852382382390971491630999701617194893L, - 74287814005325706960840114010406717339638651149367996645855364919384064717234L, - 62813730919553857955038486382168764703884469040420815758550554930257596578121L, - 105545450997141255192635926957785838960634589257071510058148660009878001071768L, - 41327280573876048725438022338561500502955010393411792104623229499363429415913L, - 85305487863348628556082654688864393129756375287687859474166404086269915423521L, - 36217864842258952910470692818799400265537629839424907972768337859708224272429L, - 27039273786118956176256074242317720472159292773454814400065255644876377528081L, - 28257168443684587877664745623305158713429464605548802435968837515560446426794L, - 68860966611758451913434265377941548143707704988022881496208085576333989847578L, - 50407008970923325200185226986886055210151299406994703375093867352751009080672L, - 43833750391299030896607810025375205862164543819507809304552665996364584049181L, - 47517341024382467669841982663807010004070648542247729079498904960356542542124L, - 59501796603968326047997181784800665294370948166459642689928940044827716558887L, - 109356913084047950264750047637950104857997683486400548504377705982514288943104L, - 108764899133114175375894919353622844771053823794722043622829189650510861136931L, - 99702504117576275465334878690444650629284364394408283363533027878927080352437L, - 70841547470305287589274784901197362472932969076958924125873672199972429659380L, - 19614776128064776638184459221726965378454315076371196529553499930811313773642L, - 98079213119433189881285407717482612916878647506982538998109042938607065006624L, - 112302150976513929199789954934292839584625436975546042670097483152919172778948L, - 101270511568225377472511122900933114546675915482267160241459205096142886966303L, - 92601020688553922078305762385834063943477781040884163604477818272829952897893L, - 106516807503153752241651444005385814426259174908471724892260099441760067584006L, - 59558617948858154025583492179361041670311410135471546029253455165957065077880L, - 34589958509803762243288779574845189860253197080624774122757136677990409899676L, - 28956991241739635872887354391751915589336163031718370818567680713934561473546L, - 76284552793775899952782267192739926313427643498917773454793559446244711464210L, - 15169808245466745617655858126391662017843438763733740347957895786030136159686L, - 91303837629389982299584271607446771694386497564892828967340596042435535849746L, - 76706271293505348906195831263098926710454398027822085522661720229864395551030L, - 81385857155455424676782786224373024348911426134535495090280538905769333221176L, - 114027723567722411367125115195503223432492147480300914967916421352243226160863L, - 58683566049686664716231137094943841721169978722173124650775160588312999544064L, - 47636821537401183076676334731710145678811127526881622883432088094747228792951L, - 91536282035304813234567796434364946910865772878331169793296557113000386367870L, - 56229624882039089131852205427165270210088805730464734083125360041622328297139L, - 97669934343014072373530806803228099401901106327901588136030333298365599485060L, - 53610175098509849726221624535924354414085033990383931412157822600931356912963L, - 8456028367645624034579366182003257637590273712555737187498744052364695741913L, - 13590227372717901967224485586122763093032532664741134262481610836479299684660L, - 79363333042777866174143261304028217995231430841620433630348966723071049374254L, - 80310669348385703633478885178056527674053360397404660465646404494861426931512L, - 76053449640184337682215337408166493809582813223481816798649267699315054787614L, - 49557524797100181322234668564746448411465269913248832928539280364244877291571L, - 31349668130482234266895705887351848689030288515397213507254429683422494453226L, - 100523078506928710661710840376918307325379729091199276698426711431092321097251L, - 27321541552954853256201290168037140371906027004144414749507597003937123653687L, - 2631189220012736809936028959130414511579464458347740950181563826394086700286L, - 37707599701619752022054658444093282978945371896935011773965043895870793891121L, - 45394733945061302000923340867791152664821559733507222856568779530413756014405L, - 95340874961247979683533214972331081503913736359038376005637154187518984386867L, - 88761528612866195484152119688406674192445577846014439797767556449630773022806L, - 36135078039044087803749644587304316979939253848565308604143673942545508786330L, - 108170833529393902283960998731357956456749612811200500384024666342150739083393L, - 47512502507757503875846460116015295158758283453564371558196514794284165616746L, - 21507325004620818719248930115081453354560870683510626857344667716802398423589L, - 99684522227981982474613932478640264245627478765595518455357931316430023823495L, - 91539177891906741755261397047769750765528783737254354701533514995475896738514L, - 111129281145592623960314201429479518089274650176023170447570611164057042267360L, - 22578859183323245626833259777830627448647768500237823313657823977240236412741L, - 10349676642954124319464106128855803407368741329325517831607597138586570370450L, - 75813035507443498537723420624776215351694467717077489892101531934015707573318L, - 97594492003050383323388967820362561331982781928579140428340544398792480580522L, - 84556662590705018272581684903772636103662143419126207773614399679368447253016L, - 57438562249538101497765961483071062601181323207590598012932050384594326670864L, - 42369525618969729821281192750986928123562580701994358465110068123545593923346L, - 15631178904228263960240009595109284018356032359409694306860390850287169084700L, - 77010475411668698882543270552280721918070811228191463399116907778221183212574L, - 15413551241691563916071223025427025890072141513575960221673968406988693415755L, - 3886635086355795958441009792222975023324676133650112900867529851708672954448L, - 73012476638251310907687233534174360901505256204961617624515953950293599750069L, - 3722822644273822339360433160044015759398827051858643263577138590741753934176L, - 80408423812406792073723049542224711512546383585571999932848110527229812679010L, - 95727805294873918079320757434531209634714565678497703702813927918339782560622L, - 16089981349149755158831064243309353835117501894530652592287993704563215911068L, - 93181713378293406240141116118372622123133778817521454218943819809275284420273L, - 9073415722502328216365879393933068130631879884724670922841802060437301096372L, - 93517519773643331571375204738306910084371612303010400324402128977187968977848L, - 105094715911488287236836140179095673404733767807464456430714007607658401214137L, - 112024396687943913146262498005010531235678882540698412132370591267309885962221L, - 37165995241123181677724541737159514391850143080304163810158263549467466680559L, - 61968583687972759389885948258239494882619324802275296237733196640628370858735L, - 63829405995677144318484221414124274002955652352509310923559860713163722856947L, - 98532673930518295340902238602168289554424153910232929900036974384290255073529L, - 85997627804527857570889685520722152596798858230903042330943741382704463195389L, - 91215913435294163483873667979004310085424847448801135410605514096401666218327L, - 76227221506957628957308362003009905875501659532083775433150630010718621705923L, - 19195017703426046951233699673722502733267585758017903840970278708816922827617L, - 105129253587366388020090858980091040319396738451908098974287286821774711695811L, - 22781834725370441481771875988115741479803940767486902303521722492815410363472L, - 83195080117942179663592464716172666739649362186378211516611789972838421162501L, - 86594886402366270550826764806089860917730898934318005632123043261335819892530L, - 83097351296768607442750079314496113785526355672285553689112761857786549765444L, - 100851987071723593535660952515023915930748460098144529099521019911796498728056L, - 29042120456464831028285966716896898582592761151226643297300308103175984272554L, - 56883443662087622362160331291011107290929701370651644081822008095958676071604L, - 50508584653566925697655566823622736349705765459212244663848880793217444659655L, - 75831090901176908887931690796034589711040965462782105686888900253525610531547L, - 11323562829041465752257738545564075178220860053461170862535572762094853821959L, - 5217823388742578674217850823134011496634030019904331757976562616609709361164L, - 82174942362135905037353353709043782001314603797222727559986134053342781187860L, - 50202630649501021671704278043532121482846273707780410024950587977821359472153L, - 3324209706684823637468553443562813490050945432671016742542032334965381665098L, - 4740060306871125788724607025640175962029290860483506225787759615413578438990L, - 66756383172477268799988778531049589331084006212114401164616926079777855044701L, - 83247041555794071645514293521408585641895568480433766852375217524052544918626L, - 64541219727160203814701276749279883931437393757546403279238766945040313755497L, - 100963507275073289619694246177466848460225709327667594121286073708287464725661L, - 26318972549610462498778216602226802420225960415781019953778522488339924158401L, - 99012221291939162309007280658070035717355324092069715622838077145257927103682L, - 92091797836947203259213765762741251602220686559266784005426706139740459141585L, - 566796505847571272464524383407843341080331238468413785758834675896402367196L, - 103374921238374169420375942200248561514811450987014707811049404971341441272037L, - 71305169363493275648250184362479744655365934928015625437582365751156384329615L, - 107205417221582744390211344577307126967827612893837438184727896737548023950882L, - 92441154917234429638228535136154961872027655587283604258871139699670937581874L, - 84140778256663318467116520240058290998668299902088911664587745367709172336743L, - 45556845552016678147898181410667713972502449643588537645594148304307860456075L, - 98113204640413555142202002286205408580623426788130742652307101656799772050073L, - 111799582795648235049116568249188571666873753213621452178599923815977556575921L, - 3042745249238721747695258464570962925050325502231269880406471834698690245832L, - 79260931570753127951538043100557443222802554197894319158635554110571800139727L, - 48702562806629641894403284159379781964963463868578074138953921518729881897431L, - 537996483305687316813696733498511854451212769284793136798416670104206068964L, - 45276599793096426247844394503795241641541521518296716355002195232712186494981L, - 4711833054533598595597708926805930010573801678420856245651307107366104375822L, - 97959533653164703009028487058357458563569018661009994100670383461131095168534L, - 56124016112344825540146770224663139087319680635554267370628216094675068256283L, - 71388779211443877362892849696115871962852377897600069938201061972182558679838L, - 114814453627856262931674961995498158354061768715887759155072831158860551322403L, - 65127402122408243624228517277824006852940650639347380715847184158968045247524L, - 1229056862661197769327296679752341218679776095210307284806779517414384801320L, - 88972395288849790723139133497080910399041124169028974570218083938890114004777L, - 6417453592935644328519665655589014205209280966147780959484836123702535239210L, - 56638073514396757799909911152303525501958212228412740313805086645241850996013L, - 102579127893915729546257461329702255407926414660089770043815514719934869948974L, - 20052431404475309206985582743289944850004744789499061844247836954142431470639L, - 68972067553519121689794584486338374542497793488247844436269266153426384773936L, - 96254500393585373611088611894723205133243393228141813526638537758161133409852L, - 80604912450770836457589058367594765669839829467281569025199209131769915023420L, - 40557914330758410323049101458954929392166012791964555533532404907549224133950L, - 102924567605188907865161299769801785501600541170723406168868563766023720606017L, - 40986531312936695996240272556535388723561976353121061639925326611244396991048L, - 28844823668885701249680419649255648386959547672924676354836558450976588992597L, - 42076520546468627288297575294464954056406207503095735542678160715511123561313L, - 94876977270169549606488747653929487420735806539860621916222965017197647068258L, - 1260266738845674456679509616730441729777121674928342543364246627967833933416L, - 4523993849979047481739506944107708609384274326378844553994163227711790536816L, - 21431759397973169356219560894746023951943840789713921880195064784534930889845L, - 108821013162731753851414548436779028343880653825788920240350346162479970834805L, - 17906353290681234638813612028432794825791013736587994117250116787654462521721L, - 112736826194075300427719713325582084166039134281584305446092387153477526778234L, - 107984435224618494468183066425582748291745849218527044060754498637893340408708L, - 107611717886305319460852919775001524194407688118585221081009301252444206524552L, - 31954918240493906832747929653137205316197877563475871197676620430438989407116L, - 77294555680991456511548367452653169657122746699638304443667609185820666636173L, - 19208527960490820332864206665914487032201955968257931377530926839178302803854L, - 47154831783488794566405507384999216172663640884519299346477725192479294180496L, - 36423542791664575997770771722288221039652387193653371043205717125378764567191L, - 77555976342427942058170549023956985435812144640382949629341651348262760703138L, - 43412768734709911583567081706048412075584631674582341311496091557570021430187L, - 21959336236996441015148717897872088078662058498333610499842166795787287723L, - 63538326993401217866500688544194665721345933982165421139569219846509127908016L, - 79905845359365877877977624880233920057502841691739504437421524898586928213681L, - 10681792139241101858432940958581751179421847022560211889898357291399318170290L, - 112260621524927562855578944812289876926535469187048546674396920462184750797235L, - 88165566912353893589942666346863387620695272982391966569779494467819900828598L, - 52862665349173572715756317207877669753232762053342595347846461744880907785143L, - 71358808321103202914714309465454097348521307041367555204585916320180062656951L, - 93235845147880238951137684176889200233801378964276260704523792127410129667002L, - 72718808086725231119910981405922538172045185301228107871813451017267501324734L, - 100667480493446758970550426412588176704820604183058808112051923130687851060417L, - 110775042139845391601861530470426219464494762269966163468273769019688062035653L, - 6766593846697232623171307629298150462867897707371440407908986231567520535493L, - 12014347130699256114344244004512473658069924388663013028615566904229193256134L, - 27825969965105678940460966110158495152943605697219083763059951984078990520011L, - 96435523890332143175359238075473964932141166205743687936858586223483767233740L, - 102847003350359276120002279360870264522047980390554207969181636483503095996625L, - 42632940521258859773147600430080503936968451360493233839016831022987058093266L, - 19571300828974450772611380433683631913081195861922411543580528176815568926419L, - 111434655731367993894950670902059551750517417974415170312236407315260290389462L, - 23608235690717222095431745605482011235852604694934703409773120155291836044504L, - 106017757556879327169455640610201808008611274941425491584640844534727352975071L, - 100194237331574385430116872964535571014096315483635839836478381542863902431208L, - 92713684320292866626136347893934030297322201773422349467326040890402300878056L, - 58846607406140216612620045773658739808395681978926887219599326204302567728361L, - 80320823438646334388944027405481388252815446922782408490922543251513074510569L, - 30088741070680259716939238344801295759478996236886884148932817972902909245931L, - 102456232221700541259096693281931704007044911964379487697537170726371186702827L, - 72013500902968439013009687254900905169470508758023366846525128188789265135853L, - 106985170799722298842517273574171215868269301677890670174617203613091093254649L, - 77997640775942562320971444102112760963667113775720082983332959043367735711227L, - 62683654055983657992170448747531715227967029489145137570086335419775873779452L, - 75730785749340338179389112993153891613304743397576005533979099055998292284413L, - 66762291762568193891644841951279936563042785960280188860221342501381190300925L, - 56280313917343127517410849379001990997102543396430104866007467738343225409664L, - 59324467591512799624869384909984173499050034803780230329333867633862365756418L, - 1683044441174010502621700456254295998648099133489320724296168910612291517957L, - 88147253662322403593684832253266581017635988274298267439887723370830751451921L, - 58343716962123094353217839136626066057811742662832209148417055342402360726551L, - 102042089450135571288922375868967077092525830608023966680006742666402948847384L, - 8877283783700618681680100555294742645257799463038156608677788927594556549403L, - 23603148240625376790483040108047997409689131038732623508816589309969692005150L, - 45015696176505669695533330960506968194871235432630036247404021112955562173216L, - 27273242071094864677506735514648924422422353640301315884299919790802198722080L, - 62678209183628422275371869480260753311103544944645063056338863808623721685285L, - 11923803399857345669089076785461272716003074233828906615691242807109868335655L, - 95420412784378862133673297170980411225412791573819301925339594272229792658217L, - 17242422577646832103051643021716840952370970640892134824779146297889642365746L, - 76855577286732301379172865713619652579012237579727566874656827498872644015159L, - 96726325685354130145050911060879275730162214936626524357987449789504855781432L, - 50745123236844673747407500019857240986658479523835409288316425468889488181049L, - 59608141320400525935940756103659561296276824613682462900519909091472268126521L, - 74882687980309051986643522889218926141822412835990533021799272338776009053754L, - 37859908444522631436936741182357425966710844086898180834365036809567321014587L, - 1087203752576771943069656551595484272469990338994559269489909016589514126652L, - 60991521814750599780727542170354024457607925232661659210215919494766881930053L, - 64453051011344733857015590621639093213503986155441055021177965898233993175376L, - 77377955478500669379169781583746316561065084791761434771728115325544750893909L, - 115326776852904211740113046848936493585624387044642876008916017320233794968670L, - 66843638661901395342217121671364591758871761375478716017443685647803085332321L, - 76387522032998444590998554577947521953962127682731686273317708994350303287398L, - 100509585420698840447268897418682940179825506131319550264533306588834528678763L, - 102377125275632046267335597508238894551107275260674055251955140441510121413999L, - 36110335244868694900388842961776862479127814736923771794282870914687512014449L, - 48087901527306675458708724967244354205948260975796662098779427969098790475382L, - 26119165494218941379201102037784208684098799025173516959855235591131867261046L, - 67086317163668808852789730141898373404855391395159096739380812113635207695994L, - 115168997510970741273100147764087527929755242529074042878380720661984664186493L, - 71535154458377942923293268040443538978433844030766213484797279484920033289087L, - 74490351607525076344048122662784676925669814471098066911158732124307598110594L, - 95439581330187916957676081877421602929486334373742119907277873013637003421577L, - 87656814270301577281831314214475467755247771966329097774569394359651653327245L, - 81443161254179142501416466831321807477101179745994194567006581832939242932109L, - 54885804727455974455027736324678176988523863264697016122398430190356272496015L, - 106282862423962463801232566002528433716003843973088523363294352394910521613455L, - 74867103562016151054298336491250814339466536972863952799828325501346473267099L, - 35136655267440539281917001436812264484530523764622204463869657683025401996705L, - 114542145761998514467316137164479580426564663277916826776976176241309854292901L, - 114149603230109641409300300317765387311421041280449018556882166752625241532070L, - 22647598703536487002308745223680732687562703621499663807315267259473542957737L, - 45267848095711354051242143972062700550237336594373265586388322482699877540522L, - 37825297758958875478292750297344134694893802502002915810386272456730388494252L, - 76481269729086848596168842665464734492043245153991095180531790034161352572085L, - 107707648591247717508601437529840582949327190645047841981368706376540258461110L, - 40819894040158651744374093809592828959931640536131204592389598534102797112503L, - 59838558611940351927330467880089282310889795164199406620582423258897569518776L, - 88131656420112027093931319604678436950372558469915672228896966267905920349641L, - 76928539760456696194165042654470297096029479697948934824843832220438705590987L, - 62168541405737812225774170936595749260003015142194074807536949077284496093645L, - 82355551589038236450671947962490907589266314215583786237831900265624228666064L, - 91040078168525896186995537827257061882913779922844500756638496647089649182672L, - 106710078268466423920902446391414721044408430843209044367846557222141269618911L, - 8295944548002166402926075220981155129901615305773735264509560278371576354533L, - 32348596508610154850455749911780223725761145130705214865401572962784236696550L, - 92625991916613363364099403897508115714291540494878622711747426375003813151719L, - 22579452154116011806600193670899805077492814094240764086078790176929517654760L, - 61501673693710664558466566656679485767427270786661384288828507176068731874794L, - 54673841047622207097241337143648657461679490594088615644422753114290872923379L, - 99978210348430706642339409751264239100280674966640993530444682285055126424312L, - 77497348920315250447640649448270009364667831704951223117844325527179785810683L, - 44696363875663259716003609140601027659047948267389412486743757199567011857917L, - 100580552325682292262365631780644228565307253846729715876945147438523292289410L, - 11518861677132083256648844750152763986628976608478800601214858206199205313024L, - 62264363214572670209945783622006803827142264044650362355019724123136265172741L, - 33230973733442066812841097555869412305470922004648204666631516339173994362885L, - 99622694327542991641172302475186123081603436578607813888441614484377927724293L, - 102417455616494351577269429386609166099735639986419056945044716149347214777607L, - 64390549037290695081029250664557746977094876129261502170393311974899571876873L, - 4971884117270309347183734480578381967398702549340681853078909666997516183307L, - 102449383389506438850158445094726115013107692321577632033000101955980429851662L, - 77032065671909070527193774031803934854547369734395171920960771534661333256720L, - 51427001524546076067275517116230075777739059442665380893299690996681123652882L, - 57846707658031795839501691960956691748675157963351582448198375141276585300760L, - 3207400714205273428098068317265434706725664575349062007860014575398316976155L, - 48996192045666860806356015189011849203805311725988819243808235919973651832863L, - 104835176291815910614168078170778570188425290392670660463751413530619922189858L, - 14981119087540252574734932626534306481790846972083978190235605830727577496610L, - 63010711061850779941155020043897322102881519569558009332207660668803951977251L, - 81690223776687823440667971909822413569894292161339595790524996391870114827301L, - 58960316867947445772617227827225977131637752082183015768746567093022707191337L, - 20014782447901262411771703924763542338641386402379396629574630005982997966380L, - 40322371483089115316966842850857881228052744149017987508932980653077287822382L, - 75225266479277326265034150495327075359004964339592640634194742539303882532659L, - 1360427873648916040478677598931434689696693619539492831713328152985548642875L, - 102682486285577705635701705175111253737654165729779553084925758407023923315518L, - 112134468104068695940005782500350643375308818145271418444665998130374311921732L, - 65346288658858844548100134545139308403909249070489810100763409995477238532420L, - 45118385594713970159090523089169565316532036698798054140271220483524531336009L, - 97476029759653028058062317315042925637551962120190446234623575312461737374538L, - 10065604931768692054377094739162892613194529191136102644454214890555337922379L, - 51553786030402063061700254827386386701080790101951499376167131293753402321999L, - 80597011256255237792858049009205213538457159347705673937143882448274035124817L, - 33844272053464645237023714379137059342202186464203853865794780890067672118609L, - 81205844186930169830914915295886776634252574020398512386640220917751422229332L, - 55618115254902954328799563061770051404707267477826050932521018559065029105496L, - 72561727906788411099387267207379154973461292291399988323244582016927347227225L, - 38200302126249889943153227138035137817990392515788356056607004367257772863324L, - 40512699025239178899189201917599830173998902277981571855357988350276694199133L, - 72852130373113254447550573789839549535122462986768199497118255107335826856543L, - 21556543496705918692009455279894741802994438873807382234282828641568574702944L, - 94910435199430807117493052677366099392273747913236237307831525304532287282531L, - 75861377249331562077017399628408234437628214897939132885265899294794269531247L, - 30876075781213658129907831810717284861780673483216317641763733274897623510641L, - 20703967708517858057303822389608487644244865221307109638361146216007403372403L, - 75484464698550708496430527575646346430950676445134417683713610303229079110261L, - 87129729198669339702782235251703596679641140877606117618734732225582949267063L, - 21266603676197216321600718008268210400030243356122680120555563896175222459514L, - 63415715438466196790578746287176311213905572186996635167094209280910967331710L, - 40720368057718102298431544796123435043114356544273008650218191651074186725758L, - 112712268248652359734080083582461538637344066407845029243721092493183497206142L, - 114937114775233845143486959600340076179533032756834814512468454080273362545535L, - 36512901579603557913193537689480903094184396356981067116060536144286700842623L, - 56411560426836146870951539885920526009324584091242151784611722979698021316224L, - 16698912456783170995326467336104513767160540663058718259277822376227672090500L, - 106066760722965292194719041696986145324409579006780335464791791351475409133705L, - 104207962904909832816216631384017349780647804676862987772215854348086512657034L, - 69243961841176518549263230888469400531404144027167071188890585689044072806794L, - 51253655298165523882286604420161472846136153868591164972577972118747996841358L, - 57522621367187189331324803586575115229510487362376403257825249297783421645198L, - 14008691686569941249702994950556981918752597678869294675116218434795486754192L, - 17559590831409421526199061660667061847018920246172867120529710154254038520982L, - 62030850813603681661213529210192297536410672609839415084110307444989808291479L, - 39483769639853010170216670313190346123132594269609674789398817914937545130137L, - 27373432150674246539366656193993633656856212404804434949408972838465544294041L, - 80515524415230956277423458011407925895348914691856987154482076010610066957723L, - 49603749491658761343063310147446444301134076709989236516539085749722917173407L, - 4638234616841955479208035396665903927460428545633473766627229552734393840033L, - 64407677702144975949151853501065869572610657480257459923595074962489696100514L, - 113729063033800538237563507194947437935179109496004542295476338932824489294756L, - 27559869753538413456779817442066339470743784389895941011935964995056981446309L, - 33384381289532990083476970734483649138372535104356143628107394996921728224933L, - 16207109765807602992397132829767586006453433292590664044414937271538578787238L, - 37996198627725162202981310547747180578940010211813882018801070905394782922923L, - 24628564513391374841142496199906953696196889294968272338406815750563978886574L, - 77311986397370469321099234043385939709573400347645098238364769839769499352239L, - 101459630443329721289871636542291648339599060924804682699203278554752463558831L, - 11458472762629511670071313487968925641575058276033733567554002191834171792815L, - 91390821097036566407235558097405985046641826208230501464531008191101542628783L, - 88524914862823500026206667566397083358529858623465072900012276950788691297970L, - 47781205217992275185276602931233775137652615298547884028338694579101702392758L, - 107336460889271365479382359792329448251372014941188862765727741363490731115713L, - 13683491250017276293402705979452529337188096939209334955030433229234688947905L, - 5985774502351629175676960426324333914303410190559821961461920762704934667459L, - 23304448933988759752992693834848658743002695800222397537634383934483905592268L, - 37564289103624408045017967248710953371026230579918885993454830860061146739410L, - 93440226217921584938869887668526350605552124529469174921820542544604456138451L, - 35976156482283765832545022774001668880213841650251182381063592287413945396696L, - 57297350844970429984695678794987814945484137417192146181343109118733204280547L, - 53078088315412211833793751124187365422715677410329852285061982688379219527395L, - 4620670977723745073636505024767100328367801928808682752786389987771180617957L, - 61803525948465253364619959990876209602238139167016879456633670301134189240552L, - 46585052829677515250319943717834196659280187016435597500044886010686587628012L, - 91743224621411738136401680004986839707449070953296895944081573638514545794541L, - 15610234236458785326957282756613241231461484896412468404866135527865235041775L, - 94701869446822483372701416835685032588722414109357932060106387983998248530160L, - 75638383867886646067851120099891468008833811906034441039017079502899866891760L, - 109323217313071505720530793462159030982066925855329700973555314076623421322997L, - 86842647332705482807195494061715107567592560678052902441669254344785129577974L, - 34022377235592061794214362952580373770895570995095680439673944392845030735350L, - 95953533733989408445261475890619634519580457917243229943281863657327054532088L, - 26422928960874356778655042269888582567356205407018615492158941838555144306425L, - 18967698604142970614994714313564229649235700012432985379836668529749470929145L, - 63892359660797867642513857940530011048856439862103598115303570201290361878010L, - 74588898331913850583986198817678327719748410068857456293342190987907207856891L, - 1891303523949303133994914040695860991496422858712772749043232242469596454907L, - 113555415921895241105938811571952390824966743626599165941730396114135776754684L, - 52531601946134219932308041725442066030140304634172421470280771996149298830846L, - 32638282716726954532165110313232679865817254425127224461225107497334788167167L, - 80840014404821550722694570450507044048598523598329185386887679198829878334464L, - 93645004356397514961947862340688942736458020763991484114338872125689456535300L, - 1472416534300792912775421675541677859235555728416376093465195351989356744453L, - 18117018437999600723844152703648593933015731624364436216442596645224534012167L, - 38755468804570185370691489631181112753516875613651439286270705031137197580809L, - 100715082849109534526089419466115812821340513907905118566143241487861302468106L, - 92098448699173499615912973532879395459946025134630609083709282508755477552395L, - 111550391766917064883209636905511974883811737658416504517110617588211693661198L, - 32590990884507149788797018565535314787256008527518350785763118765435090357011L, - 38181426751227898716885399497713675463479498492439859204929263568713129655317L, - 107065502437416259973837742628429643307293123668177644997591368635511427025432L, - 102057799846669375009489265342522217091426916766438742908452443895711329210136L, - 23472322632338496027637669774186145868837209896740446601934999472619109133595L, - 54101142996391643743621251953151149918206740135985052202976824025819666034459L, - 82460774504538637863049867790099375227234890471300564145128882983342803542300L, - 70948468164177177761098584483928896319724434505662727209543615378741024192029L, - 33320553469317264567053573050009719096602040446852816915845293451211202605096L, - 33341836337609530655545263682386433268227320320366701976523152771764387320876L, - 26832722136611840332586354012095781711272330756674126314113044937848293234735L, - 69354984871910123412344914828142550027389971844247803142882539980451463733296L, - 38887218044895438528977498335219550982795547502506023717328967765626818401329L, - 107798852115196024784748025278489888281525855258344453618798858457928346979635L, - 99869280657090254472597381392765515587357272194286676483834483257630760565045L, - 1150972596982422542285349832340838048711887764822274317800353265301858729270L, - 76377579111292113222500505883636325603958491053990945762690246057076144688192L, - 18688447831653735278420733874064402883741520741110564341076606483438814241602L, - 61229082344798583966128461730723769513868549112845325753229329289005961153351L, - 53704530304758293508517397341653702649777610155695564065012810155341918026824L, - 69672085999224845630835786708571653616226767123886631733530421027118690179402L, - 104228058758416623080861378964448311854955016876464394251376949850452541418062L, - 69861378734358355516299556986446323876811798280712171940673944522961928182867L, - 50903666105609535885983150746311206289999522994573939931085951723263504210006L, - 69762411846342189978617721366439039456328223786210517096429517225270053858904L, - 96785295693675954518102108713098751227477969718126822490988190873035929951833L, - 53902883677242743134794950840131929111141762734886047716628834964250614593625L, - 13628634261468974632639423922822047532604745471344190636598823923634914237023L, - 105452706964076144192933322428871834424779481173006000018659835215130331082080L, - 68824702000389919294367590560891160312350680290197141749599999274678668891235L, - 107609796248259641295614822376326549134793895930280222093108768885474705237091L, - 17806410755485799985163149261014742382557649011328574576946479857183305924707L, - 80007950390934227990091902500313518817123793596835360540614202062387629313891L, - 57047043109144241791334156670491897780217521286517046751569717659939230041956L, - 22794699983082178924910854965780938016993946962403974783953812352356032881765L, - 91880390829879836574992268062426895025565288343047524546899311051396352657767L, - 24705349683829662791049355586479945768768745480311908459758516972931716053864L, - 28545444886607560846867534556715623648900007232552276819418615066865497912938L, - 84368788466806781207329001318048580816467702441792122148092700034070300901484L, - 19817770163640889510029214040635317313099932200316047934680130517821060351858L, - 87805468381594296285408693509948150567016409818567107939512282924564188137587L, - 26449397396497515260596530903090322378234325869858244148315111808400524166772L, - 91146992636787877641545809782917382766985304095181848259100686451357469554810L, - 68715426009894030818044978141743928912101323309208159313960265269320869827710L, - 18040473385285586900378723202640495963593962530797220344080340777191012984958L, - 39275664807235457103450939776074687460408340433109552545236608964230082437758L, - 45010170468168442348096414353924442562300445083918439509650577849987595206785L, - 99879829272458403583514272136956716403150130902119831861390384493801483015043L, - 35376889736154427903457914694629675374773640299681275927534732356185078510467L, - 87403267383558378895382345674614868515698911467377552912077501940526884632199L, - 109908987783177734919635133225811271606397029398938708298511253484148973027208L, - 17295173665271586512698645247530859200557285101599023956986141259468312403592L, - 21496543647128813611837541425310251098581298051727650082921765810637490227593L, - 73924679330956858959462999425158452737576816314412552159708766718249552631433L, - 53384497678887864522475977345281785491278676926191527209728092457073607815820L, - 14370611267386563421622036936506899557654641367326539546895441154821988158355L, - 111107545720208053555132620274411952639184732975950045885811881349875589168275L, - 63911110056340508982724335631458613598435755978305300013119800762745751222164L, - 4991172388731658875474305317575165618935711992108917888386354041964307307423L, - 21176876470041110100700684587046880911769841360105649899082567843002481283488L, - 74776329531575971143272497818603797944162195101266803339847407068460367192736L, - 15972742698609831215845555456389847006456706745673491891035631526317253802660L, - 80767473484885926201446229963118832797391190102702298632676421820670824097445L, - 77635205730391155379004464305903567091707977567941142496628511694966092103340L, - 11406599509413455790469570789130258223474549240858015981787947665751680818610L, - 96083529219145290605954079034682972299178843718214603389887111115574190137778L, - 104182749557752609588066266373190615208480722850768531026125751278015041103544L, - 48631184147785440090049279800185073974284491295936065880067181420459954812348L, - 41623436996314670663601629719379360870057342449489798887029141584109168613308L, - 86601098079032759868258107257839306539563142953815642076039395625817415854016L, - 105563939493052531934014237726522354074579599535236523608564993934980248877506L, - 50848326516601423461822147317609300665761371880723719335691811236205966272452L, - 53443239328296388634032728319465566355172671311595650926236448987473879053508L, - 30110729293997667786865555990487461290947942687167400634833810419675629426629L, - 70614983488614829546558717115340990183273642848289705990085731487163494754764L, - 89024264216765437369979043502108523385158180365027814309471804683407653556180L, - 115548456861997880437700681078370418758203326265657797575702284309135822057942L, - 112898553218512376742308538661783506627001284418604607767529974448192381368278L, - 109432813267443533585437973840676971983433963567786192632155786340553107824601L, - 2662704726986836670271768579907165881708722419900219067428758353742850375642L, - 13613520122626383917675800206671181232214326649155827042925689433090213323994L, - 83951988661545836264706075188513666042462298465297935608985505609887277022428L, - 81975715382817024762173756105467480535625820756145068878263626750270374605021L, - 33997601865631325889191208753159898949487673964493425383191044088181413836510L, - 33488295268844659105032035017240770147984662735095586450543153485248709891809L, - 27897772709719653846193537544497924350188353304930329345920284332030672261091L, - 103238249936633036841613509228020446121198544683486725789653177543671611484901L, - 15221234255475442610452844759838468002249815991530457101462023560018655644135L, - 17374917198965396359597519847766098730144580751652864844888052673202112933099L, - 8453689025481713885958764231345740830096722466471336992142774209143222748396L, - 87435019133094385353914686858439226234011979874934283937402214350771309380333L, - 30093263016783185690488553559991952213412981757409197134146673791181871176688L, - 105801262676376315091269117615337342244583356570492008726505273535486858061809L, - 42199981988483184642320328432699178004289296046138328468300467526183146227702L, - 24808975952702810597769395794187108416393214214233361021554486032419759604217L, - 84120069830680241121422959140358303947709189290291804052804239677555153714682L, - 57145075288344878951245955904237169364079244068759619386581476461806309049596L, - 87037046752894812688116764896029579808521078387282643645990731265108120107518L, - 53833716710984099268840341191170265452631444148382059443690844846479300578103L, - 60433892667251911178190082663895913801033234243285558434565454351653288706673L, - 7637894742751632937036126902481741313410477934705839951387925907797272353418L, - 28569702262874571106266993749405212812150257672385615282012173882373397380508L, - 107293178132644939554701238383356912595689041895825953526773070844500251747242L, - 18692107709494833026133957730323867060831844188841832042897420729557773016764L, - 105215836386255858696570193840069945162296319710058502813576963156340050516978L, - 109640003434925005994749370852914721031598383660045299893366311313447339993673L, - 106102241749728113753317719222455613176545485853188672515226171948431738326324L, - 87967514603464604336907917322902677786986284949310789742480895118474916781293L, - 10452097529658641654898343046410822952471479992533447520610095024013678943251L, - 23998548314685811912152945805085035389917998668934352311929808572528389431896L, - 25939865866010035882167964456470371600163942045972853680854911794476690635624L, - 53536172862391339437029795049857615030014626954364478815337794278161579085454L, - 24964604048144863368823580632207625813548165209250855284071966109033283731090L, - 52287877752354792178225670823552022200923488758331256946005040333293056268993L, - 96364922991497529805531577328219502400267879296003605669407596718895309312833L, - 61165071124090622680837349796264330231271014144745669869678812170302746438904L, - 9862529443171077075599421597487817548148389090427391749462809411148822924295L, - 75677951243046792472455949187424104363526002297883608938230835512231614460344L, - 20163041695099153318595027251967745914329198374871561563937490346110992293826L, - 4157835572607732630870554716292314261800050096614393441327328109790858960534L, - 234905883427193112047074061162947269770600226722370798297521202217780089105L, - 91529499029030045728854142855955178901186723463577650890340040626063925568268L, - 53064575229034380164833917313889589009225952735529633244690296853431154256230L, - 71892978348861232155473269601937640066130013123066638628775441335656959331296L, - 40998639209287247912295936589461636559410311612976640996950055711787143531252L, - 74374227204789972278808498765271912946485755525825491620610959018166890338045L, - 62451921477571070161755657423071910758989601872448563362100668997102713530293L, - 32134737138246725932856372118303955100968116041295195433870841168959896235470L, - 14190585998210682942717510078458953206645440166185429761253301462636372114475L, - 79474335301119452810238376391469807601074622440831977333649965428730079239176L, - 109567049092477471774993763016826103256542113119281030515153187392993745961610L, - 71418646896161860312481461467422529279350093001628823852273582513872656562972L, - 41392339283265326163133896826928004235033698573178712532596038286942483842323L, - 18532945973520998179912609429658373546802263504125602083549893779219578139579L, - 23502144262977761670759481544729389592488156074598394643273279227888279825422L, - 83046195510510798713138622300841149569770856741428985034371033319940242464301L, - 23317281782700035804616836877354302486621457146647933488477033449530725207908L, - 40206452017693607115032426904290824747142352947913355465262447954871640645456L, - 53163461084033728365981239326186532325844271665541815079115687724016913988956L, - 90965467319718316905273128864160965695596596780960242040099814032727903699091L, - 24734798197013628509636652015719753306714635092667911866378518743709796261090L, - 37433959738761870117015745949755180738344986700115614650383604888597901882339L, - 96646475389668069819458453779252760710336863933494930937260323864991302234708L, - 63952408163647557708732940735667268573608342775050439763837379155559584330654L, - 35844370870822577464809521336934643034645139191512223195918819231967528273209L, - 89048024331773490818384593068703118412135203188376388473438110057526922667796L, - 78113748600148180492734505349333372472964024933653400767458434453974032635824L, - 54173776002260823255859915512510128977943917299469817997380229925381045687010L, - 883432050479911142807166205485507168437530802395363642851350109882719118561L, - 53485353294057357820057190873528970994022313820577768050270880081771824850957L, - 1376947404935534290290878709800598865563628523586336626789091230720889887532L, - 54782114845126438876586530210393782366489074178219614384072439562477141776451L, - 37861199306489999468439170251565816928427173812130674532522879137489546050394L, - 53640132153877617295148818056655406698667002755494762787727014438853749152110L, - 36094520090494132568726788901733125729887512412738145324559488327331435071209L, - 47708537139701186414364911096104061211191086914223449210282658811429201866114L, - 44642009019249741536518128251511543839799104615312192651332257099676514463852L, - 87290192662809247283905546878108315691917779968148474260664182424127696884795L, - 97671292518018682890893268494597883645013579196143231920993066499185701120805L, - 13691409391483500819401386629732148379513193717278663452790161368555897957557L, - 61144617532654697585779294384326603485860537145081158448917611664126233388396L, - 68193985570254974036684107457627664520913551894845023070425351866316352884045L, - 35186058029995664124689643983995007874332255773767997499577488346513719121213L, - 115257539531614541222503830830159607117913671948645429228004653119055141552616L, - 74108023471371767946328733814543864504216020164356715756271718337888099957251L, - 50699915395557109958628796848153707137790179197796094586999504919502748430036L, - 77098747316761893952761000882437066900927643357092640800471523098528858444741L, - 44196706823041307166630159413528024217064296070484564708314234712750074312552L, - 54311600462392327021859357736603954008201712037004116839763570346563191882613L, - 4712645262686969075341091045084853692873346753675156591723064046102802703035L, - 52633358246598132500454344861267240274924230486539615588687078210860399265530L, - 38428397862610980636995024113151064406919418462458968489360301281168699108774L, - 65770083666590557138121223737091159168021553714387718826049997301601143959193L, - 108783332248779216345938909800809951905550875303335887996223250993612985109020L, - 67541554565935595782234506279937914447172413779479709071277571759315214810553L, - 45528057480829729537027883221412675091168280876932366391030724386747243695450L, - 48574723508575577074482350565172348685996516743512538163088285343250059087877L, - 9595676212719659333705612367115264818901075522839724031540792598785517533717L, - 59222796090174566623152004867125933154676846013253132266547265719068942874438L, - 28479106166280290479941097145545460264531379215822491299649689124114882347783L, - 115221963463389482008089037619913365807148966626978913613183808690538393935135L, - 101487675421171222328197615408486453515275049269610846629698626471597817468619L, - 11861229503001181872799219422814386750646316223301525603925541253591330339851L, - 96655017127890694119104679709472928946428042193874408633126399252134207784565L, - 11246562242800184036344964010942066327949582707661185521174872759601179948207L, - 54766903279946870433142580654753133656570753651046881012055208086423906484859L, - 12192385043177507341587627086564649875670041135249486182299191259186947947309L, - 33889531687457105202492185235855624065169098231120588348582196414732626535731L, - 2702104856154794760471215991723866354322572371902534169880991721008960334465L, - 68399366990142009038460674908987124974500851011439562754022428310012312459736L, - 78108361281240995542833859700117440464383194760701784594883633821430667130670L, - 20035281797630887972432431961122297110119895828130977481522636878664781657816L, - 13736069344130597091646675811814843306462843438451714675670050863189721631975L, - 32797729242950926186099069834265616197055885262156260473288373265286966785666L, - 7176087548488327762842449594330860235875811675839995669904883805237403372677L, - 113919392582812074400730572616241013136099488419784443992170205486316725802184L, - 6715092456584007985435621264275230946247108351204840102696310162955301713392L, - 25855087501533639303583124882822163677359861627083537912598182866705764685815L, - 73934603666361975032570131227835167994759894693957111126295581402147687386059L, - 13155636084969680059396242142814026699440156979544128067323264470699500335748L, - 42306337368511321037651705965062931061532427873546337575440482816973756453706L, - 43179078116044711766386466429804449951992950924570899179710697254606382745875L, - 34589225484126804958636126788397727945345620051478889688357109997109890005014L, - 81931093869411066216897619171196290190324526017703113902729211983823973198308L, - 100801062496088586609073355121887698810253404134289205529785971351082004400626L, - 99269301541754630549915461021109784052069747562594797681818988947004492282033L, - 61431623606091659417184920719838855026021341187124428079635438195442467589773L, - 9519969107896444550582618655543816405745746174812287787612255552324868264143L, - 108303744709536731848858243495069052456568556669038315047210235861188168386162L, - 17605988239301767548253595490806242996920114264054495381453921195513354999860L, - 23513923262061982218339986786461381461131246534613851254442803506567387541335L, - 70320038567705804654621831197499164818764202927326234150367518419292464747401L, - 61770709396189132856751404198972986135331105234997307478609738138959714680310L, - 111407271105634327977613271210808817656742352508264185802621981796146688951099L, - 15954738196663214636264590882028009749755310783326530535915292337735383603085L, - 109086491948127246516313897338785542867893034038519662369776732342690211551400L, - 22416782135059375987641999873907617075278492784876893764069641551099207960272L, - 107190810929285648335320627529686263179826994927201194238265606988725047028872L, - 47810903731926258316473414112936857581544784502116140622649113458343351162853L, - 14454090390604916607961786668722881948090859391738149034831583240117470604831L, - 80666783391091672187446797184315344472571236464839098416522221749649677801945L, - 23585443718157415684307873337161851844207024662853153813554868062732814732990L, - 27775727080975118707880751458940094087572807407477642227664452738359631508370L, - 22354007203029985550445000393366637942734285325695079942493657830869029668598L, - 24464348418592982883315752347111913022278560091043014074779583772448662366752L, - 106481239012883339270648085769617156311063292444742859382987025194184948418926L, - 39011227711841896540196435699763946582967257133741224577226414069292244419921L, - 75596650937734374746478074849258927780055535729028164467001982844458079870248L, - 88162372027313872123663368261082673963273796229751284714193546223272846212213L, - 2576040472443446723468928690754824660481396613576535456145099796125956902445L, - 95649859930869763777362274239913473448995731775502386044062500006671888513755L, - 23725060470714314999599710406296489493250175197054609214912167919579998507169L, - 49555424134665943820304057631658137318054740093228750126361525347694586145134L, - 44501457404504533569101232018780451136332705470598006749312845628972786270466L, - 100795118997594249476658996026745105980251851253722641580769711477747550208479L, - 52747201652346084586405369953639735566684715221741890642605754187445529566660L, - 15680619346733759700182666282587216548584469338339459683294440044467091673631L, - 68505014731494649040515369252814152095031304372285998550214915975944235191441L, - 56366185904135320986610028835710099815916974781671600220135407206376964487938L, - 105321308694088112597872430790563332351422354737991856346326629773665525386705L, - 61278886852279108332938535370025837653652736250991006419628139504400281796611L, - 28953313899949437588722414376475346673461869492846759563387769216822610712214L, - 28663118357329139790106382764693217907262920349622948757012124192236390817438L, - 21039077739131275359790923848462140922244215451512024187049160113337117620791L, - 54889718246598634522108317610961305620004833993443435630553026048923012178008L, - 90874603760301401413929288679885214040045826428675227957098967087132935830117L, - 112920631033471745311323794101261642576610674750854945256558164996387712631992L, - 111963032704632250385492393582328571618828927494502871768426528581215908256143L, - 51274066318211493418085421333723782799031831706515873891234805824063678178014L, - 30258011402192701880534182314866634113801183941256349214452534369042216349987L, - 54681898988358136071780093135450779338110800786503156323504807233876629268293L, - 52116004686547134015512079196737968242196127056558021115790624820932553017441L, - 109513064700864368200790843893897908604544097571420991817771435722981765661285L, - 58488394191083420053831021890307144018799701571894914444409455704836690297967L, - 62092454581727457732790593578509538844015144815933957266786304773060873782649L, - 14368297750194560111165577701486485277892655455414407596509400442670064486023L, - 67269488270555162552654401829506802539249729946556386383844397948411601017492L, - 88377116761526687308883019385729653416563320981418855150352008673734620992416L, - 53028559510875446303088848877733416279134739545287887275996211473197952858536L, - 18170944619136371204284994471814938841783677453339517631096364967572114396852L, - 2059644653191624483771262513065435276723804841147324755869599281586451784121L, - 67005151150252609617525866625502990805012970844697359601920455075585694928057L, - 108445302124264084923797508969188019268300509993700767586409058734506501816026L, - 31825975368442157656648045088070797333742837391042415004089769634419342157546L, - 92373133245786521768072671120807298020874152547973833174760183943173402771443L, - 20288281055571831952965968033892228523356643855585483236574844945395093559189L, - 105647291748962183726252681179938945648788659297315616260960540621695497879605L, - 37833694536671453212494333478156156499705175090441264557352190244699875139348L, - 102602930401694946546947058823975116987885575233548964388547148483039393577630L, - 17986089761536074808296642067282970280697535186488892744151942385581010099201L, - 68302507041169065371244854845092650671048888830947577079872550921188098246733L, - 103723227189535347897681598138697061790401969590975977817284610334967586624371L, - 85601933490467107005659057944158927790168058335522482015593505983064091002688L, - 72566572839803178961075260801968244942124210943021330655184096386449590375522L, - 35059921056683300948407515200145646684406772201818796747803118929279743459461L, - 110175048830391929923807192301406443121803247399292272801332112057564703231241L, - 89882285710142524187416311971836674082740664835810560379381270807979647760647L, - 70399401443372985077677851434886144983714060812456753675306983539671260338480L, - 94184317541206020457753610078145103270501645532598184588800128385125278401946L, - 104314965088674766481912048088686697905047754561911560292135031019128925521909L, - 16759208768307130872010233216200768925859942429678535169150770158493348620840L, - 13312049214029984094125277617043550651736083619871827277320968871324596984413L, - 57772980362021788072324853329424041285142553464137832050079118990473332575549L, - 69375733674087675844485774733379151295737062349294143700229381969561369710274L, - 74182466324362383312773623566448418316679680460167345042228292669832757876448L, - 102551475084433340433597725405003482858429650260736516785950146965463760130080L, - 87871859628381700091124119902940792161691323803993634475404190944633451471207L, - 2271931461440553944924676609864205915472545722242321043389109755049110980703L, - 79159816565443796059736871395004807034524018072484301692430191707423760150320L, - 29883226291024495072614404351628092395902350071825263946645968892560207990766L, - 115120985130692563114301206512024055186792485071581230311061507127951583633034L, - 65575467306404035265299368906717521523933770838335685501468397360739564342250L, - 42205652281356366407511084862172573538584011195306289505538491848403141436696L, - 80956675972222351626548870352985655925726199776618815554949057515111559885624L, - 106838054064585501497489884559010507476859749974884867124569682177542395636357L, - 58508613315380006091312439893090755459648238433588983488046836958077836737962L, - 56148822318227387858840396109889610931297126924790256588515075449476241527368L, - 87943746830857581847154346372383846697749344328106573109857573515682121822367L, - 96523912520065820718774993637097552798296898412284402472198573038137304590111L, - 359683682346866350672530414988029153152780243662150094655719975922703921067L, - 20653639768030400341518830556816476408986031232568656102751458314632334992472L, - 43741907665130124851875589584874693089547759382726615954038820251232049326509L, - 37602134064186142569024483775410247813923563006964949437626361768237954885625L, - 28319089020767397392393687573389812686784796486679445318554621348732771061676L, - 77246899118638359174675247864166883750187313215548163645424934342464850069490L, - 51416646531409586193575382020640831077354780179380885705693619583419896628285L, - 9530718880612395598296191543657574992246299996911703966657028659200776742208L, - 60075035395757026542736716551158662576872365983788226206193619250298945833195L, - 100042375575081934061659861835216643653798304415561784355714218575018603177373L, - 65280708434371170784603853111027779811634446129501474686503326478617370733569L, - 36082491953381980967358850906638601152925053882808553201819544090274971464190L, - 55038301814136661088634961160554105058230388568456004416928702345321148540302L, - 81148342511575768823385245247395685982245196252288670733274133346415300143012L, - 62080887902672390781432753313761551609714174003612865233793627417270483286982L, - 90578703271753009632879728735384597245850512229571538778074284994607743071518L, - 11920275443785083579547863592574994475431467374061276954952200960834359779284L, - 7901870192306432837816630504620172895333432875298603507830571901927621351928L, - 64620902328386916608189819363308224701333637778025950310007247161243381930720L, - 14902225266028720042380084120086803828537629249534266721931268127595544410505L, - 3011605234853758422230399637839989432595388927734475258720799035294793988797L, - 62520715887062371683474293194758668293503352226300290954191460249653358455165L, - 109449423401707713638949069954372475340901757609906893414045046366250410887842L, - 65974474648235806363505863545271426056265018043065296667037687570697194645520L, - 78525856195119157844801092033893631866360334827506128936210376962749108345401L, - 70525687758401237580803794876205413841795807333861929519952792049645580777583L, - 97952100411220391333417229298712459908053373138048531526005534270083998312321L, - 69482302697726023028500675325521804008063245604738851814471767661199529941929L, - 36996168631023473249056962961772045554540227552693956887219738140514501713089L, - 93939398376370462515305712120711503754068326322098998720488107315540935981941L, - 92811710090398157690207572646387238821209630261125711411677156614949689675192L, - 18834793150066231989363619595201423057509694963201888288496365825037060604758L, - 106508534598402557052256441317317198663098123351872314746403469913152131748542L, - 68522515409348199421798410175290099384706005335340883038949614431817306224878L, - 62056677592132596903749111258191415116948937518303008459322737884771944599453L, - 75008671987138723041813528774734130483329012087779153368244930953066728755167L, - 25846618857014646943662784856228290889267917537184350552103409496789701481086L, - 25790780303502933878708389860107244416128741360072781451027326248893088259707L, - 86875321517220196586131106365815943863232969130696292969809460985631264761642L, - 99520552726149464340676459841037055051665646298827646711852273930103091648025L, - 28302633324103476432059489855553140037931375716779079709591381558250668123793L, - 16413483725800636879585566339979225218650831073900754551215329181184498261405L, - 5834089563252237195293366572204070003116504012683549677285781788725993972990L, - 35905663211833345298444865971856108258053566719588841426933466057767703473670L, - 42906799631117753263723316951849157590527745414511096962646744155280717111546L, - 113670886560446927486126023588018623266901616824365249620085243678045044523580L, - 25525758440992399567030267413743803341303454964963442669812892814158222062282L, - 104441409846129220251060822845729677685228867748033158812417230194198574238533L, - 106926133638744077158340790093952487284445071012880267650762665555269754374498L, - 37777827102888811508047114457204124487000904404039738423689478126649282839504L, - 51858935644246862204293187403674270409729920230211975583979198407701235735521L, - 56677604980298282251218999943872661748831571233436439285726091418251163563349L, - 11310141567806595553122776509434966668730767143112763614244324266096150340396L, - 59568236466598403304367610877197823731593346955230100312347937134124139658515L, - 332686942346604243797197324078593908184771416824239020666066869442498248085L, - 101184157155811626748420360485115445073052410011352426753492759316284346161562L, - 115094616142259749323636183065876615795354632139540977617593311052542877457287L, - 66300571744633578417215135324779936328456592743715185456673735987112942424605L, - 48613583719208218896022351529040027028353166267451589591626141321431999840359L, - 45070517798055973346480716269485737939145848218807134819900436803766392242105L, - 18266861866071039658603879196433265099201917997393304488121681245291543324416L, - 52949442752612150788933147633704799723834836139570886640702983283974722895359L, - 106873847237792435016827377973268501512512482320890214232588930141196288884343L, - 15569634565317975671895423006707547283207063591263118835559221760770692076397L, - 90410110389444957150115334781777775354854962401059551674224262867875151944330L, - 98759087287127560374112096364011567243755138613650190558293039088068825947972L, - 1287633407928248584990208256896924805269922037761331075659055166636156115579L, - 22643922918408084792057622355331184265168520123778802808674980998986152545614L, - 102677598412504156466181238289651366875920363577612196890121675411616205869266L, - 19140515938422692005504349297136392120094231942932381661045006694294659348157L, - 47479392819189321863253918556058608916166486549752862534298736674771025808601L, - 13428886889019792224212350792850118124090630647372479978118330056662258502463L, - 68571236458166791056101358438734290027379299621943855185416588699972634133780L, - 4633337738236570848343873069653422967090076837450676791156853186692050402794L, - 32382211421012107606460976657528067674979613660057986786543262682245644259590L, - 49639024571546822434524105347091704925075399249527661103359511686788829885196L, - 79150125805409043239175151923323021000363071231306074866016474509777361482770L, - 46020124799831855390812128987233512854385899496185315940524095352093195890971L, - 42200218224318860824812897583916208482127750284199576543492190147676370417951L, - 64700565615105284242392888668153133511395198324059560256734863083190822363501L, - 59145319234225054834945074280096748257562105951751962357531680354887635001400L, - 109370459247823410861206598303258770585360943296040735774085402452631141651780L, - 99481385472715246129926858424348527055022021148459424355992992054695772159341L, - 106443499252933322798773565879555301129880638649751583766224653285758031752820L, - 48322095229054470062821743113612945636849765668600709958419576797966085161570L, - 33515809494782069567661160659390787788200157314799375723046535826284168620654L, - 41773109623016210625345820625587661213509285213374502863725211353920331959319L, - 32596302442968981956571340635208447066531220945981080109400249909883451742829L, - 50293273819739386025452529051468445849720809167855795456149610014885010486032L, - 6910633429019905036432475110661116328818994641038989881657155395188306704390L, - 36739677912617989818047420712503342474631017220638134413720724315512974000159L, - 3964263570883415651111729390801978904288959584848347710021696283687789159623L, - 76838244100886277189026448893466799361279981208788651739691518178972257722132L, - 92524917854272347189223844521544945952894951731953465698994423607211481407873L, - 1094849487752948258678172481737220834950670442465200017592137082345698226431L, - 3596236676932905175558069277075687614251277541835254759691559615596064312685L, - 56005578839865927004448053246743798933430710945010825095181046140154895131866L, - 1314127155138080693497666074353154060396713254293604808680984177855232304261L, - 36079022347925238197361912803669504456936416755264778056013696625210364374000L, - 79928239193218591378736729828916925283195818566702883627512029456337551009455L, - 87280873763535086276579332440354325979085979245763538853389996108825086763328L, - 79088598451415009995545325883504732536821464222073838688397002320856965960467L, - 29529206497868610658911692751520344135841581721873597197167956508451037256464L, - 68962738620795461680733506696324122017627315086893424184557692404464821111592L, - 93572497740197828471049179646299056635884123543357390488670201160087939843899L, - 109112927198443847769716053669067351023083576209487571197569706896608310925118L, - 78320138979699033593001420093104880827612562754837671875766294555309495104202L, - 95892698234673850732008345163508421145472860369307879265917900554439055906261L, - 52508743067911278204516869676571318573056040990507652640289868030751665490151L, - 56994997415220046511429900048521489214694637343423249626411942011111939288506L, - 71574140278649739406151462243925929626255276234777571372081177974273056292218L, - 57977933207626507502343730286904755443422417664609976290856101067259261389718L, - 30725858941570916315616848092815937606144309685272835634213112076952585877767L, - 110473526277817823493675607940407425195035436651994426913113113990131038771594L, - 105339752952469208380404795676091420067960822602777471440244189030880744525350L, - 60412306346911354225557884409801026607941275825059578233151896523412434667888L, - 64762896208805433524854274168206836106667758808610346128969223715455926942062L, - 114121970583461064873502887345233051121046760719381233728555193955719803766740L, - 22466369798521351869094158272110843558129416676735676800948475727909144865782L, - 1273143111631474652637353240638822545534481239484935749829192671246967606089L, - 39377944484720355113556279550540837896684650949388624339305746596010745626909L, - 63079304104722256955147865058876316182244124456443107773876720891861784821084L, - 33221257928046204557801831132902516455160914036846369006425441924291607025375L, - 80679899250014086830309864555340554281732747123983833428628620753799828044171L, - 5520825008571730037184139397180716999457189530901529770850492308003578875767L, - 59694340447804748768906699434149795298842348528160974268732147404640124393210L, - 452563556894037949847124302231763919722502556228150568682921788421243334751L, - 83854452012839253111626789157033805803261637170087741884414752071471826558651L, - 283272991722506593509965059184081095348010472560457003520196925295875056666L, - 59350272485483507974402333665923264559817712090262181583567887818422454308664L, - 16338840576891551738619490263301906938135318609839255904209395903360130014526L, - 46887472068834101766737497605695900287149077542777324401279045289085727998308L, - 27174317468173438847162307838360842277547238744619453235356053140862073414260L, - 112575472680252768107064569686641717727552530114258489447701964544612039691469L, - 43063725488321823412272058651233665663191029952662442943522280495342602080041L, - 90830677820996662813354986968787850850731704888547154385037797274293046703638L, - 70047206624525168690255326916881812569905906194673856593528183032623465434742L, - 71932800557222775253672430273153491950688623401220405561142140951028444404099L, - 3524882399256427360585197251246913676161052633148576017242006325063275126755L, - 84915443337732578818997000978842662417557339117578770822366157872988174094364L, - 102232608410210054811388604493718844283297081753473792064431359920776022339902L, - 11882496039470984872154583878418111610653426303980401438591456011459127971244L, - 27070654687706280950633862831653465867665464018299863662869902069164060373468L, - 59282461672939092456574734414184106943172040535313215840942116814265767233014L, - 39322449749557599925777702791134894551704245880064456282757223026426700817213L, - 84409894515543743365133360610171100432700100978076876962858654568459632558541L, - 70410397268065594155629455621579409449732600786692188366223472666803032234736L, - 86437295053666828368055440450007075213754895898533783771617866512671397744683L, - 86384600756600571727069592190350822580086961094261465255184942610917254056508L, - 4169531244596552262243178471088999423056390095652168598109446883464017011602L, - 86603605855539825936467660126213888629382588181317117671233455664505351619526L, - 25878096712841480688730079454202227773191841010361550139385684121332714629463L, - 99813837622569325637706593871916293083064808065063361750746121189938957277689L, - 14956623686382273272615490920074162785270993021184365086380120813298528059035L, - 93908520539656727693859962706714600909136420168083833827053820488142240463583L, - 83081019211385062731225376037722543708554737255330978950713306087481031283567L, - 36815584092143113621447019134638924615387138159781448150874431541732703251995L, - 27767427697076154124730046958859599439717449798059676397788989550469671949780L, - 53600549360476208788118667076969768573563511569083599363977385485736870317987L, - 40069546660661468479507161040144333240272420504696612481157064445735524256694L, - 64349920087048287004064232121909162159550862928450387719558872044596012144788L, - 25013984982049649107171523463463889703338165256520376243160360152675368481526L, - 56530789998533237811002520653364573824966959264503360163423839174743884244110L, - 89406926438927534192610084006478320830683811663693612304775430631620411804801L, - 55574766621966719960163780039456412444050688884284171043913720122255495107796L, - 33020279523875150194000155658408234335900802700471563888608219712097607743977L, - 39498198091413081719576717245537304877776071588314076270987466307013267227910L, - 70681075792817924907613405300595003622717961584972201658078688437473039265438L, - 48951085699919588601707434724938021996754135624356894480749596446244429933265L, - 46076452959520639654741492991168821701045167530336503508712707346240564741218L, - 8728181522716895277616722691463990661112351314732695827427219145365995323248L, - 19242851635027303632228665680918645839152069598195025604323474183363371673284L, - 25966598671941504091044550838540299535978523911690095545251052079003170032500L, - 71133170285960273109650294555239514035629927341569053089582833944222072014831L, - 30435235918882008095386416250838409184026844557375343024273010676275207110067L, - 104562805601059808628406233133505378432310209782968933305541489051827992880492L, - 91277304545170701366302646927851740938169501660880043983344902890228057721474L, - 72968288915422114488753941134393719877980024150813811771584482481396265125949L, - 50190389952851782334476549812324728201959717776585754131252432379408670884706L, - 53714686822709417243703749183305098173984141991560038668837805048340367561590L, - 13019991109569669604370656032243178191139406686858546771510153010511250838270L, - 67191821789817756119878795240970869267796221550236335817460044506254776968216L, - 89413994372950940556769387668380627891258272606614021693905340703246441021190L, - 3238798850498286807700621225209517329350934282288143100877405970636083894028L, - 40280480816202472888365258789002776543316182588753634995486654906107679474981L, - 100948637697121602892593946642196415807276046745009059316006093188332302195851L, - 59549093972846780800207597390208066964914903435241152123606789627760509502894L, - 56236214012501625186577071933242555430237150566129745066454391719068199835078L, - 15312458892596540523573781893452331775717723839950029000658676210347347105776L, - 15065967432271076782208794251450447638704140909495321523677229697077825888248L, - 81462686679992445078195460793727301193796564055826032266815725029072364753429L, - 31004446882658229570973377729390630349014033711496954983225868580115438114327L, - 60881893889918255607808992891845327895300679183604457662116021281288533703990L, - 97792511094095955002259897688952303128451022225469644595824040325459774067007L, - 85913628620745056720111254267901487607688940204230673170586457241362558878343L, - 93647134651574147110255208072279336751625499609376994365444326737671287302291L, - 95297138551582102493747902466790249344233763330665546307118323022618048561591L, - 108463575541952340309096840275345034615524455193912269881763882512567995129048L, - 63752885008263504388047741845098568103563297786649728967903987339414173639912L, - 51652681214709060534046883217927679865702663716840951262115852661229709210049L, - 25666020547072989328764514449251093742665833312099176399036564710247119178076L, - 105269705630708453158082837912213449941815841741276439302485601620747579775816L, - 65617932013055493829408883154321843518026745982706002591323727944029169432460L, - 94643632652344258820199676940750707745466458768098493560902616544464843965760L, - 49809197967029981470578121511861493072658984885955900534570018643169459879500L, - 102662538334700555252622216842908651775931234046909341778615018802143214957476L, - 113970501048318453425661260937695608103427766826948186238861232440963627235790L, - 97357434013974794220454749439782687637175698528098099543305920220485529874907L, - 103359508964986835222997521952836123858692215225816927552645056779369173307125L, - 104648991169616025859256185054957149293934618168732324711445261097281286483384L, - 29389896106165793254800955426429904448077276420102833967961101728159111496532L, - 17397917556551293611662477830858792324055081846212709299057150741059732651921L, - 50788640561521879066172340254498727900679747579755154172014511851379974458947L, - 43965205532676500510494796343253490918535053747950216680447581669069174426591L, - 100561339115325893421374415912582953869602487255513883614209616721298762293250L, - 66562569251191910581855009906754258851096490437585719106689692764515165118239L, - 67070916062081221710677371810255878781339891113828513253753023678578232819493L, - 52415447518906441393794278066188435528329456347676300491553094758338552659004L, - 17009851482897642242445115289124882968359106779691578713402357833717216053836L, - 61968470418522694182319110141621058714670097444452023370385834134761702338776L, - 27439043782857531293775514029155149364935936471052539789861552445308867719563L, - 30218119149287409542698267261174862353671414654735376656319890010900661088921L, - 83722683198541680548895201973968476637707037053891833391243959378912592800774L, - 19652496154790936363470942073050420903905231179229766615335909262494502477191L, - 23969602441427232334456125239419063180005947434249931440170057765321521250792L, - 90618151362150405843626387583735913551480244697966345084341144901688604590826L, - 27676891003614533451066859478651393460424961724309167669813674464058417433664L, - 48885749436680584753253699027466567472476019950871823824817684140175042353781L, - 13267791426425915825084467964002602513349413057053642731529682261674822047612L, - 100956069784946398219932550061775672758363289794138417517773642672184160729734L, - 40333404357937385101624655022577772019936956721874332897672372735097268448719L, - 112458551997636897766716155683532996884022983846949842366437224888526599748808L, - 23316998467946250104913668497817687100083031851500104547322812301787623570579L, - 114394200509243537380938016740401885361078260317260020773041307235661790091892L, - 99719653520966822770708772752147805183461502263709831815266009451647654614292L, - 80463081199638265711615126414788957383015583042168341270906917065212011993945L, - 50926914333690872697842264658756713296670371241774121393831877283526588419443L, - 100062544342282326069874559551624201016023530655383269001194311119868943621261L, - 68068020862521353358271257272528432308814754476130540913318084327101476116934L, - 89713823805042130782951935424222440168641332400199911482603719331288815293140L, - 86663612340636044221653557765291814987022783456558531881892865420940708049900L, - 97012438822187244992111487410059814894762267734855323936613215189062559355135L, - 115456008377472687851341171402794820555293289595636141868079756635653218048019L, - 81637305032596027004552048722644010360182923840044995348167774103369285666664L, - 97121760667459148346469656712964477195431899223427151445530984851020542596352L, - 6578517421505427291741521771648219090909965045148358527570559142102824534423L, - 23086743857819326290801520016575031684614920494950123918961905329612171231094L, - 23628162222808960592749692098872758091298189792059288171046583885877037641335L, - 101388589635381044996545324324358828419653240720043387756210449566569798752243L, - 19620842733350906207666446984047918346475081206033132332574377900120947277685L, - 58850961459606306328454345527935376781678482106551478360041198414567673137778L, - 43698525283886526392550172261457716557843922626739855384146946891975974274489L, - 33442616784854796480120127349523708269380041829170238927409871884711003926345L, - 31440958616586333198744531091618349581229397477920961786477030476125699377203L, - 44037228979451760962709036660497370545619138069963535388089488696166164155925L, - 23590773350114689007036710853590152873533078071389046302374175660283306490466L, - 18131169300372102223943835158584186528386930775158492999096691428947406557415L, - 39927655185828305299260927622503627720853145613611115731691007206417703553425L, - 11424009611604260676731914046838190987741247394671748550647759787863888855045L, - 106023534126028046641732471111988021743803815895465330462725283504186924886296L, - 68648138318007149508312965301811805457613385583647580389322272105745929897884L, - 35861285852404043153958153302267356973075068570728747603030615815307744210613L, - 106692958162079488264120234780830351073717987694440147487544240096771860117721L, - 35352165220882402184782264824036691776623462733023306250733408557343340031618L, - 14822282545311489372618874096495046863376384328360624764062544361258616982209L, - 90058495310599262422511117754339705110389948235968347407889592750909695010887L, - 21259014153908036079063449386092480951127340321580415067545014550208450347867L, - 49578982519822747108721142362544198831986643922392137320722032016810156482162L, - 65665457104798265380017369229106214332204544903481853344404382438501436156569L, - 46018977419201235627988083346481532946551841328607691952313437865601296427242L, - 113416128614229392197633061170738475687415527961785321345301343863175386165517L, - 72463005488702624466473135908636810035589105683486970959068404622715441569172L, - 59228871780580991287064899135413738163280222266776423016341942379142878232367L, - 101201352577621865867741734209721921320372326316364435635877898695764520096810L, - 66116563724113303807752208614578289149445196066311339830443507231280061604629L, - 13321204435294557952842567742569975996115680491875120393306454427480274484373L, - 36529495391678241787355855199218483020906667770134006834459752188063285439610L, - 35393105095199709649781810185938664796603926906726475046005623027995804964106L, - 113361361018964027876841710235293117483566240411336430409058248094509057834062L, - 56058022706730182635086646281026455259878455394424198569146889542596113129821L, - 66753929570993866861390801432055977675383761839911477726742625804552736120589L, - 74152311818771099103314467028135724751017489427625904392334704355210509580327L, - 31198424329271660749070167123360180921447024387653094853673347433987050304147L, - 22161946701832864123687613890591146417821146631382982059389586208424000204466L, - 94967039535410902433511564054776055297924708482731388778074270625836429181955L, - 101475833650921340211888028594926417400342939939712197963470191975265029710193L, - 79962135740629681563625093810301473611526352358650698543209321831966059946624L, - 56272682759487817327630201911621468568787831319876560851355108886611853690280L, - 16207947677319863057883738635880375181098797652544932176091223066346375051490L, - 12460144515649247367915525233698250971185931821776303597267414038731840286158L, - 51054786755897257128286507633905426324682484384053936277176197456512130390304L, - 10703878109914147630505465569165181194027864988338264878868171200825538401849L, - 115685353756232495339217522336126365180680521522774025001885108695820705688417L, - 83226966733874965537402061370252269001515863926279260739350326649028536299415L, - 77938744096446474082267536742558675453940850900461721849890994416621104090335L, - 10633870472986141781476912229206066131123339936733321854914824362473808144140L, - 113510575592024639046669896504932402330073924767594979636394504576918529901216L, - 28379840589037358195922115459139921091333875451323683305010087241069639779529L, - 68908866292479473675358078430426242309570647071553534729550787498549388810019L, - 85064447307132871909177013858601355916860955316576015102216104307635029791583L, - 77186435129631197486790630771123285886766192713169155391189231991556959095716L, - 60414018856458490333814081994581651087732522729798276054216916727420669351085L, - 15212960114472650545070192717970430908214794269081770422708773881411744953726L, - 91224252022784031862609153680374804011878245543758948021324002141712805960126L, - 32852025867914048360009115451838876000739199003298617884603266303681339764885L, - 90430620054982219798453934435971461264346611664955594662891046662935943479733L, - 13338386818121995340931685371910002793929630655642421076019735160380543781323L, - 40653500667926695898384831471872360638429317201349831757934492645361540497806L, - 67321568092347244312715622868186600495817055327877174732272932813970025865221L, - 70715000708627427291622464491836570367362782168418821476624235419363483259945L, - 84043980417318042435355782997773720153113022161240961471727136125668369238963L, - 29798594605740778420056358126875423873995928394755977101680155850123119250391L, - 64002739827413206738226844763112689896661441411156309137061786336417769703477L, - 3588603057028759016516615905510790682984328594608376145047909364187513464636L, - 3640113849242551147598436231961262195794557060841458006515147063563330050926L, - 1640132195779173611440482231813667282421653121121602402434590945825472442840L, - 49068472178525986111154992744775813894727777720616888679062692031878337421358L, - 96192283625043345803403853295797930138631783468065211663912714475454912223870L, - 6954971225007597775332578994474487107224665847376481897752901005026393306331L, - 97393736206168610177884752596730102881738900341429244953817508235326571383796L, - 94909591388534814899291820790552061136385772226849013926462603889535592881658L, - 97674360923933849538463126507677339914984305763250246342376050684551898242883L, - 32326926938638905804883899181301661258230876915152258405205012996608416781550L, - 75390581215090777419512899469184817486741500441160386876671097045280744103963L, - 28804629663351536283608294940890058716535755608630490430113412747955228667658L, - 60447958849385594887539070469446902724535183262968852417615873607098806913852L, - 8125208983647045861984897883686502701322221318693649876878694074186762628187L, - 36321868365872483629445089690287082140134307447167490214574356871622219403958L, - 57709458796817421581094858125640847564231293595234253030255350196483238510592L, - 91095279696055361262251522830528584660460437046515798029216072868459979120103L, - 44532164232708863754616743805204681846712941356107405206330557447816291011231L, - 82208417295733503059286375823323713635312814599695203151770014470900456987599L, - 53218356925724630008953848654076130625327239502715186839430988002470436174754L, - 103554102753645173083230160287208141011684313770251269836708493649081752862464L, - 72287395332613701308297970061776214857593209467851071250674303651221966830038L, - 112865201218690365602584250859438997853312303007342038664127484151947604421851L, - 41291838747727535371059951015751018368504265132868457130021365214694571571467L, - 92321496241942947597791657750257580964557018699552530794530263121140397570216L, - 37515108533270448750288663012299557149226500210493523635452776907623328856429L, - 37214105745309188663227709885588423990475595550200641028725694288049442381499L, - 66026046826623319583285558889237767047321089955197672372001047479175205896446L, - 86009085237117764324645317760115874450966674584814179702294705584255233604565L, - 33185045770056932059592647392427809676918726541992147755240707155667223682899L, - 46023623848314803736144086547851606591564509262002830448897260077561784218820L, - 42523124325040682188734262163872238263680769760068502922583738355277833409027L, - 43707136259254660167975670736625147170919263966206567519289343836142728631399L, - 21521825441002412494075821461882476872411719294243082231960424810761025191406L, - 48122500507820495999476353174639285803696600339217273502305348939825292700219L, - 49878520275844083983319755300791139094738827955932471155805551241054438329047L, - 2805019867980114693815396887224782179488381114608760082927920707778360709391L, - 105889067420694513962034831440622840599026391402123723795085189461218881974289L, - 102558012501655260354950544752269559998052103195524742467138368293898237029032L, - 16045802253454647592499420910737935432914631479977716060114384687065678301780L, - 80694383907286799753016956692597880457418319936546114189777042852889181009843L, - 45850888441967478025176403282980379370302486077816358544941791347388762431349L, - 9822479882591964996717128488720209197592583016104263091855355188495072624739L, - 41490103892755957014843857901396132258425254981457143869266365008399083279040L, - 34519981273367805712892296713884551032214931453997316756563875546090058443001L, - 2204281960270913078934060534754054590010912521750041700731012295673872332773L, - 92879205321717292296810987177742604902961904529684091274391960440163557121327L, - 41403519020039174258858740326538709320397612146458889978862506507151277422131L, - 111947766000272845386624725317499390083375963268740317913926980175304352248010L, - 44798112599245343572207281516281531139050763947036736697165944844889144497323L, - 102928340995534633866971381779815005780491954768232728403102468494951518351494L, - 66337378476294102778291887843438742910413779900212622781148464034568280254968L, - 56039934765763148611871383231487354654011870687696514609659661607478831015720L, - 7243934517681747968364197778847060066342821260703071558226452908378440385078L, - 43364489650928129730233785795919833617213540527726447567395441755408708398916L, - 16933912852581238794524291841725428888822250244726609065961340398924870949717L, - 54768614708066909525315386122663122276375311305049103019748441649763658994275L, - 84729924206104494740489514335112458905233956780655780501973210222476988806778L, - 29277322938893302888357826868792039003063313376342436323759513526491001984139L, - 33678771073152611527552742313583324855195425614537548275601462267609589426650L, - 40480447890208441323168952362583473949174442538879435603137691975180301383746L, - 65210427913223998114073591571054279597918449996368085666409957302627619255436L, - 111284762645559333229566598767525655137451767251557700547569492602611598002069L, - 50665611021509129153232399523138139121727712951188291590955745185443078240605L, - 86931224979232700964367085464905271967542987118370864162794587044708482189147L, - 92693707272386441235566687750404882227556963036584756954337957832491130977997L, - 70894179854964118329416027715184058487050172319260701857034205839242947658113L, - 20513835149287058783883311526714694783960711471827520770677981391121169168188L, - 37103649878375472784485755998128283116660545800082210023430808909026154302526L, - 74614844021522220679243984385072619161892523493843700560224775866754791981920L, - 97311144748272583637604206920752738211872018258123062151560689856785735825863L, - 97282949503352293360803097343846237726987612672755574861990237772557028505976L, - 59608183641235251570641614121211116914759763966651068525325858377448039839390L, - 41425581102453324286811424366295817652848042620102193704137772391802937357490L, - 91727177117026636081336266391338970810553560215502305083610747696747683685793L, - 68439194926538401577683867233319787531164608915005784342794051150521461201527L, - 26655576452391615777326024672685686800005203134710901209242934284945454570702L, - 31143473283240774865431214789334098152628855471357068527866219002194338185533L, - 43767943504780320684924240111007984914196536241705792566933468927031866775345L, - 11283889953365847458363049262619110738826915372417900452192942436343871320790L, - 974565422135080726870643057160743950307503695746121908539734697315502472220L, - 94062505243292442540029663203966839941224750263267455031867783142742670480440L, - 78569047934219441892890028502182108887887232992809410286724319457974676246343L, - 20570672053778381542185367122111196326110468346235368248193378711812323865668L, - 35891241806860952479960032306262991307022140205471781583482653582223995413261L, - 35151043765988565325231303273718710458180489642575355611039393162107912168489L, - 13516481613278628333357957526837653942837798816895627584645924375527859723467L, - 34469930884670250090266784851545679585931608749135259869539338790142549281813L, - 39226231188171088174526313909055943501898474232244682466949149864418497268943L, - 54615970833110299035691143075517066092024314562334728541220099178048293031173L, - 32112512508947520360789081302708296505473974754959805858145203408010165306517L, - 85823074697072165443604848224465370037251188633431788581582515681368854801201L, - 31114787763081247662741790576136049613765531079439068967943198919548089945587L, - 63717636094936942215167694521013396640695049671398758505544873002956659018795L, - 46914261527557896290966299653166097704478129043511948482391200512036428481288L, - 58923411056640153904729588987353811241292425582618364248734832424160839974386L, - 50179833858476307391456910536402872857772226397005827658938467543897282451575L, - 7399171788955838786742152597854977502050982099899715132733135899052117217545L, - 93872684832704986670149158334194509247022010222886860168702211704099201069352L, - 49687140203619698793673849263115576429481975552290236422892493685164901278792L, - 106273531460025463668310324173446244018738894282871539525215762780591291706155L, - 78923513349831944924537330470080754191114080083149247605929918579383623068456L, - 50243690472052874553737143971668585250777706389716966541123706593833557464197L, - 14928097276738110931661959936750002490113274595862260538156282115884646749788L, - 97636173389356917548748277423523694672226762969414452501536910222011959459104L, - 38744780619051080555509054290722104884136581161684592091596609542691541950131L, - 76305797460097674690462320779275684579026918868641674002970602312667876025735L, - 99319412254964041675502828069665819342149052987152987392086750651676744471964L, - 107366432170606397254180573522955903423026319357594955180473440028782517094811L, - 60344379454835700583625574565166971955283221980442020016988265483327836660340L, - 95273062361487489226108456769564185591569827803892488719352432327283707461867L, - 73877209629254278089333997149988436753355233586765712584450550875195469403371L, - 38331123804163560494485279204166810888417461933985250355314098023958239314736L, - 106556711876247251021682631221360850922372713031667061589770635089283360994173L, - 102890474760259854630170581840930262487721108245862113115575459773534870169628L, - 10877466614767430581872310973382352169813318491535129598341036958018579500908L, - 15132085524877042223936003242005723023770131695295306170112330353422335928637L, - 3408214602678813270177848587974025101499057941607729407576635677028440290643L, - 22831370693433669028556328612098143404459453567000719312466316131142036071459L, - 74211345545461458944362705130817924114329322029498646950905451251295568342426L, - 94895738810491560992102232998379123954726818134284590088519056362101447835763L, - 64506315879394373126856628745726235941054214495972234400483028618989952757987L, - 106930502633370520988542875453726404799932590091198881910056842282511120061402L, - 63059265553965330371504563689275766573397530656579610486037010959773696718956L, - 31512172698707291596500870726909806676259139754688878095971669931502804321283L, - 93031196312652451383813928381228909877151502052237064392916714826509373089585L, - 82724472015882148694886881638447653377563068883520170787685590352921926596050L, - 78121869861392699423387129877415553564692968777285986403673962560019302484340L, - 20258020069777856163090242646144629794277057648649514391298447286083285034755L, - 32973811953722044083062761445188979149444368409290717867611463700154466899554L, - 100967605565380205645936381274506567491641207181843358499345916305538920337268L, - 72390949360272585354558305064341289855739955365721481655730333617637799338135L, - 78596368190128155349530458347836368925860306679224721978650253671304172715997L, - 64558599892689557707415227444937142675646389328776207164588655540569754417692L, - 69890750668381984505944991731554411154122182634278802023177924155853842361584L, - 75213803206394369769719191236935557715315228259768150739077153503198332841035L, - 713865771311928611559082824635799123841148346944239416389783564059397504708L, - 4217795646636310578015247225747573138661168845810261717953458054214996036225L, - 14223818603976320398373336938059290367291506650169228998269707219657657502998L, - 44533811145809402876828177271382335586411109486962835140128777341409519124066L, - 56478819008987592389931597077140177544234702081912837289515448214765496735886L, - 41258256854642400777318742135929865726252276026583411020939043927579371704001L, - 32535465328823065094547672642752747105689591965757061603966987782796974127350L, - 23434894256690473532436335396098545716482453326684491095059454432435759938252L, - 4515178580927686433863854609466342253346350175973565061169476933553924807288L, - 65770803916636481644628148613372261887549160616947240346727958158444755593659L, - 114798502242093794221481920571539075400854081537219790402383806659924239244922L, - 103466805083180111290955563590402548161602269088414100675034153636453982865616L, - 66361002558103463011373871292547992240921236981981800156173849080633424047414L, - 90150266278052170098912652741812718604491081514435199062728898334011964228224L, - 36567956334608768029893876357995916604172470588123723310113672944970409924185L, - 46650860437157018357739959743023898085493491236908063185519299139520792639406L, - 113978114883605403381413308200143069475162868763769589424052527057919562649859L, - 14571193172626764868769895240295272901205374509807718235249232780047466971143L, - 111659244927862512621498176100521641413222297574328242618976729145778411664511L, - 82034860778342408421882094700961549400046231575887188360865160569029015368325L, - 10986581324857748680434572967584355674417783647660484243309314356294235419564L, - 92858537763245692873202265086076587568238962903876900745338895179532119508522L, - 18339610539274968865123664850767402285705195044427828900485970443286417207220L, - 13538034569168160542835032989304290525603956489730090399726793567665517412863L, - 87337008194997323770465815106329850019371469234027785444177768809208013119159L, - 112125623929639326154462925416473189479530717874389249773728934274872083539360L, - 61811828574222500034860293512459035118173463561779508177733222650147479627330L, - 70625019741896412319666161595692255408223851946053030491711034192625695311154L, - 31114107047925640925691588320620064382112493361732342885797955717132599150912L, - 70525362769848742843404668520081397515062752648420532788584164390189894512990L, - 108287759814593544590262575481791776872680324980407117552849781196331047384599L, - 85387852113504375586844599166186916406411052267265654527897135913950060156638L, - 40134198285988487818395286719554733436191219534549769841212811939461508995568L, - 69806395930233422010938395428540531695508125391128576669383501857429014956937L, - 44383692378809958030463149383028662193648870703734337280232496838471404247085L, - 37833558523062077358848765137334633785118860579595709545998045785130920980485L, - 3268293153421591881795839414598389483173330552458107165658729486103728565214L, - 77951073855122558364387084673085953939719040770257045049299878073346449873028L, - 76984991608538690954688115855190325839694754137431141187376382430106543868181L, - 93615355202516268803076921422310991177683947384769878854894366353714252044126L, - 60234877428817903309190508886460324009733004937113526208989019315210791944330L, - 33927171987103289784332757937408397612271411032618895616710265773785239274493L, - 62751586340416939520022904096477984413978099039576677831404761995575552315844L, - 79096845625634241486337000390213892498887026547983695606552343643993944205508L, - 56607277381466759972527220638522037041585786602990954025182664870898055166046L, - 105099214982421911456533751426434700095520255776676657271423129923536054520832L, - 29582307170920269245836667040710117212364910971553902349708895690518740962757L, - 51525428900100125428338361910656641381520344565592714922493084097344073408068L, - 73323090782644445487360500184647646874013297352287052267419439034447355313955L, - 42074869647782598060314873644565016035441665324811197181005830202139356631768L, - 49516601016421746490828567320796527574863065300399590108648952143654685296842L, - 101314357451866153975039589602508192430740189705116816076869220828467268315913L, - 88980923090328250648862355979591435016413649386480432455268529739504295345776L, - 15707128794614645030714351199307318033849401835667149765610375924999588869883L, - 77511917891799010985827235351236384467882281290686256570463416416104546138427L, - 27943387849678302292044484398402168990691301596538116310444055545884976771013L, - 19749168743340741306635090410006638912945188174485211732216568263415920341373L, - 110789801144406654444181504369931261651183190658803897486643694522318446568384L, - 111910951285111471303966439319667616844668129429657794435170356211919277579869L, - 64147784543118635414563383484030167666202507166484036570675270255297126165260L, - 99913572267196567877319742365398686938289096843502998402751838938328273984887L, - 61912678161667434462636754144422785653695352053266328100030124472361121727010L, - 12299820910982805096697839779225272595462474269921644240369174382745979084779L, - 80008737233047206717240240077776181123924502441138518168275632598548473290921L, - 6684578692884812110830772551575493594375150652729291190368776629426171995494L, - 80133188578788653578983640222626744956569177797805198417065918779464192766695L, - 57942453413835213225435448672981881534592741151757201589563305307336621432435L, - 87685211353117027234090822097140469947198214797865560071601838941294973153202L, - 7547796482819319598121012311536540374463683191931557261758758530851465076359L, - 54060890438191534474558742520648986937754275778265604066368599326973622569689L, - 78357711406267871216257348186633230496936120953321466832769258350299271104052L, - 72208899450897039911453923106460555945446631019167927879457798069485436071614L, - 86994295236717513157031581145699694598783814912966809088491089396659163682924L, - 97244105930727320030735077718524611223480015127922147743806741309675521879079L, - 46821515488587058205364014839711589321117284967092038043247007816710617728693L, - 82315402245454235277239179882713578934450718774877171286651269842515546478132L, - 55355121149793329341491568922859810743076027837495668746928753313320784028442L, - 42221834724290400485539396543033664771532182150925832325958854155795366523478L, - 87249997762767830341600338935741630869825543641091056050376516048003954742924L, - 58558417182931840799015706010437816068003141871832295684836511897319630625377L, - 90646689685247775188276308153618129893731239475659232289832005405515669988326L, - 63683910656135883846693664354006872928429289660323804927116553890410402744276L, - 73646744644242548749883175466483401844333446237506988919813083538330014578910L, - 85919627442938766454979481519476484600102963398676046674149532757672136761149L, - 64957081418575043979714297341612993135633790903778335261242655622165156332212L, - 29283238504458590433727764033703034539298186204430885648887030958624101078615L, - 50598790870845205532351724958280411560891250360617652734747758016988149198171L, - 10306946966828842793988543700100474093954288222334589458433870591473447195363L, - 93383782227644581114167680223172364202388922104372471669591829069905858397958L, - 82966873968832985802244497000030550194805538422317370276494899473213646851979L, - 4027642553970535969311123433477994982343525472269994271857098984287380720120L, - 64932250603442933539699423260361937248779103514954901344147579197676217756640L, - 63381364269661782217446841274244572801089064751400868471443219719117302379478L, - 89337765166828711465072824407846271739115759092046994775855761829607340698291L, - 37157897758371600825668509176880331562987468607783977443610366189220797974197L, - 41534934721634715930611008172599711544497734643155781372014343681790669364258L, - 112735375116638787844782315517638234687460168051981878310975790323286363026088L, - 44815892726968755143968284781276350856920407289787182546753769254711106115218L, - 73765220109154434663293010450222677595849326210282420822914450455411937218591L, - 19046147831205526962143235015097089305983840736658408039985872584514849628852L, - 31753560382955274777878729452469734519263341263905703152652424047617012910493L, - 56528025820440181696825070057657365283122302389065973072494098663897292594161L, - 41066471144730765134600137862832271630122062375243402496719925662898072198693L, - 108851329254976771349627232810962078381505305529587704183132855479691338712848L, - 45782657390386471176610468297528047836250202785736711627364068797589681138163L, - 13769034627836120844100658009617426562555329579887732814047250887775448863280L, - 91886422773794532801222091625683935487344783841540159553327484687000636325716L, - 70938338241174470130225413153663707473714753847467789419746515939387842634852L, - 5081470653650919697032287018044092084092842228152722277640491736952861518287L, - 87384224223795844281156267148828305127744906809784439076782484004066862869869L, - 83135611780027591027682274456558526274255537793123206046910850760235880941791L, - 26743961105136074430834051214103958003960563505905839817476457138423173675682L, - 22532030310824157473834189040749196884472319625276013760738464337151683132120L, - 9223359857298668416480913604076640217732278101804339064756632068747169056686L, - 43412394511915951857863635554194292193503187659320950873874888169969934606567L, - 19540647784236022954078780536334098246701450053639191959885522181851578280143L, - 71587401330535943733922874821763431990405754036794794138238438292733445233699L, - 103790307236613919508929772229700629005668617988873224466508371105117012562987L, - 89116229333069611662836452246834379761276878778773993046975813349301975642089L, - 60047475482079971862702861973547277445273443433938108001179616873639206191099L, - 105237746554462793613846056861019686105800551554072941029028992382625121556795L, - 108391064994861542098103057536170382703463232050039865861210830246886064642840L, - 110383719200324290778877899200827280537419832857090151213029275153174188328612L, - 56369802721495976759703590739732925453003019836218073381299943293726210959561L, - 67824664024071866060860723203033616624610241498079726646141225934231284489040L, - 45159812622314756489071056435012747197513643947726183348977174794660175401921L, - 29296954400904356672668069693952291315485556260607296282533960483836433979890L, - 76106615054094606689894451859423809759777243569958547825532072698676714040418L, - 5517992596372205135413284455502946396874073843593485016177731091209621874839L, - 9724201821967171817778477679164357954891718482431336993565761149726302114836L, - 45542554343757874556691080182439354069259169845263357645941920619074512124227L, - 79059911237787761355786142449084721324880577341618157694256750391350537062486L, - 115786316403345951187691814407840538704442194426719706382741211660595173475920L, - 105687268163191512547271109273471750962837412332239380776346295964553305976497L, - 641258152423358607374245087436094702887710998998879657218575138866179694170L, - 34918116761157411029029681750290380087959536589760031623593631605070011836982L, - 86733179478836654074634035858255743097571821664563540316458099385240257035481L, - 113086666043116430399253835601479039094312618322742825628481191177379738660202L, - 103301498851231514835967626096243756844549852791107967107923613754526980379538L, - 1651919439985859444491408709564730224223820746948125282880693118387650876117L, - 80269411800902188931573551003528315954909340244161255641481971716807067432738L, - 103187269017000460087939889423990743627681184005670557263265110388521169879892L, - 27385560509092500720395856130598082707942600977300912640432654141228655178445L, - 107652647931294956586290584221071654371666328241876406501118657506007254046943L, - 109383960812021608113740637890792861947378602118253651071418735979014605169061L, - 24473638831899701011565294289730402096556538818403721088526153883042840554535L, - 9846224173247720118208988355886449746221404346771257873203847593754202649381L, - 102662655145442873782814840517129831550928080840160897718839099050785781175135L, - 24769028559101252337658335936502954359630879554079148605126140767727901283670L, - 102821123227610042686764153690522375182677506827827832342000174379234062178744L, - 60538888992399585100188494834855797182490850730309328816036386231345644229215L, - 56747790988637790596587979176209917702739680389556019048562115837953952267398L, - 9224557252190335845864472186397193775037369708890663500594671214088086824396L, - 58089046639627170807553197583490632702317744454629453559915943786066251486257L, - 74949361634317882616197100154818029751641075065519686630245499728723502225663L, - 105545398481725748667686070344023456127053912307622115118349194570728151561119L, - 96294784607579792305326288940729254458275562685216135309295354370964466029600L, - 34328922589712547669094465607489877401482600620030853266258077636447981546356L, - 18110461155777227445374994029850716211448646774400881505953510470384215199053L, - 78537434946813056541168915993760737477882442677466379329177719239172423182692L, - 111106804033498663019660817034212500168436030590578934575114513900954089486870L, - 20543778763384287988255356980462999591217639906342191122936886104376666865277L, - 69979944623130434564811529245979905974313299607865406688863390911620650257910L, - 88614609534752528145316409849545368978458252813231050595082528618337797076735L, - 7995464870181106459552493232604981462677493629412316765483289847351235347265L, - 100192274241892552681190226484205380391922603818121665463215615979772537115864L, - 30847471440132562192014233925845021842448082053920988531492175687183917968074L, - 106009185612771953580724677639158743261086614185589474477921583095102317131789L, - 49735300414964737529491213716306437700529673700238380306699221823733303723174L, - 42296385484964299260902884207793819465227119884367106359772287942267145073536L, - 93593304161408139774523640635460792414857614919210610480868549384197419330447L, - 7307278256192250911523652383382664203801884378859697798524144209347411695562L, - 18934939823841293868681632502455986241698102383548884630270722263874880398705L, - 43283869834883514902972824061825697765239546801239960953793806213312596802825L, - 107888776586099030304117156182622666349074642635491167423219807486571909525778L, - 19948679973004498477207834586951113443324398857053845225583222119183232046870L, - 50305572885024780377252640298448269964041958825899848189464836005752312581326L, - 17957692981886673636454232993276843374119256753359106269322222189831856113863L, - 111422691829901377404737395845927346210827807226636799443579882624708609365647L, - 35057558979908802301149297993008625690553232451739489974030332712652372942428L, - 8271418085423819013964698074529169854775001702800643323022906177424203703083L, - 95776783826327761194533189686403822667566952732273808389244803324783559110250L, - 55822732767027188710611079562737037991442760661059919562757495979770070666144L, - 103614045145995991890236468704385440365125497675629655757612419615576150527791L, - 87513741783132396068713089588620948980723488867680227376787276852526192933443L, - 55552929424659084882785912106713339977120404300237157542683068762661378293553L, - 84664683864569336797064920623351348778513486903342749721000288115697128471386L, - 104361585239922573268411896468856061370967679820339291656804345380123294060172L, - 46822832815505211740572070976737690066327407879609766293770252440181868527692L, - 88470610429889848909371987571202519929606149566353623979633232649819391839491L, - 21217767838674031593209000030922624021864035273440757623029183032373951859918L, - 39042335512346489471717361398437756204636323437411437537189789423683761561710L, - 86442774758568312656401659509053290041123867274913356674473628038417414829493L, - 113806448666308018747966264668211386340372262071098026619512205348392151088141L, - 45153806677195857979510903836363840677463048472110015455406459480723140223725L, - 97334203216670484425268039816716055393857356067821621681894285069289537669509L, - 67193255267112054349760010507498744752198692106570527636339214097464687827537L, - 81185334980593365913398292815226546600884118367183289558160087849132791424244L, - 12921122705733458236412898300226456271149442787043645595882704362635257990521L, - 110055998335300512236087341926352379950960601501991014010099184622406481793585L, - 77139483211748002386028346276011723994405859115530932359608253990088367613167L, - 865625561970301391434196309728509123451610413634540227535321268004076433672L, - 108754612635541080639882990556158702758706205788981100657043890206061298924142L, - 86496620785020440462916059088633665849539823972244049253964132681259815145822L, - 73752785340032369597592046414242059481288944280197119431162690355293187577921L, - 76333812509898319452265571776088275942948075256656811503062171691465792579689L, - 18845650409398669124009722455618374943009112428972476564130209535570391768764L, - 43511659326057468625602972503578453064018125560338912679073995154067283138008L, - 64270851568812346119372921352206304177423772039374360571692446205558560424316L, - 48189501702687951961851261342991672185479431528996475565083904793743302483895L, - 51652448170417401985758269959496462088808587633362570683411562516282339723663L, - 86183630114394770772835958503974162466656890874954444443342810473800261348359L, - 98585705806522812032842297868214539650203262095642521648895956808352467765267L, - 59410890204389510036140216042252448504493477335011524938179497971199717305547L, - 79692516469537176955017944775787893146924076162153293307063191658453502741472L, - 12432710324347237284896617988789981712783547199850940338980122961502346647L, - 49592934995857332651759267474856443132519544418352754847288367996356656691937L, - 63468479982956839729212721587679969020632022261218715793449791969059912616587L, - 79726775435156236958035748237207339224635083220013141836013794482812664174893L, - 97439345351107479101311900679824742011570195518527030936093022736134075877223L, - 61439533978052825633404164344305939269052214769581290601237619818703134422539L, - 65925646375200235135034156136282711234867299866000891109079493439328470795047L, - 92647022735627851948294852752752098294773762350452912414771473196540818369499L, - 53400774345197286237183566296721826734794479119161252505898756075092325583570L, - 18549628192384656385867793408043562242534554119928007805043907299301292851757L, - 45924414799022304950097724824274324379367943084065939452653667451362043712158L, - 110368172458658774534367668868855149355835365633017730507261220602074136357580L, - 55356767012696396487888840708634740714627097581716711294537656522453810654192L, - 83416396599254060146049838691316246058574249801635121553905647193061068866458L, - 110441512115054554323328435082029553243998576227583907858301500757366120475425L, - 5164266238799687044525084398880093204493750009620562934380079626078590439263L, - 62112452133361441117532405096833208471426063825484850899602116494310825198459L, - 52389563076184118231866178069377019525451392209944527621243747405999119881158L, - 77471837700672776462143670534678094168615286917735022997553045888835689474044L, - 97248062251206783328422303190498256046114164902336901334927638079052337150453L, - 44557364878670238484551439989433283624658758938335690573618524717659008860008L, - 22845430661687852453692201570370974035118060832596493006725109692601228195123L, - 101774671819854099857301702937453537028276907591416223309013262298077545882301L, - 115424369238578734392390181363816162554914372861226537640100957340983063792061L, - 65338990673211792003751730933129632843822135869185645371725904873020174573629L, - 114366266324461572987645959226855826836558496449355152538893794925039413357908L, - 38290463890585456589610194511923849736640531333686863956945526584298699155634L, - 7104380315235996039834757743773937751945660895522076520018612543110852786459L, - 34063076360765794300903320551561479083798148054160557055090751714448348977580L, - 88515727367536907576580039700060644168096251873610359912666009463379104930336L, - 85688099884478097401412463010714767804521859141166118376027704285006781806478L, - 14445723047504895678503624598372731567242295091642621226825454965131390083795L, - 105307177643870861376704975142705763093068186022149591472400706068356332439472L, - 12181198007331198915733875662579743177739833828445541594284924339103615308304L, - 62933037901514195978439869420541917885790480592974041452836435712764159078101L, - 52555289574484375459494295200716138077661544231852518075468094221843139579759L, - 86408859083267213849608593421889984462632203882937681896919607104631355327432L, - 70051205085977014123218344822140748695927537067367675872085026215066718894743L, - 50797171048465065012378418419172514464250671715708065222018882517586360384952L, - 1874317888706801165225424155060739439373484623144774569528888912338861648442L, - 38874893955970871201241959699801474013365631094709837269682371327988779676411L, - 104322546406750040921614923005640070242124422454480957460434283544970707542352L, - 23147399194890360754983100314529471966962125675439669012987512541660909601887L, - 113716952306498842347322645003014352390572038776176836124593516338466562712247L, - 36491396924188980583576281527414767595941752681245588892480488446261854718575L, - 38216976432626963996039883979812057589159795992093245757044926702099226967348L, - 85587142213637727516383870845271383623475010977583594130085419463009564864338L, - 35533148518664300451429836377972871634877828724353146250247780775257353422007L, - 113707210930207064201021028732858411605515726532230715404906758865563077234074L, - 75824923843135090956145055465695508337185470645181390611498070674519003917260L, - 517810143330059297111726991869775122342471182773654878085285132699610899L, - 50861474394015924342453430596667275885104852995589344919703556856402567899764L, - 49128412736542266992374724288983384107547040346367154413952434327740311640374L, - 47543645103034546966956344310497478320796706577135425732862193708438183083055L, - 104362722607070431239825878525881711307409736427324214678751128935605816076393L, - 80901019799692946784836164248044967464623235366342139951562029269656667432776L, - 110624134448533690643403812634937132348892276454673187051666134504903397472437L, - 11332041837814640069950573118531582178208987766303950473353104817780737513431L, - 114511557839319259473147664196208197224825143530034423580198024049395329172086L, - 24477487820919013861878492454371985336148887712503686787747853806123463883383L, - 74040016346037455510908086012289778987837758722229815721408903133181977325126L, - 96749297847359416454833866356682485133755505677563601198251552625663438440432L, - 105430261721149398447580765021122166604918996215042858470481616269905803048056L, - 79791601172505672167793297591283334154149075873735960889429812469226954026924L, - 105202723479492288927374257344836310443937408752137121233450227157560518344862L, - 55234807745596018650242903018904912018598184333302650803122102037867969201617L, - 56423886371978150980154069718343902250360154531587393738217763986684950825660L, - 88632533967648931361876213430954972474334291020155125072956484147361066869548L, - 41540602080447885068364895020121589125387302152191845916811236111088863892018L, - 95866258397646314612666598700519648912023398181779402139994107785390987444312L, - 27628687861999017469863173929132991859361239157743671136807907482842484525757L, - 22955560086190754038224423146795686308407664057168960419442490764595085154106L, - 65789816766575105386987428306722263967996208491478635414490253295806677267237L, - 82684435593876653391617483275086404180129265328752928074553653452882266716384L, - 72237491753010540389666548672706287377763382539591172617435007730770942255029L, - 91236125982365567095084044215283415421174038922356284420876986552831895925029L, - 38797497641204948824685934977074563130952656775734483696648184436815878338395L, - 29450032252377291876076927760824111963477380682854888797165017462555096944777L, - 56730302001559397227949378973374467269278644362656612891556529840301717911829L, - 98242189100315465844672884345381556806359119306380506851927541428933452924066L, - 28677972722989033022627551059078009839201978571186307987703270591903667393859L, - 99738128485488861889095050115251628549635211973689063501970159747511621921740L, - 30997311945733736603873632098585356219772217871223883018619638323654487757602L, - 28224354554309048810328838069554720792169684263283916760516197294490610224088L, - 85124825409286476718381863601395474198658538100703311299861597204493450641541L, - 33495241866568199932364800498179948306100803665579334596416761183215430930567L, - 93748165502429540390752326809177733395625010372302844333039023440166033586473L, - 55324812000863319402611450577106072802300534535282967325048243381567366931526L, - 80357114434371146887628065499243008165063530763945754592622384417840027467965L, - 107865294290004154300446549420262135970395626999303173983646891465019259411900L, - 5508815310611955958841554110831533001923895400754839050062910862461100459301L, - 110628211683082298216277468869689191392002603451165823050580500240786687598409L, - 55985642162590842695604595049296570925761414222698667870879574427317007197666L, - 97764919624729977852728415456251595728184019866527129367997851555640066937264L, - 74643707599685076167689738607577307206746099799250672992619750183209913242853L, - 49133405248477455105183361148964553976430211270825632762949204776004710322794L, - 37230040854747304562375397764365441637954424575214865336492538924135663966611L, - 63747437736511981100055958734032121409103137779784520500023115828550548157803L, - 92465863715828612410373874850044721058409898660141083488253065869311301451090L, - 6351072607009588886312852820229505037726353682229809706757173440945171422619L, - 9838929347538877170506725037253611521513180438396714957522150626475756420461L, - 99204566522761543817262712571166152669532726633519888841909895085964712336655L, - 69918315505074486879510735964313251337723667425098772438138374615816323649757L, - 22681711155652187343546055126161350570283330104128570540811080279694440822143L, - 21750456202431669808487018168451361794307926238637912778044917235186332446479L, - 30519570078854889369012242379857888860540880339074771627807263792784619013620L, - 20376068409590712757607835967606049587305403398114621126642144077359498527634L, - 57816154972820637842015295227302274063569924591337076444074648595872211158951L, - 95691029341486059200249030288647234422421749471197931071422339405240735862309L, - 11519542049335586856333108489270183185166357336465460680941349039750739928735L, - 22783439924801660726284099891229570248136801431901846601891271372699792905284L, - 70729988904710801782067722428323428729842006762136396716832906516070438688711L, - 768552533597076344166841212199031455655598934592602393555086804800112774869L, - 98831924163537997575724098258335467593562129475748349635164470060889590458882L, - 37382848764098449827367408283658574687701088781678841348230180499498878655729L, - 53826850050413005822237153286307533863893346772982720285374142965133922653879L, - 25951810197328049743686791099294062865971179361142244965197955644658101600157L, - 95474384724371876447009575826440626126046120241573648796622832772631585264496L, - 70476826338218251611930664176436683399501082487873755494166711051527638761783L, - 76923865001237318302242629280930995101767102325750980390341316214129992580813L, - 40956221428999184253153145344417098366615680167022358702893001610164574343901L, - 91258443117772646022741710991832326954876277981466384820051070056034422875382L, - 2480557044803086659730155829638171859667302394336109731251787909625140565271L, - 61639252942303938393953410722684371324573405948544383860756787815149743841457L, - 98914761414072197737759435974083305544825672459974434243172911974632891210585L, - 29288287586124734903823974425198481871396075964331854237020621667490857027993L, - 81096783908540223370427893690448374939257060429500261220346276552248672456700L, - 74747676270852284893146081460311377544280534136250755452302483452475496380216L, - 63033053896061914085783155702720696714750947306037038383801589545505815881432L, - 94880829835360619082014919456168353457187296887555045263008281138204580283367L, - 86243603393894632034932094738373100868235939788410709773198835748922138060758L, - 67131877324481198083331599258988391019642445909308522741466882560005818253968L, - 102683920792339364282974702901715431944837387943507388228071841895827490267651L, - 67912889912992465913671388521556367869860832024272229385213244739156885723035L, - 110551344711509013940497589490244356994772645505463674067940200925529505761908L, - 104422433462351861857430424561648719344140239925429049064348391098425777060514L, - 100603579863145210162568134411179495346102952400578060579232432345328678086454L, - 17710591727487898159028074633066319868136748315666602801147712313056885200186L, - 53732990047516765000084978562862022705259609372298873348902438890119898623374L, - 16063942819871515158604960419497507463530060358628017675103659556150568988243L, - 13585242300922194490912783518156384483056462406554099581421313205860094128821L, - 76994709296314604651310848255466212541642242689150752484555866697766091663044L, - 33296060443744609438007182562715573632713908461562972975440130123920242597757L, - 29823994004951149189184908981344484820146203926650734339978490701532207194556L, - 103776639447780865799844373251019648483604076101633302998164136777107089845724L, - 27990243782682546566545330419534660325166080888765328331520724576716550919124L, - 113681986404859899855489671628136330088521242944577866066930355758292916513082L, - 45480499601746912260141581373860143599455659573335060265126978654014754221255L, - 17167575884693203444847451450046828526150267046959529487681959810698891407385L, - 17232940152909869508566737574957302716450723866625646764381462079454170596871L, - 24214206196439198683369378114670659640997897837434151686387225792702458393845L, - 55183796882852678728455807147620724129591397410719508810015917859305209452709L, - 92370933471589006522196319239737831765721169148478103724946044654059765601417L, - 17522830276676507022127809210712926924538214418291549746406033322309804857129L, - 87667408077498737584593526761134529744998243816543685429013918180276747535564L, - 35876311000604112586101254886917742346936145381127393394295529620071642297812L, - 64014796749105076572734082259912640230298578835394516523304221995273728541304L, - 109135151229310736573817700892379334871732763504302882245459230784275778553575L, - 16595347687222128839702418478080362109719600628112118618015869217388018348883L, - 27921579396834813549066464299860827161466322958768833372792240664949404130922L, - 35216545495698359652086372205977503250042279321493167643258328475141020214977L, - 77117275761337491903648618157611979840190321352254166350918569716805510962886L, - 3512462062819212238377009967268608332372746022904412658531847429663264146953L, - 213044529585981392974692935043822025246812794554747287575324449148243168071L, - 90614765757064420969737750920642735373288480403571675818369451509266111313712L, - 43010469421403140310031850131592004520255679316973656230812272291852743048436L, - 17874078946148102948854789032214343103123833912541908620511389535466184704924L, - 76374819091154956586181248706405676913767641045061029782061788515868087538531L, - 91564172717501273329995063951618906528857595075266378905429418245106395050386L, - 58789505790452834130580711788253867271536111224105841840343521525916385542461L, - 94823773647415317483248568929403137504875117257673993971772751795386631246368L, - 31071978519068803513374467918831947899554357997409504867413818015530559683839L, - 109592819189390091395615159423891840082650968805821245525286882876892630923722L, - 80616066711957337978951763597092204520874538220618039320146978247698657786081L, - 64203516468165822104466698698828118320320864571064924456056450888616400337511L, - 103067832985679360302134342271731680480045309368319718638093837086698631245958L, - 30994341470584926691685619262200638787457244500478165297574371511860341551214L, - 43059466595763778882700729036090686919073527598798723058851954243437716781460L, - 1693610051920013413013260181546765312124540120437967991917459665994774806656L, - 29747748984588778023562256318712123283140459273364657199320201305598273808458L, - 2226019244043447714854361308099740688341176962586376492892706683593154499175L, - 111825037103273707978537161414761443953313270130816743531156536888415537666187L, - 57012205858056204387551272724902421605062503962555598394289313492857917886835L, - 73396140276984806244229093480477275338765263475608983452937019244211554654915L, - 52185746418253605003953484521693480852645094839324127943959781713020251566259L, - 50505675019443410862922296532230977928239665449385358680361802744120140462921L, - 103527676053816135570616835980879956268458289266085079078826558654717425055498L, - 37617128485103969063185558784266247787128354307686582970131100302629254527846L, - 3949720678750428446742361510648883442144623585510859201354543637462177325467L, - 8377131978218315616004054453094037374246718190084282403194726043647197331954L, - 98499196443008033569836737659884708297867418596615891296810167773834208174281L, - 42121509521270915625563632437621319638187814758192852640255865671287440139483L, - 54521620577162531111131330281903686807795468830466555651310259043543872094360L, - 66064747392912446974895440619261318611730429489615281970747108278167294355782L, - 15861793885995247826508971849873138627436785517062019866020823181933822773077L, - 50417649252747305086029996312270159725838959845251999690819139767623694163939L, - 60967184333674743131822441242997898492742767225047179691417061973722239944947L, - 73565820995570455127474583774784016066992595310121051611101407971504048052224L, - 47717427458146179166467332999539387013301359408189577401273175767693692453323L, - 35573979916120244358355161246610600681290513341867535117841606123840359214158L, - 55465053138138231865871429602166148592952938948327069774639169783483929311911L, - 89922242028593373850468806452435133814895318351027088363939566549861423260982L, - 7260051358784579178211291605910298603242692991248241261024859891086923720596L, - 50317517160556980163700750490597405064413342021023424187016993522719004120455L, - 87371270432617946363711807507156078446234415221813830125207964609863093118621L, - 27000773119819018574170640928922861914753074552580644933183545957332034747811L, - 42744032928437813310951510403245788701064218473001042858648361006941304001965L, - 76198115222883112855784539112917622084905060815328285716682730794880576768334L, - 114932917350143510828430027883300271265708086718065058264252705465767116470282L, - 9610974877671120553866505474605601682004052160358709919274483117463311190651L, - 92474887406473624527438845790946877750741294442993385940737555271563845356352L, - 95819697123437827240587022445477470694580782453486472141994789896836183073008L, - 82576926300800526546816921752229648351862505582178910495285630906170828895289L, - 36331361540866341658048510064579643468711158646220392124923553254704291134611L, - 46706376926626599549529540821623039003107481030515487331363332254949059300295L, - 24353324713995083211377472060712587339255670962552600293093997177370010283872L, - 17744557414274810664273678005082172557385527892208091029498867778266373488849L, - 56066104524526790445623264175822473453166467950159100460795504735296451738899L, - 40071689527430667542335410521584503230790415282110381507426618602815016600595L, - 97068851296966062329360158937101699476338603966675190512721689359550742961475L, - 13969867861865221931999418683636285972452065394091786729793578646408460767223L, - 13402549437974009817308837850617256407627963323533150555689533553100160454642L, - 23169130976851413575920663428801683336183202112522615818530455538814681264920L, - 73126837115915344741919698095460455134836574049715878677508376002500599470046L, - 51710669535427444724897929166023883778940757809780776797890510762630448624310L, - 65459597945614518793759359804869521417840631665365659577536148549160988012759L, - 99536540797642825729053298966404765630223414089769399041907943006297494502254L, - 7231784615563341371222177706031919697765617500669178646820618965091525245269L, - 64122892575584255333550310043295962304217347702067254836758984377389312146209L, - 69248968822867743402900338268396936215300699222302567510938706021051626135289L, - 64459909137581310426551257040551710383071141138993080363067287522213927798621L, - 14742948626675895933533391365441723565532113660732414550931873522030034019512L, - 101026147667033095088031322524669123897108657000068395582372759819856524166100L, - 97132283027374971785455860106820479123230279733803926192840002003879833286015L, - 48174593663265457342497520933640892306528134783146005057970749272631234283734L, - 74551484614022999820896938159235147290009705262572638175995362448915115498394L, - 81601548335524309052698158698589563941353346599566891312827725647743560184478L, - 73116932619185543409919325389077397889594304746432961767623869175317287185372L, - 78451402876589854041503318631172224868580679846789904044103380578733159665917L, - 25278739790620556963219300167564212870292271442363451960486351820583837139810L, - 54024414835705416394037079934860587885462867299076814905051498941170825925535L, - 12709638555468534409074810722501233896922211667428202064180614948548059924987L, - 109281347151792376395175929897929142137597742009438761488009676534981761856468L, - 16470158444709895683826130913545011787920959743525928742480188668207944219469L, - 33406377458500154516670820483669335835293085173957908437058831034560493583766L, - 70651281087265592816851172939542041804024378961122348021431916454524247790489L, - 15011995722660902024441911053627059714343883973195603000940078283702110970661L, - 60427227238830697144277240793209456816279000880530019187076244777817884523535L, - 73198894917046063685454861451165348985337783045276609752624079662516919395132L, - 52648112848562399965004618163424195062430864847411322395474185938980291731L, - 46952045577128128984196543819547138980588172892696841047616483711048800831812L, - 38909633917723662403734030142535327200838258593674509362814721541421705653523L, - 36951437270215461622576063193731153491767942719073115216210481817146240857984L, - 92822503191844212655463849745092161447288970592157336557684564917523937215336L, - 84480307232364796251559974103849511575079628779655490273875109276765190178723L, - 106057656691067284889710670931617111774869892493222578009285738015216104199486L, - 50285055439186252264142373037616465668991452296519079373148506341919008268750L, - 78003171201677677069703279513949889987108271075069361566266810859043252937983L, - 64453673133771094732624316824642625674863019043565952757271988552769922400941L, - 29805577196918899769094433216516624649076210170142890295156230438586048629104L, - 50610652056964241897013258015357131289798599874450894042464476448686702359961L, - 10024375724653269362076861050490688019867324376431134908728274873640299983107L, - 20099480645892697329859357230912484796162440474084031441826835523655027693529L, - 100792873803969996263214820952884165824106259429335511491915347262961892880508L, - 86443050097462445856293470117100998266448796130220785484639349760511085234485L, - 62493564312100186064427427417117666594707205791525662548029251711951566036866L, - 60815635553906897843786462875595869090330869400668845634096204596758855111587L, - 54281424165775245149047042922146082135949549572932079829465992045937393672669L, - 74021344817398757290513151277223087668710121503273636682391094231782749770700L, - 16222693587880103215091267709100201935033204551967066566340174152337034953321L, - 64854495973466647368119047189801005714647298965547779804728922234754460334115L, - 66156422490209642024390094889796380116453699147039750930384800064026934138365L, - 59162561901138024440671086229264803242477291850185999106080419650007825378512L, - 113428284036516428934053001628874526792165406098429275385198763774522401427944L, - 111140673486972944751467248651865505957171579227015974964548148491340094995994L, - 90432726771831661687839542256693210493875909818720677153929560601908121383500L, - 2390919648734978074097981145050547615724582463369080238376044032599650107614L, - 49332193518446776132944417804065758531799919519408365833179026382028719983520L, - 16844021875070676344672196613674464028860686904528695438809665425388692369173L, - 22208903991552428459206403129446096484807223815807553864934395942832909219895L, - 8470667490115807139655695206731499698365090407835540156609649204316736630681L, - 29607486220536299908185616788433675853306188898233656208864422976785534500767L, - 55118842515725647019019878765585413332594787746027915581881910388738408646424L, - 31910033873055731616439342645926302105855563249650949524593687360947729789548L, - 15249004806671842399815833602781130699951102693998767469481749653230294593874L, - 85097158794392283171134330003436945020524999931707164209325774911384422465861L, - 92337636780391123093193065736517181950044874147359453864596941896834587479688L, - 81770882671219571269201880802795916873693733809261256550764580716448072120657L, - 109583447871166176511030634751251665357804926356882348916566457471791219148698L, - 33041073929036620922360347074319390103534684016051600747456031455430385017729L, - 108424534147165186079145303073847199616635687885160726047462790685870976681748L, - 65466602632971100068355288774598280106426058641124876268394001659223836069645L, - 107641753986594632525502111115099769636983568416823019234524819230100469522603L, - 92547027142788556353581494504297445272586237217296313499446131893737076379384L, - 69541455046268708819437791119267330009898994511210767829863401709512584810458L, - 20683825595930889143744204778164811636370929774430171382638817741714146646945L, - 68959317146250332731579840421564642471623237343260120632739135572400765771872L, - 75136672680989279656751656653469346757264616237780764363366620630149278561860L, - 65274157817701127289444792569660195555080921351115383684189138252807150175533L, - 5671810715501868418714897235974689704610658721161649160921276576457817696398L, - 32568801760929610669780246928825630234306103465559662342639770719943071342978L, - 31899447127694546827922655815214626986764525342903626632184418123093532656512L, - 63003141567059498680563562093390845575545068586635328388915837737844428759540L, - 70087956425710666655344186549677283948431739775064934115249294220789854801496L, - 96881713732723589740390122209289842484955185396098544778614220722895740850551L, - 89237512955632773061271413557901783236118038302561303247107569459787144818073L, - 112118405390625361521548464552534195496997945375550852266100803525541201727785L, - 33904857415053067229197139510264516938417331929376843105857293570196041520971L, - 48522847509609438313128709265627345451710945368961593399628287664898038164824L, - 91056620479732242278474722192940264910288151744095649278941504581401540449953L, - 42454405296693924745760817549955507790390623134504450887729884356981838532961L, - 35030768339325008940202682440941830086788807713862271459455227060337963697143L, - 76921540239373072453559061952320735174206639807330899944744976047937876699873L, - 87313302559766459446612529641999212574650068965120597614758044727899601126563L, - 85948403720638571645843862057038267931439810108286533704380282114389769690937L, - 102712334707504592210422830464242789803304045340009355833863840935355054281233L, - 94470218809718120080570248674808928917664121326980896607385772596791210451951L, - 96714874093759650815767707274474804647436412655194229889130027830810105566348L, - 90560653385295469951283340686561937543329860648565143016813141347608348309770L, - 97278756244816945769091623157631764025785549528861744690219325787907757258583L, - 12787384876026770751311821152285407097958609676209647525714649917996657137791L, - 111365386353352057081142976967121545231460934814610163846838785509473478412523L, - 15855654177408095839420876568842174725956725477718681446815705857360133039548L, - 13613067531464775022897443935245026219078965310211939257939155377034750399483L, - 53599180093597527139803296608347730592900213586810074862762070055923081925887L, - 109874297062501167725957708311475864732403598441326553362751272707261568662384L, - 62026410132917555004142622013490428434559262880726789688913922211434254293678L, - 69990878268615015540850257545647020092925950033932397468539774269767930535788L, - 46148111074747174985444160627533010103111238143005508215961769040553351778998L, - 23993026969283007462891903025371029530657636041776082074957040840681347062672L, - 62723723611957826574595272650561099300243361574943730452358922191121111061674L, - 76340649745758155554625149618785305464754542824525250122399731297158354264663L, - 15837561555738656065767725180400482404681801919913975045773939318745845984263L, - 105119521829476483933530638019437870029370019711702822008898832331289067484392L, - 7291749539674147019747062201586411084842572291128907423952995408405892100963L, - 65013291183221361739104571406600258574431018032115683832998746110848663431012L, - 74416822669806249454905354579497934095659080083745742323521762825978234983069L, - 70217915801415324814036558083191157011253178132273839677239217929046681111383L, - 52822571979686773549263007153634661328724765101960886598181125802824843744692L, - 85084540761085038167328810682153785502187359953023443483659246715433874377435L, - 17919493739690550119173011906396520738790100449060828636904189737675067753013L, - 8753055507807332329092024422759223028946116610837360212572206564324859497192L, - 101442777402520754988049398976065637522779631216807807980617705038535932675933L, - 93613042346895423070777734295453195501234828548390083832828585777394921975624L, - 115679083135995843528428655785554265543348465123557615743425866085657195630772L, - 85006051186273983656712317133303577235830200124189978238717084236218090367799L, - 34333573637219205118420094443995074034493561802092461779027403313373099601691L, - 35189022959577001573805734144369663325019195000227392065871711185529124943225L, - 32689872839747969623098377119527495462616398137669607462373350312515229991731L, - 103745258912467430098305432326720007810839825724431256975721435465827854704696L, - 111225344560598664648051279891010744012128492170821826558713137813157281434239L, - 3466886922840330421443444212104214765524780073349638551662327285414226854534L, - 7946315494471381810555577128618511422384327737049853483679549354788468130213L, - 3076724494501994539266352909036638114646061933241823745589772797079417802097L, - 80201445786202863305009838285176241856966733784843008991995734719279416808953L, - 8112902368594797931221819200919292221021772941918237295784918701063234565200L, - 15011316795691089479720529488623729771501984477270295019597053341404102052683L, - 14531308717016851912522270687986348621938782352029325259261451363753331798064L, - 14475543381502739866650612835155797140849324779223382420456476543541914007157L, - 34250879873249948376780103739612546234429458040921383053109198787687516563242L, - 21132301512997263058260097006372649706666831671215239991570848647957174616799L, - 77966727789626456653703890909082745388036860307486696786258643979395477862903L, - 48348599032496065689789046447495164129294029601311550101881502246726053044881L, - 30591585628473853387107376937243281713490713265803514876892851595162308216107L, - 71738225032601406785775004217101075055854433856894013548057305624203466443543L, - 27217229884517976935899785988505853584828688257347597962188032829364968170938L, - 44756840659025885296126961117384530731317800298202182960176805351569228854286L, - 38668580781907195245542626308359941894176998299710914697165283563516778207207L, - 43693964395969386392964155926684449859875865222048362674249498822011082820656L, - 80461938315975545512173828261970891228241326895564251202546405808916150483297L, - 45432269566872848767641908318861074801627514223856906024230905187766701717465L, - 12678521597571020971780057618300692180983344253909210537250788727290096554978L, - 97409418157538176229864525559359313733999642795465001194416903811362627615593L, - 17666883743653414392559150083937046549092823963784149243759424141836210233910L, - 96782625814774464062993476868578132781345525016849135775601050656059041410584L, - 2589884068630509097550648194665847101140988344084741061970648890085736538515L, - 58488365439641276883795150591910380251526838715002588792626138011101348675288L, - 1813293167819395115836130599948938455484084779362371406466311001918030964005L, - 35340220851947076236063886985035545280799271738054743782918773396002557344778L, - 80163356255106591665286360265413448326273305137096780883148926687597663905577L, - 49801921889865181447751677663987234697606127697886569264700309057813207631711L, - 59894875910103667367409317643259441162201665326496448852510137372381968995716L, - 87469288780169906217585293668973559107829939167624410352054240605037124036000L, - 65416999407884660802908802332759099117091753912680717604556155547914616943818L, - 33543113511755320947035734241812378346692006754388632274310122264159183686133L, - 6989834185236560473590886201989903335709920654637458336580794634454864779353L, - 9453561663620506951490984040430770639868514448821537257271793950020777271020L, - 105062194568187351926318870584626853622541986915663690777614658033338966643115L, - 65905392114908010515935577424561787413515312201266618394119529564572597370853L, - 61522471806184297068444697896474869845301165432237624155233522574862888263839L, - 65082189782883353413832260729892578207198876064116884181613458383803356186631L, - 55398095354679161133669588425385416998485439302343789152075296268507284135371L, - 13018671651929370889661237502802954643194745186030256377106894194985175920719L, - 96154415633980356153660997875529716848632792795013003883875081002686931112788L, - 93139410818081574961854973782340701603283319444130717937000321633720917307669L, - 74982635088784842541527066797261617026977713638310182525162946945256591745055L, - 40862289967799826228545391981178363057389423168913946439484036341887370282888L, - 115470852263677408358942349816123249977382801878297678823132394197567085154385L, - 35897816581846152143635977795416125182617662098748809515257511460935868885146L, - 61988263153194461099176854937541307276819945276535646700336661490807805382556L, - 93891412733270087417761433122770674128749014393484622769741056647992441829292L, - 63363889674615416185536434160470933196244381606602233633288614871350958608504L, - 57953588880482920105228087436042056269218205544984405688887514341233961288312L, - 37202716535882957410130484132420426975239211348162703069752022374055651765109L, - 59958078232814986757506823520029439210847472575998198149597771923729988334392L, - 73560225664101637419846250616223941610802361458139353280488006007864786858384L, - 81381083859887868238086072685326819996965414457869357163869779792123472412145L, - 7085157882501413219812434835854687065900159933181862064353013336638344373447L, - 96323965032233713206686700414364668247910934428106349399130592377824653246232L, - 109910000529236051040407434199551066023563179445669697010121447722899830279198L, - 29188016024553324107045322080633386051187027206810697421409137837163892129804L, - 69051366764640468571833531247770505999662252760133413951635904163640777044146L, - 58560547696548319526612391997822952465186480118537362269015526826027757417740L, - 22275095446365462043728943933714148759928743432954182246695721705534082344697L, - 32440427492278481575108223374055567802781007843970704532426169346764205187443L, - 41556024815868951360471047174340574741453577779166316317557158788820660359372L, - 61661933840312781492274315958954278472042150432717237773790461095548575693145L, - 6137370242550349594245563032374046320144928809115178447381366073042770592892L, - 10784033868363152271525359654516206764188060950961748694215913733347737194708L, - 93458426197448767708968587401734206036890706232650366929251257287232932093955L, - 32182467509803439353060788902721293308799800424277552498919236591376797449692L, - 19905311904012949311946045324734835900907829038092268103727592712825419198393L, - 81349670002808635614408479409192446726446433374714920809694925383765045053588L, - 25112713878147477692953589488753271343242533609759111433667358427542542008198L, - 60019911613653811171605697997215853912977083567615046627768945974967091633369L, - 110060553792790452991226553887730741239931728059117544299208218340355194120899L, - 52472093447443104162058607107887554229116455033002880481336298766763597174398L, - 16018921466897698896156081392704882247066006769479130883817841930714591042055L, - 75074666851877113899616333515338055571471639917059500598430590967335041000483L, - 107829759140907569121705481139140786708243601909904041925571380978266885881015L, - 110203864258910767650677989801220374978575649078213706976487950103512413007872L, - 33249993498895082693761709690886961413973170394967421765825300309291439473141L, - 33599956176531937878455156018238941038814691588379287252798756848228642505392L, - 19100199957826794651029234724727734792825020228073638641069144245982458822183L, - 60121413197680311130470905036256694688241753904073246384310947441968611565234L, - 80645344121742080353214519933523794213979070171462352629383436979802761952708L, - 98351881265043784186559710632543399429272683613985605391421284117545858542139L, - 14017433979803198226154330856830790332261264890698482665375720508339161035991L, - 30516489360385339243081132091198892165384226000774481543306716914568057465886L, - 97262268011116201032870333958564942189735389039959597184902148026269190625323L, - 44302058790028060916126872364366042291348234243300830403542701853910262565263L, - 100126191029254623002799581013043940654677772195235073918460201407296040680690L, - 113612569986669295254547518177010746360552558111270202623088663779762845091534L, - 79338999083369807218098838241712623564953252458898876987930131393363981132533L, - 81807534317337842862569492328339540959987672906429139903192484831200709514072L, - 69099350832806607094526178983385753179896696665355438989566508005886743564803L, - 104259526504989324371680245291688817485009636865282319690324704259405386257323L, - 46048548168319243519174905186864753621453350991053076001561241537699241451608L, - 66640009876573485928514453698651726041930085834893369045270051012573764107562L, - 95531661476915771479769287984347060951383321441714868684347591823941686092603L, - 36621915424047154550909586666586526731143413141205089696432779807915110104143L, - 25500685371009586014518949017154447180688166852684264562707954581065369462252L, - 59850567117714407775930240974346637073681921343555100772661936520702888306819L, - 115240343733804709663552973618107878245728084071234565876664228408998144978871L, - 75977065295485323432275465827564116229512558339547601200993934982654176176682L, - 67106553301726645936161667104383224711510817789237945465187962215825839722899L, - 15052746491449311800683700291988067594040431185050499702507607734364951905357L, - 77228459676908565530579109017013955701427426823980882226769852055847968646873L, - 28481534507829921014499911445631371835270965059049968012173586442641858927952L, - 27655343420845351169311232623978922158364959548141208019319314427965146860850L, - 61390729924093182415849764127651822560510081296074798219284080141718724008037L, - 88129944448482016453604390978413099869373896352594669526016264003367026195399L, - 38820696845826898829976095148404250957464753986673114269538352848960231325444L, - 104864171396750025491806631675409842204085024417616047758696760234858107920399L, - 29863292310431477550036730221574081680999194850430672446200391363561085417234L, - 108934618562963817298313547225211668640768732952641926484962109008979027015980L, - 41160261084770991353568707663278346821082281639019262987685055833901457412654L, - 23902699369871836004147116325299221152105461157750810215575910523519613918256L, - 57114879668068671783566032963607014449535061298073571460193859097850285363274L, - 37740277704857454409433323326798536839332127662247774735096314702899351447384L, - 39914634986182851804611052974947659631845131120833743915944769240870362593379L, - 22965980825421074760380373511994945118819421738400198826034975683511728924290L, - 73619859307004883133329724216060887068813702155629102968658791645311681234318L, - 42626616499504872195860607227372694794739202104648805507402666216755461948821L, - 27180887820987086213590533893445179350362971981710837961686002209737537212844L, - 12547893500051955564697063098116328089916920751126177272831111779806370819273L, - 6383124061192694324327191518704951714003591914147776609778722446554041043444L, - 89411656982600583277095337085872844640689672310374820842567348576660511067132L, - 4931640018542825079475053288396739880495257267545752981767551051947673810942L, - 80248612782720605198488022986328769667781816440810765901226254387763015785345L, - 12092028429774224084710381054351226042549085986572748481457195842303445170944L, - 26146229475813700978605757401016468603312254089417985071251062419204372869133L, - 2255026428176704188457961449019441350458062228079742175788548046834027109457L, - 30641380654182036069530143269080252118551203033739743249775363571491017684138L, - 44132536981272426733250999775220364339758797280204604071812543124861398018806L, - 97024751195532280486870245916635903805436538356870918818446669289591316332013L, - 4810943785165798842561294064990846266172612239112183384692997244675590825324L, - 60594647937573463378142351679499462396718637663411923885077728572312508937315L, - 106092534838894147114435074387638776799689173170382306928669206389784540697869L, - 100350214583612771332744853931993730296314280302784006748300068964803633975616L, - 25710297987605883256119632828274987784677421689316367238798477028078257694760L, - 29123071143314070212924653332015086436019595290116122837247518928607737843641L, - 37069274845961702330619935671375654808915261415409206654572437315129646216159L, - 2103163731858609902987804239281112140757230958868454407748185686103644104654L, - 91719028230181448577144939867970479811949564076488402186589520277249859672867L, - 45391342576703074661603595308417176373809749380471106452418335380970183750772L, - 50417836443890530817649488762692685498657632698803055765969038288656593393888L, - 34993633927197235881176833068161353999691277150832894468130305354530984616662L, - 23534323466104975762076177772455333857141585658769252118576206968469709039438L, - 39190055558058842754394430495897983372596751221323760953254502173782252535142L, - 5617230096167612764248946716702642502766239621115392206755049019979230559644L, - 32624233651603541264283870096797526990159646990330514664119567353196848504711L, - 21363196553685646388482503553351021443836786242107559712907126251012523897415L, - 42112366171549880891784673677527916736324180967747066190759040259635872089427L, - 31712983983859822934236230461736938375537587184471429809349770647766964613362L, - 74651608828926796831778724801848604143193793124412646850410456430951695800169L, - 31502721543493790295404111094528405894067828931947636951691670700174890250826L, - 102574444995694059195989875942166747896686576241543887339972917475254377264441L, - 58923697429970839605545650361257859389315238453492910577737280661934024153811L, - 16221053517648313779827464398992879024760686223416307556464055966113117947553L, - 109701043134056293739478294456803747863765083543565182448038033479701054048528L, - 65816269916986847737385553699150904532407302373423496719383228101901272943934L, - 70001928020787580403762358730682449600681762898554760863881455775439041137303L, - 92835367615230954932800230862822592318664461839493603556446445656699449453378L, - 93409393995636902222277907243315184462474445317717554777742524489810073788186L, - 44944993053488547857105740048665806597453515566906605777139078245225097180433L, - 93147772939600424893831062804221581869839889700389384361883509030083325459072L, - 93699923460095428776239408139222448679391585676571354740183685749691866973106L, - 28313899678800266849949575207359059769753981681483869123271093014071444124871L, - 61980149181396054245246180188404056134144458238839049042934740845836722322193L, - 83761141920500308170795379388798930091217620626009308983653555795715338404376L, - 77583463966607201364140641884271595665228078550964189961365384033866394446111L, - 80177055029944784643184325870695103284420396003327948777031706405120637762L, - 42302991430237898859125813865021036118673882270642203528092518119294645903684L, - 4649467931816382483273696026378785302400244682811030991459498686575099150156L, - 78548973939426759637134164945491298621159043871261650725671742941506653898601L, - 9051589590564582504749773754686840417554590132961904954760198468987586822006L, - 77803423932364165861392412958113594976070611557518916054916203199233755060600L, - 26046137849807276252157032709063139003783870331993295994337272937649474571460L, - 6806190578010603245277071337490254136831601647535271379706078675914970059991L, - 16981720309854773294680220969620151753458051082222505206356213090810615697908L, - 73621371017082581941086697199063866558700710317876168463219943638793043525611L, - 5952160277770873279520267042269542633750554504802687675616904371318313037651L, - 52265032098720508825832900808795289730022498334923517214767581511816371160360L, - 64203215183045625683829538324346545730789123127866404225520269502345859682640L, - 61977029726438030483088364022031817298674742428501177198938113200147052841179L, - 63873459224412672703987885635119052772459003219750133619548346313457608388807L, - 2626598937072069170981383608611653141972138783930451201089190662220200167801L, - 105014669327949873689179545239646646974007368914386147379235001429273363142787L, - 11058529282049329098457406723662177612408721530338848074206127378504846492509L, - 44749368542125353666772469444721723570482557168039493611180344700250046286426L, - 82636319376686946962602756101799261516414332824933119808265360381269983331970L, - 13088270297708329492219842466712903674306400272058781766367139492318558196219L, - 11591604651699081578146653012861739738078724779779787286542890320841633665451L, - 97519884363160378542487802378317147290010864449964759770643202943420127802264L, - 103765153602223202941810462552259746944903813443024472202605276597249915550516L, - 32600862571473499155120994502986447984301774518748393315923072385051983867738L, - 64338343114782119882494380267000892758659016560115644027856295197639197948121L, - 70304745803552289295010000663269329670062399995172397487425903556106015777747L, - 87347608635951993976054878729536381464515997284559134215265552082827409594709L, - 24760837937750392637884760244568573306303303059586669681982903741732781839222L, - 68020556769566088130464495831741210649627126271195366251054339005471380772233L, - 86590404461941557319594983758896584682276289501907160003869380343558807853496L, - 94630469610568401285910552228574044151085286499697244331788352911775713556752L, - 83822984587785436336173127551996786655166471356009859192359391421830649825006L, - 71650994979519660718419404000182451979557170967460452856442793385735816213520L, - 60034133458392675961813041938242460116247157326651441051172749157474680023596L, - 10660815632412363754925154884806582403128772462046713154365199157403468694836L, - 57343971592477554658280327617393743085274397711175189009881604060525070733420L, - 73136733094148658877333160562415430650644927143105773716954983060143555464306L, - 85440404039981866230662121118907356481404696270556642000862520918533196511366L, - 54186828323348403871069766176623160867804111384527021970525712913574837990790L, - 32861639005228661799058532545666296094313263213354030663415414372379631425417L, - 62435477407429153105556804571106761272657217234349922083765158636344368857752L, - 94926996881981248755683541557619155057867208528997836939147133929580669784745L, - 27273317232039193629074002897322973019198533330295869185646245861510825302456L, - 31726650026399007682055306299222171571994609109467630721479608436601166965718L, - 85013291104442307260009017660850455440506230923010172390105254539733688893930L, - 84688515467817936667035613961749011469178113827874947947379728678073706146566L, - 8000043581903044187626831087385233308531161560821002291292997344514542574861L, - 10728274265650945123021280257565412765339875792613316790968277574570999446809L, - 111135492659042640357368642438991986111591796443110514832717954055225841917978L, - 6236940258597480569622393766940064897052031664905049950316462273891076916773L, - 58417064614006717254677727841191592439764295565971175433684326510821412906023L, - 70012991223690604574612562233920263463367959170941379143744868125063733461799L, - 17553430856785112551823227172546504414011567388464825466464197810448732447528L, - 75196746683260204555069821976970306322235611913986704735160941551727952033066L, - 4177972925249999774044507880679510925550422339555421875354512693137551690541L, - 27448422819485949892314642973888660461231831322749289073425574105469045850930L, - 27112620315203548630765711479115662240898743220222720489250776217163293899317L, - 26134395304252433927428638508624421444181051640605704105587542606157063995449L, - 48055323471155904642836017878381028173995433638774830311507610768180329654595L, - 70141232116639303275594215341122469578214451440984676820315708818941014992455L, - 97362039991400118937375759014771301617335051074072313576160597167578291390798L, - 59498744397496254750667205892414552312610986306068383637013423466785034099790L, - 55044250507270497890576271409360951399826457451259584081702979748858005203540L, - 86460171717901445827863985929268084902846893704625439056276885241262726292821L, - 23317071379891553315536795196696703048777217042495816527324818815408066653789L, - 69890525662715194049154543702027410940146763855258347319639321748735889979497L, - 807754007251343896556493206120078763843560177950734372358432427844496623722L, - 77424154811568910487481703168165337863100562624125855039718328432698503749486L, - 93949479019947052516081318035249182358122773984752884230110312207153366729333L, - 97760211342925377297437825666192384623290098931846409798755562000376733120128L, - 77181003455755887222976169144131126435281559444659146032283108699843332894598L, - 50997274636133212992178205232269582410770523045049817158913788640979779352714L, - 61231394068599753397319023567451156377698547296646407938855024402620131810189L, - 46310914417223978908533423400825451583213902177986242878236812611298604355472L, - 78888942326033681852705394726853367790161963641378980320379968016449930685335L, - 90151588908348778869041727455142325010460208866421868063206862658979874948265L, - 101238573938475264930714769670270045927562839001970232615122789155233670330549L, - 83652134723285667921458928125975232181677272064498439631790176512445454644410L, - 61468550413865472928942441294978158372461565592774474901910649619331836187067L, - 68968765571686686397063145320479094890030143916895297753270420895004404993476L, - 61798872554856153172882074877619765904740475127065862941126349793363494166468L, - 46573338659142703050162402964081032893158138933434106948619884258857294581189L, - 76821769459519910456910493244642048141126524599000215211005977027890045356229L, - 89086634531739016620632886341299561732233750668263297234175608574626121396169L, - 18269148541058486241010937897742237182199410971901533756451007075618937411273L, - 76923947773185174765057467292696242693333690444075916837651017268597779815634L, - 62695560569368951962459199106700268385861406656184888348015970603993321745363L, - 26832497031250022393767443558295003607600636870355540101612314164483985398494L, - 84500534994186893964493029171522541229852180881150794942307211861255304189665L, - 44285508261404030081594397671657378017322357155781010987117103200851080243425L, - 25196615663499142674509946643517325695854942451182260008714651637872065420777L, - 99305442900943338519472778437924071503211993055069645190669845163220239479033L, - 85805364957344632634503891932617006982380155923881856744098377218203920005626L, - 22003381338649782334514084338378593509593067056870368289820493521776668981292L, - 26683687105195595843237580804763455823398788251332890875215104940188091381305L, - 110464050858264031539622445239391998647121739765959319356287939977867756583210L, - 7471593350788657207469280053433570067608276131171165125985695259621860735775L, - 7072736435435639398038184766439270954408782138488579773109528448839765061925L, - 91915806855501146789139310965134211526570393731188376833859398667377284243750L, - 99943867953856063709009671783646897434699022116226004816229108766854572108352L, - 112512909775115735554911667864282563207101882551451616049056831921300839997939L, - 89811407047407829555624895871864026223819909399804432889050602539801401778700L, - 9783936934062210669870013025405367475847037992961269431928666557105333563721L, - 17689031339513906290935146137191811608520752036415931065520192894550435528269L, - 74506200654851987166002021578306575647964038829730730235301577986725269609295L, - 29375611824092877766836458231480909424396049346662276819264199216780614622064L, - 111182298710139321563429299459765615479697973255643684101123508918407911950721L, - 4294505797147786823273071195005043753762920020598557544942753458123114846075L, - 57275241925930861287940759914062157843551774344909399581448062686591181552526L, - 41739812182070654271446030749818843305078439752905007960302736948968768527279L, - 100388248499073296003495049107965689661715991201892422837884938420800455401908L, - 94647112259790764004341239190106536582922466276741897004777141745122827893692L, - 27446994966727462152927989428229968706010108700258464710153635664447896532671L, - 103373964168408557192568459497755505893114456181120018252418821037265999834056L, - 603593167867271518491104108137635331738625984832948984670941407502421070068L, - 32482470803410666246991240533581465544766721670327269586518246785064239341341L, - 15478306694515520528408137981305949551146588074589891340158266407120269983585L, - 109697884910557339350000389307898510984056547954200064982219359838158244450424L, - 96778364314892915288067907539120948802273189980642443672533483697868422413249L, - 100813271987197293905436808180399861301221576585368731570245700083531204773003L, - 9848580500683416928405022232606276693901753536749519022578044851207387657060L, - 73523051401127073155274337744466609879882552549678863351677289698080754673835L, - 62012384606146752910447709580267400389050652975786343740374267007192517899887L, - 6329346062960593046227575807350591579764645666581841805906036452574243008636L, - 29583010969615540826792019459651511509381447857198039888276001242967767234916L, - 65835705131934183080553848663343278612885924692142996907910714583672555845377L, - 4364909788959277766712217703804484155156260164483696706579821797787137363172L, - 112610231123167259542597130270426227120989272677945330157706925167429173140529L, - 107693949755472457951745837658200211100579646605318103464779275189662278470233L, - 53338620743491463081500010144251879985952578124463654647813503945567112458709L, - 60069833177830629042515976514509458207591731897826645444119853240467445435959L, - 80011918027478292382958888691939134014729035069284567739709264874848025331642L, - 693516542070478331317581801443570898445939579828262533667011598135337800866L, - 52273809695441166643905208660760083039527258194483886293511034201908954878996L, - 48840733848173156679330379150877002447700620824155961692002854641298012804735L, - 57177651229823916846632576714273702678467236897696718891161348734004407812481L, - 59394243546052552355200754776478221651851463486911732831269290583482857321475L, - 16550719962956545897901372302476500994527294219803046882654724802025294071205L, - 103573320409090652734324495377610928985983385722787900423283112507251713261092L, - 33259673518751152602505157075003093660493455933849778537815986914270085152394L, - 74697264217938195805376402721144297590227837706586684301299004109144351872828L, - 57387628008782592076131064352669617337376803473279453333601127767137583857477L, - 90422943937783965896251880446521463249223856747181789740898758791488438837484L, - 113188214051724646646456570193904272345906028281841758217826198787143028495469L, - 4725842050268204896602970921870440551872346835384443987009524265770910466024L, - 4778857974002036103638830854878962023487637980147632054374917120421147120458L, - 71182355475849174278623329984818066985224976641858783457500578440294279148410L, - 72094742982743112683755179909216029882769719959110477054673870672995765541751L, - 75741926097018879807801122021779641641562337391714906414741504113426658853579L, - 76126900933152711297871037994157121871573845125038375622160747593285279534261L, - 19830826319186275635688571464121512174409870248240482681104224344061615797680L, - 64573166387796849563286812336358178156005102893400560929809779223903861483443L, - 101097866236081389888098000095331715828027273652681294902448980739269851411008L, - 52162381067850701656566498610323832776957726621962737317455499639791958990412L, - 94082137239985688188363912099465534831440190635458223532770690103361964844013L, - 115652444030331992062393380162120316167274799004276617977305614784404324860459L, - 48239714105427667448028676320558629477947116995528830707706487783344070508841L, - 18298742473303593403190358887380999495268221015304085069258395387129220030773L, - 89419164611619560895129488892753456065378884899899321136201939028192506686435L, - 46512579469931031012454561431577598449179436511765097562464071037556392173159L, - 11365130369903604063701150118354634945169822928467615495117669802645927944576L, - 90296872880306319520426117190162644370735495254783860509181863060854358311328L, - 3064805101495055213296802278482194523432209139269798785583154428719886535606L, - 112510516323184654550370145031913966115886561142387688498612170316060493612773L, - 65799272257840358508972376212059939632458511650405519990658343838813041991930L, - 104469330504384979723835167750074174595011007208572690780514408491293026170337L, - 44097538443652398316024901024621650082431061306706863983908612088229385740399L, - 28168711387058383734069740442192452959396267560259894904955433799272947786897L, - 76673831642747694309752168954866945349512011868688362715231305509609849727884L, - 72440938281741438731682859404930699562374425734631837607004099593809295051580L, - 49618858294338560068114914330057108682505743160850176669629454424505174616346L, - 51238128137426358668925849219007726695779985737877829986685740285562359544792L, - 10449463158360741808383631154708379943574507465797386131598764949138172699572L, - 24787230318545162296239661395115840747564078510007070819457101050783164233636L, - 43738608852046525353044056554316319515407993225683285250641284054665952152168L, - 87308324767480248378827366446197165365680286184097744194620305788730928305516L, - 68467423757054223744534485288056970030507932912656868536126222694537999843935L, - 99551305565430698469897528692615525808389688973499743484191509164464808554608L, - 2805794391190892615517138450112964718804088830954071044888071981444981842272L, - 67462544854592285234311676075848013111822062648791501445495208766715408210452L, - 90362569237855451876768483574628188017104635283145505301524182249740503473110L, - 37739346114138090521447256475932887661950965608832859320789365081682214187788L, - 4499714811554158216842822430945649787280447854769752290740438437966466559531L, - 102369149248015131943645007413780706509197937636266855825431159592883576061213L, - 22179530984562929628384070687261456333567726884427550471714078080277228065658L, - 3397034101705588119837422265366311030004336547608067328525989607785074936400L, - 44487665660362560575633525987282110179252707591470599866380025044957848994002L, - 95049251801876739675358915317357015643829756121158870062343404958137371541194L, - 42228188721118081080597415253758205887654404769736840376732244792357168117892L, - 113757043780032994609345712507472572974091505003593717775470795421675541262984L, - 23615244247918703049546704460060439462953967155462759139128539501350473155914L, - 53243534348195532076957598606114144129249355968988626098408703360652154766187L, - 115618204587893893274359016327918209112806924602727398122553782591435225035373L, - 56068952059157442208361930215025005045212063250457549369355174758845097644389L, - 40201472928718222686247967989618662911095902396540675751803899004449543422269L, - 97262537493909608971879260716928796376441056682079966774415185189313950580892L, - 101040102522021954144496233388048838908914985541201524245964512290152093595016L, - 104065213343612462433668547993058893155143062558205030417481907250861051160711L, - 54164051333323392018264807122286881007819610004544290318301784699782740494727L, - 17178322845420293670506479478095862935525147906371352990015630951354405204117L, - 24207403759043941550002622245810099448988169647987358910264658566113023673284L, - 97893275948646750795844075314867713251431667911688752825572392821935831477894L, - 24290317215173540311007859893908168241331987929867467279934345912742952377984L, - 53926347079284540925311991363289237894705847069184254052331319117054041254217L, - 105313882509607236215732282457558953935794770549701506139173735884175592666982L, - 6944139113409158320640054982157829153153522415230203410215931075104241813254L, - 37602684865240322276075958512543936825387414551722232012809254570964990054622L, - 60777986907418238537483961852631560251113922012380595581132011431647836278021L, - 34682873899123282659618414278813954580989931945082638940334336276199402331913L, - 42540704749490734548590151557974200445555615150336999427394356713934282075421L, - 53153299501808942899564651629912059037225396769177138834993594973053736210974L, - 105585869386527149056716157859521172100198094195959299023871299766026342650917L, - 113354363915282766977203322855279352763821991138523752496747739793548582262822L, - 75424532118741279363488252023911767554618840529965130939740366448758875782184L, - 4439807482980730374510298496665716914334305620630331412903993034913165146925L, - 30727541097153828201764723553842993115169070897950012909388868542573666385716L, - 103008362554072140466700303831958932797234997992982263819180187677186817085249L, - 80623908296799616999777507864282843681124042363433810574152577763469061324867L, - 28349169669479822483205562367414202996330892888199332220395572806735555461703L, - 113900912792872040410403240577674873719477013178903869199323606604923093571405L, - 30224379048730325693410919508581304622475560029506816828601176685784678795346L, - 72234046861066491457723789293052688074676341089098656700220717628125173853779L, - 99546892349044656661121257122995679014477835381889737006814891893958202957655L, - 15512267973694783353132493188406085596362132876448796928946116997366462809691L, - 9400778046273479327502093151284276664010884959994675621166361747318350952804L, - 89592060439404733259888376435645892280562212771881972933721903148652308071017L, - 102450428168216917531418362005063954636205790831228589315712731489113501024618L, - 107909987869703865839335914478906554575900715925121263447699091776556670058351L, - 86676645246010272085840970316089310876993969523858851107540147645044216163952L, - 68336252452515937317782368891663662686785200662516138809513057864607989318778L, - 91831508704716131412917103553270414899872728809070184327717851660212196843644L, - 109786828933144432394911478009316869552352130265579777491349261143926213918079L, - 5595010113556280475032918723136883910299867363479473841458733665179864671872L, - 113525351160122475410136007145101573235710105026277540925591288138447129819522L, - 72910725461368390546014551887660947465949313131976256229881696474765928389004L, - 26428119304350087877144913825220295517930917969594874106702876047575509972366L, - 198177523344743488276673986937791356115006214012642934810979910453327806351L, - 48210866776355476814452613006576792095963994031606832413694934914351729124760L, - 26677926086622761684169705546666844986337774654988886790683004025979772638371L, - 92518787491651627474392478627710856396394429876911284908743156322317642012325L, - 91148179121452220792707220064146355596329082424267274836845689871494110759845L, - 86073495203265901224224453161153256631957850927927122103143994329144122822566L, - 12818795288132231462950399347694153302566589430553387001242182514527626170790L, - 62248068059723875437012723520034795174125562260402110125826038812872187643832L, - 110608982670103182042242482032427610844240076839950365573606079223328409355195L, - 78167635377618814110162347981498721934361620232397571224907504845957748542909L, - 36338691029869568447029221322780901417127869777942839657962807528707077256896L, - 108699759920792964189987548117378027407499105148697934363241941477702931245249L, - 16501203186381799715338918455483551022902482956994606572128593664442966612430L, - 39762259881604660299365909279205844700068157653159841986142539057335531674576L, - 10046537791435493051792504559145384185910998025953759563594074132236799421656L, - 86671159097820686680968230014125883092833903842098905694626907991871547633368L, - 57301915970888906063733515432406843374394059767651437471805332230536909958362L, - 93426904697748347827965222855341808166178565952737098583583475462462536167900L, - 44350928168303253623722781745633905147882532565092969224150452809748996280036L, - 93173086301410035717634339585647580002113016622861296627516167981780551746555L, - 8366781001499557370550533591839340293544024363456523122072215160112880257750L, - 12329685773447802271549583850493254475069810991867526934039869397849222349L, - 16230538461811379350348469588059499176574348370854304599112241163870553864602L, - 92816429693561262818114877682147382548868326562423812288663776263628024148012L, - 87852900148887772390342327105836793287541385667129345364350246742366296779346L, - 51326750497837373912478505248289974534244719139966156370298656826530185589980L, - 3499816569314049891236325912108479431434735029203016711694324294681015204840L, - 26457404095845529330854346025893590159277804369550628148623786950648477003773L, - 24926174935336091420837850673329234888823523744709807086598558364417822275875L, - 16803731629740620024725898830951457486274852852760429791276542893422716678225L, - 3948832460210106619389041757945994063963159033606770467334190977972829030183L, - 85049526100537084877505077761714489555701405265805842660811985317669527871989L, - 25350582102996927026689430448224301392957308891921472951735335493635866336407L, - 60537844500584773305641630171984978784790470400724362271769965237701900174567L, - 45022750508048122815744181661326097297262276140979586253963643761974079717981L, - 57140965077109190670829356615466111731338865349736559658058205897145616370408L, - 80015762649333825816661151111873034959017000295095618003179484989143516884891L, - 68458710222209214842506394075028919042188476751929762393792318510421683095271L, - 43645007422496087334663760197741967172320853484122496653182376185495576899204L, - 112003393994827276244773756218471185967512084571340799773689817573306469206263L, - 7658030109408667297131882809581532208521574379621079898151516389976382653625L, - 14928682774251926156428882795050052778567869666299635936211771282087482553942L, - 114390663543914230432905108462616961558054356210675761103139443219584438688615L, - 10972878399642611296660015200978592680579107224306326398185282296885436061006L, - 9007342991680696392504229398589165234312778605628039875895507877324685092363L, - 30475420419978535023920151069170547102259590228374616250418624757282282195735L, - 33667010784226657661673564383234981410444047229057340678787668226330667886055L, - 18833587012287161637687679698523713776296844817374046619083388409086608511690L, - 83329756202690734392712012887878306217569821435251530250203721296593615124218L, - 55742993096306032911508957718152700960657218300662938540716065232756052886868L, - 59069738496199852357888488504496837524707245944979831886538683727461765837572L, - 76692315097894461904905712237862355556684996581605859275773671781648633239531L, - 102311518815104786513438877425696349895244416443761384391746812515891354901663L, - 108292848623501996568777474118124492675956835236996846394287840959461359892533L, - 66846077633165686389225967668667732771800880086241059086489464057674986005059L, - 22335298303919535970984936536522839718167799493003678860350198818295075465738L, - 2088697474239766820326139473680869686396348464276988437478814345420083505818L, - 9800257844942895221705227904598166674104099914828570293509530196452825545504L, - 84283096978529678101470952352414822239619478167556858308263226683711074772777L, - 35646898143459950642531227649203826514534211024922557008822990314034309304433L, - 68915930166816467711824489388113659827317973854400695237936435184043391478328L, - 56786622094195026554749982293266861483291312099436126378785512576413836585289L, - 52986120986935921545838191743970961171986680075760259417072169853574832864665L, - 55730199715094414714886285920916344245810582363662181367565129139346775272249L, - 28013911804949354618732433403226606802345188396893083812221407974635820017527L, - 84362723691744973839838972125261811295443192909309835617607294104927003952936L, - 18663696167800267373969633524123621566457528201764664569269468800461253546977L, - 95006906185000498991255962130538001031712321341351425677969542483421002146191L, - 5298440261353315066653747668512592893807787544136161589618108501962462817514L, - 38859838558420878293396896040655765820066194302595304614249299799701969873194L, - 62289993275906160934056920090330345027894665501715138137507968483175261858487L, - 54327880052340833269705542570479360069680899057285136322248724902866351935413L, - 51589366609300817829884327471651091087876029045952488993924436150453442479962L, - 26921021563144202460027521541302976097726425054221581760939871319832557643863L, - 101477144862558339592010201891329191270629339715062256088293623057030867348979L, - 67901316707740887510310995207708798642284386699689148075505836704418407485069L, - 96718178609507532031066376256798405052465386662125419099155741693554343774050L, - 26057346807973776004736732145629815785971179124940162688537365590581469134766L, - 26770976915973141876303489733568808500475934582010853170967171874980845098246L, - 90537729648129293845193643651455395479833726477469470782714543127473429100348L, - 78719234803528776224284174552393513450742431864330850991766081667160518666329L, - 115741964230218343116772577584589437166858663623766911355333279349212378134179L, - 60736666566738901086957520290853833532308103148114718279563506956913408659154L, - 84824674252182552088479543210900337519198211029548558621905965950134454374603L, - 108698872909488424998665637094840058468812393615025954637639908183042354360600L, - 54146613227259189275128214044106391528698365412789978664946702873429739984637L, - 19190887228990422929580223605469121255650473937306765963637636391220651049472L, - 31605008932610104655767242657796968638230499973988956357574853626591971480779L, - 21103212080963866244523528876877494131679414677588148235986943988755883248080L, - 114433155435970775041646627039729981953845379846848605819115413366608262825881L, - 12726589349335878729249976242215037847246102781344349200442775736571617727558L, - 16348031017487936874087593829569595549359699409440681460000690670264945676325L, - 8079418078298720650319255840051391336673776121792199200691556022312641097491L, - 49016412610833629546076523881989632302516443801870284008552322936908913276281L, - 48108164327189276601708754200109210550466531982179750884137124604620310192671L, - 33323785856914934052554007066896820682065933988796788273060445714801110487215L, - 55980415036549356073951832253654659224774915615566934805570347344702524747730L, - 48834300971025104683284825297084497636993068991657920535339159305238900570088L, - 50066304004711728127351550601173794580986385856635071793333988822495730607725L, - 70184281603894380046704481689884562737604128791797582166531084708793507801120L, - 103740314900311257783843055667868990009195980840809088897105849628760722031759L, - 19130793700542452310802196566561977019324274086824135479591721613945804942848L, - 54590768665000126682694282951395760648682789569338177215520354887037069453620L, - 50868057716401903309161037229172724679957323003493534436996695949002302698299L, - 36781356459191931011600117685830070874073058722198240004696684668583145145326L, - 43557711700151059594566785929505872853275997468603754860423133239299703134109L, - 70405173861222214879721853552636256016629983385583392200333832768240706755239L, - 20602869602080648291256883292015993801819651681435012039740250944363000867500L, - 45506777931975876010479331290127536397930187117281747538274184363845795563139L, - 73270206960413761329060196522798466140994226053167164073699349402732976355898L, - 10274987270816121282125090703863593180533037743998837798294992210631156864964L, - 87879131351137173809037376974459187218923500439497420833727325550562921766961L, - 50500649920892909656581358369272905405509859712585197222619060367145853591930L, - 60002540843130784915238777242828345941657276753823987721511537115805772233966L, - 17876170006535450045595809605004023872066609387627296872289556538768974728940L, - 90126356835141450793793547926498707574717345260769659813421525345098587452928L, - 112944503501188873438274931598670061856218197700070555795176334769848830361786L, - 81344765621859749512418566552971466151256463347262095479995394806870250601473L, - 34985812588638590340101846738441452101844632705556866640691680099130705768521L, - 94315112519297120008255853383632882596162459211449976831118989248914689025991L, - 86042187705584591024459410832934257357435022905972134758608851702942264805202L, - 2821114061220849213085489316613766784410642518139164250358498114064425922217L, - 83805514533090333581662989229422579908672469271335615753129023089921408578636L, - 32469432841958529172977693130360061887717363260734452190518999882773889459568L, - 69836311334757211631915702001143378378952602813636255147052862837655873207666L, - 114341316793003925518903877654831341272002262827385568726522400658279073969977L, - 42036575077054530678636585677127203560811102811633788713639445775098950827890L, - 85024910361862565336099650819774287102166807753378096928032881329427815521769L, - 55324226505217249310091374352904161647977647990440486665314182718184535148848L, - 23774778001643343109035069197094064479934349580513929703915702361582199771099L, - 36135572570758544226449039845346088053007954845788478796484389702665205938997L, - 104622322503420343506071899107410854115368216537400932667643945873586388988474L, - 389281662728734117438239273197528971901632440354548723962746311938389643353L, - 13887266920459997663758749023053891008408327262864848553695117135139951924070L, - 113398698433123266112256228684235751911280685076715238906090483706357974168771L, - 41418884883552210730285397107293628512937328351920791008272399625649916279934L, - 63699551918624295606055691752881366993635727303118120108439597851383005453287L, - 50154599554853174485564607391603409580529574992148828368548193179539679674909L, - 51703605626896590030046618010369360687957477624327788169856216005448479387131L, - 4254159162821452371420317804393480625942943403575549832090888849849889918055L, - 15994248797720315522494478793549468351058780330046780693018975672663231539965L, - 44913976651579429253078278262016794427101984405074296648368178922249612290679L, - 55662236854568822130536931586799458576438744718846422902642897867994969412235L, - 60593956633691922365055386174888982322636015875495123255951932272851240046423L, - 79840315755370384435368745515780152703826574510631894136049959024831792794703L, - 48644766712239836359694119014710616190157901341207003336118677673407448688923L, - 100612379279849216310165116354954973678629607402136409286521772357575945971148L, - 59994648821001237513756641873976607150726605608960199640918238245215509648308L, - 48712470416113843103136163865510682111313459152099075206858086723443199273005L, - 95821167575999367493941993342990442968534950462811882584888797462476089447849L, - 33570276304028281823882462087420012695341222883505352567736372456364999970213L, - 99191846026210766831404978275719005046516500614621590164715392217051244166376L, - 109610567663228431015302456984255778900920308033165954585745352621200067331765L, - 31032627033603205165834722286199725602157845358281914391605244950018749496299L, - 7063528408033626067363446944124854257162281483962217036269600681339714787775L, - 7318697804418930338469979084221440770838906114098018890045696421115636529913L, - 108303941675744539461697768033562059126012241267783838357006066216166416041781L, - 103236756975627192725277761755162659731457044329436581638688108553215730186833L, - 20596951972290376704311532635663539108148915164977357699006051363295112367206L, - 104536807628201476731998394098514135063083330141521028296049251912857238440272L, - 38065964407284187458617688532213103578907361788934199049541867476852212335869L, - 75191038560850565714894322679218775253538355739973723428850602904090007279728L, - 72648426849031778232845605485771163272744424442086663449190842694864645857666L, - 35718436397479589196342813536603814186576810029069519027097936562708510815018L, - 35441616456217063002811486804112246378753603347110016969586504782096378776683L, - 36552949537513875964367615978283214397350720512954261656001869636744696854711L, - 66230245543721501499347494133332683934585182720290106391160704649591126983909L, - 92401348466732404649752976519802259664760098700303490488817623837298318673652L, - 26992406869008023043647847129537166411932602578575016857893104760230396453136L, - 51221845871734479006818602103550380559586000811487750582760158347253561072325L, - 75485133178739805765053595064186644875798231775269982191276342775641707240237L, - 88811591798079582527046453990811302455289778782185134732740829452542340519670L, - 26225704416619357441596521658519323507514175989981185058236712931341096746136L, - 78782982165736229551869135568277406074490791528493343242322082273563321652016L, - 60359811765908282755511626114780393416610047871673899143332664498746264076298L, - 15274724303609579349356745665791547953979631067956604423502076684098487327403L, - 71281087229709837015183351813981496389569989054420770291787547655194554690751L, - 98825830315893142240400255914954806230312123977694093794622783773073061745342L, - 81218102972290087186618612391371696647175536205476846499197960517743584691989L, - 59079349608768172644060026122257405757661335559716972006510889173341302488322L, - 58259135880071943941673098258960167125954215539989132287883961865838366311966L, - 72588412345101524408679765726619301630933571308028841224460292037914734277432L, - 69777632434818220447028556774052215998833067070441864447454250502953724668784L, - 69515308394164181697305216564141988818540471859544560239873847691984914307981L, - 7538376676383976207567498462364717279572775093710341794352790939328588648176L, - 9803392422766580525157619117624375849814736097370242762134772309051722811027L, - 27130139643102436431038936912152291983027488837782003210295257396052409809950L, - 77650526933463086890153450013608988112919204054815839999502568215562887434230L, - 94674203144743741514864160727398774240888824698818486470696961375689358528652L, - 93770165091863769227788806398663206386083827550581044563606731066480269358829L, - 111378765033993484391882337707422953321277694203406660477324298951102613825734L, - 39809193796622332440293870438058332217694944250206080134289520062428343001737L, - 110870634040500564945971057237575762714154979673916904401552546154172138615045L, - 8851591404930274221548347869361746554959861627955494892882847992678154891937L, - 6397420782027027462379873995946346804165115556775281463749093738526431115982L, - 55704567981532789275534204705754990135998505407557369403373317053732745273564L, - 8138117798159946842967048834635783117780956760913983284463438018081785732656L, - 75207222606857282113674665116246272876796696875090278021343263631087734013534L, - 12543847255758777525431737763032947657720105489722930407956988066841287650624L, - 78327321252130535570250911410466280437144972998159516285164686828945050773948L, - 90196389423575822520118171822181490354156852650241068673543270798740759570959L, - 60670122714012186216557490273944849058369509679550006105881736692248220097574L, - 10232203056784253994937591704858661588355868348916079002690715804987716383826L, - 56250443820912421779940932299238540687284557162371086043710647395166341689424L, - 106745151287508984114611432352663460679320831899507458596226828448613433574629L, - 70711680571992803186174027940849656610654068847875181643669226730609160665543L, - 47838106257302756155005461503289142780947408144101902856502705120104859749974L, - 24941360228300096083350701077862032603070060851245288110063415582770095103463L, - 25700025266950766720457426715819491124434076610164997964285411086712832180087L, - 107105239401310902784345766590657302797260120893605526156704024791074790374486L, - 46185480896420842135218739225912740102667560536884160717641823450312574499972L, - 76998048126760891745588080774341297240858572011912680574454836643717168013962L, - 33808836046696640438659929011730514035734389148647466846824484796567750758787L, - 18996931853760987572934181889690919742941525826610089655395851453039249508242L, - 56604122983388823053785197845481098255785257267522212256255952697702335462767L, - 44492985817019328377489391042409249255481209488552954877743884032952084108568L, - 60262700527314881511672082853298753610747395905734558549210201078525650794369L, - 69279306977580749647980374713849506038229420028933569196853781248094801112495L, - 56195902117233403955930282133702481708365531910713600561984930561415179141605L, - 47314831690761571391132666893984250546663032935010391247733227625093836049663L, - 10812783025036209706047425037985337032725721168017483330083142580280303327499L, - 53162496752508809045501362001473691445566319961581721263708067457905101215933L, - 58945457420632645086059903599934816006401780540563391798565832004056019028674L, - 73919100242037593331579812218634568218168417235823351457219323808566405869284L, - 52403495269684702131086435910831711916163695522829566636660560660799048967805L, - 13278812163520552951184294461865367827589507065203666088515419774920490046846L, - 16362695154562914334155901193231892822961192810812064385472498730784665801421L, - 3517056216483029262257506847130510185029740665166150468006894224027844758082L, - 106493755768367304437249140676246166044758096968225683795417475315940492882512L, - 76108738678107595032074077639412467077253203334192002336836719868953673062592L, - 24636115565757631437667031550958535438978674430521834147987218537021781123234L, - 25741695857057356211640713390935410123855223996729071384196495225008418025128L, - 19955118751219367788486540195772941722619062836730568279729801630161390967599L, - 50727362120812021647921340345708573849532470529549431357712839661035232260499L, - 115008990003359379169498136566608005415041400711302906652756982799431888611581L, - 76011030665703432674887267454022929576997959526321421566956239532190756808010L, - 43241178286167700202427095152526401603732039957292715002566291226481343605762L, - 102116375477349183975745809892072191840693105552331542023102178483468604884270L, - 2367482012407755484187720340622873573623580517843674370407488519063191397691L, - 111361344211502819366872854692911530822999459773812287285457324369283709635699L, - 109657494092569138881317447671628359243100703575477818863540322790386549722230L, - 7109401893987191796852399187756624249465539674575008049772377454960266500911L, - 62109127966662221855456045871471976300684717590594143452168774326137424630915L, - 21215429047648886881079414922583785408461108666443625793715979556096401731625L, - 19279814532392817913943697877621536160592294051765916138025545274590518161014L, - 7059996909933719857026691582224036233378957254796742907276770679435914795575L, - 42259543559452493904761078751431150845991251989321528250253410612380573321732L, - 86565632998965501509262078248502654145399501775070068265403951188763891315010L, - 31945957244800771720929732584726907607349704858229698053899900669252052622291L, - 33092687574736978943259443103172536628775258103460837384587272224669777291246L, - 49991423183781203023419136847708046249824217732070381815053725604886162286791L, - 67696544473506340614845249586113063722931832682767051358934753387764790299157L, - 44300165309779156455215620752097569573691489863138402159754167727039908383175L, - 76858130805950970498647404197161756362591695546650290097815117903992974846379L, - 53276036540992571104528236913288618220936509140158418588609708019288597985187L, - 28836557358889989094439138775987779139189528452622475804026978942568149457238L, - 50644949972958677693536850596115077476481883558935180276892583079964074035276L, - 4313035479479260652957532662237992841202310127861671108799014761208414897840L, - 74980974204719065713949925256433789927275757602890792189077543891295362364291L, - 31221916081651421283201076921082457505494774434921329664641908873546309091178L, - 25462244836002487199485405445806588780879544203146092339551376405142372822334L, - 3482999242917196361310871854038227752332154051569125713305221689612101519921L, - 49649109741645026225189814305214367307422381752801210793812082736369288961982L, - 114342386537218413877218058901138371235899462628051411191197914515720248423341L, - 18244185134630746982865432082289142945107926531633581824930025314084943124989L, - 9665298437683704295641756074486242506598006561010687667829341839141938852852L, - 91836819741188398512794812056612855114211149643842653549306158789633836413366L, - 57810787294785367000539906087988355564561182541447677614819545817922883191528L, - 85477736256329482640831710125138739960164891241946693192003483355122399931470L, - 115588965459262364728375262949658522780633344307835283517036286921264684089297L, - 103260352544636963665161503752217973936299959481004422664857988702309622109391L, - 107574880423637027149194310946125447078638778251855934418764355834865906839141L, - 38988557583051884992589337804370923392967342739458652510352831410409331956778L, - 39591776179706661567132036672004460722863449502638455439206618051085740669736L, - 17295299718391811533844201860737415438218877987077723172426193442926174384820L, - 94322782843392951587915185212638734339638010622233846794995601632684618885460L, - 107541695690889810178451969317913054918582980088580045884174219118960727155090L, - 24433009999316283894057987656228233755881297257138490518346832470476102407067L, - 64913204017500537734788292080991565393911137003526637813960355193901612144235L, - 115739811155188017616770707442608984663061587821428694051419951407332221405139L, - 93268006609628413900343026290606426540202253537136988008591079738656031181746L, - 13590790537658288260517954266302244984073327090302715612632694655517502725700L, - 9498887082168469013904002090047017291677776306533899049946867646338221837834L, - 20985918901466134918911053217454386226167289283904644490924463147213654696049L, - 108491228858878295885197481281971955944345047178278524028275614393817966339188L, - 110455899523979317579311443631776197076040047784034262076820899919827473519107L, - 6844215318841599774529444511351358879098255296841141296301492647973263268428L, - 65682796126283140741520637070656076629243815753310091189872944625436827968376L, - 23517150246395086433614856150225290129244330727029257108964098352151836879094L, - 26047331263994186391482269519815462872757319506074471845037389898789825875247L, - 62205044018158822229377151454547290134230969846786281526843611718601819536542L, - 66160405117911721687124720428207854312139716610213208728467032646776645997376L, - 89866281829404081780535119126058454023598298022311318229115957056736118948204L, - 97205043720275181149133603109928920179681558801849363897295499342651072536519L, - 108224954134926014239321602285859868141619691513421327461634944098887365621534L, - 62127427428237051674420339353192007342916027118439813622162390804228610889186L, - 57893944818747416682894353987640739673658057551300981538784349653023861351437L, - 107011232727952378470666194813019614835857006938192015800662810852391320603663L, - 89838837943621207939392244168865315732107983537751534574579886291497141924371L, - 54632573359551426723243036703760553108536426479720114683903078151290806006296L, - 20738611782374605156646956064605162095779086604063221130932249292604798904608L, - 16350363247384903293056062323455724399281244734754303492438311847607498851127L, - 55070254729385682469339142212209832394927084852791974237827777250490914753097L, - 70055365590940376112291979561642970183096463801380594679980002124302391877728L, - 15817205455682046340394432642972339132738094355192512023066776236228524938855L, - 15040978696204192679398805504602074348777447046879772840279566034525028940426L, - 108792775256107403391456813738746267828500095466992838148489801045427465606822L, - 114140463922141397718650461353581416960441573637400625636182861671768677438889L, - 9266792816924420616455524252906093074312617869373528239786435567511909850584L, - 97488859087996168454354238919383087328089783573229831853115198044932227680474L, - 3306941597490810404824812394266973664265011528485160051134428993448930071057L, - 27016887126238838335087822685515964453061603198222243802559900884953482302042L, - 97101633243587215197612635088560080796283971276295720139023256646675270471260L, - 25761660448050799443702883851485246968893581735447113348244062051810472315861L, - 96251340403079234568523076954219291233649081305077170874462689405885368052190L, - 75368196346776588329316860276886265399075152883748080407426829578422175435129L, - 91108890034381164604848107828959181618294467488462096583429208296553396043494L, - 18383384042495707683433916491880915065880560710098616373862311370236787240918L, - 44789830627835059483221298616711282663434668638226788590848493956012207964209L, - 38153747047003712884045129440118737151596726392380182899055728495102932659985L, - 90925175232108580050872154670675943004849067464852756622340307812594900959940L, - 29597858466294747689192446973316153084480675933662710109785528207120195200469L, - 30968239515894501488693884336782052877086193232886478078956587970878260034042L, - 59826399967474621112539680250762484645711532878507177809792747649555312814580L, - 40402883816060368873826918443535580421498743432306583826516865452640652948322L, - 103109304131739697403920071232053479325353382647749396046095727994357758653158L, - 113907958699654324296036491251366551291536643809192490851021647257172722312741L, - 79076197470325995404429433846475816380495936868943975590060606361744446919928L, - 52531615235368617688492296476022505542606817220887394120841707850740416286419L, - 30664922842482873679297001457676095151872007267296250671933573720922787459336L, - 30338238369716210451901275376355753739782785259557498904281326087027882772736L, - 107608350383853963907659536716445700493759943543416131734911204634602117385813L, - 65958965586872418238783384214584168006245471907166614590353170781284445954796L, - 80100118013905022223143324948397185079833858834625716770701184726442665663404L, - 753530398879515371191977801468379293063900654445395626327580672606054877507L, - 98346097904140024964664837653986502379950088691600210302337297775169440639538L, - 68460124867614206585581761966234598146096085494429653172723430586270068231542L, - 10156644715043863684754272020547715914552869529746645671847735023231474881787L, - 50037510783686993668491424242622645275356136505150554174611012370627318553265L, - 46635569144774414838714487804389576990391955732471735046915355826842511298703L, - 11331911067863218893379169383664565180878880913796054989967284257140363619882L, - 38431294446985987431601905683782568620167714717333814578413045166534585452311L, - 44398384057199342152223969332814986205258828369979802367663368416306336770085L, - 67122871004391847638552204302083639336767183534269367207129447715800509018682L, - 3185747797477333309165013849816031863402475405227910777645999204588338374694L, - 20212423021896630323680720693447115890743243190987789155927280923344887433011L, - 113041857669352149316452161645207210759507019267113009449613325743667591164470L, - 90089900835203336560391195533592788756531865029726231487722601178812519556153L, - 46284131926838691930664774155938163805065005910783958732358715540938183409978L, - 85040548258253186425024226442365679373979881285185303165972206176571521063490L, - 49181137362332369980594604018187366669178450916134692029234819013234711506547L, - 13457800508316250378270810188212591389582022611819870961872314725573569742709L, - 28310457312048552763922552235973792458586658559020099776560334928303823615104L, - 91802058223571710415618380655206945885744903142322074359852783750098855244202L, - 1458357324379714821644206493939764731936748367480744939372106599086073017803L, - 63702161321507657016183298112199231445184857557781471811164211011615511339748L, - 55190937570062919240127539671282073297739632266328637800033009517383010297911L, - 94277248020362510715582054891654760276529287046778461621178691119693563583975L, - 82859741372764296636768241929911801196238429127180592114320811090384150685430L, - 104562860753267784619445400790772714882729078394982823289975936490331272791548L, - 16889624196322371361266895699658135728060861265972295698439575298043018913798L, - 34479797656774547066878888197995074225619744124907080334510867912345784550424L, - 80387078517716327864546305704044833524499425210992332886027138566405211949138L, - 37549033433004244794842287776531066340633053426769345268287856569678436114386L, - 60316902522755554226756020982946012648154833857999156815198525382516758499558L, - 10143956916498717878031035057356220149570716018384658787517849952091665062748L, - 3912509644482855673597958622581443601329189689401725406963587135080599187065L, - 50430800078500925926672261287243186812393870674856580679176377598337931348098L, - 80833354465541234648807619310308615804391105320459261341970413653583833113533L, - 53863620091753446321119113825771322976178950096485580378658224965753322915403L, - 34029141710705938408243180450001896394916135191279220565382517565616904896359L, - 110854352538937945899668215350440452593413490541522697725121447074200141851200L, - 81046774007854559953999197808086686539317219540931646384361653602077060041223L, - 107687652164547475479236163744753167668835962743928369818083365194585087015543L, - 58823056910078960427905691862445249644862136913115302747303130775438455735056L, - 64778828223477209419076856275481409064383004061886208433177545609448634696126L, - 30173966981334520079423222215487422166896399915962359334610255417081222799465L, - 2340646407364631466381505408539285802787096947595343952239785490644612934384L, - 26475480720325421705921984788405401195876336116695776091373708687906144742488L, - 34606822859413066968238325944878055764810284482770801054372683400600651526057L, - 9871410681115479619283048859281220153931475276229831902121199950676477832267L, - 8769623409176998516065671597586972387597796975533092120484096420203928746136L, - 13544498690312614332166725673893888577247744865804701623207685161160253505761L, - 5306151177942053484126937889717689408884966428672822323845525566148989756444L, - 28025201307098835479206645219070345873102513040684754347962573977234053211580L, - 25143765306193849064256195119390421696760090467999556182038230913063376614600L, - 63784280865426840029958873741062502952909156932939012297017563642120915436814L, - 13569651136871605558107219756231189260242924214757216499556800924663989415245L, - 19844149102409145164899383702905431874294284279975799650463349302848431722345L, - 8085702973244851511749511458252001251656396567279831753386435292626763485519L, - 7228553768733225658404951895408814447072687956541829973973278098033771266133L, - 105596656275798929748166863934885182363689635847234124436621303088018075316318L, - 38676776859894327439306496331637879961583690003149963151737467525103054120562L, - 85477686937823419543333196992932299365632271007320851702648643772402369864328L, - 22229920646492402606981052724637320840692349558623293033865697366530470978486L, - 112072965867338239573889213937723730433670062735410160872920205584142628381373L, - 88467625016731521493423548833553071825397026551739211671998589112975698905278L, - 25992504298006565830470368312378721049979960036048125625454280742210714251460L, - 110617272903019771469499444823257727911904694075232295617275982602998246137287L, - 94505591102923281633582187298665869748706738506552940726297726697376921139940L, - 61045622704434071646267219815056009885098917557981157258992889212955684204266L, - 13211097245463234511960758135014635595928033177520118564099801801920862689783L, - 31074512854902337288625257590954829730900652551161723130126776340859848806649L, - 44538331896767374738844648938521484715615151697818866991405461337364931895882L, - 3786568789660403200852996085367121779229835783673034074459126889865476618736L, - 72424083303309042927901775547713806199923926084563159364314982079354479060001L, - 69591869790363947775648315338788856147382399631102361163617626569778221519868L, - 106509905815215444060470900722560683767640278101044067202990911217013896112782L, - 75058175866682352019928692868488216877528414265350511354981207385403679685195L, - 109283868054331544143387891859529236421627373812326736608285770178840546643871L, - 39542883202479093211584799838746667716395625614225499740058888501390961106452L, - 94595752330744041906541122701037256583611801936861866206832963585263438630784L, - 34480068985205214181016984831940818548407005320799816662621545126994276346383L, - 114416879116659179519307017042905732586005243477405363334331745379987475067267L, - 93554579979664800565805397539022039007161035481361397011797715647990161496531L, - 37458354615498032052130382782686290665116597801796388569749611201056898324191L, - 78211335442859054923244898760943187603468759051592897374525429261348823850504L, - 104588047790860320948508463604431631555273959929178380837535562211583725095865L, - 88533984364671327208043309765991916410177054136632659494361043900096687170520L, - 74588505857600708421962930087161186000599018292750334781125400525294975481762L, - 112752987453712306641220876847544811759380413999723354584980558175049754432795L, - 111842592677353494948943759638834566424266950480736197950303220951311759187720L, - 87665696940715095017967264494167805840067603241734544580898800636588266337037L, - 1090280637203525009115725313643458642172735305034978144675368327513392247829L, - 21753965389658242894657840187609862990171336384073809699643086551343848128137L, - 37267372813267449023828933209579531160284908765644872895890883410796155625935L, - 20525524186444105429231410481483640675344979756404898092376935063963326256122L, - 17829422600439756392151953943391238535480033142831909162778609983726106228512L, - 41303271138985816303296672094245939680365497185281926261467432770171849579687L, - 82823394409558916672640587646663901611551822982421273865503472173163167718999L, - 89478479736184744977933126085668082981809605801479155792211982965923398348835L, - 72802133526370933145427659656755439051538517225580881768607137090961663653241L, - 56795692519940407526356010151860193442211997985387315152113952611744213237658L, - 65045391625118939077142106477324833186625602113180931858323879876662297724336L, - 60215294995007274230208134932676628315723527736391064120561973669174161015242L, - 102384662082935928315339426378370186792048305200094289382112523702987931678926L, - 86368559242380026121168902695823179093385498595197919919615211855084622239196L, - 76235896788712829841923795664649145649147848714227066730165805925937789379638L, - 72992440794182055655060490731957945978590420791714748896924137659543510472586L, - 15723779340218563391801553289451295401220280130193367650215088217189526768359L, - 30603739299926735280879233651788480382377350858560583934915975115996384292593L, - 8101282996304339298994017877392052576046111197701926575394135086300838023721L, - 69033295643745724490836407920021999057814583179181837046014642230728249600037L, - 28592965524777064039257774571078878759841665290321422900007794665753963209279L, - 95154479716567613162081487366086494132497147280317769959985517566899309948498L, - 108553069643570880564956047611599133271427665479694942397557048791568628806341L, - 69224388903325553975837255173974350182140940603228387437579339810084845588140L, - 69488977682955929391489137768839210032315303077149524445308821275179637103618L, - 103550700012517797839435246873195350567462382035099666630363804973887578951682L, - 80470716205192474589208272562729613877970764510034314437155960568801829613842L, - 112583208063995304540833406455352374509563782461174974145340713205469621096979L, - 21235325283616647578043866271225113202675335195508649707145172457286606141984L, - 13232627578013637215675687823934034972596548934524658253356832731455209989160L, - 80784032631716142178242469184070553027785085685565997102326912501697626517313L, - 7294942691445791409321257747702350408857270500228961118000714872988950089560L, - 100772570340278999113223280379402631778048062948247847159753669667008184399193L, - 93587022358381030729294375674433618701473827243484730592562292037522832295003L, - 12737685905656421304213895995337275908318404485567864095208751640392542517598L, - 81233734395237990325768449723927093657671481576169330485233345190291219225952L, - 69512778664259522863106646708774602335322872849219726033944719523744694631269L, - 36669514952127528526341931671493672830634333916199618253712407351482889565809L, - 97346345178315596579217753012380963130055862224614585562240721150355306874228L, - 13449222348375695803892334533135453122514801303614797298523227568622555689334L, - 111794849936821285647563352046412563483827277208655139522183147941449043408758L, - 25187687048590001973910956793862908958872565981170214377638157852182312571777L, - 55862026463301963985147590306728434778192433670354908742622764392746031586460L, - 107785046518206050102103260006811728039839192809289141151521472969098636975265L, - 41274859515500512327009467093125014649563642645719036935586636904971032950437L, - 10299670577090336347573507076381569009327310672260051284732727198668044375733L, - 18740447824932021856268111049021888133877431116345567968724621857825852217796L, - 4200073393579074662096737509517039478021146153843100404002844295789247718888L, - 115576924713829251952645859333145965259890905433609922733592169128194952064495L, - 87425681026423479946473975739545745299695172284233174785085304201530867212284L, - 65736003615206120019604160931933626146807817697708257905273663093461844861061L, - 68698660336679412340895678893606703366897742543340702318992030146867902614180L, - 44400381641247529974285344732897027714954070929727664425687199824471755385014L, - 46555944721400572748889917900484247677570522028454099304526874957996228277640L, - 56052117678289692910179076027864117534973430091370827276740312219466644295458L, - 51748509441971377338792270423435778413464548039401662932068905447231552317480L, - 53395434963484081809584000769248080961201539725305176110314209609198276843005L, - 102434000750709668610540259777148461533918495390223949486442439090058827800013L, - 96141612716022589616404985290434799930705037276016344215415912879442379598580L, - 96591358795046026482098529344557085339678356537480328665895473626353390068389L, - 112104425472056185088019792401011431491830983633283699577373234088114766893436L, - 51780038800394905147287732963986021681826029961029983295292280356900630107293L, - 90468410940773955762555388721724170986097417025247277612326047693927134761732L, - 113787635886243420042401677550920536626562907700369504319047304745280100901418L, - 111779868770549036631826184857346768528115424108766292718925491951245933743262L, - 1383125703245276385224109432750410273570943264665440273972968132086223737228L, - 10134161562116399785048841072740269155277614330172394008099010154300508745698L, - 85359232392513032206474801086296076557552199612332987313423759360551941365878L, - 69985192971521624329386000344285194632994126063400847362182991679001359572122L, - 72339149377714492859924370474917145875893849616485364424005757780516635362611L, - 56503123851498363828048317347521935671181721935176822509117384860437039033081L, - 69126853016586767696897188960560669018253492992061804151504417258940449344728L, - 39330299812728222053701305104575256287844208382743784690202813602370359607539L, - 61409899640378687296788156525781772854856509888081169135029103081562169908862L, - 44269150079628873845638315214130972701808044677291019812697071769115672935826L, - 56056168260782053795842288560576748699255446589292665370729220513400153079489L, - 94019538583512079156144786365665989285876713092214620288958055665535262050530L, - 6834852430700466562127587266714618514791343291417644589017511016990783355745L, - 1084959959337983669962278498441227418643027543409497426675351029330200853686L, - 64821350110428042832338872266823351253349947620020469893450914763400045302935L, - 22204946803601127399408985692110346044027239156293394966858530118282477639552L, - 36613852788587714200712041764597325017119186926330078817308927114268321888408L, - 26739566197878673394088065441468330922752350618279648337693390784942075313366L, - 109670313816477888214462529089772292089024783630384470625837201599719593046890L, - 9085296185093309738730942628356656484204324720627282267824811810925662595035L, - 67276382158235748718561293466013901431928725764841701443046468437965051147045L, - 115445059586456935708290213758207585365166442358212557650034476554494941939444L, - 34033762681336554454951042883589284119297586773260294008883858312798983889577L, - 83866729665675158021340977072788355765911500343677100521455474728603516009255L, - 26788652676730796537917986715149006710765916810187150134747966504780018211344L, - 112795501658550766885671569168821667620039498129435866835194249729273062173932L, - 81689027014275899003176195182576649880349411490162790721514953337217510955511L, - 23104687795143537561327142876926268973710826452557480157496720794591031951797L, - 79090184824195591405644231645740858320626756246048056690624496761396450959013L, - 75123652463963764877061425990770347795868876195886491732787070736510177074581L, - 77091020794518126957007731150277876565087725347784962070706816290965708714058L, - 31114546311402643974968758145439532479304783698429893469155806120143455812451L, - 16341484285447878518397457523390367190854409959942210272347307256339882781267L, - 98181118887583940465875837223088150093242984007371151495130338967180219414272L, - 87592008363538304439079982818695061454989580615310070537839242259041736713907L, - 106075531380976054958175634829001075730548704272684079170264173702598392530682L, - 96922583627707115101968615484176462533918860323875268927225616132861429195662L] + 112016540517777279124582056964762882775092635530152119738265592842063160830965, + 56016915772221477937604398882069387632763464690103128956960662776002935411782, + 27489797435812445852286074542232496823045696260790971196874895068817967327914, + 29231458257536678058796531788726312001828885265742980097893645233605822098575, + 109621318833012795682402637604567380346073503361634966798913016745742953699966, + 24909319073749908615499772821230754597736318049326474726843859675116381978383, + 73116838412628052670152025319686481320276280169380738966717514804364097533428, + 80886863176958214668563050365622560907514596142176225339217204583899265998125, + 41589402369775626260554332252036838054298791596933198958489513673258971505130, + 90207124876116528982898796178611787615303549079587054631783065386394107105504, + 114354507635998358018416447246810731083459038073523320387363301795032648400355, + 3468633635759129348396311811642141059611148041398510578008184000944189646411, + 17514043107330244526426315235805045874023023428775112862062056950974122062033, + 53259785307043432607139655762614467196491065248189533004175348159284660172869, + 52620393715353636218560129188772966967309800948433722877797002054186316980514, + 81916037529722914583852010621426568426887061600075613109986180610980935124387, + 28887865002743070237254048932842508376262793422026358600329002055567891885209, + 26911650718246041071462711157596525307850141815199918550035772490323117482977, + 98782771420179306759562155487949995386960639005911027478989653998061955681574, + 21385446635146895191163854777028162803169770223985713636865070264449808450295, + 115312282836937207946894229413241455580662549241543640118420474329115656990460, + 8038616326053636715857944728508909614506215005454136641706259209707589435714, + 115648774472085869829557067749566131339376972955485372286312437113097810332113, + 89977569599113102467001097812324253681742984229238600181917861256506653234721, + 48924912067861623118041172086475435793443440679010754712941941116717440634853, + 36587039210909234246472793549041156245733357108593864427518986567710598392952, + 46109624864431307857770609789747492326638809391439411091696680294058837799477, + 16046121833973661809951046995227302935987263834895748044292415373871029012138, + 87103134101714405379218872339020541911369109388829618784084371041796944430262, + 71849222861024798916155067399910267006659711014200840638927330075305001351870, + 70844616719056711586280497702324062435759674335122542937012422880906044773779, + 9335799715313274697512042344496215317099396583298735675248312763375363020532, + 96310452005589395003812166209756935214142758015493698798130407204945344186095, + 81905963287417508258305936184419375724301111181318778863757865663441633463111, + 92370163495579471744030437129029154007365623200242295216366697364220099495719, + 36375283506059775931024155362654312316148209788950930164000462865078958359360, + 88726230387220372332073897600804273225361892039757582601238798806528910444882, + 6070129213356042314691499461742835393224940498627879606963066377266801299612, + 58583931103886568102124231505465601207272863084913352879958978958829547119677, + 57463926047214227742724634341326914848675917055176191431046747377307567352099, + 27012546757231614922088904355562654115959540651898947136364052388242505768569, + 99433045653889563967150006921846226712363259667263341416016685182002637504325, + 98930772562583899742647561893951122857272411004257815634561920125860196333333, + 50108682577013406020347739879562585417576253647642773177726545361365392252368, + 64685183169410827677125410208853885791480988563246282885484253607919434869157, + 63831879829294080751777051276131359248834082161927565636980809995812441758198, + 88444488165896703625205363380828907087113537711070698319237824422865316278850, + 72159984086399288134669843460215053409686501596375218830869388391271515007149, + 93923006498599762246269011802512049338272400480966002367955078528607110984351, + 56582486764232203710657643460558786621824618256032901506993654680411374403506, + 27247248238300328134410397652427878380336360748128996791026616325378108504335, + 49761339576008033226113121759699928068150081352868219274106736813953326265638, + 9161675158558004739448120378002634293608802907093779336873863369459008891019, + 93461397760483743306132919367837003785210423820141031416311717270390284637122, + 62900762991748812547111882734991529379973619367968883782425707337170895993596, + 32757595965065373444083144038461103402985094949819621309996011288543377384235, + 103960048224805408775641108708179160892191001524201247681388380155314536724637, + 53456560041009681567044041341204706503806618637681525958328705890594461717036, + 77717709415749147611975161379861131154824772698687245241144493306107366243712, + 74890197579975358597780466905530025112143596353512857089470046812806235935743, + 24637040035557619748551503164358139880147695176857752327797598473320679714713, + 12816399163497874874824956046851796108049172420116309081964631263041327964849, + 74494961293884467664954304349698851458635838653133923701487804959710521062367, + 90993195954149572297606851545725050698910241708435138297753626520345755984107, + 58215138150929360293081719766024706035215643415428831405694694330692503719259, + 89956111261673835060385930154948690999626591425223630675807002157058238821032, + 96913445328851719786024423266233282775668924616055488595011129416530218434040, + 112072065079699680359500521368330428382079803608836130990153785318838270149395, + 14850098647561667617732277867245347785629166243871670796634517953513118025474, + 52051372518516601581864957765692485097071703085140267671692394559015291978948, + 22428334879466085092832984704566361590992480397962998571491363448424996051481, + 83668121237531480514218115266149211167088412945398880150294279995083596674859, + 57326589617037353335933101525368632749804298967102525145907702271743943446814, + 88632149646179999179343911262867363834501950399527016409018248336659121987348, + 103513396087040744916176505331390959339760897230049404623861598220178425365949, + 59405515372488566742785411177582096185006244999302269156531451569770912827320, + 94410488185034888630546519641288768107950043015563130381678422847498960827496, + 92917043115324816161356018866304701890979909198500356250790217418537154937706, + 28387412679588455802257935903781479441774758695531218575255221599977885477398, + 45345338964765670288443753460668457262803572116668804743820613946584039806468, + 17554385903835687117359760867293914739385241051772405021245097638788516398348, + 146704054663283934711294565066041188709559059689193984271952431577139905378, + 55534501706042922186966773974076149855785615244193978550637186387298665233797, + 12402292003490764097291803996915545804946326347843103552862034174944187019226, + 33927279023744526352720281963382595793226423508933214565592188289555773451285, + 28674729283795803892989231482389874960373994212629043184176027814493098577767, + 62979428877521372940895063007616268821966798956402214474988446361024679512490, + 58059928852559648909397597332991639414174241397379900252886480855366523869880, + 23149549033567608603378576763933536979652221515126523824297157005037634154491, + 31331785003632325691521049665971090873036911275170678595855097146136857650528, + 69805883028197720252962280781148286012966422594772335803511661210608982041459, + 90136259271208036140807781305121794369112527230665007487380885920988164491980, + 108284363538516685124971597472434350564615615957983267557967320689537268236763, + 103872916138223246484444709027601996626359494810040925740369292169665090170821, + 20163745130684015554427748135506154842279311229136081884933763731166339971930, + 38861078160039252718353485169669430755389752224759618377580811463418472015059, + 106492657875624040584059066389441241595276994256407827006904008468691816706346, + 9776670813106470420023500205860682589193759333647761957028971310568162594911, + 95547750627942877263332803284960121334737730663663425653187528890288840934155, + 24595691744900522268361546496044420497232882656768597381664524102565879647753, + 20560951005227323016094269978149633908118400347609938515652741873881000822274, + 97538994901021840060915370027943000291340661051520734452728118980746955504134, + 3206096951624214679035489155064291884200717537349225004749377469262758264168, + 87213128872816361850234696481403629146111393159791555573774379367698747440969, + 52492154392359966513135657643612646077062522044723689819581548433266475660167, + 57874848912728677019093831563261174317645429492784161819476727716797103478980, + 34617353845582173186339818095469634689208812124426987406603484565520843863162, + 63352994991869902985863831141264774104112904508101336521440783817476166378616, + 24896526347641187332629740257374236902537250311446894531290446029320129805493, + 34763391532733369762581513657392564500863299511718590960540820980612119494337, + 56490223225145450506626693194447650046194222302382964227296839561606036891082, + 36970817473630539387769860171583437005195045204732265535515596613775570972383, + 87053185231976002982248680324703214694723208963143948890114515885935043320397, + 29847036569571379084663465808018400062560795577661654153597262068169908014170, + 18988090895065615698635043358038852667590102293148566014706810260439102513807, + 64469609724802831866389115122647676877222365077735069104786062834889597393919, + 83556789821922402798488159552377663265175622639952608675121508387029580871368, + 109936006775042091714841318781806779763941627558694342588009783709013194834414, + 22968733154639340981140430196449031182859954403940180947419570045659083407700, + 17789275781319118050581425161808713092125058324692136001600328252471260119734, + 25745380119689470807209093393218039737578393498273708320349637209328821820318, + 61641607478575128527700451527718093807683009050940235589813631356624939032595, + 47110848145937746368414424058821501259911814303529144556069358271853914032200, + 41533909436391753047012504052982996026827131975414910405032096368886062826129, + 13054948048121635721506270513359775546141300282536389803702833848405874430279, + 16080681035777294584165123624695238589201445166830763492914391196185304360703, + 81299539459149782016401935277584722958566375743744658185491349417910196375678, + 18945061964739542292675224703307880535444665336511089699084814584597438298960, + 112797159538436039343555668735819394839428598748222619016939149100522384391054, + 73300295966858556355393607143518982906893794572692795215344888739320658186069, + 4041434409204542945242581084870345689830618454597899093695016513143642290802, + 97508794687679881071902975234200563849411621855344235991749755970686207161839, + 15282141413086994702794900287401256763476842815020057731420569793924926978911, + 99728292502384296296228667181892942533052936791849702203347135028416281206377, + 3411041873042499785540450848806342320912326049804985044239917476630471753169, + 4048033594044406973983364298209147826637114833783700079142995185645222879854, + 101860405294836197506128289253832975563582041161562488561533643193912164273168, + 78905877433925568584515437130206044862818139296717285038469191868676799310061, + 18775690530628442604546733798201529558056066835322234540392467080880913809254, + 82947397524614988691926143062900829869324231456303333360721539341888846038725, + 42694379073331099052172297715130893406380955641898301659263525140461504293047, + 14442033767533181542149794383759150549978335385330888902568884429150620610599, + 93313581709603325926029120119082923112988831425916606563484732721238387656810, + 72801205216710264428360436666267791931111107489657889310598331480989588029387, + 67672324229006698997429333430044401253111346908650081260433438623710584187265, + 70772702159994604749028832792273009568408747593795621407790253945395559706842, + 29729304049522432818646784254663965006745767318792991694212308384739446301778, + 84627931201730893564670832781378984288443711600180448657831065852784023499012, + 5341943877865281034686860324729716028225611069848222572406801055229289775947, + 29363932365380673199419088786644528126811770594253361078602977419321774803891, + 9004928131838813677658487282066233255501121930576377831608071926739686700330, + 105136954397546093563754645032958827106234484325609968808287454474846711319990, + 99816460821225201342714853579093969388961697645623860806505884442477625580990, + 106681508148883422742224326307154802018855256554317516173086564531286716004164, + 7006763686362832983859018353853556207867301220635874533560223129687398063238, + 14321478981818480518746074874714729340600984755356898480669110575494399252101, + 20175260458757597605277157497724495661959897504305393475703533111106974204442, + 111769254449605230052328802781178889903176520895536759727961315714921223704351, + 36426670645651890452930640114977419417665421141639862712468284926884279415361, + 109432460300382670484067214653957247313416883180489696636197853559990484030609, + 7520403297596573819592781546673822831071168643752348400012072445764927721892, + 73196937925500377714455439113432849037994391890274802433562823511838920107695, + 36752755571095894428029260872947166518412591768027342056659080137127900826464, + 99995344805296217510853913486463991681280426231577702483100113184040494219000, + 112420429371656727207370103196793504245398270791446904347278453314283313337871, + 47191946582297313211416991922641768931234133845492807678047578621589626189485, + 109778423006027852506893839915943588591107046052313487963867787449068930618840, + 10345675446434556619929989818962829290520520574227315805411995298022315933978, + 97692937909469320640194638870172745072367628197340418062076997031203937194269, + 18683260981785212200820959138526719721818988710798906741300704329047908844217, + 6892696773191096918392700093236074630398023141032592274451349049962035542623, + 60564427846980699670576108199909223771359549125660413891296955825422714914983, + 38785763103128427613833647061323411816642055799472850145381412858873101474209, + 10266092268719998396552723710961267337810574916933175583941362520043487533883, + 52632148605242242206734320602317136445314295285812595150816657145404960256128, + 86430865182180102182285826479504223564509795487884784384886813129147931898614, + 109654073516008488670419221955708597615091266827715478203469017337766287849746, + 81026678297990230131216764193661112039622434667965493171991305981991014657474, + 82622748792598278407144966529781092604914661332588100202486823117756878578049, + 25507322366608129176928204743509962836694925557984874383693252038444933529306, + 51980179894131690770292900838955321107735899831146194979127760708884582438956, + 39893713525243360628219119209298547936570206617596529159668900841315961417217, + 14387364924292276198604346380005369236826342347182298818726067797096427891678, + 80725549608704072432582752894272065317134564903036018699016358034851243292524, + 57931677269404600136349629037176710293905732342675570761221364386370582050657, + 108241043767163664167205246362258726108503618735082308459850286665596958398812, + 27041560631327932383266441142102307786246412560862312846135065301507337248992, + 34625690239551233696337914812047380316989766280990608029448299992841381318556, + 13597595180205500577632878824504131058343151112673827495505944816766119242943, + 68657989526988390460365803072516350579228727483683299855487425203740805321173, + 68128720652325683666418891539682215901319669332175011784422584094377594552002, + 104041769249150650432713286188297298874807527317507734388055926579788565698935, + 17506611583023822782703007270314878467544710450669560774683033677129500120696, + 79876035561916781816687040564988738579362298771175915576172207704762733629456, + 82330566824257956442496960295477270673561486600504288976568497333939224637217, + 10998126045115673379715696210992497023523769066924127029147032066105877814739, + 6134205546032008896024930332940593161437017366857148587377265090739938507808, + 11583121769842881304585057168682659884964100675720338197866411629831388260593, + 47948467738357486329944891563527055069643980603315028338968162313802724094371, + 11215667885570749573396172846938492308466387752575072442893328939856592581070, + 9534445050215996549574184314121246759691522074947006611864912586114253182980, + 26960993245824579668286903301462553933094711257295314684210187284207914046917, + 42268713249784757565602219772893477530395402041957575219491013329425037932834, + 18253096826887824215101051821620413966925375390818892158612837687736493874269, + 32647453224566146209026428358709030929789472415884155623819230563509430098873, + 287767308279396009793123999269205094524894944712599136360128064711797483633, + 34729615465854230937966579696686155883411529356665280280028584403769296316609, + 68281051772180230242281621506957421090373838565755113033691729820708913107414, + 99139670525431256093001603279585358199342573071415589508037259484090669834518, + 91267441814111668449455789360877685829217853601929030146847181639079805725296, + 112331375053079340953180040166784320778361475210237842930567257762115150453895, + 28371709961045497162723804260663265229524852382382390971491630999701617194893, + 74287814005325706960840114010406717339638651149367996645855364919384064717234, + 62813730919553857955038486382168764703884469040420815758550554930257596578121, + 105545450997141255192635926957785838960634589257071510058148660009878001071768, + 41327280573876048725438022338561500502955010393411792104623229499363429415913, + 85305487863348628556082654688864393129756375287687859474166404086269915423521, + 36217864842258952910470692818799400265537629839424907972768337859708224272429, + 27039273786118956176256074242317720472159292773454814400065255644876377528081, + 28257168443684587877664745623305158713429464605548802435968837515560446426794, + 68860966611758451913434265377941548143707704988022881496208085576333989847578, + 50407008970923325200185226986886055210151299406994703375093867352751009080672, + 43833750391299030896607810025375205862164543819507809304552665996364584049181, + 47517341024382467669841982663807010004070648542247729079498904960356542542124, + 59501796603968326047997181784800665294370948166459642689928940044827716558887, + 109356913084047950264750047637950104857997683486400548504377705982514288943104, + 108764899133114175375894919353622844771053823794722043622829189650510861136931, + 99702504117576275465334878690444650629284364394408283363533027878927080352437, + 70841547470305287589274784901197362472932969076958924125873672199972429659380, + 19614776128064776638184459221726965378454315076371196529553499930811313773642, + 98079213119433189881285407717482612916878647506982538998109042938607065006624, + 112302150976513929199789954934292839584625436975546042670097483152919172778948, + 101270511568225377472511122900933114546675915482267160241459205096142886966303, + 92601020688553922078305762385834063943477781040884163604477818272829952897893, + 106516807503153752241651444005385814426259174908471724892260099441760067584006, + 59558617948858154025583492179361041670311410135471546029253455165957065077880, + 34589958509803762243288779574845189860253197080624774122757136677990409899676, + 28956991241739635872887354391751915589336163031718370818567680713934561473546, + 76284552793775899952782267192739926313427643498917773454793559446244711464210, + 15169808245466745617655858126391662017843438763733740347957895786030136159686, + 91303837629389982299584271607446771694386497564892828967340596042435535849746, + 76706271293505348906195831263098926710454398027822085522661720229864395551030, + 81385857155455424676782786224373024348911426134535495090280538905769333221176, + 114027723567722411367125115195503223432492147480300914967916421352243226160863, + 58683566049686664716231137094943841721169978722173124650775160588312999544064, + 47636821537401183076676334731710145678811127526881622883432088094747228792951, + 91536282035304813234567796434364946910865772878331169793296557113000386367870, + 56229624882039089131852205427165270210088805730464734083125360041622328297139, + 97669934343014072373530806803228099401901106327901588136030333298365599485060, + 53610175098509849726221624535924354414085033990383931412157822600931356912963, + 8456028367645624034579366182003257637590273712555737187498744052364695741913, + 13590227372717901967224485586122763093032532664741134262481610836479299684660, + 79363333042777866174143261304028217995231430841620433630348966723071049374254, + 80310669348385703633478885178056527674053360397404660465646404494861426931512, + 76053449640184337682215337408166493809582813223481816798649267699315054787614, + 49557524797100181322234668564746448411465269913248832928539280364244877291571, + 31349668130482234266895705887351848689030288515397213507254429683422494453226, + 100523078506928710661710840376918307325379729091199276698426711431092321097251, + 27321541552954853256201290168037140371906027004144414749507597003937123653687, + 2631189220012736809936028959130414511579464458347740950181563826394086700286, + 37707599701619752022054658444093282978945371896935011773965043895870793891121, + 45394733945061302000923340867791152664821559733507222856568779530413756014405, + 95340874961247979683533214972331081503913736359038376005637154187518984386867, + 88761528612866195484152119688406674192445577846014439797767556449630773022806, + 36135078039044087803749644587304316979939253848565308604143673942545508786330, + 108170833529393902283960998731357956456749612811200500384024666342150739083393, + 47512502507757503875846460116015295158758283453564371558196514794284165616746, + 21507325004620818719248930115081453354560870683510626857344667716802398423589, + 99684522227981982474613932478640264245627478765595518455357931316430023823495, + 91539177891906741755261397047769750765528783737254354701533514995475896738514, + 111129281145592623960314201429479518089274650176023170447570611164057042267360, + 22578859183323245626833259777830627448647768500237823313657823977240236412741, + 10349676642954124319464106128855803407368741329325517831607597138586570370450, + 75813035507443498537723420624776215351694467717077489892101531934015707573318, + 97594492003050383323388967820362561331982781928579140428340544398792480580522, + 84556662590705018272581684903772636103662143419126207773614399679368447253016, + 57438562249538101497765961483071062601181323207590598012932050384594326670864, + 42369525618969729821281192750986928123562580701994358465110068123545593923346, + 15631178904228263960240009595109284018356032359409694306860390850287169084700, + 77010475411668698882543270552280721918070811228191463399116907778221183212574, + 15413551241691563916071223025427025890072141513575960221673968406988693415755, + 3886635086355795958441009792222975023324676133650112900867529851708672954448, + 73012476638251310907687233534174360901505256204961617624515953950293599750069, + 3722822644273822339360433160044015759398827051858643263577138590741753934176, + 80408423812406792073723049542224711512546383585571999932848110527229812679010, + 95727805294873918079320757434531209634714565678497703702813927918339782560622, + 16089981349149755158831064243309353835117501894530652592287993704563215911068, + 93181713378293406240141116118372622123133778817521454218943819809275284420273, + 9073415722502328216365879393933068130631879884724670922841802060437301096372, + 93517519773643331571375204738306910084371612303010400324402128977187968977848, + 105094715911488287236836140179095673404733767807464456430714007607658401214137, + 112024396687943913146262498005010531235678882540698412132370591267309885962221, + 37165995241123181677724541737159514391850143080304163810158263549467466680559, + 61968583687972759389885948258239494882619324802275296237733196640628370858735, + 63829405995677144318484221414124274002955652352509310923559860713163722856947, + 98532673930518295340902238602168289554424153910232929900036974384290255073529, + 85997627804527857570889685520722152596798858230903042330943741382704463195389, + 91215913435294163483873667979004310085424847448801135410605514096401666218327, + 76227221506957628957308362003009905875501659532083775433150630010718621705923, + 19195017703426046951233699673722502733267585758017903840970278708816922827617, + 105129253587366388020090858980091040319396738451908098974287286821774711695811, + 22781834725370441481771875988115741479803940767486902303521722492815410363472, + 83195080117942179663592464716172666739649362186378211516611789972838421162501, + 86594886402366270550826764806089860917730898934318005632123043261335819892530, + 83097351296768607442750079314496113785526355672285553689112761857786549765444, + 100851987071723593535660952515023915930748460098144529099521019911796498728056, + 29042120456464831028285966716896898582592761151226643297300308103175984272554, + 56883443662087622362160331291011107290929701370651644081822008095958676071604, + 50508584653566925697655566823622736349705765459212244663848880793217444659655, + 75831090901176908887931690796034589711040965462782105686888900253525610531547, + 11323562829041465752257738545564075178220860053461170862535572762094853821959, + 5217823388742578674217850823134011496634030019904331757976562616609709361164, + 82174942362135905037353353709043782001314603797222727559986134053342781187860, + 50202630649501021671704278043532121482846273707780410024950587977821359472153, + 3324209706684823637468553443562813490050945432671016742542032334965381665098, + 4740060306871125788724607025640175962029290860483506225787759615413578438990, + 66756383172477268799988778531049589331084006212114401164616926079777855044701, + 83247041555794071645514293521408585641895568480433766852375217524052544918626, + 64541219727160203814701276749279883931437393757546403279238766945040313755497, + 100963507275073289619694246177466848460225709327667594121286073708287464725661, + 26318972549610462498778216602226802420225960415781019953778522488339924158401, + 99012221291939162309007280658070035717355324092069715622838077145257927103682, + 92091797836947203259213765762741251602220686559266784005426706139740459141585, + 566796505847571272464524383407843341080331238468413785758834675896402367196, + 103374921238374169420375942200248561514811450987014707811049404971341441272037, + 71305169363493275648250184362479744655365934928015625437582365751156384329615, + 107205417221582744390211344577307126967827612893837438184727896737548023950882, + 92441154917234429638228535136154961872027655587283604258871139699670937581874, + 84140778256663318467116520240058290998668299902088911664587745367709172336743, + 45556845552016678147898181410667713972502449643588537645594148304307860456075, + 98113204640413555142202002286205408580623426788130742652307101656799772050073, + 111799582795648235049116568249188571666873753213621452178599923815977556575921, + 3042745249238721747695258464570962925050325502231269880406471834698690245832, + 79260931570753127951538043100557443222802554197894319158635554110571800139727, + 48702562806629641894403284159379781964963463868578074138953921518729881897431, + 537996483305687316813696733498511854451212769284793136798416670104206068964, + 45276599793096426247844394503795241641541521518296716355002195232712186494981, + 4711833054533598595597708926805930010573801678420856245651307107366104375822, + 97959533653164703009028487058357458563569018661009994100670383461131095168534, + 56124016112344825540146770224663139087319680635554267370628216094675068256283, + 71388779211443877362892849696115871962852377897600069938201061972182558679838, + 114814453627856262931674961995498158354061768715887759155072831158860551322403, + 65127402122408243624228517277824006852940650639347380715847184158968045247524, + 1229056862661197769327296679752341218679776095210307284806779517414384801320, + 88972395288849790723139133497080910399041124169028974570218083938890114004777, + 6417453592935644328519665655589014205209280966147780959484836123702535239210, + 56638073514396757799909911152303525501958212228412740313805086645241850996013, + 102579127893915729546257461329702255407926414660089770043815514719934869948974, + 20052431404475309206985582743289944850004744789499061844247836954142431470639, + 68972067553519121689794584486338374542497793488247844436269266153426384773936, + 96254500393585373611088611894723205133243393228141813526638537758161133409852, + 80604912450770836457589058367594765669839829467281569025199209131769915023420, + 40557914330758410323049101458954929392166012791964555533532404907549224133950, + 102924567605188907865161299769801785501600541170723406168868563766023720606017, + 40986531312936695996240272556535388723561976353121061639925326611244396991048, + 28844823668885701249680419649255648386959547672924676354836558450976588992597, + 42076520546468627288297575294464954056406207503095735542678160715511123561313, + 94876977270169549606488747653929487420735806539860621916222965017197647068258, + 1260266738845674456679509616730441729777121674928342543364246627967833933416, + 4523993849979047481739506944107708609384274326378844553994163227711790536816, + 21431759397973169356219560894746023951943840789713921880195064784534930889845, + 108821013162731753851414548436779028343880653825788920240350346162479970834805, + 17906353290681234638813612028432794825791013736587994117250116787654462521721, + 112736826194075300427719713325582084166039134281584305446092387153477526778234, + 107984435224618494468183066425582748291745849218527044060754498637893340408708, + 107611717886305319460852919775001524194407688118585221081009301252444206524552, + 31954918240493906832747929653137205316197877563475871197676620430438989407116, + 77294555680991456511548367452653169657122746699638304443667609185820666636173, + 19208527960490820332864206665914487032201955968257931377530926839178302803854, + 47154831783488794566405507384999216172663640884519299346477725192479294180496, + 36423542791664575997770771722288221039652387193653371043205717125378764567191, + 77555976342427942058170549023956985435812144640382949629341651348262760703138, + 43412768734709911583567081706048412075584631674582341311496091557570021430187, + 21959336236996441015148717897872088078662058498333610499842166795787287723, + 63538326993401217866500688544194665721345933982165421139569219846509127908016, + 79905845359365877877977624880233920057502841691739504437421524898586928213681, + 10681792139241101858432940958581751179421847022560211889898357291399318170290, + 112260621524927562855578944812289876926535469187048546674396920462184750797235, + 88165566912353893589942666346863387620695272982391966569779494467819900828598, + 52862665349173572715756317207877669753232762053342595347846461744880907785143, + 71358808321103202914714309465454097348521307041367555204585916320180062656951, + 93235845147880238951137684176889200233801378964276260704523792127410129667002, + 72718808086725231119910981405922538172045185301228107871813451017267501324734, + 100667480493446758970550426412588176704820604183058808112051923130687851060417, + 110775042139845391601861530470426219464494762269966163468273769019688062035653, + 6766593846697232623171307629298150462867897707371440407908986231567520535493, + 12014347130699256114344244004512473658069924388663013028615566904229193256134, + 27825969965105678940460966110158495152943605697219083763059951984078990520011, + 96435523890332143175359238075473964932141166205743687936858586223483767233740, + 102847003350359276120002279360870264522047980390554207969181636483503095996625, + 42632940521258859773147600430080503936968451360493233839016831022987058093266, + 19571300828974450772611380433683631913081195861922411543580528176815568926419, + 111434655731367993894950670902059551750517417974415170312236407315260290389462, + 23608235690717222095431745605482011235852604694934703409773120155291836044504, + 106017757556879327169455640610201808008611274941425491584640844534727352975071, + 100194237331574385430116872964535571014096315483635839836478381542863902431208, + 92713684320292866626136347893934030297322201773422349467326040890402300878056, + 58846607406140216612620045773658739808395681978926887219599326204302567728361, + 80320823438646334388944027405481388252815446922782408490922543251513074510569, + 30088741070680259716939238344801295759478996236886884148932817972902909245931, + 102456232221700541259096693281931704007044911964379487697537170726371186702827, + 72013500902968439013009687254900905169470508758023366846525128188789265135853, + 106985170799722298842517273574171215868269301677890670174617203613091093254649, + 77997640775942562320971444102112760963667113775720082983332959043367735711227, + 62683654055983657992170448747531715227967029489145137570086335419775873779452, + 75730785749340338179389112993153891613304743397576005533979099055998292284413, + 66762291762568193891644841951279936563042785960280188860221342501381190300925, + 56280313917343127517410849379001990997102543396430104866007467738343225409664, + 59324467591512799624869384909984173499050034803780230329333867633862365756418, + 1683044441174010502621700456254295998648099133489320724296168910612291517957, + 88147253662322403593684832253266581017635988274298267439887723370830751451921, + 58343716962123094353217839136626066057811742662832209148417055342402360726551, + 102042089450135571288922375868967077092525830608023966680006742666402948847384, + 8877283783700618681680100555294742645257799463038156608677788927594556549403, + 23603148240625376790483040108047997409689131038732623508816589309969692005150, + 45015696176505669695533330960506968194871235432630036247404021112955562173216, + 27273242071094864677506735514648924422422353640301315884299919790802198722080, + 62678209183628422275371869480260753311103544944645063056338863808623721685285, + 11923803399857345669089076785461272716003074233828906615691242807109868335655, + 95420412784378862133673297170980411225412791573819301925339594272229792658217, + 17242422577646832103051643021716840952370970640892134824779146297889642365746, + 76855577286732301379172865713619652579012237579727566874656827498872644015159, + 96726325685354130145050911060879275730162214936626524357987449789504855781432, + 50745123236844673747407500019857240986658479523835409288316425468889488181049, + 59608141320400525935940756103659561296276824613682462900519909091472268126521, + 74882687980309051986643522889218926141822412835990533021799272338776009053754, + 37859908444522631436936741182357425966710844086898180834365036809567321014587, + 1087203752576771943069656551595484272469990338994559269489909016589514126652, + 60991521814750599780727542170354024457607925232661659210215919494766881930053, + 64453051011344733857015590621639093213503986155441055021177965898233993175376, + 77377955478500669379169781583746316561065084791761434771728115325544750893909, + 115326776852904211740113046848936493585624387044642876008916017320233794968670, + 66843638661901395342217121671364591758871761375478716017443685647803085332321, + 76387522032998444590998554577947521953962127682731686273317708994350303287398, + 100509585420698840447268897418682940179825506131319550264533306588834528678763, + 102377125275632046267335597508238894551107275260674055251955140441510121413999, + 36110335244868694900388842961776862479127814736923771794282870914687512014449, + 48087901527306675458708724967244354205948260975796662098779427969098790475382, + 26119165494218941379201102037784208684098799025173516959855235591131867261046, + 67086317163668808852789730141898373404855391395159096739380812113635207695994, + 115168997510970741273100147764087527929755242529074042878380720661984664186493, + 71535154458377942923293268040443538978433844030766213484797279484920033289087, + 74490351607525076344048122662784676925669814471098066911158732124307598110594, + 95439581330187916957676081877421602929486334373742119907277873013637003421577, + 87656814270301577281831314214475467755247771966329097774569394359651653327245, + 81443161254179142501416466831321807477101179745994194567006581832939242932109, + 54885804727455974455027736324678176988523863264697016122398430190356272496015, + 106282862423962463801232566002528433716003843973088523363294352394910521613455, + 74867103562016151054298336491250814339466536972863952799828325501346473267099, + 35136655267440539281917001436812264484530523764622204463869657683025401996705, + 114542145761998514467316137164479580426564663277916826776976176241309854292901, + 114149603230109641409300300317765387311421041280449018556882166752625241532070, + 22647598703536487002308745223680732687562703621499663807315267259473542957737, + 45267848095711354051242143972062700550237336594373265586388322482699877540522, + 37825297758958875478292750297344134694893802502002915810386272456730388494252, + 76481269729086848596168842665464734492043245153991095180531790034161352572085, + 107707648591247717508601437529840582949327190645047841981368706376540258461110, + 40819894040158651744374093809592828959931640536131204592389598534102797112503, + 59838558611940351927330467880089282310889795164199406620582423258897569518776, + 88131656420112027093931319604678436950372558469915672228896966267905920349641, + 76928539760456696194165042654470297096029479697948934824843832220438705590987, + 62168541405737812225774170936595749260003015142194074807536949077284496093645, + 82355551589038236450671947962490907589266314215583786237831900265624228666064, + 91040078168525896186995537827257061882913779922844500756638496647089649182672, + 106710078268466423920902446391414721044408430843209044367846557222141269618911, + 8295944548002166402926075220981155129901615305773735264509560278371576354533, + 32348596508610154850455749911780223725761145130705214865401572962784236696550, + 92625991916613363364099403897508115714291540494878622711747426375003813151719, + 22579452154116011806600193670899805077492814094240764086078790176929517654760, + 61501673693710664558466566656679485767427270786661384288828507176068731874794, + 54673841047622207097241337143648657461679490594088615644422753114290872923379, + 99978210348430706642339409751264239100280674966640993530444682285055126424312, + 77497348920315250447640649448270009364667831704951223117844325527179785810683, + 44696363875663259716003609140601027659047948267389412486743757199567011857917, + 100580552325682292262365631780644228565307253846729715876945147438523292289410, + 11518861677132083256648844750152763986628976608478800601214858206199205313024, + 62264363214572670209945783622006803827142264044650362355019724123136265172741, + 33230973733442066812841097555869412305470922004648204666631516339173994362885, + 99622694327542991641172302475186123081603436578607813888441614484377927724293, + 102417455616494351577269429386609166099735639986419056945044716149347214777607, + 64390549037290695081029250664557746977094876129261502170393311974899571876873, + 4971884117270309347183734480578381967398702549340681853078909666997516183307, + 102449383389506438850158445094726115013107692321577632033000101955980429851662, + 77032065671909070527193774031803934854547369734395171920960771534661333256720, + 51427001524546076067275517116230075777739059442665380893299690996681123652882, + 57846707658031795839501691960956691748675157963351582448198375141276585300760, + 3207400714205273428098068317265434706725664575349062007860014575398316976155, + 48996192045666860806356015189011849203805311725988819243808235919973651832863, + 104835176291815910614168078170778570188425290392670660463751413530619922189858, + 14981119087540252574734932626534306481790846972083978190235605830727577496610, + 63010711061850779941155020043897322102881519569558009332207660668803951977251, + 81690223776687823440667971909822413569894292161339595790524996391870114827301, + 58960316867947445772617227827225977131637752082183015768746567093022707191337, + 20014782447901262411771703924763542338641386402379396629574630005982997966380, + 40322371483089115316966842850857881228052744149017987508932980653077287822382, + 75225266479277326265034150495327075359004964339592640634194742539303882532659, + 1360427873648916040478677598931434689696693619539492831713328152985548642875, + 102682486285577705635701705175111253737654165729779553084925758407023923315518, + 112134468104068695940005782500350643375308818145271418444665998130374311921732, + 65346288658858844548100134545139308403909249070489810100763409995477238532420, + 45118385594713970159090523089169565316532036698798054140271220483524531336009, + 97476029759653028058062317315042925637551962120190446234623575312461737374538, + 10065604931768692054377094739162892613194529191136102644454214890555337922379, + 51553786030402063061700254827386386701080790101951499376167131293753402321999, + 80597011256255237792858049009205213538457159347705673937143882448274035124817, + 33844272053464645237023714379137059342202186464203853865794780890067672118609, + 81205844186930169830914915295886776634252574020398512386640220917751422229332, + 55618115254902954328799563061770051404707267477826050932521018559065029105496, + 72561727906788411099387267207379154973461292291399988323244582016927347227225, + 38200302126249889943153227138035137817990392515788356056607004367257772863324, + 40512699025239178899189201917599830173998902277981571855357988350276694199133, + 72852130373113254447550573789839549535122462986768199497118255107335826856543, + 21556543496705918692009455279894741802994438873807382234282828641568574702944, + 94910435199430807117493052677366099392273747913236237307831525304532287282531, + 75861377249331562077017399628408234437628214897939132885265899294794269531247, + 30876075781213658129907831810717284861780673483216317641763733274897623510641, + 20703967708517858057303822389608487644244865221307109638361146216007403372403, + 75484464698550708496430527575646346430950676445134417683713610303229079110261, + 87129729198669339702782235251703596679641140877606117618734732225582949267063, + 21266603676197216321600718008268210400030243356122680120555563896175222459514, + 63415715438466196790578746287176311213905572186996635167094209280910967331710, + 40720368057718102298431544796123435043114356544273008650218191651074186725758, + 112712268248652359734080083582461538637344066407845029243721092493183497206142, + 114937114775233845143486959600340076179533032756834814512468454080273362545535, + 36512901579603557913193537689480903094184396356981067116060536144286700842623, + 56411560426836146870951539885920526009324584091242151784611722979698021316224, + 16698912456783170995326467336104513767160540663058718259277822376227672090500, + 106066760722965292194719041696986145324409579006780335464791791351475409133705, + 104207962904909832816216631384017349780647804676862987772215854348086512657034, + 69243961841176518549263230888469400531404144027167071188890585689044072806794, + 51253655298165523882286604420161472846136153868591164972577972118747996841358, + 57522621367187189331324803586575115229510487362376403257825249297783421645198, + 14008691686569941249702994950556981918752597678869294675116218434795486754192, + 17559590831409421526199061660667061847018920246172867120529710154254038520982, + 62030850813603681661213529210192297536410672609839415084110307444989808291479, + 39483769639853010170216670313190346123132594269609674789398817914937545130137, + 27373432150674246539366656193993633656856212404804434949408972838465544294041, + 80515524415230956277423458011407925895348914691856987154482076010610066957723, + 49603749491658761343063310147446444301134076709989236516539085749722917173407, + 4638234616841955479208035396665903927460428545633473766627229552734393840033, + 64407677702144975949151853501065869572610657480257459923595074962489696100514, + 113729063033800538237563507194947437935179109496004542295476338932824489294756, + 27559869753538413456779817442066339470743784389895941011935964995056981446309, + 33384381289532990083476970734483649138372535104356143628107394996921728224933, + 16207109765807602992397132829767586006453433292590664044414937271538578787238, + 37996198627725162202981310547747180578940010211813882018801070905394782922923, + 24628564513391374841142496199906953696196889294968272338406815750563978886574, + 77311986397370469321099234043385939709573400347645098238364769839769499352239, + 101459630443329721289871636542291648339599060924804682699203278554752463558831, + 11458472762629511670071313487968925641575058276033733567554002191834171792815, + 91390821097036566407235558097405985046641826208230501464531008191101542628783, + 88524914862823500026206667566397083358529858623465072900012276950788691297970, + 47781205217992275185276602931233775137652615298547884028338694579101702392758, + 107336460889271365479382359792329448251372014941188862765727741363490731115713, + 13683491250017276293402705979452529337188096939209334955030433229234688947905, + 5985774502351629175676960426324333914303410190559821961461920762704934667459, + 23304448933988759752992693834848658743002695800222397537634383934483905592268, + 37564289103624408045017967248710953371026230579918885993454830860061146739410, + 93440226217921584938869887668526350605552124529469174921820542544604456138451, + 35976156482283765832545022774001668880213841650251182381063592287413945396696, + 57297350844970429984695678794987814945484137417192146181343109118733204280547, + 53078088315412211833793751124187365422715677410329852285061982688379219527395, + 4620670977723745073636505024767100328367801928808682752786389987771180617957, + 61803525948465253364619959990876209602238139167016879456633670301134189240552, + 46585052829677515250319943717834196659280187016435597500044886010686587628012, + 91743224621411738136401680004986839707449070953296895944081573638514545794541, + 15610234236458785326957282756613241231461484896412468404866135527865235041775, + 94701869446822483372701416835685032588722414109357932060106387983998248530160, + 75638383867886646067851120099891468008833811906034441039017079502899866891760, + 109323217313071505720530793462159030982066925855329700973555314076623421322997, + 86842647332705482807195494061715107567592560678052902441669254344785129577974, + 34022377235592061794214362952580373770895570995095680439673944392845030735350, + 95953533733989408445261475890619634519580457917243229943281863657327054532088, + 26422928960874356778655042269888582567356205407018615492158941838555144306425, + 18967698604142970614994714313564229649235700012432985379836668529749470929145, + 63892359660797867642513857940530011048856439862103598115303570201290361878010, + 74588898331913850583986198817678327719748410068857456293342190987907207856891, + 1891303523949303133994914040695860991496422858712772749043232242469596454907, + 113555415921895241105938811571952390824966743626599165941730396114135776754684, + 52531601946134219932308041725442066030140304634172421470280771996149298830846, + 32638282716726954532165110313232679865817254425127224461225107497334788167167, + 80840014404821550722694570450507044048598523598329185386887679198829878334464, + 93645004356397514961947862340688942736458020763991484114338872125689456535300, + 1472416534300792912775421675541677859235555728416376093465195351989356744453, + 18117018437999600723844152703648593933015731624364436216442596645224534012167, + 38755468804570185370691489631181112753516875613651439286270705031137197580809, + 100715082849109534526089419466115812821340513907905118566143241487861302468106, + 92098448699173499615912973532879395459946025134630609083709282508755477552395, + 111550391766917064883209636905511974883811737658416504517110617588211693661198, + 32590990884507149788797018565535314787256008527518350785763118765435090357011, + 38181426751227898716885399497713675463479498492439859204929263568713129655317, + 107065502437416259973837742628429643307293123668177644997591368635511427025432, + 102057799846669375009489265342522217091426916766438742908452443895711329210136, + 23472322632338496027637669774186145868837209896740446601934999472619109133595, + 54101142996391643743621251953151149918206740135985052202976824025819666034459, + 82460774504538637863049867790099375227234890471300564145128882983342803542300, + 70948468164177177761098584483928896319724434505662727209543615378741024192029, + 33320553469317264567053573050009719096602040446852816915845293451211202605096, + 33341836337609530655545263682386433268227320320366701976523152771764387320876, + 26832722136611840332586354012095781711272330756674126314113044937848293234735, + 69354984871910123412344914828142550027389971844247803142882539980451463733296, + 38887218044895438528977498335219550982795547502506023717328967765626818401329, + 107798852115196024784748025278489888281525855258344453618798858457928346979635, + 99869280657090254472597381392765515587357272194286676483834483257630760565045, + 1150972596982422542285349832340838048711887764822274317800353265301858729270, + 76377579111292113222500505883636325603958491053990945762690246057076144688192, + 18688447831653735278420733874064402883741520741110564341076606483438814241602, + 61229082344798583966128461730723769513868549112845325753229329289005961153351, + 53704530304758293508517397341653702649777610155695564065012810155341918026824, + 69672085999224845630835786708571653616226767123886631733530421027118690179402, + 104228058758416623080861378964448311854955016876464394251376949850452541418062, + 69861378734358355516299556986446323876811798280712171940673944522961928182867, + 50903666105609535885983150746311206289999522994573939931085951723263504210006, + 69762411846342189978617721366439039456328223786210517096429517225270053858904, + 96785295693675954518102108713098751227477969718126822490988190873035929951833, + 53902883677242743134794950840131929111141762734886047716628834964250614593625, + 13628634261468974632639423922822047532604745471344190636598823923634914237023, + 105452706964076144192933322428871834424779481173006000018659835215130331082080, + 68824702000389919294367590560891160312350680290197141749599999274678668891235, + 107609796248259641295614822376326549134793895930280222093108768885474705237091, + 17806410755485799985163149261014742382557649011328574576946479857183305924707, + 80007950390934227990091902500313518817123793596835360540614202062387629313891, + 57047043109144241791334156670491897780217521286517046751569717659939230041956, + 22794699983082178924910854965780938016993946962403974783953812352356032881765, + 91880390829879836574992268062426895025565288343047524546899311051396352657767, + 24705349683829662791049355586479945768768745480311908459758516972931716053864, + 28545444886607560846867534556715623648900007232552276819418615066865497912938, + 84368788466806781207329001318048580816467702441792122148092700034070300901484, + 19817770163640889510029214040635317313099932200316047934680130517821060351858, + 87805468381594296285408693509948150567016409818567107939512282924564188137587, + 26449397396497515260596530903090322378234325869858244148315111808400524166772, + 91146992636787877641545809782917382766985304095181848259100686451357469554810, + 68715426009894030818044978141743928912101323309208159313960265269320869827710, + 18040473385285586900378723202640495963593962530797220344080340777191012984958, + 39275664807235457103450939776074687460408340433109552545236608964230082437758, + 45010170468168442348096414353924442562300445083918439509650577849987595206785, + 99879829272458403583514272136956716403150130902119831861390384493801483015043, + 35376889736154427903457914694629675374773640299681275927534732356185078510467, + 87403267383558378895382345674614868515698911467377552912077501940526884632199, + 109908987783177734919635133225811271606397029398938708298511253484148973027208, + 17295173665271586512698645247530859200557285101599023956986141259468312403592, + 21496543647128813611837541425310251098581298051727650082921765810637490227593, + 73924679330956858959462999425158452737576816314412552159708766718249552631433, + 53384497678887864522475977345281785491278676926191527209728092457073607815820, + 14370611267386563421622036936506899557654641367326539546895441154821988158355, + 111107545720208053555132620274411952639184732975950045885811881349875589168275, + 63911110056340508982724335631458613598435755978305300013119800762745751222164, + 4991172388731658875474305317575165618935711992108917888386354041964307307423, + 21176876470041110100700684587046880911769841360105649899082567843002481283488, + 74776329531575971143272497818603797944162195101266803339847407068460367192736, + 15972742698609831215845555456389847006456706745673491891035631526317253802660, + 80767473484885926201446229963118832797391190102702298632676421820670824097445, + 77635205730391155379004464305903567091707977567941142496628511694966092103340, + 11406599509413455790469570789130258223474549240858015981787947665751680818610, + 96083529219145290605954079034682972299178843718214603389887111115574190137778, + 104182749557752609588066266373190615208480722850768531026125751278015041103544, + 48631184147785440090049279800185073974284491295936065880067181420459954812348, + 41623436996314670663601629719379360870057342449489798887029141584109168613308, + 86601098079032759868258107257839306539563142953815642076039395625817415854016, + 105563939493052531934014237726522354074579599535236523608564993934980248877506, + 50848326516601423461822147317609300665761371880723719335691811236205966272452, + 53443239328296388634032728319465566355172671311595650926236448987473879053508, + 30110729293997667786865555990487461290947942687167400634833810419675629426629, + 70614983488614829546558717115340990183273642848289705990085731487163494754764, + 89024264216765437369979043502108523385158180365027814309471804683407653556180, + 115548456861997880437700681078370418758203326265657797575702284309135822057942, + 112898553218512376742308538661783506627001284418604607767529974448192381368278, + 109432813267443533585437973840676971983433963567786192632155786340553107824601, + 2662704726986836670271768579907165881708722419900219067428758353742850375642, + 13613520122626383917675800206671181232214326649155827042925689433090213323994, + 83951988661545836264706075188513666042462298465297935608985505609887277022428, + 81975715382817024762173756105467480535625820756145068878263626750270374605021, + 33997601865631325889191208753159898949487673964493425383191044088181413836510, + 33488295268844659105032035017240770147984662735095586450543153485248709891809, + 27897772709719653846193537544497924350188353304930329345920284332030672261091, + 103238249936633036841613509228020446121198544683486725789653177543671611484901, + 15221234255475442610452844759838468002249815991530457101462023560018655644135, + 17374917198965396359597519847766098730144580751652864844888052673202112933099, + 8453689025481713885958764231345740830096722466471336992142774209143222748396, + 87435019133094385353914686858439226234011979874934283937402214350771309380333, + 30093263016783185690488553559991952213412981757409197134146673791181871176688, + 105801262676376315091269117615337342244583356570492008726505273535486858061809, + 42199981988483184642320328432699178004289296046138328468300467526183146227702, + 24808975952702810597769395794187108416393214214233361021554486032419759604217, + 84120069830680241121422959140358303947709189290291804052804239677555153714682, + 57145075288344878951245955904237169364079244068759619386581476461806309049596, + 87037046752894812688116764896029579808521078387282643645990731265108120107518, + 53833716710984099268840341191170265452631444148382059443690844846479300578103, + 60433892667251911178190082663895913801033234243285558434565454351653288706673, + 7637894742751632937036126902481741313410477934705839951387925907797272353418, + 28569702262874571106266993749405212812150257672385615282012173882373397380508, + 107293178132644939554701238383356912595689041895825953526773070844500251747242, + 18692107709494833026133957730323867060831844188841832042897420729557773016764, + 105215836386255858696570193840069945162296319710058502813576963156340050516978, + 109640003434925005994749370852914721031598383660045299893366311313447339993673, + 106102241749728113753317719222455613176545485853188672515226171948431738326324, + 87967514603464604336907917322902677786986284949310789742480895118474916781293, + 10452097529658641654898343046410822952471479992533447520610095024013678943251, + 23998548314685811912152945805085035389917998668934352311929808572528389431896, + 25939865866010035882167964456470371600163942045972853680854911794476690635624, + 53536172862391339437029795049857615030014626954364478815337794278161579085454, + 24964604048144863368823580632207625813548165209250855284071966109033283731090, + 52287877752354792178225670823552022200923488758331256946005040333293056268993, + 96364922991497529805531577328219502400267879296003605669407596718895309312833, + 61165071124090622680837349796264330231271014144745669869678812170302746438904, + 9862529443171077075599421597487817548148389090427391749462809411148822924295, + 75677951243046792472455949187424104363526002297883608938230835512231614460344, + 20163041695099153318595027251967745914329198374871561563937490346110992293826, + 4157835572607732630870554716292314261800050096614393441327328109790858960534, + 234905883427193112047074061162947269770600226722370798297521202217780089105, + 91529499029030045728854142855955178901186723463577650890340040626063925568268, + 53064575229034380164833917313889589009225952735529633244690296853431154256230, + 71892978348861232155473269601937640066130013123066638628775441335656959331296, + 40998639209287247912295936589461636559410311612976640996950055711787143531252, + 74374227204789972278808498765271912946485755525825491620610959018166890338045, + 62451921477571070161755657423071910758989601872448563362100668997102713530293, + 32134737138246725932856372118303955100968116041295195433870841168959896235470, + 14190585998210682942717510078458953206645440166185429761253301462636372114475, + 79474335301119452810238376391469807601074622440831977333649965428730079239176, + 109567049092477471774993763016826103256542113119281030515153187392993745961610, + 71418646896161860312481461467422529279350093001628823852273582513872656562972, + 41392339283265326163133896826928004235033698573178712532596038286942483842323, + 18532945973520998179912609429658373546802263504125602083549893779219578139579, + 23502144262977761670759481544729389592488156074598394643273279227888279825422, + 83046195510510798713138622300841149569770856741428985034371033319940242464301, + 23317281782700035804616836877354302486621457146647933488477033449530725207908, + 40206452017693607115032426904290824747142352947913355465262447954871640645456, + 53163461084033728365981239326186532325844271665541815079115687724016913988956, + 90965467319718316905273128864160965695596596780960242040099814032727903699091, + 24734798197013628509636652015719753306714635092667911866378518743709796261090, + 37433959738761870117015745949755180738344986700115614650383604888597901882339, + 96646475389668069819458453779252760710336863933494930937260323864991302234708, + 63952408163647557708732940735667268573608342775050439763837379155559584330654, + 35844370870822577464809521336934643034645139191512223195918819231967528273209, + 89048024331773490818384593068703118412135203188376388473438110057526922667796, + 78113748600148180492734505349333372472964024933653400767458434453974032635824, + 54173776002260823255859915512510128977943917299469817997380229925381045687010, + 883432050479911142807166205485507168437530802395363642851350109882719118561, + 53485353294057357820057190873528970994022313820577768050270880081771824850957, + 1376947404935534290290878709800598865563628523586336626789091230720889887532, + 54782114845126438876586530210393782366489074178219614384072439562477141776451, + 37861199306489999468439170251565816928427173812130674532522879137489546050394, + 53640132153877617295148818056655406698667002755494762787727014438853749152110, + 36094520090494132568726788901733125729887512412738145324559488327331435071209, + 47708537139701186414364911096104061211191086914223449210282658811429201866114, + 44642009019249741536518128251511543839799104615312192651332257099676514463852, + 87290192662809247283905546878108315691917779968148474260664182424127696884795, + 97671292518018682890893268494597883645013579196143231920993066499185701120805, + 13691409391483500819401386629732148379513193717278663452790161368555897957557, + 61144617532654697585779294384326603485860537145081158448917611664126233388396, + 68193985570254974036684107457627664520913551894845023070425351866316352884045, + 35186058029995664124689643983995007874332255773767997499577488346513719121213, + 115257539531614541222503830830159607117913671948645429228004653119055141552616, + 74108023471371767946328733814543864504216020164356715756271718337888099957251, + 50699915395557109958628796848153707137790179197796094586999504919502748430036, + 77098747316761893952761000882437066900927643357092640800471523098528858444741, + 44196706823041307166630159413528024217064296070484564708314234712750074312552, + 54311600462392327021859357736603954008201712037004116839763570346563191882613, + 4712645262686969075341091045084853692873346753675156591723064046102802703035, + 52633358246598132500454344861267240274924230486539615588687078210860399265530, + 38428397862610980636995024113151064406919418462458968489360301281168699108774, + 65770083666590557138121223737091159168021553714387718826049997301601143959193, + 108783332248779216345938909800809951905550875303335887996223250993612985109020, + 67541554565935595782234506279937914447172413779479709071277571759315214810553, + 45528057480829729537027883221412675091168280876932366391030724386747243695450, + 48574723508575577074482350565172348685996516743512538163088285343250059087877, + 9595676212719659333705612367115264818901075522839724031540792598785517533717, + 59222796090174566623152004867125933154676846013253132266547265719068942874438, + 28479106166280290479941097145545460264531379215822491299649689124114882347783, + 115221963463389482008089037619913365807148966626978913613183808690538393935135, + 101487675421171222328197615408486453515275049269610846629698626471597817468619, + 11861229503001181872799219422814386750646316223301525603925541253591330339851, + 96655017127890694119104679709472928946428042193874408633126399252134207784565, + 11246562242800184036344964010942066327949582707661185521174872759601179948207, + 54766903279946870433142580654753133656570753651046881012055208086423906484859, + 12192385043177507341587627086564649875670041135249486182299191259186947947309, + 33889531687457105202492185235855624065169098231120588348582196414732626535731, + 2702104856154794760471215991723866354322572371902534169880991721008960334465, + 68399366990142009038460674908987124974500851011439562754022428310012312459736, + 78108361281240995542833859700117440464383194760701784594883633821430667130670, + 20035281797630887972432431961122297110119895828130977481522636878664781657816, + 13736069344130597091646675811814843306462843438451714675670050863189721631975, + 32797729242950926186099069834265616197055885262156260473288373265286966785666, + 7176087548488327762842449594330860235875811675839995669904883805237403372677, + 113919392582812074400730572616241013136099488419784443992170205486316725802184, + 6715092456584007985435621264275230946247108351204840102696310162955301713392, + 25855087501533639303583124882822163677359861627083537912598182866705764685815, + 73934603666361975032570131227835167994759894693957111126295581402147687386059, + 13155636084969680059396242142814026699440156979544128067323264470699500335748, + 42306337368511321037651705965062931061532427873546337575440482816973756453706, + 43179078116044711766386466429804449951992950924570899179710697254606382745875, + 34589225484126804958636126788397727945345620051478889688357109997109890005014, + 81931093869411066216897619171196290190324526017703113902729211983823973198308, + 100801062496088586609073355121887698810253404134289205529785971351082004400626, + 99269301541754630549915461021109784052069747562594797681818988947004492282033, + 61431623606091659417184920719838855026021341187124428079635438195442467589773, + 9519969107896444550582618655543816405745746174812287787612255552324868264143, + 108303744709536731848858243495069052456568556669038315047210235861188168386162, + 17605988239301767548253595490806242996920114264054495381453921195513354999860, + 23513923262061982218339986786461381461131246534613851254442803506567387541335, + 70320038567705804654621831197499164818764202927326234150367518419292464747401, + 61770709396189132856751404198972986135331105234997307478609738138959714680310, + 111407271105634327977613271210808817656742352508264185802621981796146688951099, + 15954738196663214636264590882028009749755310783326530535915292337735383603085, + 109086491948127246516313897338785542867893034038519662369776732342690211551400, + 22416782135059375987641999873907617075278492784876893764069641551099207960272, + 107190810929285648335320627529686263179826994927201194238265606988725047028872, + 47810903731926258316473414112936857581544784502116140622649113458343351162853, + 14454090390604916607961786668722881948090859391738149034831583240117470604831, + 80666783391091672187446797184315344472571236464839098416522221749649677801945, + 23585443718157415684307873337161851844207024662853153813554868062732814732990, + 27775727080975118707880751458940094087572807407477642227664452738359631508370, + 22354007203029985550445000393366637942734285325695079942493657830869029668598, + 24464348418592982883315752347111913022278560091043014074779583772448662366752, + 106481239012883339270648085769617156311063292444742859382987025194184948418926, + 39011227711841896540196435699763946582967257133741224577226414069292244419921, + 75596650937734374746478074849258927780055535729028164467001982844458079870248, + 88162372027313872123663368261082673963273796229751284714193546223272846212213, + 2576040472443446723468928690754824660481396613576535456145099796125956902445, + 95649859930869763777362274239913473448995731775502386044062500006671888513755, + 23725060470714314999599710406296489493250175197054609214912167919579998507169, + 49555424134665943820304057631658137318054740093228750126361525347694586145134, + 44501457404504533569101232018780451136332705470598006749312845628972786270466, + 100795118997594249476658996026745105980251851253722641580769711477747550208479, + 52747201652346084586405369953639735566684715221741890642605754187445529566660, + 15680619346733759700182666282587216548584469338339459683294440044467091673631, + 68505014731494649040515369252814152095031304372285998550214915975944235191441, + 56366185904135320986610028835710099815916974781671600220135407206376964487938, + 105321308694088112597872430790563332351422354737991856346326629773665525386705, + 61278886852279108332938535370025837653652736250991006419628139504400281796611, + 28953313899949437588722414376475346673461869492846759563387769216822610712214, + 28663118357329139790106382764693217907262920349622948757012124192236390817438, + 21039077739131275359790923848462140922244215451512024187049160113337117620791, + 54889718246598634522108317610961305620004833993443435630553026048923012178008, + 90874603760301401413929288679885214040045826428675227957098967087132935830117, + 112920631033471745311323794101261642576610674750854945256558164996387712631992, + 111963032704632250385492393582328571618828927494502871768426528581215908256143, + 51274066318211493418085421333723782799031831706515873891234805824063678178014, + 30258011402192701880534182314866634113801183941256349214452534369042216349987, + 54681898988358136071780093135450779338110800786503156323504807233876629268293, + 52116004686547134015512079196737968242196127056558021115790624820932553017441, + 109513064700864368200790843893897908604544097571420991817771435722981765661285, + 58488394191083420053831021890307144018799701571894914444409455704836690297967, + 62092454581727457732790593578509538844015144815933957266786304773060873782649, + 14368297750194560111165577701486485277892655455414407596509400442670064486023, + 67269488270555162552654401829506802539249729946556386383844397948411601017492, + 88377116761526687308883019385729653416563320981418855150352008673734620992416, + 53028559510875446303088848877733416279134739545287887275996211473197952858536, + 18170944619136371204284994471814938841783677453339517631096364967572114396852, + 2059644653191624483771262513065435276723804841147324755869599281586451784121, + 67005151150252609617525866625502990805012970844697359601920455075585694928057, + 108445302124264084923797508969188019268300509993700767586409058734506501816026, + 31825975368442157656648045088070797333742837391042415004089769634419342157546, + 92373133245786521768072671120807298020874152547973833174760183943173402771443, + 20288281055571831952965968033892228523356643855585483236574844945395093559189, + 105647291748962183726252681179938945648788659297315616260960540621695497879605, + 37833694536671453212494333478156156499705175090441264557352190244699875139348, + 102602930401694946546947058823975116987885575233548964388547148483039393577630, + 17986089761536074808296642067282970280697535186488892744151942385581010099201, + 68302507041169065371244854845092650671048888830947577079872550921188098246733, + 103723227189535347897681598138697061790401969590975977817284610334967586624371, + 85601933490467107005659057944158927790168058335522482015593505983064091002688, + 72566572839803178961075260801968244942124210943021330655184096386449590375522, + 35059921056683300948407515200145646684406772201818796747803118929279743459461, + 110175048830391929923807192301406443121803247399292272801332112057564703231241, + 89882285710142524187416311971836674082740664835810560379381270807979647760647, + 70399401443372985077677851434886144983714060812456753675306983539671260338480, + 94184317541206020457753610078145103270501645532598184588800128385125278401946, + 104314965088674766481912048088686697905047754561911560292135031019128925521909, + 16759208768307130872010233216200768925859942429678535169150770158493348620840, + 13312049214029984094125277617043550651736083619871827277320968871324596984413, + 57772980362021788072324853329424041285142553464137832050079118990473332575549, + 69375733674087675844485774733379151295737062349294143700229381969561369710274, + 74182466324362383312773623566448418316679680460167345042228292669832757876448, + 102551475084433340433597725405003482858429650260736516785950146965463760130080, + 87871859628381700091124119902940792161691323803993634475404190944633451471207, + 2271931461440553944924676609864205915472545722242321043389109755049110980703, + 79159816565443796059736871395004807034524018072484301692430191707423760150320, + 29883226291024495072614404351628092395902350071825263946645968892560207990766, + 115120985130692563114301206512024055186792485071581230311061507127951583633034, + 65575467306404035265299368906717521523933770838335685501468397360739564342250, + 42205652281356366407511084862172573538584011195306289505538491848403141436696, + 80956675972222351626548870352985655925726199776618815554949057515111559885624, + 106838054064585501497489884559010507476859749974884867124569682177542395636357, + 58508613315380006091312439893090755459648238433588983488046836958077836737962, + 56148822318227387858840396109889610931297126924790256588515075449476241527368, + 87943746830857581847154346372383846697749344328106573109857573515682121822367, + 96523912520065820718774993637097552798296898412284402472198573038137304590111, + 359683682346866350672530414988029153152780243662150094655719975922703921067, + 20653639768030400341518830556816476408986031232568656102751458314632334992472, + 43741907665130124851875589584874693089547759382726615954038820251232049326509, + 37602134064186142569024483775410247813923563006964949437626361768237954885625, + 28319089020767397392393687573389812686784796486679445318554621348732771061676, + 77246899118638359174675247864166883750187313215548163645424934342464850069490, + 51416646531409586193575382020640831077354780179380885705693619583419896628285, + 9530718880612395598296191543657574992246299996911703966657028659200776742208, + 60075035395757026542736716551158662576872365983788226206193619250298945833195, + 100042375575081934061659861835216643653798304415561784355714218575018603177373, + 65280708434371170784603853111027779811634446129501474686503326478617370733569, + 36082491953381980967358850906638601152925053882808553201819544090274971464190, + 55038301814136661088634961160554105058230388568456004416928702345321148540302, + 81148342511575768823385245247395685982245196252288670733274133346415300143012, + 62080887902672390781432753313761551609714174003612865233793627417270483286982, + 90578703271753009632879728735384597245850512229571538778074284994607743071518, + 11920275443785083579547863592574994475431467374061276954952200960834359779284, + 7901870192306432837816630504620172895333432875298603507830571901927621351928, + 64620902328386916608189819363308224701333637778025950310007247161243381930720, + 14902225266028720042380084120086803828537629249534266721931268127595544410505, + 3011605234853758422230399637839989432595388927734475258720799035294793988797, + 62520715887062371683474293194758668293503352226300290954191460249653358455165, + 109449423401707713638949069954372475340901757609906893414045046366250410887842, + 65974474648235806363505863545271426056265018043065296667037687570697194645520, + 78525856195119157844801092033893631866360334827506128936210376962749108345401, + 70525687758401237580803794876205413841795807333861929519952792049645580777583, + 97952100411220391333417229298712459908053373138048531526005534270083998312321, + 69482302697726023028500675325521804008063245604738851814471767661199529941929, + 36996168631023473249056962961772045554540227552693956887219738140514501713089, + 93939398376370462515305712120711503754068326322098998720488107315540935981941, + 92811710090398157690207572646387238821209630261125711411677156614949689675192, + 18834793150066231989363619595201423057509694963201888288496365825037060604758, + 106508534598402557052256441317317198663098123351872314746403469913152131748542, + 68522515409348199421798410175290099384706005335340883038949614431817306224878, + 62056677592132596903749111258191415116948937518303008459322737884771944599453, + 75008671987138723041813528774734130483329012087779153368244930953066728755167, + 25846618857014646943662784856228290889267917537184350552103409496789701481086, + 25790780303502933878708389860107244416128741360072781451027326248893088259707, + 86875321517220196586131106365815943863232969130696292969809460985631264761642, + 99520552726149464340676459841037055051665646298827646711852273930103091648025, + 28302633324103476432059489855553140037931375716779079709591381558250668123793, + 16413483725800636879585566339979225218650831073900754551215329181184498261405, + 5834089563252237195293366572204070003116504012683549677285781788725993972990, + 35905663211833345298444865971856108258053566719588841426933466057767703473670, + 42906799631117753263723316951849157590527745414511096962646744155280717111546, + 113670886560446927486126023588018623266901616824365249620085243678045044523580, + 25525758440992399567030267413743803341303454964963442669812892814158222062282, + 104441409846129220251060822845729677685228867748033158812417230194198574238533, + 106926133638744077158340790093952487284445071012880267650762665555269754374498, + 37777827102888811508047114457204124487000904404039738423689478126649282839504, + 51858935644246862204293187403674270409729920230211975583979198407701235735521, + 56677604980298282251218999943872661748831571233436439285726091418251163563349, + 11310141567806595553122776509434966668730767143112763614244324266096150340396, + 59568236466598403304367610877197823731593346955230100312347937134124139658515, + 332686942346604243797197324078593908184771416824239020666066869442498248085, + 101184157155811626748420360485115445073052410011352426753492759316284346161562, + 115094616142259749323636183065876615795354632139540977617593311052542877457287, + 66300571744633578417215135324779936328456592743715185456673735987112942424605, + 48613583719208218896022351529040027028353166267451589591626141321431999840359, + 45070517798055973346480716269485737939145848218807134819900436803766392242105, + 18266861866071039658603879196433265099201917997393304488121681245291543324416, + 52949442752612150788933147633704799723834836139570886640702983283974722895359, + 106873847237792435016827377973268501512512482320890214232588930141196288884343, + 15569634565317975671895423006707547283207063591263118835559221760770692076397, + 90410110389444957150115334781777775354854962401059551674224262867875151944330, + 98759087287127560374112096364011567243755138613650190558293039088068825947972, + 1287633407928248584990208256896924805269922037761331075659055166636156115579, + 22643922918408084792057622355331184265168520123778802808674980998986152545614, + 102677598412504156466181238289651366875920363577612196890121675411616205869266, + 19140515938422692005504349297136392120094231942932381661045006694294659348157, + 47479392819189321863253918556058608916166486549752862534298736674771025808601, + 13428886889019792224212350792850118124090630647372479978118330056662258502463, + 68571236458166791056101358438734290027379299621943855185416588699972634133780, + 4633337738236570848343873069653422967090076837450676791156853186692050402794, + 32382211421012107606460976657528067674979613660057986786543262682245644259590, + 49639024571546822434524105347091704925075399249527661103359511686788829885196, + 79150125805409043239175151923323021000363071231306074866016474509777361482770, + 46020124799831855390812128987233512854385899496185315940524095352093195890971, + 42200218224318860824812897583916208482127750284199576543492190147676370417951, + 64700565615105284242392888668153133511395198324059560256734863083190822363501, + 59145319234225054834945074280096748257562105951751962357531680354887635001400, + 109370459247823410861206598303258770585360943296040735774085402452631141651780, + 99481385472715246129926858424348527055022021148459424355992992054695772159341, + 106443499252933322798773565879555301129880638649751583766224653285758031752820, + 48322095229054470062821743113612945636849765668600709958419576797966085161570, + 33515809494782069567661160659390787788200157314799375723046535826284168620654, + 41773109623016210625345820625587661213509285213374502863725211353920331959319, + 32596302442968981956571340635208447066531220945981080109400249909883451742829, + 50293273819739386025452529051468445849720809167855795456149610014885010486032, + 6910633429019905036432475110661116328818994641038989881657155395188306704390, + 36739677912617989818047420712503342474631017220638134413720724315512974000159, + 3964263570883415651111729390801978904288959584848347710021696283687789159623, + 76838244100886277189026448893466799361279981208788651739691518178972257722132, + 92524917854272347189223844521544945952894951731953465698994423607211481407873, + 1094849487752948258678172481737220834950670442465200017592137082345698226431, + 3596236676932905175558069277075687614251277541835254759691559615596064312685, + 56005578839865927004448053246743798933430710945010825095181046140154895131866, + 1314127155138080693497666074353154060396713254293604808680984177855232304261, + 36079022347925238197361912803669504456936416755264778056013696625210364374000, + 79928239193218591378736729828916925283195818566702883627512029456337551009455, + 87280873763535086276579332440354325979085979245763538853389996108825086763328, + 79088598451415009995545325883504732536821464222073838688397002320856965960467, + 29529206497868610658911692751520344135841581721873597197167956508451037256464, + 68962738620795461680733506696324122017627315086893424184557692404464821111592, + 93572497740197828471049179646299056635884123543357390488670201160087939843899, + 109112927198443847769716053669067351023083576209487571197569706896608310925118, + 78320138979699033593001420093104880827612562754837671875766294555309495104202, + 95892698234673850732008345163508421145472860369307879265917900554439055906261, + 52508743067911278204516869676571318573056040990507652640289868030751665490151, + 56994997415220046511429900048521489214694637343423249626411942011111939288506, + 71574140278649739406151462243925929626255276234777571372081177974273056292218, + 57977933207626507502343730286904755443422417664609976290856101067259261389718, + 30725858941570916315616848092815937606144309685272835634213112076952585877767, + 110473526277817823493675607940407425195035436651994426913113113990131038771594, + 105339752952469208380404795676091420067960822602777471440244189030880744525350, + 60412306346911354225557884409801026607941275825059578233151896523412434667888, + 64762896208805433524854274168206836106667758808610346128969223715455926942062, + 114121970583461064873502887345233051121046760719381233728555193955719803766740, + 22466369798521351869094158272110843558129416676735676800948475727909144865782, + 1273143111631474652637353240638822545534481239484935749829192671246967606089, + 39377944484720355113556279550540837896684650949388624339305746596010745626909, + 63079304104722256955147865058876316182244124456443107773876720891861784821084, + 33221257928046204557801831132902516455160914036846369006425441924291607025375, + 80679899250014086830309864555340554281732747123983833428628620753799828044171, + 5520825008571730037184139397180716999457189530901529770850492308003578875767, + 59694340447804748768906699434149795298842348528160974268732147404640124393210, + 452563556894037949847124302231763919722502556228150568682921788421243334751, + 83854452012839253111626789157033805803261637170087741884414752071471826558651, + 283272991722506593509965059184081095348010472560457003520196925295875056666, + 59350272485483507974402333665923264559817712090262181583567887818422454308664, + 16338840576891551738619490263301906938135318609839255904209395903360130014526, + 46887472068834101766737497605695900287149077542777324401279045289085727998308, + 27174317468173438847162307838360842277547238744619453235356053140862073414260, + 112575472680252768107064569686641717727552530114258489447701964544612039691469, + 43063725488321823412272058651233665663191029952662442943522280495342602080041, + 90830677820996662813354986968787850850731704888547154385037797274293046703638, + 70047206624525168690255326916881812569905906194673856593528183032623465434742, + 71932800557222775253672430273153491950688623401220405561142140951028444404099, + 3524882399256427360585197251246913676161052633148576017242006325063275126755, + 84915443337732578818997000978842662417557339117578770822366157872988174094364, + 102232608410210054811388604493718844283297081753473792064431359920776022339902, + 11882496039470984872154583878418111610653426303980401438591456011459127971244, + 27070654687706280950633862831653465867665464018299863662869902069164060373468, + 59282461672939092456574734414184106943172040535313215840942116814265767233014, + 39322449749557599925777702791134894551704245880064456282757223026426700817213, + 84409894515543743365133360610171100432700100978076876962858654568459632558541, + 70410397268065594155629455621579409449732600786692188366223472666803032234736, + 86437295053666828368055440450007075213754895898533783771617866512671397744683, + 86384600756600571727069592190350822580086961094261465255184942610917254056508, + 4169531244596552262243178471088999423056390095652168598109446883464017011602, + 86603605855539825936467660126213888629382588181317117671233455664505351619526, + 25878096712841480688730079454202227773191841010361550139385684121332714629463, + 99813837622569325637706593871916293083064808065063361750746121189938957277689, + 14956623686382273272615490920074162785270993021184365086380120813298528059035, + 93908520539656727693859962706714600909136420168083833827053820488142240463583, + 83081019211385062731225376037722543708554737255330978950713306087481031283567, + 36815584092143113621447019134638924615387138159781448150874431541732703251995, + 27767427697076154124730046958859599439717449798059676397788989550469671949780, + 53600549360476208788118667076969768573563511569083599363977385485736870317987, + 40069546660661468479507161040144333240272420504696612481157064445735524256694, + 64349920087048287004064232121909162159550862928450387719558872044596012144788, + 25013984982049649107171523463463889703338165256520376243160360152675368481526, + 56530789998533237811002520653364573824966959264503360163423839174743884244110, + 89406926438927534192610084006478320830683811663693612304775430631620411804801, + 55574766621966719960163780039456412444050688884284171043913720122255495107796, + 33020279523875150194000155658408234335900802700471563888608219712097607743977, + 39498198091413081719576717245537304877776071588314076270987466307013267227910, + 70681075792817924907613405300595003622717961584972201658078688437473039265438, + 48951085699919588601707434724938021996754135624356894480749596446244429933265, + 46076452959520639654741492991168821701045167530336503508712707346240564741218, + 8728181522716895277616722691463990661112351314732695827427219145365995323248, + 19242851635027303632228665680918645839152069598195025604323474183363371673284, + 25966598671941504091044550838540299535978523911690095545251052079003170032500, + 71133170285960273109650294555239514035629927341569053089582833944222072014831, + 30435235918882008095386416250838409184026844557375343024273010676275207110067, + 104562805601059808628406233133505378432310209782968933305541489051827992880492, + 91277304545170701366302646927851740938169501660880043983344902890228057721474, + 72968288915422114488753941134393719877980024150813811771584482481396265125949, + 50190389952851782334476549812324728201959717776585754131252432379408670884706, + 53714686822709417243703749183305098173984141991560038668837805048340367561590, + 13019991109569669604370656032243178191139406686858546771510153010511250838270, + 67191821789817756119878795240970869267796221550236335817460044506254776968216, + 89413994372950940556769387668380627891258272606614021693905340703246441021190, + 3238798850498286807700621225209517329350934282288143100877405970636083894028, + 40280480816202472888365258789002776543316182588753634995486654906107679474981, + 100948637697121602892593946642196415807276046745009059316006093188332302195851, + 59549093972846780800207597390208066964914903435241152123606789627760509502894, + 56236214012501625186577071933242555430237150566129745066454391719068199835078, + 15312458892596540523573781893452331775717723839950029000658676210347347105776, + 15065967432271076782208794251450447638704140909495321523677229697077825888248, + 81462686679992445078195460793727301193796564055826032266815725029072364753429, + 31004446882658229570973377729390630349014033711496954983225868580115438114327, + 60881893889918255607808992891845327895300679183604457662116021281288533703990, + 97792511094095955002259897688952303128451022225469644595824040325459774067007, + 85913628620745056720111254267901487607688940204230673170586457241362558878343, + 93647134651574147110255208072279336751625499609376994365444326737671287302291, + 95297138551582102493747902466790249344233763330665546307118323022618048561591, + 108463575541952340309096840275345034615524455193912269881763882512567995129048, + 63752885008263504388047741845098568103563297786649728967903987339414173639912, + 51652681214709060534046883217927679865702663716840951262115852661229709210049, + 25666020547072989328764514449251093742665833312099176399036564710247119178076, + 105269705630708453158082837912213449941815841741276439302485601620747579775816, + 65617932013055493829408883154321843518026745982706002591323727944029169432460, + 94643632652344258820199676940750707745466458768098493560902616544464843965760, + 49809197967029981470578121511861493072658984885955900534570018643169459879500, + 102662538334700555252622216842908651775931234046909341778615018802143214957476, + 113970501048318453425661260937695608103427766826948186238861232440963627235790, + 97357434013974794220454749439782687637175698528098099543305920220485529874907, + 103359508964986835222997521952836123858692215225816927552645056779369173307125, + 104648991169616025859256185054957149293934618168732324711445261097281286483384, + 29389896106165793254800955426429904448077276420102833967961101728159111496532, + 17397917556551293611662477830858792324055081846212709299057150741059732651921, + 50788640561521879066172340254498727900679747579755154172014511851379974458947, + 43965205532676500510494796343253490918535053747950216680447581669069174426591, + 100561339115325893421374415912582953869602487255513883614209616721298762293250, + 66562569251191910581855009906754258851096490437585719106689692764515165118239, + 67070916062081221710677371810255878781339891113828513253753023678578232819493, + 52415447518906441393794278066188435528329456347676300491553094758338552659004, + 17009851482897642242445115289124882968359106779691578713402357833717216053836, + 61968470418522694182319110141621058714670097444452023370385834134761702338776, + 27439043782857531293775514029155149364935936471052539789861552445308867719563, + 30218119149287409542698267261174862353671414654735376656319890010900661088921, + 83722683198541680548895201973968476637707037053891833391243959378912592800774, + 19652496154790936363470942073050420903905231179229766615335909262494502477191, + 23969602441427232334456125239419063180005947434249931440170057765321521250792, + 90618151362150405843626387583735913551480244697966345084341144901688604590826, + 27676891003614533451066859478651393460424961724309167669813674464058417433664, + 48885749436680584753253699027466567472476019950871823824817684140175042353781, + 13267791426425915825084467964002602513349413057053642731529682261674822047612, + 100956069784946398219932550061775672758363289794138417517773642672184160729734, + 40333404357937385101624655022577772019936956721874332897672372735097268448719, + 112458551997636897766716155683532996884022983846949842366437224888526599748808, + 23316998467946250104913668497817687100083031851500104547322812301787623570579, + 114394200509243537380938016740401885361078260317260020773041307235661790091892, + 99719653520966822770708772752147805183461502263709831815266009451647654614292, + 80463081199638265711615126414788957383015583042168341270906917065212011993945, + 50926914333690872697842264658756713296670371241774121393831877283526588419443, + 100062544342282326069874559551624201016023530655383269001194311119868943621261, + 68068020862521353358271257272528432308814754476130540913318084327101476116934, + 89713823805042130782951935424222440168641332400199911482603719331288815293140, + 86663612340636044221653557765291814987022783456558531881892865420940708049900, + 97012438822187244992111487410059814894762267734855323936613215189062559355135, + 115456008377472687851341171402794820555293289595636141868079756635653218048019, + 81637305032596027004552048722644010360182923840044995348167774103369285666664, + 97121760667459148346469656712964477195431899223427151445530984851020542596352, + 6578517421505427291741521771648219090909965045148358527570559142102824534423, + 23086743857819326290801520016575031684614920494950123918961905329612171231094, + 23628162222808960592749692098872758091298189792059288171046583885877037641335, + 101388589635381044996545324324358828419653240720043387756210449566569798752243, + 19620842733350906207666446984047918346475081206033132332574377900120947277685, + 58850961459606306328454345527935376781678482106551478360041198414567673137778, + 43698525283886526392550172261457716557843922626739855384146946891975974274489, + 33442616784854796480120127349523708269380041829170238927409871884711003926345, + 31440958616586333198744531091618349581229397477920961786477030476125699377203, + 44037228979451760962709036660497370545619138069963535388089488696166164155925, + 23590773350114689007036710853590152873533078071389046302374175660283306490466, + 18131169300372102223943835158584186528386930775158492999096691428947406557415, + 39927655185828305299260927622503627720853145613611115731691007206417703553425, + 11424009611604260676731914046838190987741247394671748550647759787863888855045, + 106023534126028046641732471111988021743803815895465330462725283504186924886296, + 68648138318007149508312965301811805457613385583647580389322272105745929897884, + 35861285852404043153958153302267356973075068570728747603030615815307744210613, + 106692958162079488264120234780830351073717987694440147487544240096771860117721, + 35352165220882402184782264824036691776623462733023306250733408557343340031618, + 14822282545311489372618874096495046863376384328360624764062544361258616982209, + 90058495310599262422511117754339705110389948235968347407889592750909695010887, + 21259014153908036079063449386092480951127340321580415067545014550208450347867, + 49578982519822747108721142362544198831986643922392137320722032016810156482162, + 65665457104798265380017369229106214332204544903481853344404382438501436156569, + 46018977419201235627988083346481532946551841328607691952313437865601296427242, + 113416128614229392197633061170738475687415527961785321345301343863175386165517, + 72463005488702624466473135908636810035589105683486970959068404622715441569172, + 59228871780580991287064899135413738163280222266776423016341942379142878232367, + 101201352577621865867741734209721921320372326316364435635877898695764520096810, + 66116563724113303807752208614578289149445196066311339830443507231280061604629, + 13321204435294557952842567742569975996115680491875120393306454427480274484373, + 36529495391678241787355855199218483020906667770134006834459752188063285439610, + 35393105095199709649781810185938664796603926906726475046005623027995804964106, + 113361361018964027876841710235293117483566240411336430409058248094509057834062, + 56058022706730182635086646281026455259878455394424198569146889542596113129821, + 66753929570993866861390801432055977675383761839911477726742625804552736120589, + 74152311818771099103314467028135724751017489427625904392334704355210509580327, + 31198424329271660749070167123360180921447024387653094853673347433987050304147, + 22161946701832864123687613890591146417821146631382982059389586208424000204466, + 94967039535410902433511564054776055297924708482731388778074270625836429181955, + 101475833650921340211888028594926417400342939939712197963470191975265029710193, + 79962135740629681563625093810301473611526352358650698543209321831966059946624, + 56272682759487817327630201911621468568787831319876560851355108886611853690280, + 16207947677319863057883738635880375181098797652544932176091223066346375051490, + 12460144515649247367915525233698250971185931821776303597267414038731840286158, + 51054786755897257128286507633905426324682484384053936277176197456512130390304, + 10703878109914147630505465569165181194027864988338264878868171200825538401849, + 115685353756232495339217522336126365180680521522774025001885108695820705688417, + 83226966733874965537402061370252269001515863926279260739350326649028536299415, + 77938744096446474082267536742558675453940850900461721849890994416621104090335, + 10633870472986141781476912229206066131123339936733321854914824362473808144140, + 113510575592024639046669896504932402330073924767594979636394504576918529901216, + 28379840589037358195922115459139921091333875451323683305010087241069639779529, + 68908866292479473675358078430426242309570647071553534729550787498549388810019, + 85064447307132871909177013858601355916860955316576015102216104307635029791583, + 77186435129631197486790630771123285886766192713169155391189231991556959095716, + 60414018856458490333814081994581651087732522729798276054216916727420669351085, + 15212960114472650545070192717970430908214794269081770422708773881411744953726, + 91224252022784031862609153680374804011878245543758948021324002141712805960126, + 32852025867914048360009115451838876000739199003298617884603266303681339764885, + 90430620054982219798453934435971461264346611664955594662891046662935943479733, + 13338386818121995340931685371910002793929630655642421076019735160380543781323, + 40653500667926695898384831471872360638429317201349831757934492645361540497806, + 67321568092347244312715622868186600495817055327877174732272932813970025865221, + 70715000708627427291622464491836570367362782168418821476624235419363483259945, + 84043980417318042435355782997773720153113022161240961471727136125668369238963, + 29798594605740778420056358126875423873995928394755977101680155850123119250391, + 64002739827413206738226844763112689896661441411156309137061786336417769703477, + 3588603057028759016516615905510790682984328594608376145047909364187513464636, + 3640113849242551147598436231961262195794557060841458006515147063563330050926, + 1640132195779173611440482231813667282421653121121602402434590945825472442840, + 49068472178525986111154992744775813894727777720616888679062692031878337421358, + 96192283625043345803403853295797930138631783468065211663912714475454912223870, + 6954971225007597775332578994474487107224665847376481897752901005026393306331, + 97393736206168610177884752596730102881738900341429244953817508235326571383796, + 94909591388534814899291820790552061136385772226849013926462603889535592881658, + 97674360923933849538463126507677339914984305763250246342376050684551898242883, + 32326926938638905804883899181301661258230876915152258405205012996608416781550, + 75390581215090777419512899469184817486741500441160386876671097045280744103963, + 28804629663351536283608294940890058716535755608630490430113412747955228667658, + 60447958849385594887539070469446902724535183262968852417615873607098806913852, + 8125208983647045861984897883686502701322221318693649876878694074186762628187, + 36321868365872483629445089690287082140134307447167490214574356871622219403958, + 57709458796817421581094858125640847564231293595234253030255350196483238510592, + 91095279696055361262251522830528584660460437046515798029216072868459979120103, + 44532164232708863754616743805204681846712941356107405206330557447816291011231, + 82208417295733503059286375823323713635312814599695203151770014470900456987599, + 53218356925724630008953848654076130625327239502715186839430988002470436174754, + 103554102753645173083230160287208141011684313770251269836708493649081752862464, + 72287395332613701308297970061776214857593209467851071250674303651221966830038, + 112865201218690365602584250859438997853312303007342038664127484151947604421851, + 41291838747727535371059951015751018368504265132868457130021365214694571571467, + 92321496241942947597791657750257580964557018699552530794530263121140397570216, + 37515108533270448750288663012299557149226500210493523635452776907623328856429, + 37214105745309188663227709885588423990475595550200641028725694288049442381499, + 66026046826623319583285558889237767047321089955197672372001047479175205896446, + 86009085237117764324645317760115874450966674584814179702294705584255233604565, + 33185045770056932059592647392427809676918726541992147755240707155667223682899, + 46023623848314803736144086547851606591564509262002830448897260077561784218820, + 42523124325040682188734262163872238263680769760068502922583738355277833409027, + 43707136259254660167975670736625147170919263966206567519289343836142728631399, + 21521825441002412494075821461882476872411719294243082231960424810761025191406, + 48122500507820495999476353174639285803696600339217273502305348939825292700219, + 49878520275844083983319755300791139094738827955932471155805551241054438329047, + 2805019867980114693815396887224782179488381114608760082927920707778360709391, + 105889067420694513962034831440622840599026391402123723795085189461218881974289, + 102558012501655260354950544752269559998052103195524742467138368293898237029032, + 16045802253454647592499420910737935432914631479977716060114384687065678301780, + 80694383907286799753016956692597880457418319936546114189777042852889181009843, + 45850888441967478025176403282980379370302486077816358544941791347388762431349, + 9822479882591964996717128488720209197592583016104263091855355188495072624739, + 41490103892755957014843857901396132258425254981457143869266365008399083279040, + 34519981273367805712892296713884551032214931453997316756563875546090058443001, + 2204281960270913078934060534754054590010912521750041700731012295673872332773, + 92879205321717292296810987177742604902961904529684091274391960440163557121327, + 41403519020039174258858740326538709320397612146458889978862506507151277422131, + 111947766000272845386624725317499390083375963268740317913926980175304352248010, + 44798112599245343572207281516281531139050763947036736697165944844889144497323, + 102928340995534633866971381779815005780491954768232728403102468494951518351494, + 66337378476294102778291887843438742910413779900212622781148464034568280254968, + 56039934765763148611871383231487354654011870687696514609659661607478831015720, + 7243934517681747968364197778847060066342821260703071558226452908378440385078, + 43364489650928129730233785795919833617213540527726447567395441755408708398916, + 16933912852581238794524291841725428888822250244726609065961340398924870949717, + 54768614708066909525315386122663122276375311305049103019748441649763658994275, + 84729924206104494740489514335112458905233956780655780501973210222476988806778, + 29277322938893302888357826868792039003063313376342436323759513526491001984139, + 33678771073152611527552742313583324855195425614537548275601462267609589426650, + 40480447890208441323168952362583473949174442538879435603137691975180301383746, + 65210427913223998114073591571054279597918449996368085666409957302627619255436, + 111284762645559333229566598767525655137451767251557700547569492602611598002069, + 50665611021509129153232399523138139121727712951188291590955745185443078240605, + 86931224979232700964367085464905271967542987118370864162794587044708482189147, + 92693707272386441235566687750404882227556963036584756954337957832491130977997, + 70894179854964118329416027715184058487050172319260701857034205839242947658113, + 20513835149287058783883311526714694783960711471827520770677981391121169168188, + 37103649878375472784485755998128283116660545800082210023430808909026154302526, + 74614844021522220679243984385072619161892523493843700560224775866754791981920, + 97311144748272583637604206920752738211872018258123062151560689856785735825863, + 97282949503352293360803097343846237726987612672755574861990237772557028505976, + 59608183641235251570641614121211116914759763966651068525325858377448039839390, + 41425581102453324286811424366295817652848042620102193704137772391802937357490, + 91727177117026636081336266391338970810553560215502305083610747696747683685793, + 68439194926538401577683867233319787531164608915005784342794051150521461201527, + 26655576452391615777326024672685686800005203134710901209242934284945454570702, + 31143473283240774865431214789334098152628855471357068527866219002194338185533, + 43767943504780320684924240111007984914196536241705792566933468927031866775345, + 11283889953365847458363049262619110738826915372417900452192942436343871320790, + 974565422135080726870643057160743950307503695746121908539734697315502472220, + 94062505243292442540029663203966839941224750263267455031867783142742670480440, + 78569047934219441892890028502182108887887232992809410286724319457974676246343, + 20570672053778381542185367122111196326110468346235368248193378711812323865668, + 35891241806860952479960032306262991307022140205471781583482653582223995413261, + 35151043765988565325231303273718710458180489642575355611039393162107912168489, + 13516481613278628333357957526837653942837798816895627584645924375527859723467, + 34469930884670250090266784851545679585931608749135259869539338790142549281813, + 39226231188171088174526313909055943501898474232244682466949149864418497268943, + 54615970833110299035691143075517066092024314562334728541220099178048293031173, + 32112512508947520360789081302708296505473974754959805858145203408010165306517, + 85823074697072165443604848224465370037251188633431788581582515681368854801201, + 31114787763081247662741790576136049613765531079439068967943198919548089945587, + 63717636094936942215167694521013396640695049671398758505544873002956659018795, + 46914261527557896290966299653166097704478129043511948482391200512036428481288, + 58923411056640153904729588987353811241292425582618364248734832424160839974386, + 50179833858476307391456910536402872857772226397005827658938467543897282451575, + 7399171788955838786742152597854977502050982099899715132733135899052117217545, + 93872684832704986670149158334194509247022010222886860168702211704099201069352, + 49687140203619698793673849263115576429481975552290236422892493685164901278792, + 106273531460025463668310324173446244018738894282871539525215762780591291706155, + 78923513349831944924537330470080754191114080083149247605929918579383623068456, + 50243690472052874553737143971668585250777706389716966541123706593833557464197, + 14928097276738110931661959936750002490113274595862260538156282115884646749788, + 97636173389356917548748277423523694672226762969414452501536910222011959459104, + 38744780619051080555509054290722104884136581161684592091596609542691541950131, + 76305797460097674690462320779275684579026918868641674002970602312667876025735, + 99319412254964041675502828069665819342149052987152987392086750651676744471964, + 107366432170606397254180573522955903423026319357594955180473440028782517094811, + 60344379454835700583625574565166971955283221980442020016988265483327836660340, + 95273062361487489226108456769564185591569827803892488719352432327283707461867, + 73877209629254278089333997149988436753355233586765712584450550875195469403371, + 38331123804163560494485279204166810888417461933985250355314098023958239314736, + 106556711876247251021682631221360850922372713031667061589770635089283360994173, + 102890474760259854630170581840930262487721108245862113115575459773534870169628, + 10877466614767430581872310973382352169813318491535129598341036958018579500908, + 15132085524877042223936003242005723023770131695295306170112330353422335928637, + 3408214602678813270177848587974025101499057941607729407576635677028440290643, + 22831370693433669028556328612098143404459453567000719312466316131142036071459, + 74211345545461458944362705130817924114329322029498646950905451251295568342426, + 94895738810491560992102232998379123954726818134284590088519056362101447835763, + 64506315879394373126856628745726235941054214495972234400483028618989952757987, + 106930502633370520988542875453726404799932590091198881910056842282511120061402, + 63059265553965330371504563689275766573397530656579610486037010959773696718956, + 31512172698707291596500870726909806676259139754688878095971669931502804321283, + 93031196312652451383813928381228909877151502052237064392916714826509373089585, + 82724472015882148694886881638447653377563068883520170787685590352921926596050, + 78121869861392699423387129877415553564692968777285986403673962560019302484340, + 20258020069777856163090242646144629794277057648649514391298447286083285034755, + 32973811953722044083062761445188979149444368409290717867611463700154466899554, + 100967605565380205645936381274506567491641207181843358499345916305538920337268, + 72390949360272585354558305064341289855739955365721481655730333617637799338135, + 78596368190128155349530458347836368925860306679224721978650253671304172715997, + 64558599892689557707415227444937142675646389328776207164588655540569754417692, + 69890750668381984505944991731554411154122182634278802023177924155853842361584, + 75213803206394369769719191236935557715315228259768150739077153503198332841035, + 713865771311928611559082824635799123841148346944239416389783564059397504708, + 4217795646636310578015247225747573138661168845810261717953458054214996036225, + 14223818603976320398373336938059290367291506650169228998269707219657657502998, + 44533811145809402876828177271382335586411109486962835140128777341409519124066, + 56478819008987592389931597077140177544234702081912837289515448214765496735886, + 41258256854642400777318742135929865726252276026583411020939043927579371704001, + 32535465328823065094547672642752747105689591965757061603966987782796974127350, + 23434894256690473532436335396098545716482453326684491095059454432435759938252, + 4515178580927686433863854609466342253346350175973565061169476933553924807288, + 65770803916636481644628148613372261887549160616947240346727958158444755593659, + 114798502242093794221481920571539075400854081537219790402383806659924239244922, + 103466805083180111290955563590402548161602269088414100675034153636453982865616, + 66361002558103463011373871292547992240921236981981800156173849080633424047414, + 90150266278052170098912652741812718604491081514435199062728898334011964228224, + 36567956334608768029893876357995916604172470588123723310113672944970409924185, + 46650860437157018357739959743023898085493491236908063185519299139520792639406, + 113978114883605403381413308200143069475162868763769589424052527057919562649859, + 14571193172626764868769895240295272901205374509807718235249232780047466971143, + 111659244927862512621498176100521641413222297574328242618976729145778411664511, + 82034860778342408421882094700961549400046231575887188360865160569029015368325, + 10986581324857748680434572967584355674417783647660484243309314356294235419564, + 92858537763245692873202265086076587568238962903876900745338895179532119508522, + 18339610539274968865123664850767402285705195044427828900485970443286417207220, + 13538034569168160542835032989304290525603956489730090399726793567665517412863, + 87337008194997323770465815106329850019371469234027785444177768809208013119159, + 112125623929639326154462925416473189479530717874389249773728934274872083539360, + 61811828574222500034860293512459035118173463561779508177733222650147479627330, + 70625019741896412319666161595692255408223851946053030491711034192625695311154, + 31114107047925640925691588320620064382112493361732342885797955717132599150912, + 70525362769848742843404668520081397515062752648420532788584164390189894512990, + 108287759814593544590262575481791776872680324980407117552849781196331047384599, + 85387852113504375586844599166186916406411052267265654527897135913950060156638, + 40134198285988487818395286719554733436191219534549769841212811939461508995568, + 69806395930233422010938395428540531695508125391128576669383501857429014956937, + 44383692378809958030463149383028662193648870703734337280232496838471404247085, + 37833558523062077358848765137334633785118860579595709545998045785130920980485, + 3268293153421591881795839414598389483173330552458107165658729486103728565214, + 77951073855122558364387084673085953939719040770257045049299878073346449873028, + 76984991608538690954688115855190325839694754137431141187376382430106543868181, + 93615355202516268803076921422310991177683947384769878854894366353714252044126, + 60234877428817903309190508886460324009733004937113526208989019315210791944330, + 33927171987103289784332757937408397612271411032618895616710265773785239274493, + 62751586340416939520022904096477984413978099039576677831404761995575552315844, + 79096845625634241486337000390213892498887026547983695606552343643993944205508, + 56607277381466759972527220638522037041585786602990954025182664870898055166046, + 105099214982421911456533751426434700095520255776676657271423129923536054520832, + 29582307170920269245836667040710117212364910971553902349708895690518740962757, + 51525428900100125428338361910656641381520344565592714922493084097344073408068, + 73323090782644445487360500184647646874013297352287052267419439034447355313955, + 42074869647782598060314873644565016035441665324811197181005830202139356631768, + 49516601016421746490828567320796527574863065300399590108648952143654685296842, + 101314357451866153975039589602508192430740189705116816076869220828467268315913, + 88980923090328250648862355979591435016413649386480432455268529739504295345776, + 15707128794614645030714351199307318033849401835667149765610375924999588869883, + 77511917891799010985827235351236384467882281290686256570463416416104546138427, + 27943387849678302292044484398402168990691301596538116310444055545884976771013, + 19749168743340741306635090410006638912945188174485211732216568263415920341373, + 110789801144406654444181504369931261651183190658803897486643694522318446568384, + 111910951285111471303966439319667616844668129429657794435170356211919277579869, + 64147784543118635414563383484030167666202507166484036570675270255297126165260, + 99913572267196567877319742365398686938289096843502998402751838938328273984887, + 61912678161667434462636754144422785653695352053266328100030124472361121727010, + 12299820910982805096697839779225272595462474269921644240369174382745979084779, + 80008737233047206717240240077776181123924502441138518168275632598548473290921, + 6684578692884812110830772551575493594375150652729291190368776629426171995494, + 80133188578788653578983640222626744956569177797805198417065918779464192766695, + 57942453413835213225435448672981881534592741151757201589563305307336621432435, + 87685211353117027234090822097140469947198214797865560071601838941294973153202, + 7547796482819319598121012311536540374463683191931557261758758530851465076359, + 54060890438191534474558742520648986937754275778265604066368599326973622569689, + 78357711406267871216257348186633230496936120953321466832769258350299271104052, + 72208899450897039911453923106460555945446631019167927879457798069485436071614, + 86994295236717513157031581145699694598783814912966809088491089396659163682924, + 97244105930727320030735077718524611223480015127922147743806741309675521879079, + 46821515488587058205364014839711589321117284967092038043247007816710617728693, + 82315402245454235277239179882713578934450718774877171286651269842515546478132, + 55355121149793329341491568922859810743076027837495668746928753313320784028442, + 42221834724290400485539396543033664771532182150925832325958854155795366523478, + 87249997762767830341600338935741630869825543641091056050376516048003954742924, + 58558417182931840799015706010437816068003141871832295684836511897319630625377, + 90646689685247775188276308153618129893731239475659232289832005405515669988326, + 63683910656135883846693664354006872928429289660323804927116553890410402744276, + 73646744644242548749883175466483401844333446237506988919813083538330014578910, + 85919627442938766454979481519476484600102963398676046674149532757672136761149, + 64957081418575043979714297341612993135633790903778335261242655622165156332212, + 29283238504458590433727764033703034539298186204430885648887030958624101078615, + 50598790870845205532351724958280411560891250360617652734747758016988149198171, + 10306946966828842793988543700100474093954288222334589458433870591473447195363, + 93383782227644581114167680223172364202388922104372471669591829069905858397958, + 82966873968832985802244497000030550194805538422317370276494899473213646851979, + 4027642553970535969311123433477994982343525472269994271857098984287380720120, + 64932250603442933539699423260361937248779103514954901344147579197676217756640, + 63381364269661782217446841274244572801089064751400868471443219719117302379478, + 89337765166828711465072824407846271739115759092046994775855761829607340698291, + 37157897758371600825668509176880331562987468607783977443610366189220797974197, + 41534934721634715930611008172599711544497734643155781372014343681790669364258, + 112735375116638787844782315517638234687460168051981878310975790323286363026088, + 44815892726968755143968284781276350856920407289787182546753769254711106115218, + 73765220109154434663293010450222677595849326210282420822914450455411937218591, + 19046147831205526962143235015097089305983840736658408039985872584514849628852, + 31753560382955274777878729452469734519263341263905703152652424047617012910493, + 56528025820440181696825070057657365283122302389065973072494098663897292594161, + 41066471144730765134600137862832271630122062375243402496719925662898072198693, + 108851329254976771349627232810962078381505305529587704183132855479691338712848, + 45782657390386471176610468297528047836250202785736711627364068797589681138163, + 13769034627836120844100658009617426562555329579887732814047250887775448863280, + 91886422773794532801222091625683935487344783841540159553327484687000636325716, + 70938338241174470130225413153663707473714753847467789419746515939387842634852, + 5081470653650919697032287018044092084092842228152722277640491736952861518287, + 87384224223795844281156267148828305127744906809784439076782484004066862869869, + 83135611780027591027682274456558526274255537793123206046910850760235880941791, + 26743961105136074430834051214103958003960563505905839817476457138423173675682, + 22532030310824157473834189040749196884472319625276013760738464337151683132120, + 9223359857298668416480913604076640217732278101804339064756632068747169056686, + 43412394511915951857863635554194292193503187659320950873874888169969934606567, + 19540647784236022954078780536334098246701450053639191959885522181851578280143, + 71587401330535943733922874821763431990405754036794794138238438292733445233699, + 103790307236613919508929772229700629005668617988873224466508371105117012562987, + 89116229333069611662836452246834379761276878778773993046975813349301975642089, + 60047475482079971862702861973547277445273443433938108001179616873639206191099, + 105237746554462793613846056861019686105800551554072941029028992382625121556795, + 108391064994861542098103057536170382703463232050039865861210830246886064642840, + 110383719200324290778877899200827280537419832857090151213029275153174188328612, + 56369802721495976759703590739732925453003019836218073381299943293726210959561, + 67824664024071866060860723203033616624610241498079726646141225934231284489040, + 45159812622314756489071056435012747197513643947726183348977174794660175401921, + 29296954400904356672668069693952291315485556260607296282533960483836433979890, + 76106615054094606689894451859423809759777243569958547825532072698676714040418, + 5517992596372205135413284455502946396874073843593485016177731091209621874839, + 9724201821967171817778477679164357954891718482431336993565761149726302114836, + 45542554343757874556691080182439354069259169845263357645941920619074512124227, + 79059911237787761355786142449084721324880577341618157694256750391350537062486, + 115786316403345951187691814407840538704442194426719706382741211660595173475920, + 105687268163191512547271109273471750962837412332239380776346295964553305976497, + 641258152423358607374245087436094702887710998998879657218575138866179694170, + 34918116761157411029029681750290380087959536589760031623593631605070011836982, + 86733179478836654074634035858255743097571821664563540316458099385240257035481, + 113086666043116430399253835601479039094312618322742825628481191177379738660202, + 103301498851231514835967626096243756844549852791107967107923613754526980379538, + 1651919439985859444491408709564730224223820746948125282880693118387650876117, + 80269411800902188931573551003528315954909340244161255641481971716807067432738, + 103187269017000460087939889423990743627681184005670557263265110388521169879892, + 27385560509092500720395856130598082707942600977300912640432654141228655178445, + 107652647931294956586290584221071654371666328241876406501118657506007254046943, + 109383960812021608113740637890792861947378602118253651071418735979014605169061, + 24473638831899701011565294289730402096556538818403721088526153883042840554535, + 9846224173247720118208988355886449746221404346771257873203847593754202649381, + 102662655145442873782814840517129831550928080840160897718839099050785781175135, + 24769028559101252337658335936502954359630879554079148605126140767727901283670, + 102821123227610042686764153690522375182677506827827832342000174379234062178744, + 60538888992399585100188494834855797182490850730309328816036386231345644229215, + 56747790988637790596587979176209917702739680389556019048562115837953952267398, + 9224557252190335845864472186397193775037369708890663500594671214088086824396, + 58089046639627170807553197583490632702317744454629453559915943786066251486257, + 74949361634317882616197100154818029751641075065519686630245499728723502225663, + 105545398481725748667686070344023456127053912307622115118349194570728151561119, + 96294784607579792305326288940729254458275562685216135309295354370964466029600, + 34328922589712547669094465607489877401482600620030853266258077636447981546356, + 18110461155777227445374994029850716211448646774400881505953510470384215199053, + 78537434946813056541168915993760737477882442677466379329177719239172423182692, + 111106804033498663019660817034212500168436030590578934575114513900954089486870, + 20543778763384287988255356980462999591217639906342191122936886104376666865277, + 69979944623130434564811529245979905974313299607865406688863390911620650257910, + 88614609534752528145316409849545368978458252813231050595082528618337797076735, + 7995464870181106459552493232604981462677493629412316765483289847351235347265, + 100192274241892552681190226484205380391922603818121665463215615979772537115864, + 30847471440132562192014233925845021842448082053920988531492175687183917968074, + 106009185612771953580724677639158743261086614185589474477921583095102317131789, + 49735300414964737529491213716306437700529673700238380306699221823733303723174, + 42296385484964299260902884207793819465227119884367106359772287942267145073536, + 93593304161408139774523640635460792414857614919210610480868549384197419330447, + 7307278256192250911523652383382664203801884378859697798524144209347411695562, + 18934939823841293868681632502455986241698102383548884630270722263874880398705, + 43283869834883514902972824061825697765239546801239960953793806213312596802825, + 107888776586099030304117156182622666349074642635491167423219807486571909525778, + 19948679973004498477207834586951113443324398857053845225583222119183232046870, + 50305572885024780377252640298448269964041958825899848189464836005752312581326, + 17957692981886673636454232993276843374119256753359106269322222189831856113863, + 111422691829901377404737395845927346210827807226636799443579882624708609365647, + 35057558979908802301149297993008625690553232451739489974030332712652372942428, + 8271418085423819013964698074529169854775001702800643323022906177424203703083, + 95776783826327761194533189686403822667566952732273808389244803324783559110250, + 55822732767027188710611079562737037991442760661059919562757495979770070666144, + 103614045145995991890236468704385440365125497675629655757612419615576150527791, + 87513741783132396068713089588620948980723488867680227376787276852526192933443, + 55552929424659084882785912106713339977120404300237157542683068762661378293553, + 84664683864569336797064920623351348778513486903342749721000288115697128471386, + 104361585239922573268411896468856061370967679820339291656804345380123294060172, + 46822832815505211740572070976737690066327407879609766293770252440181868527692, + 88470610429889848909371987571202519929606149566353623979633232649819391839491, + 21217767838674031593209000030922624021864035273440757623029183032373951859918, + 39042335512346489471717361398437756204636323437411437537189789423683761561710, + 86442774758568312656401659509053290041123867274913356674473628038417414829493, + 113806448666308018747966264668211386340372262071098026619512205348392151088141, + 45153806677195857979510903836363840677463048472110015455406459480723140223725, + 97334203216670484425268039816716055393857356067821621681894285069289537669509, + 67193255267112054349760010507498744752198692106570527636339214097464687827537, + 81185334980593365913398292815226546600884118367183289558160087849132791424244, + 12921122705733458236412898300226456271149442787043645595882704362635257990521, + 110055998335300512236087341926352379950960601501991014010099184622406481793585, + 77139483211748002386028346276011723994405859115530932359608253990088367613167, + 865625561970301391434196309728509123451610413634540227535321268004076433672, + 108754612635541080639882990556158702758706205788981100657043890206061298924142, + 86496620785020440462916059088633665849539823972244049253964132681259815145822, + 73752785340032369597592046414242059481288944280197119431162690355293187577921, + 76333812509898319452265571776088275942948075256656811503062171691465792579689, + 18845650409398669124009722455618374943009112428972476564130209535570391768764, + 43511659326057468625602972503578453064018125560338912679073995154067283138008, + 64270851568812346119372921352206304177423772039374360571692446205558560424316, + 48189501702687951961851261342991672185479431528996475565083904793743302483895, + 51652448170417401985758269959496462088808587633362570683411562516282339723663, + 86183630114394770772835958503974162466656890874954444443342810473800261348359, + 98585705806522812032842297868214539650203262095642521648895956808352467765267, + 59410890204389510036140216042252448504493477335011524938179497971199717305547, + 79692516469537176955017944775787893146924076162153293307063191658453502741472, + 12432710324347237284896617988789981712783547199850940338980122961502346647, + 49592934995857332651759267474856443132519544418352754847288367996356656691937, + 63468479982956839729212721587679969020632022261218715793449791969059912616587, + 79726775435156236958035748237207339224635083220013141836013794482812664174893, + 97439345351107479101311900679824742011570195518527030936093022736134075877223, + 61439533978052825633404164344305939269052214769581290601237619818703134422539, + 65925646375200235135034156136282711234867299866000891109079493439328470795047, + 92647022735627851948294852752752098294773762350452912414771473196540818369499, + 53400774345197286237183566296721826734794479119161252505898756075092325583570, + 18549628192384656385867793408043562242534554119928007805043907299301292851757, + 45924414799022304950097724824274324379367943084065939452653667451362043712158, + 110368172458658774534367668868855149355835365633017730507261220602074136357580, + 55356767012696396487888840708634740714627097581716711294537656522453810654192, + 83416396599254060146049838691316246058574249801635121553905647193061068866458, + 110441512115054554323328435082029553243998576227583907858301500757366120475425, + 5164266238799687044525084398880093204493750009620562934380079626078590439263, + 62112452133361441117532405096833208471426063825484850899602116494310825198459, + 52389563076184118231866178069377019525451392209944527621243747405999119881158, + 77471837700672776462143670534678094168615286917735022997553045888835689474044, + 97248062251206783328422303190498256046114164902336901334927638079052337150453, + 44557364878670238484551439989433283624658758938335690573618524717659008860008, + 22845430661687852453692201570370974035118060832596493006725109692601228195123, + 101774671819854099857301702937453537028276907591416223309013262298077545882301, + 115424369238578734392390181363816162554914372861226537640100957340983063792061, + 65338990673211792003751730933129632843822135869185645371725904873020174573629, + 114366266324461572987645959226855826836558496449355152538893794925039413357908, + 38290463890585456589610194511923849736640531333686863956945526584298699155634, + 7104380315235996039834757743773937751945660895522076520018612543110852786459, + 34063076360765794300903320551561479083798148054160557055090751714448348977580, + 88515727367536907576580039700060644168096251873610359912666009463379104930336, + 85688099884478097401412463010714767804521859141166118376027704285006781806478, + 14445723047504895678503624598372731567242295091642621226825454965131390083795, + 105307177643870861376704975142705763093068186022149591472400706068356332439472, + 12181198007331198915733875662579743177739833828445541594284924339103615308304, + 62933037901514195978439869420541917885790480592974041452836435712764159078101, + 52555289574484375459494295200716138077661544231852518075468094221843139579759, + 86408859083267213849608593421889984462632203882937681896919607104631355327432, + 70051205085977014123218344822140748695927537067367675872085026215066718894743, + 50797171048465065012378418419172514464250671715708065222018882517586360384952, + 1874317888706801165225424155060739439373484623144774569528888912338861648442, + 38874893955970871201241959699801474013365631094709837269682371327988779676411, + 104322546406750040921614923005640070242124422454480957460434283544970707542352, + 23147399194890360754983100314529471966962125675439669012987512541660909601887, + 113716952306498842347322645003014352390572038776176836124593516338466562712247, + 36491396924188980583576281527414767595941752681245588892480488446261854718575, + 38216976432626963996039883979812057589159795992093245757044926702099226967348, + 85587142213637727516383870845271383623475010977583594130085419463009564864338, + 35533148518664300451429836377972871634877828724353146250247780775257353422007, + 113707210930207064201021028732858411605515726532230715404906758865563077234074, + 75824923843135090956145055465695508337185470645181390611498070674519003917260, + 517810143330059297111726991869775122342471182773654878085285132699610899, + 50861474394015924342453430596667275885104852995589344919703556856402567899764, + 49128412736542266992374724288983384107547040346367154413952434327740311640374, + 47543645103034546966956344310497478320796706577135425732862193708438183083055, + 104362722607070431239825878525881711307409736427324214678751128935605816076393, + 80901019799692946784836164248044967464623235366342139951562029269656667432776, + 110624134448533690643403812634937132348892276454673187051666134504903397472437, + 11332041837814640069950573118531582178208987766303950473353104817780737513431, + 114511557839319259473147664196208197224825143530034423580198024049395329172086, + 24477487820919013861878492454371985336148887712503686787747853806123463883383, + 74040016346037455510908086012289778987837758722229815721408903133181977325126, + 96749297847359416454833866356682485133755505677563601198251552625663438440432, + 105430261721149398447580765021122166604918996215042858470481616269905803048056, + 79791601172505672167793297591283334154149075873735960889429812469226954026924, + 105202723479492288927374257344836310443937408752137121233450227157560518344862, + 55234807745596018650242903018904912018598184333302650803122102037867969201617, + 56423886371978150980154069718343902250360154531587393738217763986684950825660, + 88632533967648931361876213430954972474334291020155125072956484147361066869548, + 41540602080447885068364895020121589125387302152191845916811236111088863892018, + 95866258397646314612666598700519648912023398181779402139994107785390987444312, + 27628687861999017469863173929132991859361239157743671136807907482842484525757, + 22955560086190754038224423146795686308407664057168960419442490764595085154106, + 65789816766575105386987428306722263967996208491478635414490253295806677267237, + 82684435593876653391617483275086404180129265328752928074553653452882266716384, + 72237491753010540389666548672706287377763382539591172617435007730770942255029, + 91236125982365567095084044215283415421174038922356284420876986552831895925029, + 38797497641204948824685934977074563130952656775734483696648184436815878338395, + 29450032252377291876076927760824111963477380682854888797165017462555096944777, + 56730302001559397227949378973374467269278644362656612891556529840301717911829, + 98242189100315465844672884345381556806359119306380506851927541428933452924066, + 28677972722989033022627551059078009839201978571186307987703270591903667393859, + 99738128485488861889095050115251628549635211973689063501970159747511621921740, + 30997311945733736603873632098585356219772217871223883018619638323654487757602, + 28224354554309048810328838069554720792169684263283916760516197294490610224088, + 85124825409286476718381863601395474198658538100703311299861597204493450641541, + 33495241866568199932364800498179948306100803665579334596416761183215430930567, + 93748165502429540390752326809177733395625010372302844333039023440166033586473, + 55324812000863319402611450577106072802300534535282967325048243381567366931526, + 80357114434371146887628065499243008165063530763945754592622384417840027467965, + 107865294290004154300446549420262135970395626999303173983646891465019259411900, + 5508815310611955958841554110831533001923895400754839050062910862461100459301, + 110628211683082298216277468869689191392002603451165823050580500240786687598409, + 55985642162590842695604595049296570925761414222698667870879574427317007197666, + 97764919624729977852728415456251595728184019866527129367997851555640066937264, + 74643707599685076167689738607577307206746099799250672992619750183209913242853, + 49133405248477455105183361148964553976430211270825632762949204776004710322794, + 37230040854747304562375397764365441637954424575214865336492538924135663966611, + 63747437736511981100055958734032121409103137779784520500023115828550548157803, + 92465863715828612410373874850044721058409898660141083488253065869311301451090, + 6351072607009588886312852820229505037726353682229809706757173440945171422619, + 9838929347538877170506725037253611521513180438396714957522150626475756420461, + 99204566522761543817262712571166152669532726633519888841909895085964712336655, + 69918315505074486879510735964313251337723667425098772438138374615816323649757, + 22681711155652187343546055126161350570283330104128570540811080279694440822143, + 21750456202431669808487018168451361794307926238637912778044917235186332446479, + 30519570078854889369012242379857888860540880339074771627807263792784619013620, + 20376068409590712757607835967606049587305403398114621126642144077359498527634, + 57816154972820637842015295227302274063569924591337076444074648595872211158951, + 95691029341486059200249030288647234422421749471197931071422339405240735862309, + 11519542049335586856333108489270183185166357336465460680941349039750739928735, + 22783439924801660726284099891229570248136801431901846601891271372699792905284, + 70729988904710801782067722428323428729842006762136396716832906516070438688711, + 768552533597076344166841212199031455655598934592602393555086804800112774869, + 98831924163537997575724098258335467593562129475748349635164470060889590458882, + 37382848764098449827367408283658574687701088781678841348230180499498878655729, + 53826850050413005822237153286307533863893346772982720285374142965133922653879, + 25951810197328049743686791099294062865971179361142244965197955644658101600157, + 95474384724371876447009575826440626126046120241573648796622832772631585264496, + 70476826338218251611930664176436683399501082487873755494166711051527638761783, + 76923865001237318302242629280930995101767102325750980390341316214129992580813, + 40956221428999184253153145344417098366615680167022358702893001610164574343901, + 91258443117772646022741710991832326954876277981466384820051070056034422875382, + 2480557044803086659730155829638171859667302394336109731251787909625140565271, + 61639252942303938393953410722684371324573405948544383860756787815149743841457, + 98914761414072197737759435974083305544825672459974434243172911974632891210585, + 29288287586124734903823974425198481871396075964331854237020621667490857027993, + 81096783908540223370427893690448374939257060429500261220346276552248672456700, + 74747676270852284893146081460311377544280534136250755452302483452475496380216, + 63033053896061914085783155702720696714750947306037038383801589545505815881432, + 94880829835360619082014919456168353457187296887555045263008281138204580283367, + 86243603393894632034932094738373100868235939788410709773198835748922138060758, + 67131877324481198083331599258988391019642445909308522741466882560005818253968, + 102683920792339364282974702901715431944837387943507388228071841895827490267651, + 67912889912992465913671388521556367869860832024272229385213244739156885723035, + 110551344711509013940497589490244356994772645505463674067940200925529505761908, + 104422433462351861857430424561648719344140239925429049064348391098425777060514, + 100603579863145210162568134411179495346102952400578060579232432345328678086454, + 17710591727487898159028074633066319868136748315666602801147712313056885200186, + 53732990047516765000084978562862022705259609372298873348902438890119898623374, + 16063942819871515158604960419497507463530060358628017675103659556150568988243, + 13585242300922194490912783518156384483056462406554099581421313205860094128821, + 76994709296314604651310848255466212541642242689150752484555866697766091663044, + 33296060443744609438007182562715573632713908461562972975440130123920242597757, + 29823994004951149189184908981344484820146203926650734339978490701532207194556, + 103776639447780865799844373251019648483604076101633302998164136777107089845724, + 27990243782682546566545330419534660325166080888765328331520724576716550919124, + 113681986404859899855489671628136330088521242944577866066930355758292916513082, + 45480499601746912260141581373860143599455659573335060265126978654014754221255, + 17167575884693203444847451450046828526150267046959529487681959810698891407385, + 17232940152909869508566737574957302716450723866625646764381462079454170596871, + 24214206196439198683369378114670659640997897837434151686387225792702458393845, + 55183796882852678728455807147620724129591397410719508810015917859305209452709, + 92370933471589006522196319239737831765721169148478103724946044654059765601417, + 17522830276676507022127809210712926924538214418291549746406033322309804857129, + 87667408077498737584593526761134529744998243816543685429013918180276747535564, + 35876311000604112586101254886917742346936145381127393394295529620071642297812, + 64014796749105076572734082259912640230298578835394516523304221995273728541304, + 109135151229310736573817700892379334871732763504302882245459230784275778553575, + 16595347687222128839702418478080362109719600628112118618015869217388018348883, + 27921579396834813549066464299860827161466322958768833372792240664949404130922, + 35216545495698359652086372205977503250042279321493167643258328475141020214977, + 77117275761337491903648618157611979840190321352254166350918569716805510962886, + 3512462062819212238377009967268608332372746022904412658531847429663264146953, + 213044529585981392974692935043822025246812794554747287575324449148243168071, + 90614765757064420969737750920642735373288480403571675818369451509266111313712, + 43010469421403140310031850131592004520255679316973656230812272291852743048436, + 17874078946148102948854789032214343103123833912541908620511389535466184704924, + 76374819091154956586181248706405676913767641045061029782061788515868087538531, + 91564172717501273329995063951618906528857595075266378905429418245106395050386, + 58789505790452834130580711788253867271536111224105841840343521525916385542461, + 94823773647415317483248568929403137504875117257673993971772751795386631246368, + 31071978519068803513374467918831947899554357997409504867413818015530559683839, + 109592819189390091395615159423891840082650968805821245525286882876892630923722, + 80616066711957337978951763597092204520874538220618039320146978247698657786081, + 64203516468165822104466698698828118320320864571064924456056450888616400337511, + 103067832985679360302134342271731680480045309368319718638093837086698631245958, + 30994341470584926691685619262200638787457244500478165297574371511860341551214, + 43059466595763778882700729036090686919073527598798723058851954243437716781460, + 1693610051920013413013260181546765312124540120437967991917459665994774806656, + 29747748984588778023562256318712123283140459273364657199320201305598273808458, + 2226019244043447714854361308099740688341176962586376492892706683593154499175, + 111825037103273707978537161414761443953313270130816743531156536888415537666187, + 57012205858056204387551272724902421605062503962555598394289313492857917886835, + 73396140276984806244229093480477275338765263475608983452937019244211554654915, + 52185746418253605003953484521693480852645094839324127943959781713020251566259, + 50505675019443410862922296532230977928239665449385358680361802744120140462921, + 103527676053816135570616835980879956268458289266085079078826558654717425055498, + 37617128485103969063185558784266247787128354307686582970131100302629254527846, + 3949720678750428446742361510648883442144623585510859201354543637462177325467, + 8377131978218315616004054453094037374246718190084282403194726043647197331954, + 98499196443008033569836737659884708297867418596615891296810167773834208174281, + 42121509521270915625563632437621319638187814758192852640255865671287440139483, + 54521620577162531111131330281903686807795468830466555651310259043543872094360, + 66064747392912446974895440619261318611730429489615281970747108278167294355782, + 15861793885995247826508971849873138627436785517062019866020823181933822773077, + 50417649252747305086029996312270159725838959845251999690819139767623694163939, + 60967184333674743131822441242997898492742767225047179691417061973722239944947, + 73565820995570455127474583774784016066992595310121051611101407971504048052224, + 47717427458146179166467332999539387013301359408189577401273175767693692453323, + 35573979916120244358355161246610600681290513341867535117841606123840359214158, + 55465053138138231865871429602166148592952938948327069774639169783483929311911, + 89922242028593373850468806452435133814895318351027088363939566549861423260982, + 7260051358784579178211291605910298603242692991248241261024859891086923720596, + 50317517160556980163700750490597405064413342021023424187016993522719004120455, + 87371270432617946363711807507156078446234415221813830125207964609863093118621, + 27000773119819018574170640928922861914753074552580644933183545957332034747811, + 42744032928437813310951510403245788701064218473001042858648361006941304001965, + 76198115222883112855784539112917622084905060815328285716682730794880576768334, + 114932917350143510828430027883300271265708086718065058264252705465767116470282, + 9610974877671120553866505474605601682004052160358709919274483117463311190651, + 92474887406473624527438845790946877750741294442993385940737555271563845356352, + 95819697123437827240587022445477470694580782453486472141994789896836183073008, + 82576926300800526546816921752229648351862505582178910495285630906170828895289, + 36331361540866341658048510064579643468711158646220392124923553254704291134611, + 46706376926626599549529540821623039003107481030515487331363332254949059300295, + 24353324713995083211377472060712587339255670962552600293093997177370010283872, + 17744557414274810664273678005082172557385527892208091029498867778266373488849, + 56066104524526790445623264175822473453166467950159100460795504735296451738899, + 40071689527430667542335410521584503230790415282110381507426618602815016600595, + 97068851296966062329360158937101699476338603966675190512721689359550742961475, + 13969867861865221931999418683636285972452065394091786729793578646408460767223, + 13402549437974009817308837850617256407627963323533150555689533553100160454642, + 23169130976851413575920663428801683336183202112522615818530455538814681264920, + 73126837115915344741919698095460455134836574049715878677508376002500599470046, + 51710669535427444724897929166023883778940757809780776797890510762630448624310, + 65459597945614518793759359804869521417840631665365659577536148549160988012759, + 99536540797642825729053298966404765630223414089769399041907943006297494502254, + 7231784615563341371222177706031919697765617500669178646820618965091525245269, + 64122892575584255333550310043295962304217347702067254836758984377389312146209, + 69248968822867743402900338268396936215300699222302567510938706021051626135289, + 64459909137581310426551257040551710383071141138993080363067287522213927798621, + 14742948626675895933533391365441723565532113660732414550931873522030034019512, + 101026147667033095088031322524669123897108657000068395582372759819856524166100, + 97132283027374971785455860106820479123230279733803926192840002003879833286015, + 48174593663265457342497520933640892306528134783146005057970749272631234283734, + 74551484614022999820896938159235147290009705262572638175995362448915115498394, + 81601548335524309052698158698589563941353346599566891312827725647743560184478, + 73116932619185543409919325389077397889594304746432961767623869175317287185372, + 78451402876589854041503318631172224868580679846789904044103380578733159665917, + 25278739790620556963219300167564212870292271442363451960486351820583837139810, + 54024414835705416394037079934860587885462867299076814905051498941170825925535, + 12709638555468534409074810722501233896922211667428202064180614948548059924987, + 109281347151792376395175929897929142137597742009438761488009676534981761856468, + 16470158444709895683826130913545011787920959743525928742480188668207944219469, + 33406377458500154516670820483669335835293085173957908437058831034560493583766, + 70651281087265592816851172939542041804024378961122348021431916454524247790489, + 15011995722660902024441911053627059714343883973195603000940078283702110970661, + 60427227238830697144277240793209456816279000880530019187076244777817884523535, + 73198894917046063685454861451165348985337783045276609752624079662516919395132, + 52648112848562399965004618163424195062430864847411322395474185938980291731, + 46952045577128128984196543819547138980588172892696841047616483711048800831812, + 38909633917723662403734030142535327200838258593674509362814721541421705653523, + 36951437270215461622576063193731153491767942719073115216210481817146240857984, + 92822503191844212655463849745092161447288970592157336557684564917523937215336, + 84480307232364796251559974103849511575079628779655490273875109276765190178723, + 106057656691067284889710670931617111774869892493222578009285738015216104199486, + 50285055439186252264142373037616465668991452296519079373148506341919008268750, + 78003171201677677069703279513949889987108271075069361566266810859043252937983, + 64453673133771094732624316824642625674863019043565952757271988552769922400941, + 29805577196918899769094433216516624649076210170142890295156230438586048629104, + 50610652056964241897013258015357131289798599874450894042464476448686702359961, + 10024375724653269362076861050490688019867324376431134908728274873640299983107, + 20099480645892697329859357230912484796162440474084031441826835523655027693529, + 100792873803969996263214820952884165824106259429335511491915347262961892880508, + 86443050097462445856293470117100998266448796130220785484639349760511085234485, + 62493564312100186064427427417117666594707205791525662548029251711951566036866, + 60815635553906897843786462875595869090330869400668845634096204596758855111587, + 54281424165775245149047042922146082135949549572932079829465992045937393672669, + 74021344817398757290513151277223087668710121503273636682391094231782749770700, + 16222693587880103215091267709100201935033204551967066566340174152337034953321, + 64854495973466647368119047189801005714647298965547779804728922234754460334115, + 66156422490209642024390094889796380116453699147039750930384800064026934138365, + 59162561901138024440671086229264803242477291850185999106080419650007825378512, + 113428284036516428934053001628874526792165406098429275385198763774522401427944, + 111140673486972944751467248651865505957171579227015974964548148491340094995994, + 90432726771831661687839542256693210493875909818720677153929560601908121383500, + 2390919648734978074097981145050547615724582463369080238376044032599650107614, + 49332193518446776132944417804065758531799919519408365833179026382028719983520, + 16844021875070676344672196613674464028860686904528695438809665425388692369173, + 22208903991552428459206403129446096484807223815807553864934395942832909219895, + 8470667490115807139655695206731499698365090407835540156609649204316736630681, + 29607486220536299908185616788433675853306188898233656208864422976785534500767, + 55118842515725647019019878765585413332594787746027915581881910388738408646424, + 31910033873055731616439342645926302105855563249650949524593687360947729789548, + 15249004806671842399815833602781130699951102693998767469481749653230294593874, + 85097158794392283171134330003436945020524999931707164209325774911384422465861, + 92337636780391123093193065736517181950044874147359453864596941896834587479688, + 81770882671219571269201880802795916873693733809261256550764580716448072120657, + 109583447871166176511030634751251665357804926356882348916566457471791219148698, + 33041073929036620922360347074319390103534684016051600747456031455430385017729, + 108424534147165186079145303073847199616635687885160726047462790685870976681748, + 65466602632971100068355288774598280106426058641124876268394001659223836069645, + 107641753986594632525502111115099769636983568416823019234524819230100469522603, + 92547027142788556353581494504297445272586237217296313499446131893737076379384, + 69541455046268708819437791119267330009898994511210767829863401709512584810458, + 20683825595930889143744204778164811636370929774430171382638817741714146646945, + 68959317146250332731579840421564642471623237343260120632739135572400765771872, + 75136672680989279656751656653469346757264616237780764363366620630149278561860, + 65274157817701127289444792569660195555080921351115383684189138252807150175533, + 5671810715501868418714897235974689704610658721161649160921276576457817696398, + 32568801760929610669780246928825630234306103465559662342639770719943071342978, + 31899447127694546827922655815214626986764525342903626632184418123093532656512, + 63003141567059498680563562093390845575545068586635328388915837737844428759540, + 70087956425710666655344186549677283948431739775064934115249294220789854801496, + 96881713732723589740390122209289842484955185396098544778614220722895740850551, + 89237512955632773061271413557901783236118038302561303247107569459787144818073, + 112118405390625361521548464552534195496997945375550852266100803525541201727785, + 33904857415053067229197139510264516938417331929376843105857293570196041520971, + 48522847509609438313128709265627345451710945368961593399628287664898038164824, + 91056620479732242278474722192940264910288151744095649278941504581401540449953, + 42454405296693924745760817549955507790390623134504450887729884356981838532961, + 35030768339325008940202682440941830086788807713862271459455227060337963697143, + 76921540239373072453559061952320735174206639807330899944744976047937876699873, + 87313302559766459446612529641999212574650068965120597614758044727899601126563, + 85948403720638571645843862057038267931439810108286533704380282114389769690937, + 102712334707504592210422830464242789803304045340009355833863840935355054281233, + 94470218809718120080570248674808928917664121326980896607385772596791210451951, + 96714874093759650815767707274474804647436412655194229889130027830810105566348, + 90560653385295469951283340686561937543329860648565143016813141347608348309770, + 97278756244816945769091623157631764025785549528861744690219325787907757258583, + 12787384876026770751311821152285407097958609676209647525714649917996657137791, + 111365386353352057081142976967121545231460934814610163846838785509473478412523, + 15855654177408095839420876568842174725956725477718681446815705857360133039548, + 13613067531464775022897443935245026219078965310211939257939155377034750399483, + 53599180093597527139803296608347730592900213586810074862762070055923081925887, + 109874297062501167725957708311475864732403598441326553362751272707261568662384, + 62026410132917555004142622013490428434559262880726789688913922211434254293678, + 69990878268615015540850257545647020092925950033932397468539774269767930535788, + 46148111074747174985444160627533010103111238143005508215961769040553351778998, + 23993026969283007462891903025371029530657636041776082074957040840681347062672, + 62723723611957826574595272650561099300243361574943730452358922191121111061674, + 76340649745758155554625149618785305464754542824525250122399731297158354264663, + 15837561555738656065767725180400482404681801919913975045773939318745845984263, + 105119521829476483933530638019437870029370019711702822008898832331289067484392, + 7291749539674147019747062201586411084842572291128907423952995408405892100963, + 65013291183221361739104571406600258574431018032115683832998746110848663431012, + 74416822669806249454905354579497934095659080083745742323521762825978234983069, + 70217915801415324814036558083191157011253178132273839677239217929046681111383, + 52822571979686773549263007153634661328724765101960886598181125802824843744692, + 85084540761085038167328810682153785502187359953023443483659246715433874377435, + 17919493739690550119173011906396520738790100449060828636904189737675067753013, + 8753055507807332329092024422759223028946116610837360212572206564324859497192, + 101442777402520754988049398976065637522779631216807807980617705038535932675933, + 93613042346895423070777734295453195501234828548390083832828585777394921975624, + 115679083135995843528428655785554265543348465123557615743425866085657195630772, + 85006051186273983656712317133303577235830200124189978238717084236218090367799, + 34333573637219205118420094443995074034493561802092461779027403313373099601691, + 35189022959577001573805734144369663325019195000227392065871711185529124943225, + 32689872839747969623098377119527495462616398137669607462373350312515229991731, + 103745258912467430098305432326720007810839825724431256975721435465827854704696, + 111225344560598664648051279891010744012128492170821826558713137813157281434239, + 3466886922840330421443444212104214765524780073349638551662327285414226854534, + 7946315494471381810555577128618511422384327737049853483679549354788468130213, + 3076724494501994539266352909036638114646061933241823745589772797079417802097, + 80201445786202863305009838285176241856966733784843008991995734719279416808953, + 8112902368594797931221819200919292221021772941918237295784918701063234565200, + 15011316795691089479720529488623729771501984477270295019597053341404102052683, + 14531308717016851912522270687986348621938782352029325259261451363753331798064, + 14475543381502739866650612835155797140849324779223382420456476543541914007157, + 34250879873249948376780103739612546234429458040921383053109198787687516563242, + 21132301512997263058260097006372649706666831671215239991570848647957174616799, + 77966727789626456653703890909082745388036860307486696786258643979395477862903, + 48348599032496065689789046447495164129294029601311550101881502246726053044881, + 30591585628473853387107376937243281713490713265803514876892851595162308216107, + 71738225032601406785775004217101075055854433856894013548057305624203466443543, + 27217229884517976935899785988505853584828688257347597962188032829364968170938, + 44756840659025885296126961117384530731317800298202182960176805351569228854286, + 38668580781907195245542626308359941894176998299710914697165283563516778207207, + 43693964395969386392964155926684449859875865222048362674249498822011082820656, + 80461938315975545512173828261970891228241326895564251202546405808916150483297, + 45432269566872848767641908318861074801627514223856906024230905187766701717465, + 12678521597571020971780057618300692180983344253909210537250788727290096554978, + 97409418157538176229864525559359313733999642795465001194416903811362627615593, + 17666883743653414392559150083937046549092823963784149243759424141836210233910, + 96782625814774464062993476868578132781345525016849135775601050656059041410584, + 2589884068630509097550648194665847101140988344084741061970648890085736538515, + 58488365439641276883795150591910380251526838715002588792626138011101348675288, + 1813293167819395115836130599948938455484084779362371406466311001918030964005, + 35340220851947076236063886985035545280799271738054743782918773396002557344778, + 80163356255106591665286360265413448326273305137096780883148926687597663905577, + 49801921889865181447751677663987234697606127697886569264700309057813207631711, + 59894875910103667367409317643259441162201665326496448852510137372381968995716, + 87469288780169906217585293668973559107829939167624410352054240605037124036000, + 65416999407884660802908802332759099117091753912680717604556155547914616943818, + 33543113511755320947035734241812378346692006754388632274310122264159183686133, + 6989834185236560473590886201989903335709920654637458336580794634454864779353, + 9453561663620506951490984040430770639868514448821537257271793950020777271020, + 105062194568187351926318870584626853622541986915663690777614658033338966643115, + 65905392114908010515935577424561787413515312201266618394119529564572597370853, + 61522471806184297068444697896474869845301165432237624155233522574862888263839, + 65082189782883353413832260729892578207198876064116884181613458383803356186631, + 55398095354679161133669588425385416998485439302343789152075296268507284135371, + 13018671651929370889661237502802954643194745186030256377106894194985175920719, + 96154415633980356153660997875529716848632792795013003883875081002686931112788, + 93139410818081574961854973782340701603283319444130717937000321633720917307669, + 74982635088784842541527066797261617026977713638310182525162946945256591745055, + 40862289967799826228545391981178363057389423168913946439484036341887370282888, + 115470852263677408358942349816123249977382801878297678823132394197567085154385, + 35897816581846152143635977795416125182617662098748809515257511460935868885146, + 61988263153194461099176854937541307276819945276535646700336661490807805382556, + 93891412733270087417761433122770674128749014393484622769741056647992441829292, + 63363889674615416185536434160470933196244381606602233633288614871350958608504, + 57953588880482920105228087436042056269218205544984405688887514341233961288312, + 37202716535882957410130484132420426975239211348162703069752022374055651765109, + 59958078232814986757506823520029439210847472575998198149597771923729988334392, + 73560225664101637419846250616223941610802361458139353280488006007864786858384, + 81381083859887868238086072685326819996965414457869357163869779792123472412145, + 7085157882501413219812434835854687065900159933181862064353013336638344373447, + 96323965032233713206686700414364668247910934428106349399130592377824653246232, + 109910000529236051040407434199551066023563179445669697010121447722899830279198, + 29188016024553324107045322080633386051187027206810697421409137837163892129804, + 69051366764640468571833531247770505999662252760133413951635904163640777044146, + 58560547696548319526612391997822952465186480118537362269015526826027757417740, + 22275095446365462043728943933714148759928743432954182246695721705534082344697, + 32440427492278481575108223374055567802781007843970704532426169346764205187443, + 41556024815868951360471047174340574741453577779166316317557158788820660359372, + 61661933840312781492274315958954278472042150432717237773790461095548575693145, + 6137370242550349594245563032374046320144928809115178447381366073042770592892, + 10784033868363152271525359654516206764188060950961748694215913733347737194708, + 93458426197448767708968587401734206036890706232650366929251257287232932093955, + 32182467509803439353060788902721293308799800424277552498919236591376797449692, + 19905311904012949311946045324734835900907829038092268103727592712825419198393, + 81349670002808635614408479409192446726446433374714920809694925383765045053588, + 25112713878147477692953589488753271343242533609759111433667358427542542008198, + 60019911613653811171605697997215853912977083567615046627768945974967091633369, + 110060553792790452991226553887730741239931728059117544299208218340355194120899, + 52472093447443104162058607107887554229116455033002880481336298766763597174398, + 16018921466897698896156081392704882247066006769479130883817841930714591042055, + 75074666851877113899616333515338055571471639917059500598430590967335041000483, + 107829759140907569121705481139140786708243601909904041925571380978266885881015, + 110203864258910767650677989801220374978575649078213706976487950103512413007872, + 33249993498895082693761709690886961413973170394967421765825300309291439473141, + 33599956176531937878455156018238941038814691588379287252798756848228642505392, + 19100199957826794651029234724727734792825020228073638641069144245982458822183, + 60121413197680311130470905036256694688241753904073246384310947441968611565234, + 80645344121742080353214519933523794213979070171462352629383436979802761952708, + 98351881265043784186559710632543399429272683613985605391421284117545858542139, + 14017433979803198226154330856830790332261264890698482665375720508339161035991, + 30516489360385339243081132091198892165384226000774481543306716914568057465886, + 97262268011116201032870333958564942189735389039959597184902148026269190625323, + 44302058790028060916126872364366042291348234243300830403542701853910262565263, + 100126191029254623002799581013043940654677772195235073918460201407296040680690, + 113612569986669295254547518177010746360552558111270202623088663779762845091534, + 79338999083369807218098838241712623564953252458898876987930131393363981132533, + 81807534317337842862569492328339540959987672906429139903192484831200709514072, + 69099350832806607094526178983385753179896696665355438989566508005886743564803, + 104259526504989324371680245291688817485009636865282319690324704259405386257323, + 46048548168319243519174905186864753621453350991053076001561241537699241451608, + 66640009876573485928514453698651726041930085834893369045270051012573764107562, + 95531661476915771479769287984347060951383321441714868684347591823941686092603, + 36621915424047154550909586666586526731143413141205089696432779807915110104143, + 25500685371009586014518949017154447180688166852684264562707954581065369462252, + 59850567117714407775930240974346637073681921343555100772661936520702888306819, + 115240343733804709663552973618107878245728084071234565876664228408998144978871, + 75977065295485323432275465827564116229512558339547601200993934982654176176682, + 67106553301726645936161667104383224711510817789237945465187962215825839722899, + 15052746491449311800683700291988067594040431185050499702507607734364951905357, + 77228459676908565530579109017013955701427426823980882226769852055847968646873, + 28481534507829921014499911445631371835270965059049968012173586442641858927952, + 27655343420845351169311232623978922158364959548141208019319314427965146860850, + 61390729924093182415849764127651822560510081296074798219284080141718724008037, + 88129944448482016453604390978413099869373896352594669526016264003367026195399, + 38820696845826898829976095148404250957464753986673114269538352848960231325444, + 104864171396750025491806631675409842204085024417616047758696760234858107920399, + 29863292310431477550036730221574081680999194850430672446200391363561085417234, + 108934618562963817298313547225211668640768732952641926484962109008979027015980, + 41160261084770991353568707663278346821082281639019262987685055833901457412654, + 23902699369871836004147116325299221152105461157750810215575910523519613918256, + 57114879668068671783566032963607014449535061298073571460193859097850285363274, + 37740277704857454409433323326798536839332127662247774735096314702899351447384, + 39914634986182851804611052974947659631845131120833743915944769240870362593379, + 22965980825421074760380373511994945118819421738400198826034975683511728924290, + 73619859307004883133329724216060887068813702155629102968658791645311681234318, + 42626616499504872195860607227372694794739202104648805507402666216755461948821, + 27180887820987086213590533893445179350362971981710837961686002209737537212844, + 12547893500051955564697063098116328089916920751126177272831111779806370819273, + 6383124061192694324327191518704951714003591914147776609778722446554041043444, + 89411656982600583277095337085872844640689672310374820842567348576660511067132, + 4931640018542825079475053288396739880495257267545752981767551051947673810942, + 80248612782720605198488022986328769667781816440810765901226254387763015785345, + 12092028429774224084710381054351226042549085986572748481457195842303445170944, + 26146229475813700978605757401016468603312254089417985071251062419204372869133, + 2255026428176704188457961449019441350458062228079742175788548046834027109457, + 30641380654182036069530143269080252118551203033739743249775363571491017684138, + 44132536981272426733250999775220364339758797280204604071812543124861398018806, + 97024751195532280486870245916635903805436538356870918818446669289591316332013, + 4810943785165798842561294064990846266172612239112183384692997244675590825324, + 60594647937573463378142351679499462396718637663411923885077728572312508937315, + 106092534838894147114435074387638776799689173170382306928669206389784540697869, + 100350214583612771332744853931993730296314280302784006748300068964803633975616, + 25710297987605883256119632828274987784677421689316367238798477028078257694760, + 29123071143314070212924653332015086436019595290116122837247518928607737843641, + 37069274845961702330619935671375654808915261415409206654572437315129646216159, + 2103163731858609902987804239281112140757230958868454407748185686103644104654, + 91719028230181448577144939867970479811949564076488402186589520277249859672867, + 45391342576703074661603595308417176373809749380471106452418335380970183750772, + 50417836443890530817649488762692685498657632698803055765969038288656593393888, + 34993633927197235881176833068161353999691277150832894468130305354530984616662, + 23534323466104975762076177772455333857141585658769252118576206968469709039438, + 39190055558058842754394430495897983372596751221323760953254502173782252535142, + 5617230096167612764248946716702642502766239621115392206755049019979230559644, + 32624233651603541264283870096797526990159646990330514664119567353196848504711, + 21363196553685646388482503553351021443836786242107559712907126251012523897415, + 42112366171549880891784673677527916736324180967747066190759040259635872089427, + 31712983983859822934236230461736938375537587184471429809349770647766964613362, + 74651608828926796831778724801848604143193793124412646850410456430951695800169, + 31502721543493790295404111094528405894067828931947636951691670700174890250826, + 102574444995694059195989875942166747896686576241543887339972917475254377264441, + 58923697429970839605545650361257859389315238453492910577737280661934024153811, + 16221053517648313779827464398992879024760686223416307556464055966113117947553, + 109701043134056293739478294456803747863765083543565182448038033479701054048528, + 65816269916986847737385553699150904532407302373423496719383228101901272943934, + 70001928020787580403762358730682449600681762898554760863881455775439041137303, + 92835367615230954932800230862822592318664461839493603556446445656699449453378, + 93409393995636902222277907243315184462474445317717554777742524489810073788186, + 44944993053488547857105740048665806597453515566906605777139078245225097180433, + 93147772939600424893831062804221581869839889700389384361883509030083325459072, + 93699923460095428776239408139222448679391585676571354740183685749691866973106, + 28313899678800266849949575207359059769753981681483869123271093014071444124871, + 61980149181396054245246180188404056134144458238839049042934740845836722322193, + 83761141920500308170795379388798930091217620626009308983653555795715338404376, + 77583463966607201364140641884271595665228078550964189961365384033866394446111, + 80177055029944784643184325870695103284420396003327948777031706405120637762, + 42302991430237898859125813865021036118673882270642203528092518119294645903684, + 4649467931816382483273696026378785302400244682811030991459498686575099150156, + 78548973939426759637134164945491298621159043871261650725671742941506653898601, + 9051589590564582504749773754686840417554590132961904954760198468987586822006, + 77803423932364165861392412958113594976070611557518916054916203199233755060600, + 26046137849807276252157032709063139003783870331993295994337272937649474571460, + 6806190578010603245277071337490254136831601647535271379706078675914970059991, + 16981720309854773294680220969620151753458051082222505206356213090810615697908, + 73621371017082581941086697199063866558700710317876168463219943638793043525611, + 5952160277770873279520267042269542633750554504802687675616904371318313037651, + 52265032098720508825832900808795289730022498334923517214767581511816371160360, + 64203215183045625683829538324346545730789123127866404225520269502345859682640, + 61977029726438030483088364022031817298674742428501177198938113200147052841179, + 63873459224412672703987885635119052772459003219750133619548346313457608388807, + 2626598937072069170981383608611653141972138783930451201089190662220200167801, + 105014669327949873689179545239646646974007368914386147379235001429273363142787, + 11058529282049329098457406723662177612408721530338848074206127378504846492509, + 44749368542125353666772469444721723570482557168039493611180344700250046286426, + 82636319376686946962602756101799261516414332824933119808265360381269983331970, + 13088270297708329492219842466712903674306400272058781766367139492318558196219, + 11591604651699081578146653012861739738078724779779787286542890320841633665451, + 97519884363160378542487802378317147290010864449964759770643202943420127802264, + 103765153602223202941810462552259746944903813443024472202605276597249915550516, + 32600862571473499155120994502986447984301774518748393315923072385051983867738, + 64338343114782119882494380267000892758659016560115644027856295197639197948121, + 70304745803552289295010000663269329670062399995172397487425903556106015777747, + 87347608635951993976054878729536381464515997284559134215265552082827409594709, + 24760837937750392637884760244568573306303303059586669681982903741732781839222, + 68020556769566088130464495831741210649627126271195366251054339005471380772233, + 86590404461941557319594983758896584682276289501907160003869380343558807853496, + 94630469610568401285910552228574044151085286499697244331788352911775713556752, + 83822984587785436336173127551996786655166471356009859192359391421830649825006, + 71650994979519660718419404000182451979557170967460452856442793385735816213520, + 60034133458392675961813041938242460116247157326651441051172749157474680023596, + 10660815632412363754925154884806582403128772462046713154365199157403468694836, + 57343971592477554658280327617393743085274397711175189009881604060525070733420, + 73136733094148658877333160562415430650644927143105773716954983060143555464306, + 85440404039981866230662121118907356481404696270556642000862520918533196511366, + 54186828323348403871069766176623160867804111384527021970525712913574837990790, + 32861639005228661799058532545666296094313263213354030663415414372379631425417, + 62435477407429153105556804571106761272657217234349922083765158636344368857752, + 94926996881981248755683541557619155057867208528997836939147133929580669784745, + 27273317232039193629074002897322973019198533330295869185646245861510825302456, + 31726650026399007682055306299222171571994609109467630721479608436601166965718, + 85013291104442307260009017660850455440506230923010172390105254539733688893930, + 84688515467817936667035613961749011469178113827874947947379728678073706146566, + 8000043581903044187626831087385233308531161560821002291292997344514542574861, + 10728274265650945123021280257565412765339875792613316790968277574570999446809, + 111135492659042640357368642438991986111591796443110514832717954055225841917978, + 6236940258597480569622393766940064897052031664905049950316462273891076916773, + 58417064614006717254677727841191592439764295565971175433684326510821412906023, + 70012991223690604574612562233920263463367959170941379143744868125063733461799, + 17553430856785112551823227172546504414011567388464825466464197810448732447528, + 75196746683260204555069821976970306322235611913986704735160941551727952033066, + 4177972925249999774044507880679510925550422339555421875354512693137551690541, + 27448422819485949892314642973888660461231831322749289073425574105469045850930, + 27112620315203548630765711479115662240898743220222720489250776217163293899317, + 26134395304252433927428638508624421444181051640605704105587542606157063995449, + 48055323471155904642836017878381028173995433638774830311507610768180329654595, + 70141232116639303275594215341122469578214451440984676820315708818941014992455, + 97362039991400118937375759014771301617335051074072313576160597167578291390798, + 59498744397496254750667205892414552312610986306068383637013423466785034099790, + 55044250507270497890576271409360951399826457451259584081702979748858005203540, + 86460171717901445827863985929268084902846893704625439056276885241262726292821, + 23317071379891553315536795196696703048777217042495816527324818815408066653789, + 69890525662715194049154543702027410940146763855258347319639321748735889979497, + 807754007251343896556493206120078763843560177950734372358432427844496623722, + 77424154811568910487481703168165337863100562624125855039718328432698503749486, + 93949479019947052516081318035249182358122773984752884230110312207153366729333, + 97760211342925377297437825666192384623290098931846409798755562000376733120128, + 77181003455755887222976169144131126435281559444659146032283108699843332894598, + 50997274636133212992178205232269582410770523045049817158913788640979779352714, + 61231394068599753397319023567451156377698547296646407938855024402620131810189, + 46310914417223978908533423400825451583213902177986242878236812611298604355472, + 78888942326033681852705394726853367790161963641378980320379968016449930685335, + 90151588908348778869041727455142325010460208866421868063206862658979874948265, + 101238573938475264930714769670270045927562839001970232615122789155233670330549, + 83652134723285667921458928125975232181677272064498439631790176512445454644410, + 61468550413865472928942441294978158372461565592774474901910649619331836187067, + 68968765571686686397063145320479094890030143916895297753270420895004404993476, + 61798872554856153172882074877619765904740475127065862941126349793363494166468, + 46573338659142703050162402964081032893158138933434106948619884258857294581189, + 76821769459519910456910493244642048141126524599000215211005977027890045356229, + 89086634531739016620632886341299561732233750668263297234175608574626121396169, + 18269148541058486241010937897742237182199410971901533756451007075618937411273, + 76923947773185174765057467292696242693333690444075916837651017268597779815634, + 62695560569368951962459199106700268385861406656184888348015970603993321745363, + 26832497031250022393767443558295003607600636870355540101612314164483985398494, + 84500534994186893964493029171522541229852180881150794942307211861255304189665, + 44285508261404030081594397671657378017322357155781010987117103200851080243425, + 25196615663499142674509946643517325695854942451182260008714651637872065420777, + 99305442900943338519472778437924071503211993055069645190669845163220239479033, + 85805364957344632634503891932617006982380155923881856744098377218203920005626, + 22003381338649782334514084338378593509593067056870368289820493521776668981292, + 26683687105195595843237580804763455823398788251332890875215104940188091381305, + 110464050858264031539622445239391998647121739765959319356287939977867756583210, + 7471593350788657207469280053433570067608276131171165125985695259621860735775, + 7072736435435639398038184766439270954408782138488579773109528448839765061925, + 91915806855501146789139310965134211526570393731188376833859398667377284243750, + 99943867953856063709009671783646897434699022116226004816229108766854572108352, + 112512909775115735554911667864282563207101882551451616049056831921300839997939, + 89811407047407829555624895871864026223819909399804432889050602539801401778700, + 9783936934062210669870013025405367475847037992961269431928666557105333563721, + 17689031339513906290935146137191811608520752036415931065520192894550435528269, + 74506200654851987166002021578306575647964038829730730235301577986725269609295, + 29375611824092877766836458231480909424396049346662276819264199216780614622064, + 111182298710139321563429299459765615479697973255643684101123508918407911950721, + 4294505797147786823273071195005043753762920020598557544942753458123114846075, + 57275241925930861287940759914062157843551774344909399581448062686591181552526, + 41739812182070654271446030749818843305078439752905007960302736948968768527279, + 100388248499073296003495049107965689661715991201892422837884938420800455401908, + 94647112259790764004341239190106536582922466276741897004777141745122827893692, + 27446994966727462152927989428229968706010108700258464710153635664447896532671, + 103373964168408557192568459497755505893114456181120018252418821037265999834056, + 603593167867271518491104108137635331738625984832948984670941407502421070068, + 32482470803410666246991240533581465544766721670327269586518246785064239341341, + 15478306694515520528408137981305949551146588074589891340158266407120269983585, + 109697884910557339350000389307898510984056547954200064982219359838158244450424, + 96778364314892915288067907539120948802273189980642443672533483697868422413249, + 100813271987197293905436808180399861301221576585368731570245700083531204773003, + 9848580500683416928405022232606276693901753536749519022578044851207387657060, + 73523051401127073155274337744466609879882552549678863351677289698080754673835, + 62012384606146752910447709580267400389050652975786343740374267007192517899887, + 6329346062960593046227575807350591579764645666581841805906036452574243008636, + 29583010969615540826792019459651511509381447857198039888276001242967767234916, + 65835705131934183080553848663343278612885924692142996907910714583672555845377, + 4364909788959277766712217703804484155156260164483696706579821797787137363172, + 112610231123167259542597130270426227120989272677945330157706925167429173140529, + 107693949755472457951745837658200211100579646605318103464779275189662278470233, + 53338620743491463081500010144251879985952578124463654647813503945567112458709, + 60069833177830629042515976514509458207591731897826645444119853240467445435959, + 80011918027478292382958888691939134014729035069284567739709264874848025331642, + 693516542070478331317581801443570898445939579828262533667011598135337800866, + 52273809695441166643905208660760083039527258194483886293511034201908954878996, + 48840733848173156679330379150877002447700620824155961692002854641298012804735, + 57177651229823916846632576714273702678467236897696718891161348734004407812481, + 59394243546052552355200754776478221651851463486911732831269290583482857321475, + 16550719962956545897901372302476500994527294219803046882654724802025294071205, + 103573320409090652734324495377610928985983385722787900423283112507251713261092, + 33259673518751152602505157075003093660493455933849778537815986914270085152394, + 74697264217938195805376402721144297590227837706586684301299004109144351872828, + 57387628008782592076131064352669617337376803473279453333601127767137583857477, + 90422943937783965896251880446521463249223856747181789740898758791488438837484, + 113188214051724646646456570193904272345906028281841758217826198787143028495469, + 4725842050268204896602970921870440551872346835384443987009524265770910466024, + 4778857974002036103638830854878962023487637980147632054374917120421147120458, + 71182355475849174278623329984818066985224976641858783457500578440294279148410, + 72094742982743112683755179909216029882769719959110477054673870672995765541751, + 75741926097018879807801122021779641641562337391714906414741504113426658853579, + 76126900933152711297871037994157121871573845125038375622160747593285279534261, + 19830826319186275635688571464121512174409870248240482681104224344061615797680, + 64573166387796849563286812336358178156005102893400560929809779223903861483443, + 101097866236081389888098000095331715828027273652681294902448980739269851411008, + 52162381067850701656566498610323832776957726621962737317455499639791958990412, + 94082137239985688188363912099465534831440190635458223532770690103361964844013, + 115652444030331992062393380162120316167274799004276617977305614784404324860459, + 48239714105427667448028676320558629477947116995528830707706487783344070508841, + 18298742473303593403190358887380999495268221015304085069258395387129220030773, + 89419164611619560895129488892753456065378884899899321136201939028192506686435, + 46512579469931031012454561431577598449179436511765097562464071037556392173159, + 11365130369903604063701150118354634945169822928467615495117669802645927944576, + 90296872880306319520426117190162644370735495254783860509181863060854358311328, + 3064805101495055213296802278482194523432209139269798785583154428719886535606, + 112510516323184654550370145031913966115886561142387688498612170316060493612773, + 65799272257840358508972376212059939632458511650405519990658343838813041991930, + 104469330504384979723835167750074174595011007208572690780514408491293026170337, + 44097538443652398316024901024621650082431061306706863983908612088229385740399, + 28168711387058383734069740442192452959396267560259894904955433799272947786897, + 76673831642747694309752168954866945349512011868688362715231305509609849727884, + 72440938281741438731682859404930699562374425734631837607004099593809295051580, + 49618858294338560068114914330057108682505743160850176669629454424505174616346, + 51238128137426358668925849219007726695779985737877829986685740285562359544792, + 10449463158360741808383631154708379943574507465797386131598764949138172699572, + 24787230318545162296239661395115840747564078510007070819457101050783164233636, + 43738608852046525353044056554316319515407993225683285250641284054665952152168, + 87308324767480248378827366446197165365680286184097744194620305788730928305516, + 68467423757054223744534485288056970030507932912656868536126222694537999843935, + 99551305565430698469897528692615525808389688973499743484191509164464808554608, + 2805794391190892615517138450112964718804088830954071044888071981444981842272, + 67462544854592285234311676075848013111822062648791501445495208766715408210452, + 90362569237855451876768483574628188017104635283145505301524182249740503473110, + 37739346114138090521447256475932887661950965608832859320789365081682214187788, + 4499714811554158216842822430945649787280447854769752290740438437966466559531, + 102369149248015131943645007413780706509197937636266855825431159592883576061213, + 22179530984562929628384070687261456333567726884427550471714078080277228065658, + 3397034101705588119837422265366311030004336547608067328525989607785074936400, + 44487665660362560575633525987282110179252707591470599866380025044957848994002, + 95049251801876739675358915317357015643829756121158870062343404958137371541194, + 42228188721118081080597415253758205887654404769736840376732244792357168117892, + 113757043780032994609345712507472572974091505003593717775470795421675541262984, + 23615244247918703049546704460060439462953967155462759139128539501350473155914, + 53243534348195532076957598606114144129249355968988626098408703360652154766187, + 115618204587893893274359016327918209112806924602727398122553782591435225035373, + 56068952059157442208361930215025005045212063250457549369355174758845097644389, + 40201472928718222686247967989618662911095902396540675751803899004449543422269, + 97262537493909608971879260716928796376441056682079966774415185189313950580892, + 101040102522021954144496233388048838908914985541201524245964512290152093595016, + 104065213343612462433668547993058893155143062558205030417481907250861051160711, + 54164051333323392018264807122286881007819610004544290318301784699782740494727, + 17178322845420293670506479478095862935525147906371352990015630951354405204117, + 24207403759043941550002622245810099448988169647987358910264658566113023673284, + 97893275948646750795844075314867713251431667911688752825572392821935831477894, + 24290317215173540311007859893908168241331987929867467279934345912742952377984, + 53926347079284540925311991363289237894705847069184254052331319117054041254217, + 105313882509607236215732282457558953935794770549701506139173735884175592666982, + 6944139113409158320640054982157829153153522415230203410215931075104241813254, + 37602684865240322276075958512543936825387414551722232012809254570964990054622, + 60777986907418238537483961852631560251113922012380595581132011431647836278021, + 34682873899123282659618414278813954580989931945082638940334336276199402331913, + 42540704749490734548590151557974200445555615150336999427394356713934282075421, + 53153299501808942899564651629912059037225396769177138834993594973053736210974, + 105585869386527149056716157859521172100198094195959299023871299766026342650917, + 113354363915282766977203322855279352763821991138523752496747739793548582262822, + 75424532118741279363488252023911767554618840529965130939740366448758875782184, + 4439807482980730374510298496665716914334305620630331412903993034913165146925, + 30727541097153828201764723553842993115169070897950012909388868542573666385716, + 103008362554072140466700303831958932797234997992982263819180187677186817085249, + 80623908296799616999777507864282843681124042363433810574152577763469061324867, + 28349169669479822483205562367414202996330892888199332220395572806735555461703, + 113900912792872040410403240577674873719477013178903869199323606604923093571405, + 30224379048730325693410919508581304622475560029506816828601176685784678795346, + 72234046861066491457723789293052688074676341089098656700220717628125173853779, + 99546892349044656661121257122995679014477835381889737006814891893958202957655, + 15512267973694783353132493188406085596362132876448796928946116997366462809691, + 9400778046273479327502093151284276664010884959994675621166361747318350952804, + 89592060439404733259888376435645892280562212771881972933721903148652308071017, + 102450428168216917531418362005063954636205790831228589315712731489113501024618, + 107909987869703865839335914478906554575900715925121263447699091776556670058351, + 86676645246010272085840970316089310876993969523858851107540147645044216163952, + 68336252452515937317782368891663662686785200662516138809513057864607989318778, + 91831508704716131412917103553270414899872728809070184327717851660212196843644, + 109786828933144432394911478009316869552352130265579777491349261143926213918079, + 5595010113556280475032918723136883910299867363479473841458733665179864671872, + 113525351160122475410136007145101573235710105026277540925591288138447129819522, + 72910725461368390546014551887660947465949313131976256229881696474765928389004, + 26428119304350087877144913825220295517930917969594874106702876047575509972366, + 198177523344743488276673986937791356115006214012642934810979910453327806351, + 48210866776355476814452613006576792095963994031606832413694934914351729124760, + 26677926086622761684169705546666844986337774654988886790683004025979772638371, + 92518787491651627474392478627710856396394429876911284908743156322317642012325, + 91148179121452220792707220064146355596329082424267274836845689871494110759845, + 86073495203265901224224453161153256631957850927927122103143994329144122822566, + 12818795288132231462950399347694153302566589430553387001242182514527626170790, + 62248068059723875437012723520034795174125562260402110125826038812872187643832, + 110608982670103182042242482032427610844240076839950365573606079223328409355195, + 78167635377618814110162347981498721934361620232397571224907504845957748542909, + 36338691029869568447029221322780901417127869777942839657962807528707077256896, + 108699759920792964189987548117378027407499105148697934363241941477702931245249, + 16501203186381799715338918455483551022902482956994606572128593664442966612430, + 39762259881604660299365909279205844700068157653159841986142539057335531674576, + 10046537791435493051792504559145384185910998025953759563594074132236799421656, + 86671159097820686680968230014125883092833903842098905694626907991871547633368, + 57301915970888906063733515432406843374394059767651437471805332230536909958362, + 93426904697748347827965222855341808166178565952737098583583475462462536167900, + 44350928168303253623722781745633905147882532565092969224150452809748996280036, + 93173086301410035717634339585647580002113016622861296627516167981780551746555, + 8366781001499557370550533591839340293544024363456523122072215160112880257750, + 12329685773447802271549583850493254475069810991867526934039869397849222349, + 16230538461811379350348469588059499176574348370854304599112241163870553864602, + 92816429693561262818114877682147382548868326562423812288663776263628024148012, + 87852900148887772390342327105836793287541385667129345364350246742366296779346, + 51326750497837373912478505248289974534244719139966156370298656826530185589980, + 3499816569314049891236325912108479431434735029203016711694324294681015204840, + 26457404095845529330854346025893590159277804369550628148623786950648477003773, + 24926174935336091420837850673329234888823523744709807086598558364417822275875, + 16803731629740620024725898830951457486274852852760429791276542893422716678225, + 3948832460210106619389041757945994063963159033606770467334190977972829030183, + 85049526100537084877505077761714489555701405265805842660811985317669527871989, + 25350582102996927026689430448224301392957308891921472951735335493635866336407, + 60537844500584773305641630171984978784790470400724362271769965237701900174567, + 45022750508048122815744181661326097297262276140979586253963643761974079717981, + 57140965077109190670829356615466111731338865349736559658058205897145616370408, + 80015762649333825816661151111873034959017000295095618003179484989143516884891, + 68458710222209214842506394075028919042188476751929762393792318510421683095271, + 43645007422496087334663760197741967172320853484122496653182376185495576899204, + 112003393994827276244773756218471185967512084571340799773689817573306469206263, + 7658030109408667297131882809581532208521574379621079898151516389976382653625, + 14928682774251926156428882795050052778567869666299635936211771282087482553942, + 114390663543914230432905108462616961558054356210675761103139443219584438688615, + 10972878399642611296660015200978592680579107224306326398185282296885436061006, + 9007342991680696392504229398589165234312778605628039875895507877324685092363, + 30475420419978535023920151069170547102259590228374616250418624757282282195735, + 33667010784226657661673564383234981410444047229057340678787668226330667886055, + 18833587012287161637687679698523713776296844817374046619083388409086608511690, + 83329756202690734392712012887878306217569821435251530250203721296593615124218, + 55742993096306032911508957718152700960657218300662938540716065232756052886868, + 59069738496199852357888488504496837524707245944979831886538683727461765837572, + 76692315097894461904905712237862355556684996581605859275773671781648633239531, + 102311518815104786513438877425696349895244416443761384391746812515891354901663, + 108292848623501996568777474118124492675956835236996846394287840959461359892533, + 66846077633165686389225967668667732771800880086241059086489464057674986005059, + 22335298303919535970984936536522839718167799493003678860350198818295075465738, + 2088697474239766820326139473680869686396348464276988437478814345420083505818, + 9800257844942895221705227904598166674104099914828570293509530196452825545504, + 84283096978529678101470952352414822239619478167556858308263226683711074772777, + 35646898143459950642531227649203826514534211024922557008822990314034309304433, + 68915930166816467711824489388113659827317973854400695237936435184043391478328, + 56786622094195026554749982293266861483291312099436126378785512576413836585289, + 52986120986935921545838191743970961171986680075760259417072169853574832864665, + 55730199715094414714886285920916344245810582363662181367565129139346775272249, + 28013911804949354618732433403226606802345188396893083812221407974635820017527, + 84362723691744973839838972125261811295443192909309835617607294104927003952936, + 18663696167800267373969633524123621566457528201764664569269468800461253546977, + 95006906185000498991255962130538001031712321341351425677969542483421002146191, + 5298440261353315066653747668512592893807787544136161589618108501962462817514, + 38859838558420878293396896040655765820066194302595304614249299799701969873194, + 62289993275906160934056920090330345027894665501715138137507968483175261858487, + 54327880052340833269705542570479360069680899057285136322248724902866351935413, + 51589366609300817829884327471651091087876029045952488993924436150453442479962, + 26921021563144202460027521541302976097726425054221581760939871319832557643863, + 101477144862558339592010201891329191270629339715062256088293623057030867348979, + 67901316707740887510310995207708798642284386699689148075505836704418407485069, + 96718178609507532031066376256798405052465386662125419099155741693554343774050, + 26057346807973776004736732145629815785971179124940162688537365590581469134766, + 26770976915973141876303489733568808500475934582010853170967171874980845098246, + 90537729648129293845193643651455395479833726477469470782714543127473429100348, + 78719234803528776224284174552393513450742431864330850991766081667160518666329, + 115741964230218343116772577584589437166858663623766911355333279349212378134179, + 60736666566738901086957520290853833532308103148114718279563506956913408659154, + 84824674252182552088479543210900337519198211029548558621905965950134454374603, + 108698872909488424998665637094840058468812393615025954637639908183042354360600, + 54146613227259189275128214044106391528698365412789978664946702873429739984637, + 19190887228990422929580223605469121255650473937306765963637636391220651049472, + 31605008932610104655767242657796968638230499973988956357574853626591971480779, + 21103212080963866244523528876877494131679414677588148235986943988755883248080, + 114433155435970775041646627039729981953845379846848605819115413366608262825881, + 12726589349335878729249976242215037847246102781344349200442775736571617727558, + 16348031017487936874087593829569595549359699409440681460000690670264945676325, + 8079418078298720650319255840051391336673776121792199200691556022312641097491, + 49016412610833629546076523881989632302516443801870284008552322936908913276281, + 48108164327189276601708754200109210550466531982179750884137124604620310192671, + 33323785856914934052554007066896820682065933988796788273060445714801110487215, + 55980415036549356073951832253654659224774915615566934805570347344702524747730, + 48834300971025104683284825297084497636993068991657920535339159305238900570088, + 50066304004711728127351550601173794580986385856635071793333988822495730607725, + 70184281603894380046704481689884562737604128791797582166531084708793507801120, + 103740314900311257783843055667868990009195980840809088897105849628760722031759, + 19130793700542452310802196566561977019324274086824135479591721613945804942848, + 54590768665000126682694282951395760648682789569338177215520354887037069453620, + 50868057716401903309161037229172724679957323003493534436996695949002302698299, + 36781356459191931011600117685830070874073058722198240004696684668583145145326, + 43557711700151059594566785929505872853275997468603754860423133239299703134109, + 70405173861222214879721853552636256016629983385583392200333832768240706755239, + 20602869602080648291256883292015993801819651681435012039740250944363000867500, + 45506777931975876010479331290127536397930187117281747538274184363845795563139, + 73270206960413761329060196522798466140994226053167164073699349402732976355898, + 10274987270816121282125090703863593180533037743998837798294992210631156864964, + 87879131351137173809037376974459187218923500439497420833727325550562921766961, + 50500649920892909656581358369272905405509859712585197222619060367145853591930, + 60002540843130784915238777242828345941657276753823987721511537115805772233966, + 17876170006535450045595809605004023872066609387627296872289556538768974728940, + 90126356835141450793793547926498707574717345260769659813421525345098587452928, + 112944503501188873438274931598670061856218197700070555795176334769848830361786, + 81344765621859749512418566552971466151256463347262095479995394806870250601473, + 34985812588638590340101846738441452101844632705556866640691680099130705768521, + 94315112519297120008255853383632882596162459211449976831118989248914689025991, + 86042187705584591024459410832934257357435022905972134758608851702942264805202, + 2821114061220849213085489316613766784410642518139164250358498114064425922217, + 83805514533090333581662989229422579908672469271335615753129023089921408578636, + 32469432841958529172977693130360061887717363260734452190518999882773889459568, + 69836311334757211631915702001143378378952602813636255147052862837655873207666, + 114341316793003925518903877654831341272002262827385568726522400658279073969977, + 42036575077054530678636585677127203560811102811633788713639445775098950827890, + 85024910361862565336099650819774287102166807753378096928032881329427815521769, + 55324226505217249310091374352904161647977647990440486665314182718184535148848, + 23774778001643343109035069197094064479934349580513929703915702361582199771099, + 36135572570758544226449039845346088053007954845788478796484389702665205938997, + 104622322503420343506071899107410854115368216537400932667643945873586388988474, + 389281662728734117438239273197528971901632440354548723962746311938389643353, + 13887266920459997663758749023053891008408327262864848553695117135139951924070, + 113398698433123266112256228684235751911280685076715238906090483706357974168771, + 41418884883552210730285397107293628512937328351920791008272399625649916279934, + 63699551918624295606055691752881366993635727303118120108439597851383005453287, + 50154599554853174485564607391603409580529574992148828368548193179539679674909, + 51703605626896590030046618010369360687957477624327788169856216005448479387131, + 4254159162821452371420317804393480625942943403575549832090888849849889918055, + 15994248797720315522494478793549468351058780330046780693018975672663231539965, + 44913976651579429253078278262016794427101984405074296648368178922249612290679, + 55662236854568822130536931586799458576438744718846422902642897867994969412235, + 60593956633691922365055386174888982322636015875495123255951932272851240046423, + 79840315755370384435368745515780152703826574510631894136049959024831792794703, + 48644766712239836359694119014710616190157901341207003336118677673407448688923, + 100612379279849216310165116354954973678629607402136409286521772357575945971148, + 59994648821001237513756641873976607150726605608960199640918238245215509648308, + 48712470416113843103136163865510682111313459152099075206858086723443199273005, + 95821167575999367493941993342990442968534950462811882584888797462476089447849, + 33570276304028281823882462087420012695341222883505352567736372456364999970213, + 99191846026210766831404978275719005046516500614621590164715392217051244166376, + 109610567663228431015302456984255778900920308033165954585745352621200067331765, + 31032627033603205165834722286199725602157845358281914391605244950018749496299, + 7063528408033626067363446944124854257162281483962217036269600681339714787775, + 7318697804418930338469979084221440770838906114098018890045696421115636529913, + 108303941675744539461697768033562059126012241267783838357006066216166416041781, + 103236756975627192725277761755162659731457044329436581638688108553215730186833, + 20596951972290376704311532635663539108148915164977357699006051363295112367206, + 104536807628201476731998394098514135063083330141521028296049251912857238440272, + 38065964407284187458617688532213103578907361788934199049541867476852212335869, + 75191038560850565714894322679218775253538355739973723428850602904090007279728, + 72648426849031778232845605485771163272744424442086663449190842694864645857666, + 35718436397479589196342813536603814186576810029069519027097936562708510815018, + 35441616456217063002811486804112246378753603347110016969586504782096378776683, + 36552949537513875964367615978283214397350720512954261656001869636744696854711, + 66230245543721501499347494133332683934585182720290106391160704649591126983909, + 92401348466732404649752976519802259664760098700303490488817623837298318673652, + 26992406869008023043647847129537166411932602578575016857893104760230396453136, + 51221845871734479006818602103550380559586000811487750582760158347253561072325, + 75485133178739805765053595064186644875798231775269982191276342775641707240237, + 88811591798079582527046453990811302455289778782185134732740829452542340519670, + 26225704416619357441596521658519323507514175989981185058236712931341096746136, + 78782982165736229551869135568277406074490791528493343242322082273563321652016, + 60359811765908282755511626114780393416610047871673899143332664498746264076298, + 15274724303609579349356745665791547953979631067956604423502076684098487327403, + 71281087229709837015183351813981496389569989054420770291787547655194554690751, + 98825830315893142240400255914954806230312123977694093794622783773073061745342, + 81218102972290087186618612391371696647175536205476846499197960517743584691989, + 59079349608768172644060026122257405757661335559716972006510889173341302488322, + 58259135880071943941673098258960167125954215539989132287883961865838366311966, + 72588412345101524408679765726619301630933571308028841224460292037914734277432, + 69777632434818220447028556774052215998833067070441864447454250502953724668784, + 69515308394164181697305216564141988818540471859544560239873847691984914307981, + 7538376676383976207567498462364717279572775093710341794352790939328588648176, + 9803392422766580525157619117624375849814736097370242762134772309051722811027, + 27130139643102436431038936912152291983027488837782003210295257396052409809950, + 77650526933463086890153450013608988112919204054815839999502568215562887434230, + 94674203144743741514864160727398774240888824698818486470696961375689358528652, + 93770165091863769227788806398663206386083827550581044563606731066480269358829, + 111378765033993484391882337707422953321277694203406660477324298951102613825734, + 39809193796622332440293870438058332217694944250206080134289520062428343001737, + 110870634040500564945971057237575762714154979673916904401552546154172138615045, + 8851591404930274221548347869361746554959861627955494892882847992678154891937, + 6397420782027027462379873995946346804165115556775281463749093738526431115982, + 55704567981532789275534204705754990135998505407557369403373317053732745273564, + 8138117798159946842967048834635783117780956760913983284463438018081785732656, + 75207222606857282113674665116246272876796696875090278021343263631087734013534, + 12543847255758777525431737763032947657720105489722930407956988066841287650624, + 78327321252130535570250911410466280437144972998159516285164686828945050773948, + 90196389423575822520118171822181490354156852650241068673543270798740759570959, + 60670122714012186216557490273944849058369509679550006105881736692248220097574, + 10232203056784253994937591704858661588355868348916079002690715804987716383826, + 56250443820912421779940932299238540687284557162371086043710647395166341689424, + 106745151287508984114611432352663460679320831899507458596226828448613433574629, + 70711680571992803186174027940849656610654068847875181643669226730609160665543, + 47838106257302756155005461503289142780947408144101902856502705120104859749974, + 24941360228300096083350701077862032603070060851245288110063415582770095103463, + 25700025266950766720457426715819491124434076610164997964285411086712832180087, + 107105239401310902784345766590657302797260120893605526156704024791074790374486, + 46185480896420842135218739225912740102667560536884160717641823450312574499972, + 76998048126760891745588080774341297240858572011912680574454836643717168013962, + 33808836046696640438659929011730514035734389148647466846824484796567750758787, + 18996931853760987572934181889690919742941525826610089655395851453039249508242, + 56604122983388823053785197845481098255785257267522212256255952697702335462767, + 44492985817019328377489391042409249255481209488552954877743884032952084108568, + 60262700527314881511672082853298753610747395905734558549210201078525650794369, + 69279306977580749647980374713849506038229420028933569196853781248094801112495, + 56195902117233403955930282133702481708365531910713600561984930561415179141605, + 47314831690761571391132666893984250546663032935010391247733227625093836049663, + 10812783025036209706047425037985337032725721168017483330083142580280303327499, + 53162496752508809045501362001473691445566319961581721263708067457905101215933, + 58945457420632645086059903599934816006401780540563391798565832004056019028674, + 73919100242037593331579812218634568218168417235823351457219323808566405869284, + 52403495269684702131086435910831711916163695522829566636660560660799048967805, + 13278812163520552951184294461865367827589507065203666088515419774920490046846, + 16362695154562914334155901193231892822961192810812064385472498730784665801421, + 3517056216483029262257506847130510185029740665166150468006894224027844758082, + 106493755768367304437249140676246166044758096968225683795417475315940492882512, + 76108738678107595032074077639412467077253203334192002336836719868953673062592, + 24636115565757631437667031550958535438978674430521834147987218537021781123234, + 25741695857057356211640713390935410123855223996729071384196495225008418025128, + 19955118751219367788486540195772941722619062836730568279729801630161390967599, + 50727362120812021647921340345708573849532470529549431357712839661035232260499, + 115008990003359379169498136566608005415041400711302906652756982799431888611581, + 76011030665703432674887267454022929576997959526321421566956239532190756808010, + 43241178286167700202427095152526401603732039957292715002566291226481343605762, + 102116375477349183975745809892072191840693105552331542023102178483468604884270, + 2367482012407755484187720340622873573623580517843674370407488519063191397691, + 111361344211502819366872854692911530822999459773812287285457324369283709635699, + 109657494092569138881317447671628359243100703575477818863540322790386549722230, + 7109401893987191796852399187756624249465539674575008049772377454960266500911, + 62109127966662221855456045871471976300684717590594143452168774326137424630915, + 21215429047648886881079414922583785408461108666443625793715979556096401731625, + 19279814532392817913943697877621536160592294051765916138025545274590518161014, + 7059996909933719857026691582224036233378957254796742907276770679435914795575, + 42259543559452493904761078751431150845991251989321528250253410612380573321732, + 86565632998965501509262078248502654145399501775070068265403951188763891315010, + 31945957244800771720929732584726907607349704858229698053899900669252052622291, + 33092687574736978943259443103172536628775258103460837384587272224669777291246, + 49991423183781203023419136847708046249824217732070381815053725604886162286791, + 67696544473506340614845249586113063722931832682767051358934753387764790299157, + 44300165309779156455215620752097569573691489863138402159754167727039908383175, + 76858130805950970498647404197161756362591695546650290097815117903992974846379, + 53276036540992571104528236913288618220936509140158418588609708019288597985187, + 28836557358889989094439138775987779139189528452622475804026978942568149457238, + 50644949972958677693536850596115077476481883558935180276892583079964074035276, + 4313035479479260652957532662237992841202310127861671108799014761208414897840, + 74980974204719065713949925256433789927275757602890792189077543891295362364291, + 31221916081651421283201076921082457505494774434921329664641908873546309091178, + 25462244836002487199485405445806588780879544203146092339551376405142372822334, + 3482999242917196361310871854038227752332154051569125713305221689612101519921, + 49649109741645026225189814305214367307422381752801210793812082736369288961982, + 114342386537218413877218058901138371235899462628051411191197914515720248423341, + 18244185134630746982865432082289142945107926531633581824930025314084943124989, + 9665298437683704295641756074486242506598006561010687667829341839141938852852, + 91836819741188398512794812056612855114211149643842653549306158789633836413366, + 57810787294785367000539906087988355564561182541447677614819545817922883191528, + 85477736256329482640831710125138739960164891241946693192003483355122399931470, + 115588965459262364728375262949658522780633344307835283517036286921264684089297, + 103260352544636963665161503752217973936299959481004422664857988702309622109391, + 107574880423637027149194310946125447078638778251855934418764355834865906839141, + 38988557583051884992589337804370923392967342739458652510352831410409331956778, + 39591776179706661567132036672004460722863449502638455439206618051085740669736, + 17295299718391811533844201860737415438218877987077723172426193442926174384820, + 94322782843392951587915185212638734339638010622233846794995601632684618885460, + 107541695690889810178451969317913054918582980088580045884174219118960727155090, + 24433009999316283894057987656228233755881297257138490518346832470476102407067, + 64913204017500537734788292080991565393911137003526637813960355193901612144235, + 115739811155188017616770707442608984663061587821428694051419951407332221405139, + 93268006609628413900343026290606426540202253537136988008591079738656031181746, + 13590790537658288260517954266302244984073327090302715612632694655517502725700, + 9498887082168469013904002090047017291677776306533899049946867646338221837834, + 20985918901466134918911053217454386226167289283904644490924463147213654696049, + 108491228858878295885197481281971955944345047178278524028275614393817966339188, + 110455899523979317579311443631776197076040047784034262076820899919827473519107, + 6844215318841599774529444511351358879098255296841141296301492647973263268428, + 65682796126283140741520637070656076629243815753310091189872944625436827968376, + 23517150246395086433614856150225290129244330727029257108964098352151836879094, + 26047331263994186391482269519815462872757319506074471845037389898789825875247, + 62205044018158822229377151454547290134230969846786281526843611718601819536542, + 66160405117911721687124720428207854312139716610213208728467032646776645997376, + 89866281829404081780535119126058454023598298022311318229115957056736118948204, + 97205043720275181149133603109928920179681558801849363897295499342651072536519, + 108224954134926014239321602285859868141619691513421327461634944098887365621534, + 62127427428237051674420339353192007342916027118439813622162390804228610889186, + 57893944818747416682894353987640739673658057551300981538784349653023861351437, + 107011232727952378470666194813019614835857006938192015800662810852391320603663, + 89838837943621207939392244168865315732107983537751534574579886291497141924371, + 54632573359551426723243036703760553108536426479720114683903078151290806006296, + 20738611782374605156646956064605162095779086604063221130932249292604798904608, + 16350363247384903293056062323455724399281244734754303492438311847607498851127, + 55070254729385682469339142212209832394927084852791974237827777250490914753097, + 70055365590940376112291979561642970183096463801380594679980002124302391877728, + 15817205455682046340394432642972339132738094355192512023066776236228524938855, + 15040978696204192679398805504602074348777447046879772840279566034525028940426, + 108792775256107403391456813738746267828500095466992838148489801045427465606822, + 114140463922141397718650461353581416960441573637400625636182861671768677438889, + 9266792816924420616455524252906093074312617869373528239786435567511909850584, + 97488859087996168454354238919383087328089783573229831853115198044932227680474, + 3306941597490810404824812394266973664265011528485160051134428993448930071057, + 27016887126238838335087822685515964453061603198222243802559900884953482302042, + 97101633243587215197612635088560080796283971276295720139023256646675270471260, + 25761660448050799443702883851485246968893581735447113348244062051810472315861, + 96251340403079234568523076954219291233649081305077170874462689405885368052190, + 75368196346776588329316860276886265399075152883748080407426829578422175435129, + 91108890034381164604848107828959181618294467488462096583429208296553396043494, + 18383384042495707683433916491880915065880560710098616373862311370236787240918, + 44789830627835059483221298616711282663434668638226788590848493956012207964209, + 38153747047003712884045129440118737151596726392380182899055728495102932659985, + 90925175232108580050872154670675943004849067464852756622340307812594900959940, + 29597858466294747689192446973316153084480675933662710109785528207120195200469, + 30968239515894501488693884336782052877086193232886478078956587970878260034042, + 59826399967474621112539680250762484645711532878507177809792747649555312814580, + 40402883816060368873826918443535580421498743432306583826516865452640652948322, + 103109304131739697403920071232053479325353382647749396046095727994357758653158, + 113907958699654324296036491251366551291536643809192490851021647257172722312741, + 79076197470325995404429433846475816380495936868943975590060606361744446919928, + 52531615235368617688492296476022505542606817220887394120841707850740416286419, + 30664922842482873679297001457676095151872007267296250671933573720922787459336, + 30338238369716210451901275376355753739782785259557498904281326087027882772736, + 107608350383853963907659536716445700493759943543416131734911204634602117385813, + 65958965586872418238783384214584168006245471907166614590353170781284445954796, + 80100118013905022223143324948397185079833858834625716770701184726442665663404, + 753530398879515371191977801468379293063900654445395626327580672606054877507, + 98346097904140024964664837653986502379950088691600210302337297775169440639538, + 68460124867614206585581761966234598146096085494429653172723430586270068231542, + 10156644715043863684754272020547715914552869529746645671847735023231474881787, + 50037510783686993668491424242622645275356136505150554174611012370627318553265, + 46635569144774414838714487804389576990391955732471735046915355826842511298703, + 11331911067863218893379169383664565180878880913796054989967284257140363619882, + 38431294446985987431601905683782568620167714717333814578413045166534585452311, + 44398384057199342152223969332814986205258828369979802367663368416306336770085, + 67122871004391847638552204302083639336767183534269367207129447715800509018682, + 3185747797477333309165013849816031863402475405227910777645999204588338374694, + 20212423021896630323680720693447115890743243190987789155927280923344887433011, + 113041857669352149316452161645207210759507019267113009449613325743667591164470, + 90089900835203336560391195533592788756531865029726231487722601178812519556153, + 46284131926838691930664774155938163805065005910783958732358715540938183409978, + 85040548258253186425024226442365679373979881285185303165972206176571521063490, + 49181137362332369980594604018187366669178450916134692029234819013234711506547, + 13457800508316250378270810188212591389582022611819870961872314725573569742709, + 28310457312048552763922552235973792458586658559020099776560334928303823615104, + 91802058223571710415618380655206945885744903142322074359852783750098855244202, + 1458357324379714821644206493939764731936748367480744939372106599086073017803, + 63702161321507657016183298112199231445184857557781471811164211011615511339748, + 55190937570062919240127539671282073297739632266328637800033009517383010297911, + 94277248020362510715582054891654760276529287046778461621178691119693563583975, + 82859741372764296636768241929911801196238429127180592114320811090384150685430, + 104562860753267784619445400790772714882729078394982823289975936490331272791548, + 16889624196322371361266895699658135728060861265972295698439575298043018913798, + 34479797656774547066878888197995074225619744124907080334510867912345784550424, + 80387078517716327864546305704044833524499425210992332886027138566405211949138, + 37549033433004244794842287776531066340633053426769345268287856569678436114386, + 60316902522755554226756020982946012648154833857999156815198525382516758499558, + 10143956916498717878031035057356220149570716018384658787517849952091665062748, + 3912509644482855673597958622581443601329189689401725406963587135080599187065, + 50430800078500925926672261287243186812393870674856580679176377598337931348098, + 80833354465541234648807619310308615804391105320459261341970413653583833113533, + 53863620091753446321119113825771322976178950096485580378658224965753322915403, + 34029141710705938408243180450001896394916135191279220565382517565616904896359, + 110854352538937945899668215350440452593413490541522697725121447074200141851200, + 81046774007854559953999197808086686539317219540931646384361653602077060041223, + 107687652164547475479236163744753167668835962743928369818083365194585087015543, + 58823056910078960427905691862445249644862136913115302747303130775438455735056, + 64778828223477209419076856275481409064383004061886208433177545609448634696126, + 30173966981334520079423222215487422166896399915962359334610255417081222799465, + 2340646407364631466381505408539285802787096947595343952239785490644612934384, + 26475480720325421705921984788405401195876336116695776091373708687906144742488, + 34606822859413066968238325944878055764810284482770801054372683400600651526057, + 9871410681115479619283048859281220153931475276229831902121199950676477832267, + 8769623409176998516065671597586972387597796975533092120484096420203928746136, + 13544498690312614332166725673893888577247744865804701623207685161160253505761, + 5306151177942053484126937889717689408884966428672822323845525566148989756444, + 28025201307098835479206645219070345873102513040684754347962573977234053211580, + 25143765306193849064256195119390421696760090467999556182038230913063376614600, + 63784280865426840029958873741062502952909156932939012297017563642120915436814, + 13569651136871605558107219756231189260242924214757216499556800924663989415245, + 19844149102409145164899383702905431874294284279975799650463349302848431722345, + 8085702973244851511749511458252001251656396567279831753386435292626763485519, + 7228553768733225658404951895408814447072687956541829973973278098033771266133, + 105596656275798929748166863934885182363689635847234124436621303088018075316318, + 38676776859894327439306496331637879961583690003149963151737467525103054120562, + 85477686937823419543333196992932299365632271007320851702648643772402369864328, + 22229920646492402606981052724637320840692349558623293033865697366530470978486, + 112072965867338239573889213937723730433670062735410160872920205584142628381373, + 88467625016731521493423548833553071825397026551739211671998589112975698905278, + 25992504298006565830470368312378721049979960036048125625454280742210714251460, + 110617272903019771469499444823257727911904694075232295617275982602998246137287, + 94505591102923281633582187298665869748706738506552940726297726697376921139940, + 61045622704434071646267219815056009885098917557981157258992889212955684204266, + 13211097245463234511960758135014635595928033177520118564099801801920862689783, + 31074512854902337288625257590954829730900652551161723130126776340859848806649, + 44538331896767374738844648938521484715615151697818866991405461337364931895882, + 3786568789660403200852996085367121779229835783673034074459126889865476618736, + 72424083303309042927901775547713806199923926084563159364314982079354479060001, + 69591869790363947775648315338788856147382399631102361163617626569778221519868, + 106509905815215444060470900722560683767640278101044067202990911217013896112782, + 75058175866682352019928692868488216877528414265350511354981207385403679685195, + 109283868054331544143387891859529236421627373812326736608285770178840546643871, + 39542883202479093211584799838746667716395625614225499740058888501390961106452, + 94595752330744041906541122701037256583611801936861866206832963585263438630784, + 34480068985205214181016984831940818548407005320799816662621545126994276346383, + 114416879116659179519307017042905732586005243477405363334331745379987475067267, + 93554579979664800565805397539022039007161035481361397011797715647990161496531, + 37458354615498032052130382782686290665116597801796388569749611201056898324191, + 78211335442859054923244898760943187603468759051592897374525429261348823850504, + 104588047790860320948508463604431631555273959929178380837535562211583725095865, + 88533984364671327208043309765991916410177054136632659494361043900096687170520, + 74588505857600708421962930087161186000599018292750334781125400525294975481762, + 112752987453712306641220876847544811759380413999723354584980558175049754432795, + 111842592677353494948943759638834566424266950480736197950303220951311759187720, + 87665696940715095017967264494167805840067603241734544580898800636588266337037, + 1090280637203525009115725313643458642172735305034978144675368327513392247829, + 21753965389658242894657840187609862990171336384073809699643086551343848128137, + 37267372813267449023828933209579531160284908765644872895890883410796155625935, + 20525524186444105429231410481483640675344979756404898092376935063963326256122, + 17829422600439756392151953943391238535480033142831909162778609983726106228512, + 41303271138985816303296672094245939680365497185281926261467432770171849579687, + 82823394409558916672640587646663901611551822982421273865503472173163167718999, + 89478479736184744977933126085668082981809605801479155792211982965923398348835, + 72802133526370933145427659656755439051538517225580881768607137090961663653241, + 56795692519940407526356010151860193442211997985387315152113952611744213237658, + 65045391625118939077142106477324833186625602113180931858323879876662297724336, + 60215294995007274230208134932676628315723527736391064120561973669174161015242, + 102384662082935928315339426378370186792048305200094289382112523702987931678926, + 86368559242380026121168902695823179093385498595197919919615211855084622239196, + 76235896788712829841923795664649145649147848714227066730165805925937789379638, + 72992440794182055655060490731957945978590420791714748896924137659543510472586, + 15723779340218563391801553289451295401220280130193367650215088217189526768359, + 30603739299926735280879233651788480382377350858560583934915975115996384292593, + 8101282996304339298994017877392052576046111197701926575394135086300838023721, + 69033295643745724490836407920021999057814583179181837046014642230728249600037, + 28592965524777064039257774571078878759841665290321422900007794665753963209279, + 95154479716567613162081487366086494132497147280317769959985517566899309948498, + 108553069643570880564956047611599133271427665479694942397557048791568628806341, + 69224388903325553975837255173974350182140940603228387437579339810084845588140, + 69488977682955929391489137768839210032315303077149524445308821275179637103618, + 103550700012517797839435246873195350567462382035099666630363804973887578951682, + 80470716205192474589208272562729613877970764510034314437155960568801829613842, + 112583208063995304540833406455352374509563782461174974145340713205469621096979, + 21235325283616647578043866271225113202675335195508649707145172457286606141984, + 13232627578013637215675687823934034972596548934524658253356832731455209989160, + 80784032631716142178242469184070553027785085685565997102326912501697626517313, + 7294942691445791409321257747702350408857270500228961118000714872988950089560, + 100772570340278999113223280379402631778048062948247847159753669667008184399193, + 93587022358381030729294375674433618701473827243484730592562292037522832295003, + 12737685905656421304213895995337275908318404485567864095208751640392542517598, + 81233734395237990325768449723927093657671481576169330485233345190291219225952, + 69512778664259522863106646708774602335322872849219726033944719523744694631269, + 36669514952127528526341931671493672830634333916199618253712407351482889565809, + 97346345178315596579217753012380963130055862224614585562240721150355306874228, + 13449222348375695803892334533135453122514801303614797298523227568622555689334, + 111794849936821285647563352046412563483827277208655139522183147941449043408758, + 25187687048590001973910956793862908958872565981170214377638157852182312571777, + 55862026463301963985147590306728434778192433670354908742622764392746031586460, + 107785046518206050102103260006811728039839192809289141151521472969098636975265, + 41274859515500512327009467093125014649563642645719036935586636904971032950437, + 10299670577090336347573507076381569009327310672260051284732727198668044375733, + 18740447824932021856268111049021888133877431116345567968724621857825852217796, + 4200073393579074662096737509517039478021146153843100404002844295789247718888, + 115576924713829251952645859333145965259890905433609922733592169128194952064495, + 87425681026423479946473975739545745299695172284233174785085304201530867212284, + 65736003615206120019604160931933626146807817697708257905273663093461844861061, + 68698660336679412340895678893606703366897742543340702318992030146867902614180, + 44400381641247529974285344732897027714954070929727664425687199824471755385014, + 46555944721400572748889917900484247677570522028454099304526874957996228277640, + 56052117678289692910179076027864117534973430091370827276740312219466644295458, + 51748509441971377338792270423435778413464548039401662932068905447231552317480, + 53395434963484081809584000769248080961201539725305176110314209609198276843005, + 102434000750709668610540259777148461533918495390223949486442439090058827800013, + 96141612716022589616404985290434799930705037276016344215415912879442379598580, + 96591358795046026482098529344557085339678356537480328665895473626353390068389, + 112104425472056185088019792401011431491830983633283699577373234088114766893436, + 51780038800394905147287732963986021681826029961029983295292280356900630107293, + 90468410940773955762555388721724170986097417025247277612326047693927134761732, + 113787635886243420042401677550920536626562907700369504319047304745280100901418, + 111779868770549036631826184857346768528115424108766292718925491951245933743262, + 1383125703245276385224109432750410273570943264665440273972968132086223737228, + 10134161562116399785048841072740269155277614330172394008099010154300508745698, + 85359232392513032206474801086296076557552199612332987313423759360551941365878, + 69985192971521624329386000344285194632994126063400847362182991679001359572122, + 72339149377714492859924370474917145875893849616485364424005757780516635362611, + 56503123851498363828048317347521935671181721935176822509117384860437039033081, + 69126853016586767696897188960560669018253492992061804151504417258940449344728, + 39330299812728222053701305104575256287844208382743784690202813602370359607539, + 61409899640378687296788156525781772854856509888081169135029103081562169908862, + 44269150079628873845638315214130972701808044677291019812697071769115672935826, + 56056168260782053795842288560576748699255446589292665370729220513400153079489, + 94019538583512079156144786365665989285876713092214620288958055665535262050530, + 6834852430700466562127587266714618514791343291417644589017511016990783355745, + 1084959959337983669962278498441227418643027543409497426675351029330200853686, + 64821350110428042832338872266823351253349947620020469893450914763400045302935, + 22204946803601127399408985692110346044027239156293394966858530118282477639552, + 36613852788587714200712041764597325017119186926330078817308927114268321888408, + 26739566197878673394088065441468330922752350618279648337693390784942075313366, + 109670313816477888214462529089772292089024783630384470625837201599719593046890, + 9085296185093309738730942628356656484204324720627282267824811810925662595035, + 67276382158235748718561293466013901431928725764841701443046468437965051147045, + 115445059586456935708290213758207585365166442358212557650034476554494941939444, + 34033762681336554454951042883589284119297586773260294008883858312798983889577, + 83866729665675158021340977072788355765911500343677100521455474728603516009255, + 26788652676730796537917986715149006710765916810187150134747966504780018211344, + 112795501658550766885671569168821667620039498129435866835194249729273062173932, + 81689027014275899003176195182576649880349411490162790721514953337217510955511, + 23104687795143537561327142876926268973710826452557480157496720794591031951797, + 79090184824195591405644231645740858320626756246048056690624496761396450959013, + 75123652463963764877061425990770347795868876195886491732787070736510177074581, + 77091020794518126957007731150277876565087725347784962070706816290965708714058, + 31114546311402643974968758145439532479304783698429893469155806120143455812451, + 16341484285447878518397457523390367190854409959942210272347307256339882781267, + 98181118887583940465875837223088150093242984007371151495130338967180219414272, + 87592008363538304439079982818695061454989580615310070537839242259041736713907, + 106075531380976054958175634829001075730548704272684079170264173702598392530682, + 96922583627707115101968615484176462533918860323875268927225616132861429195662] merkle_result10 = {'index': 0, - 'branch': [112016540517777279124582056964762882775092635530152119738265592842063160830965L, - 62231928775068700080431948595462536614853790863928672793937605905628779077362L, - 66845773887633903347836703158453493147168582880683740028512657283249821141943L, - 35413163942878321560196331591707630100515321374497280195772377329676459355434L, - 37851594145648910699702693859865698208518005761671890323995855296534963936331L, - 28759311701621210466484794525788189825744427228601794119000934510434164460269L, - 97476705517834473337408303529983274958448413857287704280133965753400514958554L, - 68709175280440923495943620591462095299071313388291609998098828869440974122048L, - 90452556609198907126320948644677435183782764187784779734668365678190851346616L, - 28184584189148850026532617133186243317996955074357809484626968557003017476239L, - 85372773260251254820744582777693887589760420918467118545746250872540123696352L, - 37908227336857066813559922943461275161094662141899261190542805345063102028920L]} + 'branch': [112016540517777279124582056964762882775092635530152119738265592842063160830965, + 62231928775068700080431948595462536614853790863928672793937605905628779077362, + 66845773887633903347836703158453493147168582880683740028512657283249821141943, + 35413163942878321560196331591707630100515321374497280195772377329676459355434, + 37851594145648910699702693859865698208518005761671890323995855296534963936331, + 28759311701621210466484794525788189825744427228601794119000934510434164460269, + 97476705517834473337408303529983274958448413857287704280133965753400514958554, + 68709175280440923495943620591462095299071313388291609998098828869440974122048, + 90452556609198907126320948644677435183782764187784779734668365678190851346616, + 28184584189148850026532617133186243317996955074357809484626968557003017476239, + 85372773260251254820744582777693887589760420918467118545746250872540123696352, + 37908227336857066813559922943461275161094662141899261190542805345063102028920]} btc_addrs = [ 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4', diff --git a/p2pool/test/bitcoin/test_getwork.py b/backend/p2pool/test/bitcoin/test_getwork.py similarity index 98% rename from p2pool/test/bitcoin/test_getwork.py rename to backend/p2pool/test/bitcoin/test_getwork.py index 58776f9..d0e20b4 100644 --- a/p2pool/test/bitcoin/test_getwork.py +++ b/backend/p2pool/test/bitcoin/test_getwork.py @@ -33,7 +33,7 @@ def test_all(self): extra.pop('midstate', None) getwork_check = ba.getwork(**extra) - assert getwork_check == case or dict((k, v) for k, v in getwork_check.iteritems() if k != 'midstate') == case + assert getwork_check == case or dict((k, v) for k, v in getwork_check.items() if k != 'midstate') == case case2s = [ getwork.BlockAttempt( diff --git a/p2pool/test/bitcoin/test_p2p.py b/backend/p2pool/test/bitcoin/test_p2p.py similarity index 87% rename from p2pool/test/bitcoin/test_p2p.py rename to backend/p2pool/test/bitcoin/test_p2p.py index 4d5c008..75e1536 100644 --- a/p2pool/test/bitcoin/test_p2p.py +++ b/backend/p2pool/test/bitcoin/test_p2p.py @@ -13,7 +13,7 @@ def test_get_block(self): try: h = 0x000000000000046acff93b0e76cd10490551bf871ce9ac9fad62e67a07ff1d1e block = yield deferral.retry()(defer.inlineCallbacks(lambda: defer.returnValue((yield (yield factory.getProtocol()).get_block(h)))))() - assert data.merkle_hash(map(data.get_txid, block['txs'])) == block['header']['merkle_root'] + assert data.merkle_hash(list(map(data.get_txid, block['txs']))) == block['header']['merkle_root'] assert data.hash256(data.block_header_type.pack(block['header'])) == h finally: factory.stopTrying() diff --git a/backend/p2pool/test/bitcoin/test_script.py b/backend/p2pool/test/bitcoin/test_script.py new file mode 100644 index 0000000..c6b2d51 --- /dev/null +++ b/backend/p2pool/test/bitcoin/test_script.py @@ -0,0 +1,12 @@ +import unittest + +from p2pool.bitcoin import script + +class Test(unittest.TestCase): + def test_all(self): + data = bytes.fromhex('76 A9 14 89 AB CD EF AB BA AB BA AB BA AB BA AB BA AB BA AB BA AB BA 88 AC') + self.assertEqual( + list(script.parse(data)), + [('UNK_118', None), ('UNK_169', None), ('PUSH', b'\x89\xab\xcd\xef\xab\xba\xab\xba\xab\xba\xab\xba\xab\xba\xab\xba\xab\xba\xab\xba'), ('UNK_136', None), ('CHECKSIG', None)], + ) + self.assertEqual(script.get_sigop_count(data), 1) diff --git a/p2pool/test/bitcoin/test_sha256.py b/backend/p2pool/test/bitcoin/test_sha256.py similarity index 80% rename from p2pool/test/bitcoin/test_sha256.py rename to backend/p2pool/test/bitcoin/test_sha256.py index 57d3b08..8d7034e 100644 --- a/p2pool/test/bitcoin/test_sha256.py +++ b/backend/p2pool/test/bitcoin/test_sha256.py @@ -1,4 +1,4 @@ -from __future__ import division + import unittest import hashlib @@ -8,20 +8,20 @@ class Test(unittest.TestCase): def test_all(self): - for test in ['', 'a', 'b', 'abc', 'abc'*50, 'hello world']: + for test in [b'', b'a', b'b', b'abc', b'abc'*50, b'hello world']: #print test #print sha256.sha256(test).hexdigest() #print hashlib.sha256(test).hexdigest() #print assert sha256.sha256(test).hexdigest() == hashlib.sha256(test).hexdigest() def random_str(l): - return ''.join(chr(random.randrange(256)) for i in xrange(l)) - for length in xrange(150): + return bytes(random.randrange(256) for i in range(l)) + for length in range(150): test = random_str(length) a = sha256.sha256(test).hexdigest() b = hashlib.sha256(test).hexdigest() assert a == b - for i in xrange(100): + for i in range(100): test = random_str(int(random.expovariate(1/100))) test2 = random_str(int(random.expovariate(1/100))) diff --git a/p2pool/test/test_data.py b/backend/p2pool/test/test_data.py similarity index 81% rename from p2pool/test/test_data.py rename to backend/p2pool/test/test_data.py index c9f3527..7aacefe 100644 --- a/p2pool/test/test_data.py +++ b/backend/p2pool/test/test_data.py @@ -7,24 +7,24 @@ from p2pool.util import forest def random_bytes(length): - return ''.join(chr(random.randrange(2**8)) for i in xrange(length)) + return bytes(random.randrange(2**8) for i in range(length)) class Test(unittest.TestCase): def test_hashlink1(self): - for i in xrange(100): + for i in range(100): d = random_bytes(random.randrange(2048)) x = data.prefix_to_hash_link(d) - assert data.check_hash_link(x, '') == bitcoin_data.hash256(d) + assert data.check_hash_link(x, b'') == bitcoin_data.hash256(d) def test_hashlink2(self): - for i in xrange(100): + for i in range(100): d = random_bytes(random.randrange(2048)) d2 = random_bytes(random.randrange(2048)) x = data.prefix_to_hash_link(d) assert data.check_hash_link(x, d2) == bitcoin_data.hash256(d + d2) def test_hashlink3(self): - for i in xrange(100): + for i in range(100): d = random_bytes(random.randrange(2048)) d2 = random_bytes(random.randrange(200)) d3 = random_bytes(random.randrange(2048)) @@ -34,8 +34,8 @@ def test_hashlink3(self): def test_skiplist(self): t = forest.Tracker() d = data.WeightsSkipList(t) - for i in xrange(200): + for i in range(200): t.add(test_forest.FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None, new_script=i, share_data=dict(donation=1234), target=2**249)) - for i in xrange(200): + for i in range(200): a = random.randrange(200) d(a, random.randrange(a + 1), 1000000*65535)[1] diff --git a/p2pool/test/test_node.py b/backend/p2pool/test/test_node.py similarity index 75% rename from p2pool/test/test_node.py rename to backend/p2pool/test/test_node.py index 16619b0..11a858c 100644 --- a/p2pool/test/test_node.py +++ b/backend/p2pool/test/test_node.py @@ -1,4 +1,4 @@ -from __future__ import division + import base64 import random @@ -11,7 +11,8 @@ from p2pool import data, node, work, main from p2pool.bitcoin import data as bitcoin_data, networks, worker_interface -from p2pool.util import deferral, jsonrpc, math, variable +from p2pool.util import deferral, http, jsonrpc, math, variable +from p2pool.util.py3 import bytes_to_hex, hex_to_bytes class bitcoind(object): # can be used as p2p factory, p2p protocol, or rpc jsonrpc proxy def __init__(self): @@ -19,10 +20,10 @@ def __init__(self): self.headers = {0x16c169477c25421250ec5d32cf9c6d38538b5de970a2355fd89: { 'nonce': 1853158954, 'timestamp': 1351658517, - 'merkle_root': 2282849479936278423916707524932131168473430114569971665822757638339486597658L, + 'merkle_root': 2282849479936278423916707524932131168473430114569971665822757638339486597658, 'version': 1, - 'previous_block': 1048610514577342396345362905164852351970507722694242579238530L, - 'bits': bitcoin_data.FloatingInteger(bits=0x1a0513c5, target=0x513c50000000000000000000000000000000000000000000000L), + 'previous_block': 1048610514577342396345362905164852351970507722694242579238530, + 'bits': bitcoin_data.FloatingInteger(bits=0x1a0513c5, target=0x513c50000000000000000000000000000000000000000000000), }} self.conn = variable.Variable(self) @@ -42,6 +43,9 @@ def send_block(self, block): def send_tx(self, tx): pass + + def send_getheaders(self, *args, **kwargs): + pass def get_block_header(self, block_hash): return self.headers[block_hash] @@ -64,12 +68,12 @@ def rpc_getblocktemplate(self, param): pass elif param['mode'] == 'submit': result = param['data'] - block = bitcoin_data.block_type.unpack(result.decode('hex')) + block = bitcoin_data.block_type.unpack(hex_to_bytes(result)) if sum(tx_out['value'] for tx_out in block['txs'][0]['tx_outs']) != sum(tx['tx_outs'][0]['value'] for tx in block['txs'][1:]) + 5000000000: - print 'invalid fee' + print('invalid fee') if block['header']['previous_block'] != self.blocks[-1]: return False - if bitcoin_data.hash256(result.decode('hex')) > block['header']['bits'].target: + if bitcoin_data.hash256(hex_to_bytes(result)) > block['header']['bits'].target: return False header_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header'])) self.blocks.append(header_hash) @@ -80,10 +84,15 @@ def rpc_getblocktemplate(self, param): raise jsonrpc.Error_for_code(-1)('invalid request') txs = [] - for i in xrange(100): + for i in range(100): fee = i txs.append(dict( - data=bitcoin_data.tx_type.pack(dict(version=1, tx_ins=[], tx_outs=[dict(value=fee, script='hello!'*100)], lock_time=0)).encode('hex'), + data=bytes_to_hex(bitcoin_data.tx_type.pack(dict( + version=1, + tx_ins=[dict(previous_output=None, script=b'', sequence=None)], + tx_outs=[dict(value=fee, script=b'hello!'*100)], + lock_time=0, + ))), fee=fee, )) return { @@ -109,13 +118,12 @@ def rpc_getblocktemplate(self, param): "height" : len(self.blocks), } -@apply class mm_provider(object): def __getattr__(self, name): - print '>>>>>>>', name + print('>>>>>>>', name) def rpc_getauxblock(self, request, result1=None, result2=None): if result1 is not None: - print result1, result2 + print(result1, result2) return True return { "target" : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", # 2**256*2/3 @@ -123,6 +131,8 @@ def rpc_getauxblock(self, request, result1=None, result2=None): "chainid" : 1 } +mm_provider = mm_provider() + mynet = math.Object( NAME='mynet', PARENT=networks.nets['litecoin_testnet'], @@ -131,11 +141,13 @@ def rpc_getauxblock(self, request, result1=None, result2=None): REAL_CHAIN_LENGTH=20*60//3, # shares TARGET_LOOKBEHIND=200, # shares SPREAD=3, # blocks - IDENTIFIER='cca5e24ec6408b1e'.decode('hex'), - PREFIX='ad9614f6466a39cf'.decode('hex'), + IDENTIFIER=bytes.fromhex('cca5e24ec6408b1e'), + PREFIX=bytes.fromhex('ad9614f6466a39cf'), P2P_PORT=19338, MIN_TARGET=2**256 - 1, MAX_TARGET=2**256 - 1, + BLOCK_MAX_SIZE=1000000, + BLOCK_MAX_WEIGHT=4000000, PERSIST=False, WORKER_PORT=19327, BOOTSTRAP_ADDRS='72.14.191.28'.split(' '), @@ -143,6 +155,10 @@ def rpc_getauxblock(self, request, result1=None, result2=None): VERSION_CHECK=lambda v: True, ) +TEST_PAYOUT_ADDRESS = bitcoin_data.pubkey_hash_to_address( + 42, networks.nets['litecoin_testnet'].ADDRESS_VERSION, -1, + networks.nets['litecoin_testnet']) + class MiniNode(object): @classmethod @defer.inlineCallbacks @@ -155,10 +171,11 @@ def start(cls, net, factory, bitcoind, peer_ports, merged_urls): self.n.p2p_node = node.P2PNode(self.n, port=0, max_incoming_conns=1000000, addr_store={}, connect_addrs=[('127.0.0.1', peer_port) for peer_port in peer_ports]) self.n.p2p_node.start() - wb = work.WorkerBridge(node=self.n, my_pubkey_hash=random.randrange(2**160), donation_percentage=random.uniform(0, 10), merged_urls=merged_urls, worker_fee=3, args=math.Object(donation_percentage=random.uniform(0, 10), address='foo', worker_fee=3, timeaddresses=1000), pubkeys=main.keypool(), bitcoind=bitcoind) + wb = work.WorkerBridge(node=self.n, my_address=TEST_PAYOUT_ADDRESS, donation_percentage=random.uniform(0, 10), merged_urls=merged_urls, worker_fee=3, args=math.Object(donation_percentage=random.uniform(0, 10), address=TEST_PAYOUT_ADDRESS, worker_fee=3, timeaddresses=1000, coinb_texts=[]), pubkeys=main.keypool(), bitcoind=bitcoind, share_rate=0) self.wb = wb web_root = resource.Resource() - worker_interface.WorkerInterface(wb).attach_to(web_root) + self.worker_interface = worker_interface.WorkerInterface(wb) + self.worker_interface.attach_to(web_root) self.web_port = reactor.listenTCP(0, server.Site(web_root)) defer.returnValue(self) @@ -166,9 +183,10 @@ def start(cls, net, factory, bitcoind, peer_ports, merged_urls): @defer.inlineCallbacks def stop(self): yield self.web_port.stopListening() + self.worker_interface.stop() yield self.n.p2p_node.stop() yield self.n.stop() - del self.web_port, self.n + del self.web_port, self.worker_interface, self.n class Test(unittest.TestCase): @defer.inlineCallbacks @@ -176,23 +194,24 @@ def test_node(self): bitd = bitcoind() mm_root = resource.Resource() - mm_root.putChild('', jsonrpc.HTTPServer(mm_provider)) + mm_root.putChild(b'', jsonrpc.HTTPServer(mm_provider)) mm_port = reactor.listenTCP(0, server.Site(mm_root)) n = node.Node(bitd, bitd, [], [], mynet) yield n.start() - wb = work.WorkerBridge(node=n, my_pubkey_hash=42, donation_percentage=2, merged_urls=[('http://127.0.0.1:%i' % (mm_port.getHost().port,), '')], worker_fee=3, args=math.Object(donation_percentage=2, address='foo', worker_fee=3, timeaddresses=1000), pubkeys=main.keypool(), bitcoind=bitd) + wb = work.WorkerBridge(node=n, my_address=TEST_PAYOUT_ADDRESS, donation_percentage=2, merged_urls=[('http://127.0.0.1:%i' % (mm_port.getHost().port,), '')], worker_fee=3, args=math.Object(donation_percentage=2, address=TEST_PAYOUT_ADDRESS, worker_fee=3, timeaddresses=1000, coinb_texts=[]), pubkeys=main.keypool(), bitcoind=bitd, share_rate=0) web_root = resource.Resource() - worker_interface.WorkerInterface(wb).attach_to(web_root) + wi = worker_interface.WorkerInterface(wb) + wi.attach_to(web_root) port = reactor.listenTCP(0, server.Site(web_root)) proxy = jsonrpc.HTTPProxy('http://127.0.0.1:' + str(port.getHost().port), - headers=dict(Authorization='Basic ' + base64.b64encode('user/0:password'))) + headers=dict(Authorization='Basic ' + base64.b64encode(b'user/0:password').decode('ascii'))) - yield deferral.sleep(3) + yield deferral.sleep(8) - for i in xrange(100): + for i in range(100): blah = yield proxy.rpc_getwork() yield proxy.rpc_getwork(blah['data']) @@ -204,9 +223,10 @@ def test_node(self): wb.stop() n.stop() + wi.stop() yield port.stopListening() - del n, wb, web_root, port, proxy + del n, wb, wi, web_root, port, proxy import gc gc.collect() gc.collect() @@ -224,19 +244,19 @@ def test_nodes(self): bitd = bitcoind() nodes = [] - for i in xrange(N): + for i in range(N): nodes.append((yield MiniNode.start(mynet, bitd, bitd, [mn.n.p2p_node.serverfactory.listen_port.getHost().port for mn in nodes], []))) yield deferral.sleep(3) - for i in xrange(SHARES): + for i in range(SHARES): proxy = jsonrpc.HTTPProxy('http://127.0.0.1:' + str(random.choice(nodes).web_port.getHost().port), - headers=dict(Authorization='Basic ' + base64.b64encode('user/0:password'))) + headers=dict(Authorization='Basic ' + base64.b64encode(b'user/0:password').decode('ascii'))) blah = yield proxy.rpc_getwork() yield proxy.rpc_getwork(blah['data']) yield deferral.sleep(.05) - print i - print type(nodes[0].n.tracker.items[nodes[0].n.best_share_var.value]) + print(i) + print(type(nodes[0].n.tracker.items[nodes[0].n.best_share_var.value])) # crawl web pages from p2pool import web @@ -245,16 +265,16 @@ def test_nodes(self): web2_port = reactor.listenTCP(0, server.Site(web2_root)) for name in web2_root.listNames() + ['web/' + x for x in web2_root.getChildWithDefault('web', None).listNames()]: if name in ['web/graph_data', 'web/share', 'web/share_data']: continue - print - print name + print() + print(name) try: - res = yield client.getPage('http://127.0.0.1:%i/%s' % (web2_port.getHost().port, name)) + res = yield http.get_page('http://127.0.0.1:%i/%s' % (web2_port.getHost().port, name)) except: import traceback traceback.print_exc() else: - print repr(res)[:100] - print + print(repr(res)[:100]) + print() yield web2_port.stopListening() stop_event.happened() del web2_root diff --git a/p2pool/test/test_p2p.py b/backend/p2pool/test/test_p2p.py similarity index 98% rename from p2pool/test/test_p2p.py rename to backend/p2pool/test/test_p2p.py index 5f3e956..46bd8ee 100644 --- a/p2pool/test/test_p2p.py +++ b/backend/p2pool/test/test_p2p.py @@ -48,7 +48,7 @@ def got_conn(self, conn): yield deferral.sleep(.5) new_mining_txs = dict(self.mining_txs_var.value) - for i in xrange(3): + for i in range(3): huge_tx = dict( version=0, tx_ins=[], diff --git a/p2pool/test/util/__init__.py b/backend/p2pool/test/util/__init__.py similarity index 100% rename from p2pool/test/util/__init__.py rename to backend/p2pool/test/util/__init__.py diff --git a/p2pool/test/util/test_cash_addr.py b/backend/p2pool/test/util/test_cash_addr.py similarity index 99% rename from p2pool/test/util/test_cash_addr.py rename to backend/p2pool/test/util/test_cash_addr.py index c30c57a..73f8f53 100644 --- a/p2pool/test/util/test_cash_addr.py +++ b/backend/p2pool/test/util/test_cash_addr.py @@ -20,7 +20,7 @@ # THE SOFTWARE. import unittest -import mock +from unittest import mock from p2pool.util import cash_addr from p2pool.bitcoin import data @@ -368,7 +368,7 @@ def get_prefix(addr): @staticmethod def to_byte_array(data): - return [ord(x) for x in data] + return [x if isinstance(x, int) else ord(x) for x in data] def test_old_and_new_addresses_match(self): for oaddr, naddr in self.OLD_NEW_ADDRESS: diff --git a/p2pool/test/util/test_datachunker.py b/backend/p2pool/test/util/test_datachunker.py similarity index 88% rename from p2pool/test/util/test_datachunker.py rename to backend/p2pool/test/util/test_datachunker.py index beb4f4a..40c692b 100644 --- a/p2pool/test/util/test_datachunker.py +++ b/backend/p2pool/test/util/test_datachunker.py @@ -4,11 +4,11 @@ from p2pool.util import datachunker def random_bytes(length): - return ''.join(chr(random.randrange(2**8)) for i in xrange(length)) + return ''.join(chr(random.randrange(2**8)) for i in range(length)) class Test(unittest.TestCase): def test_stringbuffer(self): - for i in xrange(100): + for i in range(100): sb = datachunker.StringBuffer() r = random_bytes(random.randrange(1000)) diff --git a/p2pool/test/util/test_deferral.py b/backend/p2pool/test/util/test_deferral.py similarity index 93% rename from p2pool/test/util/test_deferral.py rename to backend/p2pool/test/util/test_deferral.py index 02e69c9..802158c 100644 --- a/p2pool/test/util/test_deferral.py +++ b/backend/p2pool/test/util/test_deferral.py @@ -9,7 +9,7 @@ class Test(unittest.TestCase): @defer.inlineCallbacks def test_sleep(self): - for i in xrange(10): + for i in range(10): length = random.expovariate(1/0.1) start = time.time() yield deferral.sleep(length) diff --git a/p2pool/test/util/test_expiring_dict.py b/backend/p2pool/test/util/test_expiring_dict.py similarity index 100% rename from p2pool/test/util/test_expiring_dict.py rename to backend/p2pool/test/util/test_expiring_dict.py diff --git a/p2pool/test/util/test_forest.py b/backend/p2pool/test/util/test_forest.py similarity index 88% rename from p2pool/test/util/test_forest.py rename to backend/p2pool/test/util/test_forest.py index 3b64187..d084720 100644 --- a/p2pool/test/util/test_forest.py +++ b/backend/p2pool/test/util/test_forest.py @@ -4,10 +4,11 @@ from p2pool.util import forest, math class DumbTracker(object): - def __init__(self, items=[]): + def __init__(self, items=None): self.items = {} # hash -> item self.reverse = {} # previous_hash -> set of item_hashes + items = [] if items is None else items for item in items: self.add(item) @@ -35,7 +36,7 @@ def tails(self): return dict((x, set(y for y in self.items if self.get_last(y) == x and y not in self.reverse)) for x in self.reverse if x not in self.items) def get_nth_parent_hash(self, item_hash, n): - for i in xrange(n): + for i in range(n): item_hash = self.items[item_hash].previous_hash return item_hash @@ -57,7 +58,7 @@ def get_height_and_last(self, item_hash): def get_chain(self, start_hash, length): # same implementation :/ assert length <= self.get_height(start_hash) - for i in xrange(length): + for i in range(length): yield self.items[start_hash] start_hash = self.items[start_hash].previous_hash @@ -73,12 +74,12 @@ def is_child_of(self, item_hash, possible_child_hash): class FakeShare(object): def __init__(self, **kwargs): - for k, v in kwargs.iteritems(): + for k, v in kwargs.items(): setattr(self, k, v) self._attrs = kwargs -def test_tracker(self): - t = DumbTracker(self.items.itervalues()) +def check_tracker(self): + t = DumbTracker(iter(self.items.values())) assert self.items == t.items, (self.items, t.items) assert self.reverse == t.reverse, (self.reverse, t.reverse) @@ -92,7 +93,7 @@ def test_tracker(self): a, b = self.get_height_and_last(start), t.get_height_and_last(start) assert a == b, (a, b) - other = random.choice(self.items.keys()) + other = random.choice(list(self.items.keys())) assert self.is_child_of(start, other) == t.is_child_of(start, other) assert self.is_child_of(other, start) == t.is_child_of(other, start) @@ -100,17 +101,17 @@ def test_tracker(self): assert list(self.get_chain(start, length)) == list(t.get_chain(start, length)) def generate_tracker_simple(n): - t = forest.Tracker(math.shuffled(FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None) for i in xrange(n))) - test_tracker(t) + t = forest.Tracker(math.shuffled(FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None) for i in range(n))) + check_tracker(t) return t def generate_tracker_random(n): items = [] - for i in xrange(n): + for i in range(n): x = random.choice(items + [FakeShare(hash=None), FakeShare(hash=random.randrange(1000000, 2000000))]).hash items.append(FakeShare(hash=i, previous_hash=x)) t = forest.Tracker(math.shuffled(items)) - test_tracker(t) + check_tracker(t) return t class Test(unittest.TestCase): @@ -126,14 +127,14 @@ def test_tracker(self): def test_get_nth_parent_hash(self): t = generate_tracker_simple(200) - for i in xrange(1000): + for i in range(1000): a = random.randrange(200) b = random.randrange(a + 1) res = t.get_nth_parent_hash(a, b) assert res == a - b, (a, b, res) def test_tracker2(self): - for ii in xrange(20): + for ii in range(20): t = generate_tracker_random(random.randrange(100)) #print "--start--" while t.items: @@ -144,21 +145,21 @@ def test_tracker2(self): pass # print "aborted", x else: break - test_tracker(t) + check_tracker(t) def test_tracker3(self): - for ii in xrange(10): + for ii in range(10): items = [] - for i in xrange(random.randrange(100)): + for i in range(random.randrange(100)): x = random.choice(items + [FakeShare(hash=None), FakeShare(hash=random.randrange(1000000, 2000000))]).hash items.append(FakeShare(hash=i, previous_hash=x)) t = forest.Tracker() - test_tracker(t) + check_tracker(t) for item in math.shuffled(items): t.add(item) - test_tracker(t) + check_tracker(t) if random.randrange(3) == 0: while True: try: @@ -167,12 +168,12 @@ def test_tracker3(self): pass else: break - test_tracker(t) + check_tracker(t) for item in math.shuffled(items): if item.hash not in t.items: t.add(item) - test_tracker(t) + check_tracker(t) if random.randrange(3) == 0: while True: try: @@ -181,7 +182,7 @@ def test_tracker3(self): pass else: break - test_tracker(t) + check_tracker(t) while t.items: while True: @@ -191,4 +192,4 @@ def test_tracker3(self): pass else: break - test_tracker(t) + check_tracker(t) diff --git a/p2pool/test/util/test_graph.py b/backend/p2pool/test/util/test_graph.py similarity index 100% rename from p2pool/test/util/test_graph.py rename to backend/p2pool/test/util/test_graph.py diff --git a/p2pool/test/util/test_math.py b/backend/p2pool/test/util/test_math.py similarity index 91% rename from p2pool/test/util/test_math.py rename to backend/p2pool/test/util/test_math.py index a37e569..023881e 100644 --- a/p2pool/test/util/test_math.py +++ b/backend/p2pool/test/util/test_math.py @@ -1,4 +1,4 @@ -from __future__ import division + import random import unittest @@ -9,7 +9,7 @@ def generate_alphabet(): if random.randrange(2): return None else: - a = map(chr, xrange(256)) + a = list(map(chr, range(256))) random.shuffle(a) return a[:random.randrange(2, len(a))] @@ -18,9 +18,9 @@ def test_add_tuples(self): assert math.add_tuples((1, 2, 3), (4, 5, 6)) == (5, 7, 9) def test_bases(self): - for i in xrange(10): + for i in range(10): alphabet = generate_alphabet() - for i in xrange(100): + for i in range(100): n = random.choice([ random.randrange(3), random.randrange(300), @@ -29,11 +29,11 @@ def test_bases(self): s = math.natural_to_string(n, alphabet) n2 = math.string_to_natural(s, alphabet) #print n, s.encode('hex'), n2 - self.assertEquals(n, n2) + self.assertEqual(n, n2) def test_binom(self): - for n in xrange(1, 100): - for x in xrange(n + 1): + for n in range(1, 100): + for x in range(n + 1): left, right = math.binomial_conf_interval(x, n) assert 0 <= left <= x/n <= right <= 1, (left, right, x, n) diff --git a/p2pool/test/util/test_pack.py b/backend/p2pool/test/util/test_pack.py similarity index 75% rename from p2pool/test/util/test_pack.py rename to backend/p2pool/test/util/test_pack.py index 07fad9b..9a67623 100644 --- a/p2pool/test/util/test_pack.py +++ b/backend/p2pool/test/util/test_pack.py @@ -5,7 +5,7 @@ class Test(unittest.TestCase): def test_VarInt(self): t = pack.VarIntType() - for i in xrange(2**20): + for i in range(2**20): assert t.unpack(t.pack(i)) == i - for i in xrange(2**36, 2**36+25): + for i in range(2**36, 2**36+25): assert t.unpack(t.pack(i)) == i diff --git a/p2pool/test/util/test_segwit_addr.py b/backend/p2pool/test/util/test_segwit_addr.py similarity index 99% rename from p2pool/test/util/test_segwit_addr.py rename to backend/p2pool/test/util/test_segwit_addr.py index e17ace9..08b2050 100644 --- a/p2pool/test/util/test_segwit_addr.py +++ b/backend/p2pool/test/util/test_segwit_addr.py @@ -20,7 +20,7 @@ # THE SOFTWARE. import unittest -import mock +from unittest import mock from p2pool.util import segwit_addr diff --git a/p2pool/test/util/test_skiplist.py b/backend/p2pool/test/util/test_skiplist.py similarity index 100% rename from p2pool/test/util/test_skiplist.py rename to backend/p2pool/test/util/test_skiplist.py diff --git a/p2pool/util/__init__.py b/backend/p2pool/util/__init__.py similarity index 100% rename from p2pool/util/__init__.py rename to backend/p2pool/util/__init__.py diff --git a/p2pool/util/cash_addr.py b/backend/p2pool/util/cash_addr.py similarity index 98% rename from p2pool/util/cash_addr.py rename to backend/p2pool/util/cash_addr.py index 3ba96e1..aecb726 100644 --- a/p2pool/util/cash_addr.py +++ b/backend/p2pool/util/cash_addr.py @@ -18,7 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from math import convertbits +from .math import convertbits CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" @@ -118,7 +118,7 @@ def valid_version(data): # Bit six is a multiplier if ver & 4: bits *= 2 - if (len(converted) - 1) != (bits / 8): + if (len(converted) - 1) != (bits // 8): return False return True @@ -168,8 +168,8 @@ def encode(prefix, ver, data): tmp = len(data) * 8 if tmp > 256: dlen ^= 0x04 - tmp /= 2 - dlen += (tmp - 160) / 32 + tmp //= 2 + dlen += (tmp - 160) // 32 ver += dlen bits = convertbits([ver] + data, 8, 5) ret = assemble(prefix, bits) diff --git a/p2pool/util/datachunker.py b/backend/p2pool/util/datachunker.py similarity index 67% rename from p2pool/util/datachunker.py rename to backend/p2pool/util/datachunker.py index c627a20..f035cb4 100644 --- a/p2pool/util/datachunker.py +++ b/backend/p2pool/util/datachunker.py @@ -3,15 +3,22 @@ class StringBuffer(object): 'Buffer manager with great worst-case behavior' - def __init__(self, data=''): - self.buf = collections.deque([data]) - self.buf_len = len(data) + def __init__(self, data=None): + self.buf = collections.deque() + self.buf_len = 0 + self._bytes_mode = None + if data is not None: + self.buf.append(data) + self.buf_len = len(data) + self._bytes_mode = isinstance(data, (bytes, bytearray)) self.pos = 0 def __len__(self): return self.buf_len - self.pos def add(self, data): + if self._bytes_mode is None: + self._bytes_mode = isinstance(data, (bytes, bytearray)) self.buf.append(data) self.buf_len += len(data) @@ -29,10 +36,14 @@ def get(self, wants): data.append(seg) wants -= len(seg) + if not data: + return b'' if self._bytes_mode else '' + if isinstance(data[0], (bytes, bytearray)): + return b''.join(data) return ''.join(data) def _DataChunker(receiver): - wants = receiver.next() + wants = next(receiver) buf = StringBuffer() while True: @@ -46,5 +57,5 @@ def DataChunker(receiver): (receiver) in response to the receiver yielding the size of data to wait on ''' x = _DataChunker(receiver) - x.next() + next(x) return x.send diff --git a/p2pool/util/deferral.py b/backend/p2pool/util/deferral.py similarity index 87% rename from p2pool/util/deferral.py rename to backend/p2pool/util/deferral.py index 4d2ea47..c5e2eee 100644 --- a/p2pool/util/deferral.py +++ b/backend/p2pool/util/deferral.py @@ -1,4 +1,4 @@ -from __future__ import division + import itertools import random @@ -8,8 +8,12 @@ from twisted.python import failure, log def sleep(t): - d = defer.Deferred(canceller=lambda d_: dc.cancel()) - dc = reactor.callLater(t, d.callback, None) + dc = [None] + def cancel(_df): + if dc[0] is not None and dc[0].active(): + dc[0].cancel() + d = defer.Deferred(canceller=cancel) + dc[0] = reactor.callLater(t, d.callback, None) return d def run_repeatedly(f, *args, **kwargs): @@ -19,7 +23,8 @@ def step(): current_dc[0] = reactor.callLater(delay, step) step() def stop(): - current_dc[0].cancel() + if current_dc[0] is not None and current_dc[0].active(): + current_dc[0].cancel() return stop class RetrySilentlyException(Exception): @@ -39,14 +44,14 @@ def f(*args, **kwargs): for i in itertools.count(): try: result = yield func(*args, **kwargs) - except Exception, e: + except Exception as e: if i == max_retries: raise if not isinstance(e, RetrySilentlyException): if traceback: log.err(None, message) else: - print >>sys.stderr, message, e + print(message, e, file=sys.stderr) yield sleep(delay) else: defer.returnValue(result) @@ -189,10 +194,11 @@ def eb(fail): self.waiting.pop(key).callback(None) if fail.check(RetrySilentlyException): return - print - print 'Error when requesting noncached value:' - fail.printTraceback() - print + print() + print('Error when requesting noncached value for %r:' % (key,)) + print('%s: %s' % (fail.type.__name__, fail.getErrorMessage())) + fail.printTraceback(file=sys.stdout) + print() self.func(key).addCallback(cb).addErrback(eb) if default is not self._nothing: return default @@ -248,8 +254,8 @@ def it(cur): continue else: currently_waiting_on[:] = [res] - def gotResult(res2): - assert currently_waiting_on[0] is res + def gotResult(res2, expected=res): + assert currently_waiting_on[0] is expected currently_waiting_on[:] = [] if stop_running[0]: return @@ -270,6 +276,8 @@ def __init__(self, func, *args, **kwargs): self.func, self.args, self.kwargs = func, args, kwargs self.running = False + self._sleep_df = None + self._df = None def start(self, period): assert not self.running @@ -284,10 +292,19 @@ def _worker(self, period): self.func(*self.args, **self.kwargs) except: log.err() - yield sleep(period) + if not self.running: + break + self._sleep_df = sleep(period) + try: + yield self._sleep_df + finally: + self._sleep_df = None def stop(self): assert self.running self.running = False - self._df.cancel() + if self._sleep_df is not None and not self._sleep_df.called: + self._sleep_df.cancel() + if self._df is not None and not self._df.called: + self._df.cancel() return self._df diff --git a/p2pool/util/deferred_resource.py b/backend/p2pool/util/deferred_resource.py similarity index 84% rename from p2pool/util/deferred_resource.py rename to backend/p2pool/util/deferred_resource.py index a5537b8..e23e2cf 100644 --- a/p2pool/util/deferred_resource.py +++ b/backend/p2pool/util/deferred_resource.py @@ -1,23 +1,25 @@ -from __future__ import division + from twisted.internet import defer from twisted.web import resource, server from twisted.python import log +from p2pool.util.py3 import ensure_bytes + class DeferredResource(resource.Resource): def render(self, request): def finish(x): if request.channel is None: # disconnected return if x is not None: - request.write(x) + request.write(ensure_bytes(x, 'utf-8')) request.finish() def finish_error(fail): if request.channel is None: # disconnected return request.setResponseCode(500) # won't do anything if already written to - request.write('---ERROR---') + request.write(b'---ERROR---') request.finish() log.err(fail, "Error in DeferredResource handler:") diff --git a/p2pool/util/expiring_dict.py b/backend/p2pool/util/expiring_dict.py similarity index 94% rename from p2pool/util/expiring_dict.py rename to backend/p2pool/util/expiring_dict.py index c61ab38..4ef0cc9 100644 --- a/p2pool/util/expiring_dict.py +++ b/backend/p2pool/util/expiring_dict.py @@ -1,4 +1,4 @@ -from __future__ import division + import time import weakref @@ -34,11 +34,11 @@ def delete(self): class LinkedList(object): - def __init__(self, iterable=[]): + def __init__(self, iterable=None): self.start, self.end = Node(None), Node(None) Node.connect(self.start, self.end) - for item in iterable: + for item in [] if iterable is None else iterable: self.append(item) def __repr__(self): @@ -64,13 +64,13 @@ def __reversed__(self): def __getitem__(self, index): if index < 0: cur = self.end - for i in xrange(-index): + for i in range(-index): cur = cur.prev if cur is self.start: raise IndexError('index out of range') else: cur = self.start - for i in xrange(index + 1): + for i in range(index + 1): cur = cur.next if cur is self.end: raise IndexError('index out of range') @@ -170,11 +170,11 @@ def setdefault(self, key, default_value): return default_value def keys(self): - return self.d.keys() + return list(self.d.keys()) def values(self): - return [value for node, value in self.d.itervalues()] + return [value for node, value in self.d.values()] def itervalues(self): - for node, value in self.d.itervalues(): + for node, value in self.d.values(): yield value diff --git a/p2pool/util/fixargparse.py b/backend/p2pool/util/fixargparse.py similarity index 97% rename from p2pool/util/fixargparse.py rename to backend/p2pool/util/fixargparse.py index 582f17e..12a6f2f 100644 --- a/p2pool/util/fixargparse.py +++ b/backend/p2pool/util/fixargparse.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + import argparse import sys diff --git a/p2pool/util/forest.py b/backend/p2pool/util/forest.py similarity index 90% rename from p2pool/util/forest.py rename to backend/p2pool/util/forest.py index 057c6b8..d7ee4e9 100644 --- a/p2pool/util/forest.py +++ b/backend/p2pool/util/forest.py @@ -22,20 +22,28 @@ class DistanceSkipList(TrackerSkipList): def get_delta(self, element): return element, 1, self.previous(element) - def combine_deltas(self, (from_hash1, dist1, to_hash1), (from_hash2, dist2, to_hash2)): + def combine_deltas(self, xxx_todo_changeme, xxx_todo_changeme1): + (from_hash1, dist1, to_hash1) = xxx_todo_changeme + (from_hash2, dist2, to_hash2) = xxx_todo_changeme1 if to_hash1 != from_hash2: raise AssertionError() return from_hash1, dist1 + dist2, to_hash2 - def initial_solution(self, start, (n,)): + def initial_solution(self, start, xxx_todo_changeme2): + (n,) = xxx_todo_changeme2 return 0, start - def apply_delta(self, (dist1, to_hash1), (from_hash2, dist2, to_hash2), (n,)): + def apply_delta(self, xxx_todo_changeme3, xxx_todo_changeme4, xxx_todo_changeme5): + (dist1, to_hash1) = xxx_todo_changeme3 + (from_hash2, dist2, to_hash2) = xxx_todo_changeme4 + (n,) = xxx_todo_changeme5 if to_hash1 != from_hash2: raise AssertionError() return dist1 + dist2, to_hash2 - def judge(self, (dist, hash), (n,)): + def judge(self, xxx_todo_changeme6, xxx_todo_changeme7): + (dist, hash) = xxx_todo_changeme6 + (n,) = xxx_todo_changeme7 if dist > n: return 1 elif dist == n: @@ -43,13 +51,15 @@ def judge(self, (dist, hash), (n,)): else: return -1 - def finalize(self, (dist, hash), (n,)): + def finalize(self, xxx_todo_changeme8, xxx_todo_changeme9): + (dist, hash) = xxx_todo_changeme8 + (n,) = xxx_todo_changeme9 assert dist == n return hash def get_attributedelta_type(attrs): # attrs: {name: func} class ProtoAttributeDelta(object): - __slots__ = ['head', 'tail'] + attrs.keys() + __slots__ = ['head', 'tail'] + list(attrs.keys()) @classmethod def get_none(cls, element_id): @@ -57,7 +67,7 @@ def get_none(cls, element_id): @classmethod def from_element(cls, item): - return cls(item.hash, item.previous_hash, **dict((k, v(item)) for k, v in attrs.iteritems())) + return cls(item.hash, item.previous_hash, **dict((k, v(item)) for k, v in attrs.items())) @staticmethod def get_head(item): @@ -69,7 +79,7 @@ def get_tail(item): def __init__(self, head, tail, **kwargs): self.head, self.tail = head, tail - for k, v in kwargs.iteritems(): + for k, v in kwargs.items(): setattr(self, k, v) def __add__(self, other): @@ -185,7 +195,7 @@ def _get_delta(self, item_hash): def _set_delta(self, item_hash, delta): other_item_hash = delta.tail if other_item_hash not in self._reverse_delta_refs: - ref = self._ref_generator.next() + ref = next(self._ref_generator) assert ref not in self._delta_refs self._delta_refs[ref] = self._delta_type.get_none(other_item_hash) self._reverse_delta_refs[other_item_hash] = ref @@ -206,7 +216,7 @@ def _set_delta(self, item_hash, delta): self._reverse_deltas.setdefault(ref, set()).add(item_hash) def get_delta_to_last(self, item_hash): - assert isinstance(item_hash, (int, long, type(None))) + assert isinstance(item_hash, (int, type(None))) delta = self._delta_type.get_none(item_hash) updates = [] while delta.tail in self._tracker.items: @@ -222,7 +232,7 @@ def get_delta(self, item, ancestor): return self.get_delta_to_last(item) - self.get_delta_to_last(ancestor) class Tracker(object): - def __init__(self, items=[], delta_type=AttributeDelta): + def __init__(self, items=None, delta_type=AttributeDelta): self.items = {} # hash -> item self.reverse = {} # delta.tail -> set of item_hashes @@ -239,7 +249,7 @@ def __init__(self, items=[], delta_type=AttributeDelta): self._delta_type = delta_type self._default_view = TrackerView(self, delta_type) - for item in items: + for item in [] if items is None else items: self.add(item) def __getattr__(self, name): @@ -248,7 +258,7 @@ def __getattr__(self, name): return attr def add(self, item): - assert not isinstance(item, (int, long, type(None))) + assert not isinstance(item, (int, type(None))) delta = self._delta_type.from_element(item) if delta.head in self.items: @@ -277,7 +287,7 @@ def add(self, item): self.added.happened(item) def remove(self, item_hash): - assert isinstance(item_hash, (int, long, type(None))) + assert isinstance(item_hash, (int, type(None))) if item_hash not in self.items: raise KeyError() @@ -331,7 +341,7 @@ def remove(self, item_hash): def get_chain(self, start_hash, length): assert length <= self.get_height(start_hash) - for i in xrange(length): + for i in range(length): item = self.items[start_hash] yield item start_hash = self._delta_type.get_tail(item) diff --git a/p2pool/util/graph.py b/backend/p2pool/util/graph.py similarity index 79% rename from p2pool/util/graph.py rename to backend/p2pool/util/graph.py index 0c3adfc..e7e8d38 100644 --- a/p2pool/util/graph.py +++ b/backend/p2pool/util/graph.py @@ -1,5 +1,5 @@ -from __future__ import absolute_import -from __future__ import division + + import math @@ -16,12 +16,12 @@ def _shift(x, shift, pad_item): right_pad = math2.clip(-shift, (0, len(x))) return [pad_item]*left_pad + x[right_pad:-left_pad if left_pad else None] + [pad_item]*right_pad -combine_bins = math2.add_dicts_ext(lambda (a1, b1), (a2, b2): (a1+a2, b1+b2), (0, 0)) +combine_bins = math2.add_dicts_ext(lambda left, right: (left[0]+right[0], left[1]+right[1]), (0, 0)) nothing = object() def keep_largest(n, squash_key=nothing, key=lambda x: x, add_func=lambda a, b: a+b): def _(d): - items = sorted(d.iteritems(), key=lambda (k, v): (k != squash_key, key(v)), reverse=True) + items = sorted(iter(d.items()), key=lambda k_v: (k_v[0] != squash_key, key(k_v[1])), reverse=True) while len(items) > n: k, v = items.pop() if squash_key is not nothing: @@ -53,32 +53,33 @@ def _add_datum(self, t, value): bin = int(math.floor((self.last_bin_end - t)/self.desc.bin_width)) assert bin >= 0 if bin < self.desc.bin_count: - self.bins[bin] = self.ds_desc.keep_largest_func(combine_bins(self.bins[bin], dict((k, (v, 1)) for k, v in value.iteritems()))) + self.bins[bin] = self.ds_desc.keep_largest_func(combine_bins(self.bins[bin], dict((k, (v, 1)) for k, v in value.items()))) def get_data(self, t): bins, last_bin_end = _shift_bins_so_t_is_not_past_end(self.bins, self.last_bin_end, self.desc.bin_width, t) assert last_bin_end - self.desc.bin_width <= t <= last_bin_end - def _((i, bin)): + def _(xxx_todo_changeme): + (i, bin) = xxx_todo_changeme left, right = last_bin_end - self.desc.bin_width*(i + 1), min(t, last_bin_end - self.desc.bin_width*i) center, width = (left+right)/2, right-left if self.ds_desc.is_gauge and self.ds_desc.multivalue_undefined_means_0: - real_count = max([0] + [count for total, count in bin.itervalues()]) + real_count = max([0] + [count for total, count in bin.values()]) if real_count == 0: val = None else: - val = dict((k, total/real_count) for k, (total, count) in bin.iteritems()) + val = dict((k, total/real_count) for k, (total, count) in bin.items()) default = 0 elif self.ds_desc.is_gauge and not self.ds_desc.multivalue_undefined_means_0: - val = dict((k, total/count) for k, (total, count) in bin.iteritems()) + val = dict((k, total/count) for k, (total, count) in bin.items()) default = None else: - val = dict((k, total/width) for k, (total, count) in bin.iteritems()) + val = dict((k, total/width) for k, (total, count) in bin.items()) default = 0 if not self.ds_desc.multivalues: val = None if val is None else val.get('null', default) return center, val, width, default - return map(_, enumerate(bins)) + return list(map(_, enumerate(bins))) class DataStreamDescription(object): @@ -86,7 +87,7 @@ def __init__(self, dataview_descriptions, is_gauge=True, multivalues=False, mult self.dataview_descriptions = dataview_descriptions self.is_gauge = is_gauge self.multivalues = multivalues - self.keep_largest_func = keep_largest(multivalues_keep, multivalues_squash_key, key=lambda (t, c): t/c if self.is_gauge else t, add_func=lambda (a1, b1), (a2, b2): (a1+a2, b1+b2)) + self.keep_largest_func = keep_largest(multivalues_keep, multivalues_squash_key, key=lambda t_c: t_c[0]/t_c[1] if self.is_gauge else t_c[0], add_func=lambda left, right: (left[0]+right[0], left[1]+right[1])) self.multivalue_undefined_means_0 = multivalue_undefined_means_0 self.default_func = default_func @@ -96,27 +97,29 @@ def __init__(self, desc, dataviews): self.dataviews = dataviews def add_datum(self, t, value=1): - for dv_name, dv in self.dataviews.iteritems(): + for dv in self.dataviews.values(): dv._add_datum(t, value) class HistoryDatabase(object): @classmethod - def from_obj(cls, datastream_descriptions, obj={}): + def from_obj(cls, datastream_descriptions, obj=None): + obj = {} if obj is None else obj + def convert_bin(bin): if isinstance(bin, dict): return bin total, count = bin if not isinstance(total, dict): total = {'null': total} - return dict((k, (v, count)) for k, v in total.iteritems()) if count else {} + return dict((k, (v, count)) for k, v in total.items()) if count else {} def get_dataview(ds_name, ds_desc, dv_name, dv_desc): if ds_name in obj: ds_data = obj[ds_name] if dv_name in ds_data: dv_data = ds_data[dv_name] if dv_data['bin_width'] == dv_desc.bin_width and len(dv_data['bins']) == dv_desc.bin_count: - return DataView(dv_desc, ds_desc, dv_data['last_bin_end'], map(convert_bin, dv_data['bins'])) + return DataView(dv_desc, ds_desc, dv_data['last_bin_end'], list(map(convert_bin, dv_data['bins']))) elif ds_desc.default_func is None: return DataView(dv_desc, ds_desc, 0, dv_desc.bin_count*[{}]) else: @@ -124,9 +127,9 @@ def get_dataview(ds_name, ds_desc, dv_name, dv_desc): return cls(dict( (ds_name, DataStream(ds_desc, dict( (dv_name, get_dataview(ds_name, ds_desc, dv_name, dv_desc)) - for dv_name, dv_desc in ds_desc.dataview_descriptions.iteritems() + for dv_name, dv_desc in ds_desc.dataview_descriptions.items() ))) - for ds_name, ds_desc in datastream_descriptions.iteritems() + for ds_name, ds_desc in datastream_descriptions.items() )) def __init__(self, datastreams): @@ -134,7 +137,7 @@ def __init__(self, datastreams): def to_obj(self): return dict((ds_name, dict((dv_name, dict(last_bin_end=dv.last_bin_end, bin_width=dv.desc.bin_width, bins=dv.bins)) - for dv_name, dv in ds.dataviews.iteritems())) for ds_name, ds in self.datastreams.iteritems()) + for dv_name, dv in ds.dataviews.items())) for ds_name, ds in self.datastreams.items()) def make_multivalue_migrator(multivalue_keys, post_func=lambda bins: bins): @@ -143,11 +146,11 @@ def _(ds_name, ds_desc, dv_name, dv_desc, obj): last_bin_end = 0 bins = dv_desc.bin_count*[{}] else: - inputs = dict((k, obj.get(v, {dv_name: dict(bins=[{}]*dv_desc.bin_count, last_bin_end=0)})[dv_name]) for k, v in multivalue_keys.iteritems()) - last_bin_end = max(inp['last_bin_end'] for inp in inputs.itervalues()) if inputs else 0 - assert all(len(inp['bins']) == dv_desc.bin_count for inp in inputs.itervalues()) - inputs = dict((k, dict(zip(['bins', 'last_bin_end'], _shift_bins_so_t_is_not_past_end(v['bins'], v['last_bin_end'], dv_desc.bin_width, last_bin_end)))) for k, v in inputs.iteritems()) - assert len(set(inp['last_bin_end'] for inp in inputs.itervalues())) <= 1 - bins = post_func([dict((k, v['bins'][i]['null']) for k, v in inputs.iteritems() if 'null' in v['bins'][i]) for i in xrange(dv_desc.bin_count)]) + inputs = dict((k, obj.get(v, {dv_name: dict(bins=[{}]*dv_desc.bin_count, last_bin_end=0)})[dv_name]) for k, v in multivalue_keys.items()) + last_bin_end = max(inp['last_bin_end'] for inp in inputs.values()) if inputs else 0 + assert all(len(inp['bins']) == dv_desc.bin_count for inp in inputs.values()) + inputs = dict((k, dict(list(zip(['bins', 'last_bin_end'], _shift_bins_so_t_is_not_past_end(v['bins'], v['last_bin_end'], dv_desc.bin_width, last_bin_end))))) for k, v in inputs.items()) + assert len(set(inp['last_bin_end'] for inp in inputs.values())) <= 1 + bins = post_func([dict((k, v['bins'][i]['null']) for k, v in inputs.items() if 'null' in v['bins'][i]) for i in range(dv_desc.bin_count)]) return DataView(dv_desc, ds_desc, last_bin_end, bins) return _ diff --git a/backend/p2pool/util/http.py b/backend/p2pool/util/http.py new file mode 100644 index 0000000..0d1c5ca --- /dev/null +++ b/backend/p2pool/util/http.py @@ -0,0 +1,24 @@ +from io import BytesIO + +from twisted.internet import reactor +from twisted.web import client +from twisted.web.http_headers import Headers + +from p2pool.util.py3 import ensure_bytes + + +def get_page(url, method=b'GET', postdata=None, timeout=None): + url = ensure_bytes(url, 'ascii') + method = ensure_bytes(method, 'ascii') + + headers = Headers({}) + body = None + if postdata is not None: + body = client.FileBodyProducer(BytesIO(ensure_bytes(postdata))) + headers.addRawHeader(b'content-type', b'text/plain') + + d = client.Agent(reactor).request(method, url, headers, body) + if timeout is not None: + d.addTimeout(timeout, reactor) + d.addCallback(client.readBody) + return d diff --git a/p2pool/util/jsonrpc.py b/backend/p2pool/util/jsonrpc.py similarity index 72% rename from p2pool/util/jsonrpc.py rename to backend/p2pool/util/jsonrpc.py index d810ada..188d592 100644 --- a/p2pool/util/jsonrpc.py +++ b/backend/p2pool/util/jsonrpc.py @@ -1,14 +1,17 @@ -from __future__ import division + import json +from io import BytesIO import weakref -from twisted.internet import defer +from twisted.internet import defer, reactor from twisted.protocols import basic from twisted.python import failure, log from twisted.web import client, error +from twisted.web.http_headers import Headers from p2pool.util import deferral, deferred_resource, memoize +from p2pool.util.py3 import ensure_bytes, ensure_text class Error(Exception): def __init__(self, code, message, data=None): @@ -37,9 +40,9 @@ def __init__(self, *args, **kwargs): class Proxy(object): - def __init__(self, func, services=[]): + def __init__(self, func, services=None): self._func = func - self._services = services + self._services = [] if services is None else services def __getattr__(self, attr): if attr.startswith('rpc_'): @@ -58,7 +61,7 @@ def _handle(data, provider, preargs=(), response_handler=None): try: req = json.loads(data) except Exception: - raise Error_for_code(-32700)(u'Parse error') + raise Error_for_code(-32700)('Parse error') if 'result' in req or 'error' in req: response_handler(req['id'], req['result'] if 'error' not in req or req['error'] is None else @@ -67,20 +70,20 @@ def _handle(data, provider, preargs=(), response_handler=None): id_ = req.get('id', None) method = req.get('method', None) - if not isinstance(method, basestring): - raise Error_for_code(-32600)(u'Invalid Request') + if not isinstance(method, str): + raise Error_for_code(-32600)('Invalid Request') params = req.get('params', []) if not isinstance(params, list): - raise Error_for_code(-32600)(u'Invalid Request') + raise Error_for_code(-32600)('Invalid Request') for service_name in method.split('.')[:-1]: provider = getattr(provider, 'svc_' + service_name, None) if provider is None: - raise Error_for_code(-32601)(u'Service not found') + raise Error_for_code(-32601)('Service not found') method_meth = getattr(provider, 'rpc_' + method.split('.')[-1], None) if method_meth is None: - raise Error_for_code(-32601)(u'Method not found') + raise Error_for_code(-32601)('Method not found') result = yield method_meth(*list(preargs) + list(params)) error = None @@ -88,8 +91,8 @@ def _handle(data, provider, preargs=(), response_handler=None): raise except Exception: log.err(None, 'Squelched JSON error:') - raise Error_for_code(-32099)(u'Unknown error') - except Error, e: + raise Error_for_code(-32099)('Unknown error') + except Error as e: result = None error = e._to_obj() @@ -105,27 +108,34 @@ def _handle(data, provider, preargs=(), response_handler=None): @defer.inlineCallbacks def _http_do(url, headers, timeout, method, params): id_ = 0 + payload = ensure_bytes(json.dumps({ + 'jsonrpc': '2.0', + 'method': method, + 'params': params, + 'id': id_, + }), 'utf-8') + request_headers = dict(headers, **{'Content-Type': 'application/json'}) + agent_headers = Headers(dict( + (ensure_bytes(k, 'ascii'), [ensure_bytes(v, 'ascii')]) + for k, v in request_headers.items() + )) try: - data = yield client.getPage( - url=url, - method='POST', - headers=dict(headers, **{'Content-Type': 'application/json'}), - postdata=json.dumps({ - 'jsonrpc': '2.0', - 'method': method, - 'params': params, - 'id': id_, - }), - timeout=timeout, + agent = client.Agent(reactor) + response = yield agent.request( + b'POST', + ensure_bytes(url, 'ascii'), + agent_headers, + client.FileBodyProducer(BytesIO(payload)), ) - except error.Error, e: + data = yield client.readBody(response) + except error.Error as e: try: resp = json.loads(e.response) except: raise e else: - resp = json.loads(data) + resp = json.loads(ensure_text(data, 'utf-8')) if resp['id'] != id_: raise ValueError('invalid id') @@ -144,21 +154,23 @@ def render_POST(self, request): data = yield _handle(request.content.read(), self._provider, preargs=[request]) assert data is not None request.setHeader('Content-Type', 'application/json') - request.setHeader('Content-Length', len(data)) + data = ensure_bytes(data, 'utf-8') + request.setHeader('Content-Length', str(len(data))) request.write(data) class LineBasedPeer(basic.LineOnlyReceiver): - delimiter = '\n' + delimiter = b'\n' def __init__(self): #basic.LineOnlyReceiver.__init__(self) - self._matcher = deferral.GenericDeferrer(max_id=2**30, func=lambda id, method, params: self.sendLine(json.dumps({ + self._matcher = deferral.GenericDeferrer(max_id=2**30, func=lambda id, method, params: self.sendLine(ensure_bytes(json.dumps({ 'jsonrpc': '2.0', 'method': method, 'params': params, 'id': id, - }))) + }), 'utf-8'))) self.other = Proxy(self._matcher) def lineReceived(self, line): - _handle(line, self, response_handler=self._matcher.got_response).addCallback(lambda line2: self.sendLine(line2) if line2 is not None else None) + _handle(line, self, response_handler=self._matcher.got_response).addCallback( + lambda line2: self.sendLine(ensure_bytes(line2, 'utf-8')) if line2 is not None else None) diff --git a/p2pool/util/logging.py b/backend/p2pool/util/logging.py similarity index 86% rename from p2pool/util/logging.py rename to backend/p2pool/util/logging.py index 698a39d..26656e1 100644 --- a/p2pool/util/logging.py +++ b/backend/p2pool/util/logging.py @@ -4,17 +4,18 @@ import sys from twisted.python import log +from p2pool.util.py3 import ensure_text class EncodeReplacerPipe(object): def __init__(self, inner_file): self.inner_file = inner_file self.softspace = 0 def write(self, data): - if isinstance(data, unicode): + if isinstance(data, bytes): try: - data = data.encode(self.inner_file.encoding, 'replace') + data = data.decode(self.inner_file.encoding, 'replace') except: - data = data.encode('ascii', 'replace') + data = data.decode('ascii', 'replace') self.inner_file.write(data) def flush(self): self.inner_file.flush() @@ -34,7 +35,7 @@ def reopen(self): if length > 100*1000*1000: f.seek(-1000*1000, os.SEEK_END) while True: - if f.read(1) in ('', '\n'): + if f.read(1) in (b'', b'\n'): break data = f.read() f.close() @@ -43,6 +44,7 @@ def reopen(self): f.close() self.inner_file = codecs.open(self.filename, 'a', 'utf-8') def write(self, data): + data = ensure_text(data, 'utf-8') self.inner_file.write(data) def flush(self): self.inner_file.flush() @@ -51,6 +53,7 @@ class TeePipe(object): def __init__(self, outputs): self.outputs = outputs def write(self, data): + data = ensure_text(data, 'utf-8') for output in self.outputs: output.write(data) def flush(self): @@ -63,6 +66,7 @@ def __init__(self, inner_file): self.buf = '' self.softspace = 0 def write(self, data): + data = ensure_text(data, 'utf-8') buf = self.buf + data lines = buf.split('\n') for line in lines[:-1]: @@ -77,6 +81,7 @@ def __init__(self, inner_file): self.inner_file = inner_file self.softspace = 0 def write(self, data): + data = ensure_text(data, 'utf-8') try: self.inner_file.write(data) except: @@ -93,6 +98,7 @@ def __init__(self, inner_file, prefix): self.buf = '' self.softspace = 0 def write(self, data): + data = ensure_text(data, 'utf-8') buf = self.buf + data lines = buf.split('\n') for line in lines[:-1]: diff --git a/p2pool/util/math.py b/backend/p2pool/util/math.py similarity index 89% rename from p2pool/util/math.py rename to backend/p2pool/util/math.py index 5e892f3..a5aa7e7 100644 --- a/p2pool/util/math.py +++ b/backend/p2pool/util/math.py @@ -1,10 +1,12 @@ -from __future__ import absolute_import, division -import __builtin__ + +import builtins import math import random import time +from p2pool.util.py3 import ensure_bytes + def median(x, use_float=True): # there exist better algorithms... y = sorted(x) @@ -37,7 +39,8 @@ def shift_left(n, m): return n << m return n >> -m -def clip(x, (low, high)): +def clip(x, xxx_todo_changeme): + (low, high) = xxx_todo_changeme if x < low: return low elif x > high: @@ -45,13 +48,13 @@ def clip(x, (low, high)): else: return x -add_to_range = lambda x, (low, high): (min(low, x), max(high, x)) +add_to_range = lambda x, bounds: (min(bounds[0], x), max(bounds[1], x)) def nth(i, n=0): i = iter(i) - for _ in xrange(n): - i.next() - return i.next() + for _ in range(n): + next(i) + return next(i) def geometric(p): if p <= 0 or p > 1: @@ -64,13 +67,13 @@ def add_dicts_ext(add_func=lambda a, b: a+b, zero=0): def add_dicts(*dicts): res = {} for d in dicts: - for k, v in d.iteritems(): + for k, v in d.items(): res[k] = add_func(res.get(k, zero), v) - return dict((k, v) for k, v in res.iteritems() if v != zero) + return dict((k, v) for k, v in res.items() if v != zero) return add_dicts add_dicts = add_dicts_ext() -mult_dict = lambda c, x: dict((k, c*v) for k, v in x.iteritems()) +mult_dict = lambda c, x: dict((k, c*v) for k, v in x.items()) def format(x, add_space=False): prefixes = 'kMGTPEZY' @@ -119,7 +122,7 @@ def erf(x): def find_root(y_over_dy, start, steps=10, bounds=(None, None)): guess = start - for i in xrange(steps): + for i in range(steps): prev, guess = guess, guess - y_over_dy(guess) if bounds[0] is not None and guess < bounds[0]: guess = bounds[0] if bounds[1] is not None and guess > bounds[1]: guess = bounds[1] @@ -148,18 +151,18 @@ def binomial_conf_interval(x, n, conf=0.95): def format_binomial_conf(x, n, conf=0.95, f=lambda x: x): if n == 0: return '???' - left, right = minmax(map(f, binomial_conf_interval(x, n, conf))) + left, right = minmax(list(map(f, binomial_conf_interval(x, n, conf)))) return '~%.1f%% (%.f-%.f%%)' % (100*f(x/n), math.floor(100*left), math.ceil(100*right)) def reversed(x): try: - return __builtin__.reversed(x) + return builtins.reversed(x) except TypeError: return reversed(list(x)) class Object(object): def __init__(self, **kwargs): - for k, v in kwargs.iteritems(): + for k, v in kwargs.items(): setattr(self, k, v) def add_tuples(res, *tuples): @@ -190,7 +193,7 @@ def natural_to_string(n, alphabet=None): s = ('%x' % (n,)).lstrip('0') if len(s) % 2: s = '0' + s - return s.decode('hex') + return bytes.fromhex(s) else: assert len(set(alphabet)) == len(alphabet) res = [] @@ -202,8 +205,9 @@ def natural_to_string(n, alphabet=None): def string_to_natural(s, alphabet=None): if alphabet is None: - assert not s.startswith('\x00') - return int(s.encode('hex'), 16) if s else 0 + s = ensure_bytes(s) + assert not s.startswith(b'\x00') + return int.from_bytes(s, 'big') if s else 0 else: assert len(set(alphabet)) == len(alphabet) assert not s.startswith(alphabet[0]) diff --git a/p2pool/util/memoize.py b/backend/p2pool/util/memoize.py similarity index 87% rename from p2pool/util/memoize.py rename to backend/p2pool/util/memoize.py index bf0fafc..6f40a04 100644 --- a/p2pool/util/memoize.py +++ b/backend/p2pool/util/memoize.py @@ -8,17 +8,19 @@ def __init__(self, n): def get(self, key, default=None): if key in self.inner: x, value = self.inner[key] - self.inner[key] = self.counter.next(), value + self.inner[key] = next(self.counter), value return value return default def __setitem__(self, key, value): - self.inner[key] = self.counter.next(), value + self.inner[key] = next(self.counter), value while len(self.inner) > self.n: self.inner.pop(min(self.inner, key=lambda k: self.inner[k][0])) _nothing = object() -def memoize_with_backing(backing, has_inverses=set()): +def memoize_with_backing(backing, has_inverses=None): + has_inverses = set() if has_inverses is None else has_inverses + def a(f): def b(*args): res = backing.get((f, args), _nothing) diff --git a/backend/p2pool/util/memory.py b/backend/p2pool/util/memory.py new file mode 100644 index 0000000..66011a2 --- /dev/null +++ b/backend/p2pool/util/memory.py @@ -0,0 +1,27 @@ +import os +import platform + +_scale = {'kB': 1024, 'mB': 1024*1024, + 'KB': 1024, 'MB': 1024*1024} + +def resident(): + if platform.system() == 'Windows': + from wmi import WMI + w = WMI('.') + # Bandit B608: pid is process-local integer data, not user input. + result = w.query("SELECT WorkingSet FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=%d" % int(os.getpid())) # nosec B608 + return int(result[0].WorkingSet) + try: + with open('/proc/%d/status' % os.getpid()) as f: + v = f.read() + except OSError: + import resource + rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + if platform.system() == 'Darwin': + return rss + return rss * 1024 + + i = v.index('VmRSS:') + v = v[i:].split(None, 3) + #assert len(v) == 3, v + return float(v[1]) * _scale[v[2]] diff --git a/p2pool/util/p2protocol.py b/backend/p2pool/util/p2protocol.py similarity index 74% rename from p2pool/util/p2protocol.py rename to backend/p2pool/util/p2protocol.py index 328dde6..7760d5a 100644 --- a/p2pool/util/p2protocol.py +++ b/backend/p2pool/util/p2protocol.py @@ -10,19 +10,21 @@ import p2pool from p2pool.util import datachunker, variable +from p2pool.util.py3 import bytes_to_hex, ensure_bytes class TooLong(Exception): pass class Protocol(protocol.Protocol): - def __init__(self, message_prefix, max_payload_length, traffic_happened=variable.Event(), ignore_trailing_payload=False): + def __init__(self, message_prefix, max_payload_length, traffic_happened=None, ignore_trailing_payload=False): + traffic_happened = variable.Event() if traffic_happened is None else traffic_happened if isinstance(message_prefix, (tuple, list)): - self._message_prefixes = tuple(message_prefix) + self._message_prefixes = tuple(ensure_bytes(prefix) for prefix in message_prefix) self._message_prefix = self._message_prefixes[0] else: - self._message_prefixes = (message_prefix,) - self._message_prefix = message_prefix - self._message_prefix_len = max(map(len, self._message_prefixes)) + self._message_prefixes = (ensure_bytes(message_prefix),) + self._message_prefix = ensure_bytes(message_prefix) + self._message_prefix_len = max(list(map(len, self._message_prefixes))) self._max_payload_length = max_payload_length self.dataReceived2 = datachunker.DataChunker(self.dataReceiver()) self.traffic_happened = traffic_happened @@ -34,7 +36,7 @@ def dataReceived(self, data): def dataReceiver(self): while True: - start = '' + start = b'' while start not in self._message_prefixes: start = (start + (yield 1))[-self._message_prefix_len:] for prefix in self._message_prefixes: @@ -43,31 +45,31 @@ def dataReceiver(self): break self._message_prefix = start - command = (yield 12).rstrip('\0') + command = (yield 12).rstrip(b'\0').decode('ascii') length, = struct.unpack(' self._max_payload_length: - print 'length too large' + print('length too large') continue checksum = yield 4 payload = yield length if hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] != checksum: - print 'invalid hash for', self.transport.getPeer().host, repr(command), length, checksum.encode('hex') + print('invalid hash for', self.transport.getPeer().host, repr(command), length, bytes_to_hex(checksum)) if p2pool.DEBUG: - print hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4].encode('hex'), payload.encode('hex') + print(bytes_to_hex(hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4]), bytes_to_hex(payload)) self.badPeerHappened() continue type_ = getattr(self, 'message_' + command, None) if type_ is None: if p2pool.DEBUG: - print 'no type for', repr(command) + print('no type for', repr(command)) continue try: self.packetReceived(command, type_.unpack(payload, self.ignore_trailing_payload)) except: - print 'RECV', command, payload[:100].encode('hex') + ('...' if len(payload) > 100 else '') + print('RECV', command, bytes_to_hex(payload[:100]) + ('...' if len(payload) > 100 else '')) log.err(None, 'Error handling message: (see RECV line)') self.disconnect() @@ -75,7 +77,7 @@ def packetReceived(self, command, payload2): handler = getattr(self, 'handle_' + command, None) if handler is None: if p2pool.DEBUG: - print 'no handler for', repr(command) + print('no handler for', repr(command)) return if getattr(self, 'connected', True) and not getattr(self, 'disconnecting', False): @@ -102,7 +104,7 @@ def sendPacket(self, command, payload2): payload = type_.pack(payload2) if len(payload) > self._max_payload_length: raise TooLong('payload too long') - data = self._message_prefix + struct.pack('<12sI', command, len(payload)) + hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] + payload + data = self._message_prefix + struct.pack('<12sI', ensure_bytes(command, 'ascii'), len(payload)) + hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] + payload self.traffic_happened.happened('p2p/out', len(data)) self.transport.write(data) diff --git a/p2pool/util/pack.py b/backend/p2pool/util/pack.py similarity index 90% rename from p2pool/util/pack.py rename to backend/p2pool/util/pack.py index 7fbf8bd..d805582 100644 --- a/p2pool/util/pack.py +++ b/backend/p2pool/util/pack.py @@ -1,10 +1,12 @@ import binascii +import ipaddress import struct -import cStringIO as StringIO +import io import os import p2pool from p2pool.util import memoize +from p2pool.util.py3 import bord, ensure_bytes, bytes_to_hex, hex_to_bytes class EarlyEnd(Exception): pass @@ -26,9 +28,9 @@ def __hash__(self): rval = getattr(self, '_hash', None) if rval is None: try: - rval = self._hash = hash((type(self), frozenset(self.__dict__.items()))) + rval = self._hash = hash((type(self), frozenset(list(self.__dict__.items())))) except: - print self.__dict__ + print(self.__dict__) raise return rval @@ -45,13 +47,13 @@ def _unpack(self, data, ignore_trailing=False): return obj def _pack(self, obj): - f = StringIO.StringIO() + f = io.BytesIO() self.write(f, obj) return f.getvalue() def unpack(self, data, ignore_trailing=False): - if not type(data) == StringIO.InputType: - data = StringIO.StringIO(data) + if not hasattr(data, 'read'): + data = io.BytesIO(ensure_bytes(data)) obj = self._unpack(data, ignore_trailing) if p2pool.DEBUG: @@ -82,7 +84,9 @@ def packed_size(self, obj): class VarIntType(Type): def read(self, file): data = file.read(1) - first = ord(data) + if not data: + raise EarlyEnd() + first = bord(data) if first < 0xfd: return first if first == 0xfd: @@ -128,7 +132,7 @@ def __init__(self, inner, pack_to_unpack): self.pack_to_unpack = pack_to_unpack self.unpack_to_pack = {} - for k, v in pack_to_unpack.iteritems(): + for k, v in pack_to_unpack.items(): if v in self.unpack_to_pack: raise ValueError('duplicate value in pack_to_unpack') self.unpack_to_pack[v] = k @@ -154,7 +158,7 @@ def __init__(self, type, mul=1): def read(self, file): length = self._inner_size.read(file) length *= self.mul - res = [self.type.read(file) for i in xrange(length)] + res = [self.type.read(file) for i in range(length)] return res def write(self, file, item): @@ -187,7 +191,7 @@ def __new__(cls, bits, endianness='little'): if bits in [8, 16, 32, 64]: return StructType(('<' if endianness == 'little' else '>') + {8: 'B', 16: 'H', 32: 'I', 64: 'Q'}[bits]) else: - return Type.__new__(cls, bits, endianness) + return object.__new__(cls) def __init__(self, bits, endianness='little'): assert bits % 8 == 0 @@ -213,18 +217,16 @@ def write(self, file, item, a2b_hex=binascii.a2b_hex): class IPV6AddressType(Type): def read(self, file): data = file.read(16) - if data[:12] == '00000000000000000000ffff'.decode('hex'): - return '.'.join(str(ord(x)) for x in data[12:]) - return ':'.join(data[i*2:(i+1)*2].encode('hex') for i in xrange(8)) + if data[:12] == hex_to_bytes('00000000000000000000ffff'): + return '.'.join(str(x) for x in data[12:]) + return ':'.join(bytes_to_hex(data[i*2:(i+1)*2]) for i in range(8)) def write(self, file, item): - if ':' in item: - data = ''.join(item.replace(':', '')).decode('hex') + address = ipaddress.ip_address(item) + if address.version == 6: + data = address.packed else: - bits = map(int, item.split('.')) - if len(bits) != 4: - raise ValueError('invalid address: %r' % (bits,)) - data = '00000000000000000000ffff'.decode('hex') + ''.join(chr(x) for x in bits) + data = hex_to_bytes('00000000000000000000ffff') + address.packed assert len(data) == 16, len(data) file.write(data) diff --git a/backend/p2pool/util/py3.py b/backend/p2pool/util/py3.py new file mode 100644 index 0000000..7f46e92 --- /dev/null +++ b/backend/p2pool/util/py3.py @@ -0,0 +1,41 @@ +import binascii + + +def ensure_bytes(value, encoding='latin1'): + if isinstance(value, bytes): + return value + if isinstance(value, bytearray): + return bytes(value) + if isinstance(value, str): + return value.encode(encoding) + raise TypeError(f'expected bytes-like value, got {type(value).__name__}') + + +def ensure_text(value, encoding='ascii'): + if isinstance(value, str): + return value + if isinstance(value, bytes): + return value.decode(encoding) + raise TypeError(f'expected text-like value, got {type(value).__name__}') + + +def bchr(value): + return bytes((value,)) + + +def bord(value): + if isinstance(value, int): + return value + if isinstance(value, (bytes, bytearray)): + if len(value) != 1: + raise ValueError('expected one byte') + return value[0] + return ord(value) + + +def hex_to_bytes(value): + return binascii.unhexlify(ensure_bytes(value, 'ascii')) + + +def bytes_to_hex(value): + return binascii.hexlify(ensure_bytes(value)).decode('ascii') diff --git a/p2pool/util/segwit_addr.py b/backend/p2pool/util/segwit_addr.py similarity index 99% rename from p2pool/util/segwit_addr.py rename to backend/p2pool/util/segwit_addr.py index a50a29f..c556a5a 100644 --- a/p2pool/util/segwit_addr.py +++ b/backend/p2pool/util/segwit_addr.py @@ -20,7 +20,7 @@ """Reference implementation for Bech32 and segwit addresses.""" -from math import convertbits +from .math import convertbits CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" diff --git a/p2pool/util/skiplist.py b/backend/p2pool/util/skiplist.py similarity index 95% rename from p2pool/util/skiplist.py rename to backend/p2pool/util/skiplist.py index e9e36c2..ff0256e 100644 --- a/p2pool/util/skiplist.py +++ b/backend/p2pool/util/skiplist.py @@ -22,7 +22,7 @@ def __call__(self, start, *args): skip_length, skip = self.skips[pos] # fill previous updates - for i in xrange(skip_length): + for i in range(skip_length): if i in updates: that_hash, delta = updates.pop(i) x, y = self.skips[that_hash] @@ -30,7 +30,7 @@ def __call__(self, start, *args): y.append((pos, delta)) # put desired skip nodes in updates - for i in xrange(len(skip), skip_length): + for i in range(len(skip), skip_length): updates[i] = pos, None #if skip_length + 1 in updates: diff --git a/p2pool/util/switchprotocol.py b/backend/p2pool/util/switchprotocol.py similarity index 57% rename from p2pool/util/switchprotocol.py rename to backend/p2pool/util/switchprotocol.py index 29d05e6..1fa46de 100644 --- a/p2pool/util/switchprotocol.py +++ b/backend/p2pool/util/switchprotocol.py @@ -17,8 +17,24 @@ class FirstByteSwitchFactory(protocol.ServerFactory): protocol = FirstByteSwitchProtocol def __init__(self, first_byte_to_serverfactory, default_serverfactory): - self.first_byte_to_serverfactory = first_byte_to_serverfactory + self.first_byte_to_serverfactory = dict( + (self._normalize_first_byte(first_byte), serverfactory) + for first_byte, serverfactory in first_byte_to_serverfactory.items()) self.default_serverfactory = default_serverfactory + + @staticmethod + def _normalize_first_byte(first_byte): + if isinstance(first_byte, int): + return first_byte + if isinstance(first_byte, bytes): + if len(first_byte) != 1: + raise ValueError('first-byte switch keys must be exactly one byte') + return first_byte[0] + if isinstance(first_byte, str): + if len(first_byte) != 1: + raise ValueError('first-byte switch keys must be exactly one character') + return ord(first_byte) + raise TypeError('unsupported first-byte switch key type: %s' % (type(first_byte).__name__,)) def startFactory(self): for f in list(self.first_byte_to_serverfactory.values()) + [self.default_serverfactory]: diff --git a/p2pool/util/variable.py b/backend/p2pool/util/variable.py similarity index 65% rename from p2pool/util/variable.py rename to backend/p2pool/util/variable.py index 47256e9..bcdefee 100644 --- a/p2pool/util/variable.py +++ b/backend/p2pool/util/variable.py @@ -19,7 +19,7 @@ def watch_weakref(self, obj, func): watch_id = self.watch(lambda *args: func(obj_ref(), *args)) obj_ref = weakref.ref(obj, lambda _: self.unwatch(watch_id)) def watch(self, func): - id = self.id_generator.next() + id = next(self.id_generator) self.observers[id] = func return id def unwatch(self, id): @@ -37,7 +37,7 @@ def happened(self, *event): once, self._once = self._once, None - for id, func in sorted(self.observers.iteritems()): + for id, func in sorted(self.observers.items()): try: func(*event) except: @@ -48,15 +48,36 @@ def happened(self, *event): def get_deferred(self, timeout=None): once = self.once - df = defer.Deferred() - id1 = once.watch(lambda *event: df.callback(event)) + watch_ids = [] + delay = [None] + + def cancel(df): + for watch_id in watch_ids[:]: + if watch_id in once.observers: + once.unwatch(watch_id) + if delay[0] is not None and delay[0].active(): + delay[0].cancel() + + df = defer.Deferred(cancel) + + def callback_once(*event): + if not df.called: + df.callback(event) + + id1 = once.watch(callback_once) + watch_ids.append(id1) if timeout is not None: def do_timeout(): - df.errback(failure.Failure(defer.TimeoutError('in Event.get_deferred'))) - once.unwatch(id1) - once.unwatch(x) - delay = reactor.callLater(timeout, do_timeout) - x = once.watch(lambda *event: delay.cancel()) + if not df.called: + df.errback(failure.Failure(defer.TimeoutError('in Event.get_deferred'))) + delay[0] = reactor.callLater(timeout, do_timeout) + + def cancel_timeout(*event): + if delay[0] is not None and delay[0].active(): + delay[0].cancel() + + x = once.watch(cancel_timeout) + watch_ids.append(x) return df class Variable(object): @@ -91,14 +112,14 @@ def __init__(self, value): self.removed = Event() def add(self, values): - new_items = dict([item for item in values.iteritems() if not item[0] in self.value or self.value[item[0]] != item[1]]) + new_items = dict([item for item in values.items() if not item[0] in self.value or self.value[item[0]] != item[1]]) self.value.update(values) self.added.happened(new_items) # XXX call self.changed and self.transitioned def remove(self, values): - gone_items = dict([item for item in values.iteritems() if item[0] in self.value]) - for key in gone_keys: - del self.values[key] - self.removed.happened(new_items) + gone_items = dict([item for item in values.items() if item[0] in self.value]) + for key in gone_items: + del self.value[key] + self.removed.happened(gone_items) # XXX call self.changed and self.transitioned diff --git a/p2pool/web.py b/backend/p2pool/web.py similarity index 76% rename from p2pool/web.py rename to backend/p2pool/web.py index 0ab337e..b92a55c 100644 --- a/p2pool/web.py +++ b/backend/p2pool/web.py @@ -1,4 +1,4 @@ -from __future__ import division + import errno import json @@ -6,46 +6,47 @@ import sys import time import traceback +from contextlib import suppress from twisted.internet import defer, reactor from twisted.python import log from twisted.web import resource, static import p2pool -from bitcoin import data as bitcoin_data +from .bitcoin import data as bitcoin_data from . import data as p2pool_data, p2p -from util import deferral, deferred_resource, graph, math, memory, pack, variable +from .util import deferral, deferred_resource, graph, math, memory, pack, variable +from .util.py3 import bytes_to_hex, ensure_bytes def _atomic_read(filename): try: with open(filename, 'rb') as f: return f.read() - except IOError, e: + except IOError as e: if e.errno != errno.ENOENT: raise try: with open(filename + '.new', 'rb') as f: return f.read() - except IOError, e: + except IOError as e: if e.errno != errno.ENOENT: raise return None def _atomic_write(filename, data): with open(filename + '.new', 'wb') as f: - f.write(data) + f.write(ensure_bytes(data)) f.flush() - try: + with suppress(OSError): os.fsync(f.fileno()) - except: - pass try: os.rename(filename + '.new', filename) except: # XXX windows can't overwrite os.remove(filename) os.rename(filename + '.new', filename) -def get_web_root(wb, datadir_path, bitcoind_getinfo_var, stop_event=variable.Event(), static_dir=None): +def get_web_root(wb, datadir_path, bitcoind_getinfo_var, stop_event=None, static_dir=None): + stop_event = variable.Event() if stop_event is None else stop_event node = wb.node start_time = time.time() @@ -61,8 +62,8 @@ def get_users(): def get_current_scaled_txouts(scale, trunc=0): txouts = node.get_current_txouts() - total = sum(txouts.itervalues()) - results = dict((addr, value*scale//total) for addr, value in txouts.iteritems()) + total = sum(txouts.values()) + results = dict((addr, value*scale//total) for addr, value in txouts.items()) if trunc > 0: total_random = 0 random_set = set() @@ -72,12 +73,12 @@ def get_current_scaled_txouts(scale, trunc=0): total_random += results[s] random_set.add(s) if total_random: - winner = math.weighted_choice((addr, results[script]) for addr in random_set) + winner = math.weighted_choice((addr, results[addr]) for addr in random_set) for addr in random_set: del results[addr] results[winner] = total_random - if sum(results.itervalues()) < int(scale): - results[math.weighted_choice(results.iteritems())] += int(scale) - sum(results.itervalues()) + if sum(results.values()) < int(scale): + results[math.weighted_choice(iter(results.items()))] += int(scale) - sum(results.values()) return results def get_patron_sendmany(total=None, trunc='0.01'): @@ -87,7 +88,7 @@ def get_patron_sendmany(total=None, trunc='0.01'): trunc = int(float(trunc)*1e8) return json.dumps(dict( (bitcoin_data.script2_to_address(script, node.net.PARENT), value/1e8) - for script, value in get_current_scaled_txouts(total, trunc).iteritems() + for script, value in get_current_scaled_txouts(total, trunc).items() if bitcoin_data.script2_to_address(script, node.net.PARENT) is not None )) @@ -164,8 +165,8 @@ def get_local_stats(): efficiency_if_miner_perfect=(1 - stale_orphan_shares/shares)/(1 - global_stale_prop) if shares else None, # ignores dead shares because those are miner's fault and indicated by pseudoshare rejection efficiency=(1 - (stale_orphan_shares+stale_doa_shares)/shares)/(1 - global_stale_prop) if shares else None, peers=dict( - incoming=sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming), - outgoing=sum(1 for peer in node.p2p_node.peers.itervalues() if not peer.incoming), + incoming=sum(1 for peer in node.p2p_node.peers.values() if peer.incoming), + outgoing=sum(1 for peer in node.p2p_node.peers.values() if not peer.incoming), ), shares=dict( total=shares, @@ -189,6 +190,8 @@ def __init__(self, func, mime_type='application/json', args=()): self.func, self.mime_type, self.args = func, mime_type, args def getChild(self, child, request): + if isinstance(child, bytes): + child = child.decode('ascii') return WebInterface(self.func, self.mime_type, self.args + (child,)) @defer.inlineCallbacks @@ -200,46 +203,48 @@ def render_GET(self, request): def decent_height(): return min(node.tracker.get_height(node.best_share_var.value), 720) - web_root.putChild('rate', WebInterface(lambda: p2pool_data.get_pool_attempts_per_second(node.tracker, node.best_share_var.value, decent_height())/(1-p2pool_data.get_average_stale_prop(node.tracker, node.best_share_var.value, decent_height())))) - web_root.putChild('difficulty', WebInterface(lambda: bitcoin_data.target_to_difficulty(node.tracker.items[node.best_share_var.value].max_target))) - web_root.putChild('users', WebInterface(get_users)) - web_root.putChild('user_stales', WebInterface(lambda: + web_root.putChild(b'rate', WebInterface(lambda: p2pool_data.get_pool_attempts_per_second(node.tracker, node.best_share_var.value, decent_height())/(1-p2pool_data.get_average_stale_prop(node.tracker, node.best_share_var.value, decent_height())))) + web_root.putChild(b'difficulty', WebInterface(lambda: bitcoin_data.target_to_difficulty(node.tracker.items[node.best_share_var.value].max_target))) + web_root.putChild(b'users', WebInterface(get_users)) + web_root.putChild(b'user_stales', WebInterface(lambda: p2pool_data.get_user_stale_props(node.tracker, node.best_share_var.value, node.tracker.get_height(node.best_share_var.value), node.net.PARENT))) - web_root.putChild('fee', WebInterface(lambda: wb.worker_fee)) - web_root.putChild('current_payouts', WebInterface(lambda: dict( + web_root.putChild(b'fee', WebInterface(lambda: wb.worker_fee)) + web_root.putChild(b'current_payouts', WebInterface(lambda: dict( (address, value/1e8) for address, value - in node.get_current_txouts().iteritems()))) - web_root.putChild('patron_sendmany', WebInterface(get_patron_sendmany, 'text/plain')) - web_root.putChild('global_stats', WebInterface(get_global_stats)) - web_root.putChild('local_stats', WebInterface(get_local_stats)) - web_root.putChild('peer_addresses', WebInterface(lambda: ' '.join('%s%s' % (peer.transport.getPeer().host, ':'+str(peer.transport.getPeer().port) if peer.transport.getPeer().port != node.net.P2P_PORT else '') for peer in node.p2p_node.peers.itervalues()))) - web_root.putChild('peer_txpool_sizes', WebInterface(lambda: dict(('%s:%i' % (peer.transport.getPeer().host, peer.transport.getPeer().port), peer.remembered_txs_size) for peer in node.p2p_node.peers.itervalues()))) - web_root.putChild('pings', WebInterface(defer.inlineCallbacks(lambda: defer.returnValue( - dict([(a, (yield b)) for a, b in - [( - '%s:%i' % (peer.transport.getPeer().host, peer.transport.getPeer().port), - defer.inlineCallbacks(lambda peer=peer: defer.returnValue( - min([(yield peer.do_ping().addCallback(lambda x: x/0.001).addErrback(lambda fail: None)) for i in xrange(3)]) - ))() - ) for peer in list(node.p2p_node.peers.itervalues())] - ]) - )))) - web_root.putChild('peer_versions', WebInterface(lambda: dict(('%s:%i' % peer.addr, peer.other_sub_version) for peer in node.p2p_node.peers.itervalues()))) - web_root.putChild('payout_addr', WebInterface(lambda: wb.address)) - web_root.putChild('payout_addrs', WebInterface( + in node.get_current_txouts().items()))) + web_root.putChild(b'patron_sendmany', WebInterface(get_patron_sendmany, 'text/plain')) + web_root.putChild(b'global_stats', WebInterface(get_global_stats)) + web_root.putChild(b'local_stats', WebInterface(get_local_stats)) + web_root.putChild(b'peer_addresses', WebInterface(lambda: ' '.join('%s%s' % (peer.transport.getPeer().host, ':'+str(peer.transport.getPeer().port) if peer.transport.getPeer().port != node.net.P2P_PORT else '') for peer in node.p2p_node.peers.values()))) + web_root.putChild(b'peer_txpool_sizes', WebInterface(lambda: dict(('%s:%i' % (peer.transport.getPeer().host, peer.transport.getPeer().port), peer.remembered_txs_size) for peer in node.p2p_node.peers.values()))) + @defer.inlineCallbacks + def get_pings(): + res = {} + for peer in list(node.p2p_node.peers.values()): + addr = '%s:%i' % (peer.transport.getPeer().host, peer.transport.getPeer().port) + values = [] + for _ in range(3): + value = yield peer.do_ping().addCallback(lambda x: x/0.001).addErrback(lambda fail: None) + values.append(value) + res[addr] = min(values) + defer.returnValue(res) + web_root.putChild(b'pings', WebInterface(get_pings)) + web_root.putChild(b'peer_versions', WebInterface(lambda: dict(('%s:%i' % peer.addr, peer.other_sub_version) for peer in node.p2p_node.peers.values()))) + web_root.putChild(b'payout_addr', WebInterface(lambda: wb.address)) + web_root.putChild(b'payout_addrs', WebInterface( lambda: list(add['address'] for add in wb.pubkeys.keys))) - web_root.putChild('recent_blocks', WebInterface(lambda: [dict( + web_root.putChild(b'recent_blocks', WebInterface(lambda: [dict( ts=s.timestamp, hash='%064x' % s.header_hash, number=p2pool_data.parse_bip0034(s.share_data['coinbase'])[0], share='%064x' % s.hash, ) for s in node.tracker.get_chain(node.best_share_var.value, min(node.tracker.get_height(node.best_share_var.value), node.net.CHAIN_LENGTH)) if s.pow_hash <= s.header['bits'].target])) - web_root.putChild('uptime', WebInterface(lambda: time.time() - start_time)) - web_root.putChild('stale_rates', WebInterface(lambda: p2pool_data.get_stale_counts(node.tracker, node.best_share_var.value, decent_height(), rates=True))) + web_root.putChild(b'uptime', WebInterface(lambda: time.time() - start_time)) + web_root.putChild(b'stale_rates', WebInterface(lambda: p2pool_data.get_stale_counts(node.tracker, node.best_share_var.value, decent_height(), rates=True))) new_root = resource.Resource() - web_root.putChild('web', new_root) + web_root.putChild(b'web', new_root) stat_log = [] if os.path.exists(os.path.join(datadir_path, 'stats')): @@ -275,8 +280,8 @@ def update_stat_log(): stale_shares_breakdown=dict(orphan=stale_orphan_shares, doa=stale_doa_shares), current_payout=my_current_payout, peers=dict( - incoming=sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming), - outgoing=sum(1 for peer in node.p2p_node.peers.itervalues() if not peer.incoming), + incoming=sum(1 for peer in node.p2p_node.peers.values() if peer.incoming), + outgoing=sum(1 for peer in node.p2p_node.peers.values() if not peer.incoming), ), attempts_to_share=bitcoin_data.target_to_average_attempts(node.tracker.items[node.best_share_var.value].max_target), attempts_to_block=bitcoin_data.target_to_average_attempts(node.bitcoind_work.value['bits'].target), @@ -284,11 +289,11 @@ def update_stat_log(): )) with open(os.path.join(datadir_path, 'stats'), 'wb') as f: - f.write(json.dumps(stat_log)) + f.write(ensure_bytes(json.dumps(stat_log))) x = deferral.RobustLoopingCall(update_stat_log) x.start(5*60) stop_event.watch(x.stop) - new_root.putChild('log', WebInterface(lambda: stat_log)) + new_root.putChild(b'log', WebInterface(lambda: stat_log)) def get_share(share_hash_str): if int(share_hash_str, 16) not in node.tracker.items: @@ -333,8 +338,8 @@ def get_share(share_hash_str): ), gentx=dict( hash='%064x' % share.gentx_hash, - raw=bitcoin_data.tx_id_type.pack(share.gentx).encode('hex') if hasattr(share, 'gentx') else "unknown", - coinbase=share.share_data['coinbase'].ljust(2, '\x00').encode('hex'), + raw=bytes_to_hex(bitcoin_data.tx_id_type.pack(share.gentx)) if hasattr(share, 'gentx') else "unknown", + coinbase=bytes_to_hex(share.share_data['coinbase'].ljust(2, b'\x00')), value=share.share_data['subsidy']*1e-8, last_txout_nonce='%016x' % share.contents['last_txout_nonce'], ), @@ -353,28 +358,28 @@ def get_share_address(share_hash_str): node.net.ADDRESS_VERSION, -1, node.net.PARENT) - new_root.putChild('payout_address', WebInterface(lambda share_hash_str: get_share_address(share_hash_str))) - new_root.putChild('share', WebInterface(lambda share_hash_str: get_share(share_hash_str))) - new_root.putChild('heads', WebInterface(lambda: ['%064x' % x for x in node.tracker.heads])) - new_root.putChild('verified_heads', WebInterface(lambda: ['%064x' % x for x in node.tracker.verified.heads])) - new_root.putChild('tails', WebInterface(lambda: ['%064x' % x for t in node.tracker.tails for x in node.tracker.reverse.get(t, set())])) - new_root.putChild('verified_tails', WebInterface(lambda: ['%064x' % x for t in node.tracker.verified.tails for x in node.tracker.verified.reverse.get(t, set())])) - new_root.putChild('best_share_hash', WebInterface(lambda: '%064x' % node.best_share_var.value)) - new_root.putChild('my_share_hashes', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in wb.my_share_hashes])) - new_root.putChild('my_share_hashes50', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in list(wb.my_share_hashes)[:50]])) + new_root.putChild(b'payout_address', WebInterface(lambda share_hash_str: get_share_address(share_hash_str))) + new_root.putChild(b'share', WebInterface(lambda share_hash_str: get_share(share_hash_str))) + new_root.putChild(b'heads', WebInterface(lambda: ['%064x' % x for x in node.tracker.heads])) + new_root.putChild(b'verified_heads', WebInterface(lambda: ['%064x' % x for x in node.tracker.verified.heads])) + new_root.putChild(b'tails', WebInterface(lambda: ['%064x' % x for t in node.tracker.tails for x in node.tracker.reverse.get(t, set())])) + new_root.putChild(b'verified_tails', WebInterface(lambda: ['%064x' % x for t in node.tracker.verified.tails for x in node.tracker.verified.reverse.get(t, set())])) + new_root.putChild(b'best_share_hash', WebInterface(lambda: '%064x' % node.best_share_var.value)) + new_root.putChild(b'my_share_hashes', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in wb.my_share_hashes])) + new_root.putChild(b'my_share_hashes50', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in list(wb.my_share_hashes)[:50]])) def get_share_data(share_hash_str): if int(share_hash_str, 16) not in node.tracker.items: return '' share = node.tracker.items[int(share_hash_str, 16)] return p2pool_data.share_type.pack(share.as_share()) - new_root.putChild('share_data', WebInterface(lambda share_hash_str: get_share_data(share_hash_str), 'application/octet-stream')) - new_root.putChild('currency_info', WebInterface(lambda: dict( + new_root.putChild(b'share_data', WebInterface(lambda share_hash_str: get_share_data(share_hash_str), 'application/octet-stream')) + new_root.putChild(b'currency_info', WebInterface(lambda: dict( symbol=node.net.PARENT.SYMBOL, block_explorer_url_prefix=node.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, address_explorer_url_prefix=node.net.PARENT.ADDRESS_EXPLORER_URL_PREFIX, tx_explorer_url_prefix=node.net.PARENT.TX_EXPLORER_URL_PREFIX, ))) - new_root.putChild('version', WebInterface(lambda: p2pool.__version__)) + new_root.putChild(b'version', WebInterface(lambda: p2pool.__version__)) hd_path = os.path.join(datadir_path, 'graph_db') hd_data = _atomic_read(hd_path) @@ -397,7 +402,7 @@ def get_share_data(share_hash_str): 'local_share_hash_rates': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True, multivalue_undefined_means_0=True, default_func=graph.make_multivalue_migrator(dict(good='local_share_hash_rate', dead='local_dead_share_hash_rate', orphan='local_orphan_share_hash_rate'), - post_func=lambda bins: [dict((k, (v[0] - (sum(bin.get(rem_k, (0, 0))[0] for rem_k in ['dead', 'orphan']) if k == 'good' else 0), v[1])) for k, v in bin.iteritems()) for bin in bins])), + post_func=lambda bins: [dict((k, (v[0] - (sum(bin.get(rem_k, (0, 0))[0] for rem_k in ['dead', 'orphan']) if k == 'good' else 0), v[1])) for k, v in bin.items()) for bin in bins])), 'pool_rates': graph.DataStreamDescription(dataview_descriptions, multivalues=True, multivalue_undefined_means_0=True), 'current_payout': graph.DataStreamDescription(dataview_descriptions), @@ -451,7 +456,7 @@ def add_point(): t = time.time() pool_rates = p2pool_data.get_stale_counts(node.tracker, node.best_share_var.value, lookbehind, rates=True) - pool_total = sum(pool_rates.itervalues()) + pool_total = sum(pool_rates.values()) hd.datastreams['pool_rates'].add_datum(t, pool_rates) current_txouts = node.get_current_txouts() @@ -465,13 +470,13 @@ def add_point(): hd.datastreams['current_payouts'].add_datum(t, dict((user, current_txouts_by_address[user]*1e-8) for user in miner_hash_rates if user in current_txouts_by_address)) hd.datastreams['peers'].add_datum(t, dict( - incoming=sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming), - outgoing=sum(1 for peer in node.p2p_node.peers.itervalues() if not peer.incoming), + incoming=sum(1 for peer in node.p2p_node.peers.values() if peer.incoming), + outgoing=sum(1 for peer in node.p2p_node.peers.values() if not peer.incoming), )) vs = p2pool_data.get_desired_version_counts(node.tracker, node.best_share_var.value, lookbehind) - vs_total = sum(vs.itervalues()) - hd.datastreams['desired_version_rates'].add_datum(t, dict((str(k), v/vs_total*pool_total) for k, v in vs.iteritems())) + vs_total = sum(vs.values()) + hd.datastreams['desired_version_rates'].add_datum(t, dict((str(k), v/vs_total*pool_total) for k, v in vs.items())) try: hd.datastreams['memory_usage'].add_datum(t, memory.resident()) except: @@ -483,10 +488,23 @@ def add_point(): @node.bitcoind_work.changed.watch def _(new_work): hd.datastreams['getwork_latency'].add_datum(time.time(), new_work['latency']) - new_root.putChild('graph_data', WebInterface(lambda source, view: hd.datastreams[source].dataviews[view].get_data(time.time()))) + new_root.putChild(b'graph_data', WebInterface(lambda source, view: hd.datastreams[source].dataviews[view].get_data(time.time()))) if static_dir is None: - static_dir = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'web-static') - web_root.putChild('static', static.File(static_dir)) + launcher_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + static_dir_candidates = ( + os.path.join(launcher_dir, 'frontend', 'web-static'), + os.path.join(launcher_dir, 'web-static'), + os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'frontend', 'web-static')), + ) + for candidate in static_dir_candidates: + if os.path.isdir(candidate): + static_dir = candidate + break + else: + raise RuntimeError( + 'No web-static frontend directory found. Checked: ' + f'{", ".join(static_dir_candidates)}') + web_root.putChild(b'static', static.File(static_dir)) return web_root diff --git a/p2pool/work.py b/backend/p2pool/work.py similarity index 86% rename from p2pool/work.py rename to backend/p2pool/work.py index 33e2e36..bea2e26 100644 --- a/p2pool/work.py +++ b/backend/p2pool/work.py @@ -1,18 +1,20 @@ -from __future__ import division + from collections import deque import base64 import random import re +import secrets import sys import time from twisted.internet import defer from twisted.python import log -import bitcoin.getwork as bitcoin_getwork, bitcoin.data as bitcoin_data -from bitcoin import helper, script, worker_interface -from util import forest, jsonrpc, variable, deferral, math, pack +from .bitcoin import getwork as bitcoin_getwork, data as bitcoin_data +from .bitcoin import helper, script, worker_interface +from .util import forest, jsonrpc, variable, deferral, math, pack +from .util.py3 import bytes_to_hex, hex_to_bytes, ensure_bytes import p2pool, p2pool.data as p2pool_data print_throttle = 0.0 @@ -77,13 +79,14 @@ def _(share): @defer.inlineCallbacks def set_merged_work(merged_url, merged_userpass): - merged_proxy = jsonrpc.HTTPProxy(merged_url, dict(Authorization='Basic ' + base64.b64encode(merged_userpass))) + merged_proxy = jsonrpc.HTTPProxy(merged_url, dict( + Authorization='Basic ' + base64.b64encode(ensure_bytes(merged_userpass)).decode('ascii'))) while self.running: auxblock = yield deferral.retry('Error while calling merged getauxblock on %s:' % (merged_url,), 30)(merged_proxy.rpc_getauxblock)() target = auxblock['target'] if 'target' in auxblock else auxblock['_target'] self.merged_work.set(math.merge_dicts(self.merged_work.value, {auxblock['chainid']: dict( hash=int(auxblock['hash'], 16), - target='p2pool' if target == 'p2pool' else pack.IntType(256).unpack(target.decode('hex')), + target='p2pool' if target == 'p2pool' else pack.IntType(256).unpack(hex_to_bytes(target)), merged_proxy=merged_proxy, )})) yield deferral.sleep(1) @@ -92,7 +95,7 @@ def set_merged_work(merged_url, merged_userpass): @self.merged_work.changed.watch def _(new_merged_work): - print 'Got new merged mining work!' + print('Got new merged mining work!') # COMBINE WORK @@ -101,8 +104,8 @@ def compute_work(): t = self.node.bitcoind_work.value bb = self.node.best_block_header.value if bb is not None and bb['previous_block'] == t['previous_block'] and self.node.net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(bb)) <= t['bits'].target: - print 'Skipping from block %x to block %x!' % (bb['previous_block'], - bitcoin_data.hash256(bitcoin_data.block_header_type.pack(bb))) + print('Skipping from block %x to block %x!' % (bb['previous_block'], + bitcoin_data.hash256(bitcoin_data.block_header_type.pack(bb)))) t = dict( version=bb['version'], previous_block=bitcoin_data.hash256(bitcoin_data.block_header_type.pack(bb)), @@ -157,16 +160,16 @@ def freshen_addresses(self, c): if self.cur_address_throttle - self.address_throttle < 30: return self.address_throttle=time.time() - print "ATTEMPTING TO FRESHEN ADDRESS." + print("ATTEMPTING TO FRESHEN ADDRESS.") self.address = yield deferral.retry('Error getting a dynamic address from bitcoind:', 5)(lambda: self.bitcoind.rpc_getnewaddress('p2pool'))() self.pubkeys.popleft() self.pubkeys.addkey({'address': self.address}) - print " Updated payout pool:" + print(" Updated payout pool:") for i in range(len(self.pubkeys.keys)): - print(' ...payout %d: %s(%f)' % - (i, self.address, self.pubkeys.keyweights[i])) + print((' ...payout %d: %s(%f)' % + (i, self.address, self.pubkeys.keyweights[i]))) self.pubkeys.updatestamp(c) - print " Next address rotation in : %fs" % (time.time()-c+self.args.timeaddresses) + print(" Next address rotation in : %fs" % (time.time()-c+self.args.timeaddresses)) def get_user_details(self, username): contents = re.split('([+/])', username) @@ -216,8 +219,8 @@ def get_user_details(self, username): ret = bitcoin_data.address_to_pubkey_hash(user, self.node.net.PARENT) if share_type.VERSION < 34 and ret[1] != self.node.net.PARENT.ADDRESS_VERSION: - print("not supporting %s yet, share version needs to be 34, but is %s." - % (user, share_type.VERSION)) + print(("not supporting %s yet, share version needs to be 34, but is %s." + % (user, share_type.VERSION))) raise ValueError address = user except Exception: # XXX blah @@ -229,9 +232,9 @@ def get_user_details(self, username): def preprocess_request(self, user): if (self.node.p2p_node is None or len(self.node.p2p_node.peers) == 0) and self.node.net.PERSIST: - raise jsonrpc.Error_for_code(-12345)(u'p2pool is not connected to any peers') + raise jsonrpc.Error_for_code(-12345)('p2pool is not connected to any peers') if time.time() > self.current_work.value['last_update'] + 60: - raise jsonrpc.Error_for_code(-12345)(u'lost contact with bitcoind') + raise jsonrpc.Error_for_code(-12345)('lost contact with bitcoind') return self.get_user_details(user) def _estimate_local_hash_rate(self): @@ -264,30 +267,30 @@ def get_work(self, user, address, desired_share_target, global print_throttle t0 = time.time() if (self.node.p2p_node is None or len(self.node.p2p_node.peers) == 0) and self.node.net.PERSIST: - raise jsonrpc.Error_for_code(-12345)(u'p2pool is not connected to any peers') + raise jsonrpc.Error_for_code(-12345)('p2pool is not connected to any peers') if self.node.best_share_var.value is None and self.node.net.PERSIST: - raise jsonrpc.Error_for_code(-12345)(u'p2pool is downloading shares') + raise jsonrpc.Error_for_code(-12345)('p2pool is downloading shares') unknown_rules = set(r[1:] if r.startswith('!') else r for r in self.node.bitcoind_work.value['rules'] if r) - set(getattr(self.node.net, 'SOFTFORKS_REQUIRED', [])) if unknown_rules: - print "Unknown softforks found: ", unknown_rules - print "Required softforks: ", self.node.bitcoind_work.value['rules'], "\tKnown: ", getattr(self.node.net, 'SOFTFORKS_REQUIRED', []) - raise jsonrpc.Error_for_code(-12345)(u'unknown rule activated') + print("Unknown softforks found: ", unknown_rules) + print("Required softforks: ", self.node.bitcoind_work.value['rules'], "\tKnown: ", getattr(self.node.net, 'SOFTFORKS_REQUIRED', [])) + raise jsonrpc.Error_for_code(-12345)('unknown rule activated') if self.merged_work.value: tree, size = bitcoin_data.make_auxpow_tree(self.merged_work.value) - mm_hashes = [self.merged_work.value.get(tree.get(i), dict(hash=0))['hash'] for i in xrange(size)] - mm_data = '\xfa\xbemm' + bitcoin_data.aux_pow_coinbase_type.pack(dict( + mm_hashes = [self.merged_work.value.get(tree.get(i), dict(hash=0))['hash'] for i in range(size)] + mm_data = b'\xfa\xbemm' + bitcoin_data.aux_pow_coinbase_type.pack(dict( merkle_root=bitcoin_data.merkle_hash(mm_hashes), size=size, nonce=0, )) - mm_later = [(aux_work, mm_hashes.index(aux_work['hash']), mm_hashes) for chain_id, aux_work in self.merged_work.value.iteritems()] + mm_later = [(aux_work, mm_hashes.index(aux_work['hash']), mm_hashes) for chain_id, aux_work in self.merged_work.value.items()] else: - mm_data = '' + mm_data = b'' mm_later = [] tx_hashes = self.current_work.value['transaction_hashes'] - tx_map = dict(zip(tx_hashes, self.current_work.value['transactions'])) + tx_map = dict(list(zip(tx_hashes, self.current_work.value['transactions']))) self.node.mining2_txs_var.set(tx_map) # let node.py know not to evict these transactions @@ -309,11 +312,11 @@ def get_work(self, user, address, desired_share_target, else: counts = p2pool_data.get_desired_version_counts(self.node.tracker, self.node.tracker.get_nth_parent_hash(previous_share.hash, self.node.net.CHAIN_LENGTH*9//10), self.node.net.CHAIN_LENGTH//10) - upgraded = counts.get(successor_type.VERSION, 0)/sum(counts.itervalues()) + upgraded = counts.get(successor_type.VERSION, 0)/sum(counts.values()) if upgraded > .65: - print 'Switchover imminent. Upgraded: %.3f%% Threshold: %.3f%%' % (upgraded*100, 95) + print('Switchover imminent. Upgraded: %.3f%% Threshold: %.3f%%' % (upgraded*100, 95)) # Share -> NewShare only valid if 95% of hashes in [net.CHAIN_LENGTH*9//10, net.CHAIN_LENGTH] for new version - if counts.get(successor_type.VERSION, 0) > sum(counts.itervalues())*95//100: + if counts.get(successor_type.VERSION, 0) > sum(counts.values())*95//100: share_type = successor_type else: share_type = previous_share_type @@ -326,7 +329,7 @@ def get_work(self, user, address, desired_share_target, bitcoin_data.average_attempts_to_target(local_hash_rate * self.node.net.SHARE_PERIOD / 0.0167)) # limit to 1.67% of pool shares by modulating share difficulty if self.node.punish: - print "trying to punish a share by mining a low-diff share" + print("trying to punish a share by mining a low-diff share") desired_share_target = bitcoin_data.difficulty_to_target(1.) local_addr_rates = self.get_local_addr_rates() lookbehind = 3600//self.node.net.SHARE_PERIOD @@ -346,17 +349,17 @@ def get_work(self, user, address, desired_share_target, previous_share_hash=self.node.best_share_var.value, coinbase=(script.create_push_script([ self.current_work.value['height'], - ] + ([mm_data] if mm_data else []) + self.args.coinb_texts - ) + self.current_work.value['coinbaseflags'])[:100], - nonce=random.randrange(2**32), + ] + ([mm_data] if mm_data else []) + [ensure_bytes(x) for x in self.args.coinb_texts] + ) + ensure_bytes(self.current_work.value['coinbaseflags']))[:100], + nonce=secrets.randbits(32), address=address, subsidy=self.current_work.value['subsidy'], donation=( math.perfect_round(65535*self.donation_percentage/100) if share_type.PAYS_LEGACY_DONATION else 0), - stale_info=(lambda (orphans, doas), total, (orphans_recorded_in_chain, doas_recorded_in_chain): - 'orphan' if orphans > orphans_recorded_in_chain else - 'doa' if doas > doas_recorded_in_chain else + stale_info=(lambda stale, total, recorded: + 'orphan' if stale[0] > recorded[0] else + 'doa' if stale[1] > recorded[1] else None )(*self.get_stale_counts()), desired_version=(share_type.SUCCESSOR if share_type.SUCCESSOR is not None else share_type).VOTING_VERSION, @@ -365,7 +368,7 @@ def get_work(self, user, address, desired_share_target, desired_timestamp=int(time.time() + 0.5), desired_target=desired_share_target, ref_merkle_link=dict(branch=[], index=0), - desired_other_transaction_hashes_and_fees=zip(tx_hashes, self.current_work.value['transaction_fees']), + desired_other_transaction_hashes_and_fees=list(zip(tx_hashes, self.current_work.value['transaction_fees'])), net=self.node.net, known_txs=tx_map, base_subsidy=self.node.net.PARENT.SUBSIDY_FUNC(self.current_work.value['height']), @@ -375,7 +378,7 @@ def get_work(self, user, address, desired_share_target, other_transactions = [tx_map[tx_hash] for tx_hash in other_transaction_hashes] del tx_hashes - if self.node.cur_share_ver >= 34: + if (self.node.cur_share_ver or 0) >= 34: tx_map = {} # we can free up this memory now mm_later = [(dict(aux_work, target=aux_work['target'] if aux_work['target'] != 'p2pool' else share_info['bits'].target), index, hashes) for aux_work, index, hashes in mm_later] @@ -407,17 +410,17 @@ def get_work(self, user, address, desired_share_target, merkle_link = bitcoin_data.calculate_merkle_link([None] + other_transaction_hashes, 0) if share_info.get('segwit_data', None) is None else share_info['segwit_data']['txid_merkle_link'] del other_transaction_hashes - if print_throttle is 0.0: + if print_throttle == 0.0: print_throttle = time.time() else: current_time = time.time() if (current_time - print_throttle) > 5.0: - print 'New work! Share diff: %.02f Block value: %.2f %s (%i tx, %.0f kB)' % ( + print('New work! Share diff: %.02f Block value: %.2f %s (%i tx, %.0f kB)' % ( bitcoin_data.target_to_difficulty(share_info['bits'].target), self.current_work.value['subsidy']*1e-8, self.node.net.PARENT.SYMBOL, len(self.current_work.value['transactions']), sum((bitcoin_data.get_size(tx) for tx in self.current_work.value['transactions']))/1000., - ) + )) print_throttle = time.time() #need this for stats @@ -452,9 +455,9 @@ def got_response(header, username, coinbase_nonce, pseudoshare_target): try: if pow_hash <= header['bits'].target or p2pool.DEBUG: if pow_hash <= header['bits'].target: - print - print 'GOT BLOCK FROM MINER! Passing to bitcoind! %s%064x' % (self.node.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, header_hash) - print + print() + print('GOT BLOCK FROM MINER! Passing to bitcoind! %s%064x' % (self.node.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, header_hash)) + print() helper.submit_block(dict(header=header, txs=[new_gentx] + other_transactions), False, self.node) except: log.err(None, 'Error while processing potential block:') @@ -470,8 +473,8 @@ def got_response(header, username, coinbase_nonce, pseudoshare_target): try: if pow_hash <= aux_work['target'] or p2pool.DEBUG: df = deferral.retry('Error submitting merged block: (will retry)', 10, 10)(aux_work['merged_proxy'].rpc_getauxblock)( - pack.IntType(256, 'big').pack(aux_work['hash']).encode('hex'), - bitcoin_data.aux_pow_type.pack(dict( + bytes_to_hex(pack.IntType(256, 'big').pack(aux_work['hash'])), + bytes_to_hex(bitcoin_data.aux_pow_type.pack(dict( merkle_tx=dict( tx=new_gentx, block_hash=header_hash, @@ -479,14 +482,14 @@ def got_response(header, username, coinbase_nonce, pseudoshare_target): ), merkle_link=bitcoin_data.calculate_merkle_link(hashes, index), parent_block_header=header, - )).encode('hex'), + ))), ) @df.addCallback def _(result, aux_work=aux_work): if result != (pow_hash <= aux_work['target']): - print >>sys.stderr, 'Merged block submittal result: %s Expected: %s' % (result, pow_hash <= aux_work['target']) + print('Merged block submittal result: %s Expected: %s' % (result, pow_hash <= aux_work['target']), file=sys.stderr) else: - print 'Merged block submittal result: %s' % (result,) + print('Merged block submittal result: %s' % (result,)) @df.addErrback def _(err): log.err(err, 'Error submitting merged block:') @@ -497,23 +500,23 @@ def _(err): last_txout_nonce = pack.IntType(8*self.COINBASE_NONCE_LENGTH).unpack(coinbase_nonce) share = get_share(header, last_txout_nonce) - print 'GOT SHARE! %s %s prev %s age %.2fs%s' % ( + print('GOT SHARE! %s %s prev %s age %.2fs%s' % ( username, p2pool_data.format_hash(share.hash), p2pool_data.format_hash(share.previous_hash), time.time() - getwork_time, ' DEAD ON ARRIVAL' if not on_time else '', - ) + )) - if self.node.cur_share_ver < 34: + if (self.node.cur_share_ver or 0) < 34: # node.py will sometimes forget transactions if bitcoind's work has changed since this stratum # job was assigned. Fortunately, the tx_map is still in in our scope from this job, so we can use that # to refill it if needed. known_txs = self.node.known_txs_var.value - missing = {hsh:val for (hsh, val) in tx_map.iteritems() if not hsh in known_txs} + missing = {hsh:val for (hsh, val) in tx_map.items() if not hsh in known_txs} if missing: - print "Warning: %i transactions were erroneously evicted from known_txs_var. Refilling now." % len(missing) + print("Warning: %i transactions were erroneously evicted from known_txs_var. Refilling now." % len(missing)) self.node.known_txs_var.add(missing) self.my_share_hashes.add(share.hash) @@ -524,11 +527,11 @@ def _(err): if on_time or sibling_count < 4: self.node.tracker.add(share) else: - print "Already have %i DOA shares with this parent. Not adding more." % sibling_count + print("Already have %i DOA shares with this parent. Not adding more." % sibling_count) if on_time: self.node.set_best_share() else: - print "Not considering work switching to DOA share" + print("Not considering work switching to DOA share") try: if (pow_hash <= header['bits'].target or p2pool.DEBUG) and self.node.p2p_node is not None: @@ -539,11 +542,11 @@ def _(err): self.share_received.happened(bitcoin_data.target_to_average_attempts(share.target), not on_time, share.hash) if pow_hash > pseudoshare_target: - print 'Worker %s submitted share with hash > target:' % (username,) - print ' Hash: %064x' % (pow_hash,) - print ' Target: %064x' % (pseudoshare_target,) + print('Worker %s submitted share with hash > target:' % (username,)) + print(' Hash: %064x' % (pow_hash,)) + print(' Target: %064x' % (pseudoshare_target,)) elif header_hash in received_header_hashes: - print >>sys.stderr, 'Worker %s submitted share more than once!' % (username,) + print('Worker %s submitted share more than once!' % (username,), file=sys.stderr) else: received_header_hashes.add(header_hash) @@ -554,9 +557,9 @@ def _(err): self.local_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(pseudoshare_target), dead=not on_time, user=username, share_target=share_info['bits'].target)) self.local_addr_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(pseudoshare_target), address=address)) t1 = time.time() - if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for work.py:got_response(%s)" % ((t1-t0)*1000., username) + if p2pool.BENCH and (t1-t0) > .01: print("%8.3f ms for work.py:got_response(%s)" % ((t1-t0)*1000., username)) return on_time t1 = time.time() - if p2pool.BENCH: print "%8.3f ms for work.py:get_work(%s, %s)" % ((t1-t0)*1000., user, address) + if p2pool.BENCH: print("%8.3f ms for work.py:get_work(%s, %s)" % ((t1-t0)*1000., user, address)) return ba, got_response diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..f1d73e4 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,4 @@ +Twisted>=26.4.0,<27 +pyOpenSSL>=26.2.0,<27 +defusedxml>=0.7.1,<1 +service-identity>=24.2.0,<25 diff --git a/backend/run_p2pool.py b/backend/run_p2pool.py new file mode 100755 index 0000000..e555500 --- /dev/null +++ b/backend/run_p2pool.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +from contextlib import suppress +import os +import sys + +def _default_pidfile(): + runtime_dir = os.environ.get('XDG_RUNTIME_DIR') + if runtime_dir and os.path.isdir(runtime_dir) and os.access(runtime_dir, os.W_OK): + return os.path.join(runtime_dir, 'p2pool.pid') + state_dir = os.path.join(os.path.expanduser('~'), '.p2pool') + os.makedirs(state_dir, mode=0o700, exist_ok=True) + return os.path.join(state_dir, 'p2pool.pid') + +pid = str(os.getpid()) +pidfile = os.environ.get('P2POOL_PIDFILE', _default_pidfile()) +pidfile_fd = None + +try: + pidfile_fd = os.open(pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) +except FileExistsError: + print(f"{pidfile} already exists, exiting") + sys.exit() +with os.fdopen(pidfile_fd, 'w') as f: + pidfile_fd = None + f.write(pid) # write the pid to pidfile + +try: + # Real code + from p2pool import main + main.run() +finally: + if pidfile_fd is not None: + os.close(pidfile_fd) + with suppress(FileNotFoundError): + os.unlink(pidfile) # remove the pid lock file diff --git a/setup.py b/backend/setup.py similarity index 80% rename from setup.py rename to backend/setup.py index a148c6a..2b19c64 100644 --- a/setup.py +++ b/backend/setup.py @@ -6,11 +6,20 @@ from distutils.core import setup from distutils.sysconfig import get_python_lib -import py2exe + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +os.chdir(BASE_DIR) +try: + import py2exe +except ImportError: + py2exe = None version = __import__('p2pool').__version__ im64 = '64' in platform.architecture()[0] +if py2exe is None: + raise SystemExit('py2exe packaging is a legacy Windows path and is not installed in this Python environment.') + extra_includes = [] import p2pool.networks extra_includes.extend('p2pool.networks.' + x for x in p2pool.networks.nets) @@ -22,7 +31,7 @@ os.rename(os.path.join('p2pool', '__init__.py'), 'INITBAK') try: open(os.path.join('p2pool', '__init__.py'), 'wb').write('__version__ = %r%s%sDEBUG = False%s' % (version, os.linesep, os.linesep, os.linesep)) - mfcdir = get_python_lib() + '\pythonwin\\' + mfcdir = os.path.join(get_python_lib(), 'pythonwin') + os.sep mfcfiles = [os.path.join(mfcdir, i) for i in ["mfc90.dll", "mfc90u.dll", "mfcm90.dll", "mfcm90u.dll", "Microsoft.VC90.MFC.manifest"]] bundle = 1 if im64: @@ -30,7 +39,7 @@ sys.argv[1:] = ['py2exe'] setup(name='p2pool', version=version, - description='Peer-to-peer Bitcoin mining pool', + description='Peer-to-peer Defcoin mining pool', author='Forrest Voight', author_email='forrest@forre.st', url='http://p2pool.forre.st/', @@ -38,11 +47,8 @@ ('', ['README.md']), ("Microsoft.VC90.MFC", mfcfiles), ('web-static', [ - 'web-static/d3.v2.min.js', - 'web-static/favicon.ico', - 'web-static/graphs.html', - 'web-static/index.html', - 'web-static/share.html', + '../frontend/web-static/favicon.ico', + '../frontend/web-static/index.html', ]), ], @@ -73,4 +79,4 @@ for filename in filenames: zf.write(os.path.join(dirpath, filename)) -print dir_name +print(dir_name) diff --git a/wstools/.cvsignore b/backend/wstools/.cvsignore similarity index 100% rename from wstools/.cvsignore rename to backend/wstools/.cvsignore diff --git a/wstools/MIMEAttachment.py b/backend/wstools/MIMEAttachment.py similarity index 96% rename from wstools/MIMEAttachment.py rename to backend/wstools/MIMEAttachment.py index 2376cc8..de14575 100644 --- a/wstools/MIMEAttachment.py +++ b/backend/wstools/MIMEAttachment.py @@ -14,7 +14,7 @@ #new line NL='\r\n' -_width = len(repr(sys.maxint-1)) +_width = len(repr(sys.maxsize-1)) _fmt = '%%0%dd' % _width class MIMEMessage: @@ -37,7 +37,7 @@ def makeBoundary(self): #maybe I can save some memory del alltext del msgparts - self._startCID = "<" + (_fmt % random.randrange(sys.maxint)) + (_fmt % random.randrange(sys.maxint)) + ">" + self._startCID = "<" + (_fmt % random.randrange(sys.maxsize)) + (_fmt % random.randrange(sys.maxsize)) + ">" def toString(self): @@ -94,7 +94,7 @@ def _make_boundary(text=None): #some code taken from python stdlib # Craft a random boundary. If text is given, ensure that the chosen # boundary doesn't appear in the text. - token = random.randrange(sys.maxint) + token = random.randrange(sys.maxsize) boundary = ('=' * 10) + (_fmt % token) + '==' if text is None: return boundary diff --git a/wstools/Namespaces.py b/backend/wstools/Namespaces.py similarity index 100% rename from wstools/Namespaces.py rename to backend/wstools/Namespaces.py diff --git a/wstools/TimeoutSocket.py b/backend/wstools/TimeoutSocket.py similarity index 97% rename from wstools/TimeoutSocket.py rename to backend/wstools/TimeoutSocket.py index 48b898d..9ef5991 100755 --- a/wstools/TimeoutSocket.py +++ b/backend/wstools/TimeoutSocket.py @@ -43,10 +43,10 @@ def connect(self, *addr): try: # Non-blocking mode sock.setblocking(0) - apply(sock.connect, addr) + sock.connect(*addr) sock.setblocking(timeout != 0) return 1 - except socket.error,why: + except socket.error as why: if not timeout: raise sock.setblocking(1) @@ -61,9 +61,9 @@ def connect(self, *addr): r,w,e = select.select([],[sock],[],timeout) if w: try: - apply(sock.connect, addr) + sock.connect(*addr) return 1 - except socket.error,why: + except socket.error as why: if len(why.args) == 1: code = 0 else: diff --git a/wstools/UserTuple.py b/backend/wstools/UserTuple.py similarity index 97% rename from wstools/UserTuple.py rename to backend/wstools/UserTuple.py index b8c3653..8aa2cb1 100644 --- a/wstools/UserTuple.py +++ b/backend/wstools/UserTuple.py @@ -46,6 +46,10 @@ # $Id$ + +def _cmp(left, right): + return (left > right) - (left < right) + #XXX tuple instances (in Python 2.2) contain also: # __class__, __delattr__, __getattribute__, __hash__, __new__, # __reduce__, __setattr__, __str__ @@ -78,7 +82,7 @@ def __cast(self, other): if isinstance(other, UserTuple): return other.data else: return other def __cmp__(self, other): - return cmp(self.data, self.__cast(other)) + return _cmp(self.data, self.__cast(other)) def __contains__(self, item): return item in self.data def __len__(self): return len(self.data) def __getitem__(self, i): return self.data[i] @@ -96,4 +100,3 @@ def __add__(self, other): def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ - diff --git a/wstools/Utility.py b/backend/wstools/Utility.py similarity index 94% rename from wstools/Utility.py rename to backend/wstools/Utility.py index df536b9..70bb107 100755 --- a/wstools/Utility.py +++ b/backend/wstools/Utility.py @@ -14,14 +14,14 @@ ident = "$Id$" -import sys, types, httplib, urllib, socket, weakref +import sys, types, http.client, urllib.request, urllib.parse, urllib.error, socket, weakref from os.path import isfile from string import join, strip, split from UserDict import UserDict -from cStringIO import StringIO -from TimeoutSocket import TimeoutSocket, TimeoutError -from urlparse import urlparse -from httplib import HTTPConnection, HTTPSConnection +from io import StringIO +from .TimeoutSocket import TimeoutSocket, TimeoutError +from urllib.parse import urlparse +from http.client import HTTPConnection, HTTPSConnection from exceptions import Exception try: from ZSI import _get_idstr @@ -36,11 +36,12 @@ def _get_idstr(pyobj): return 'o%x' % x import xml.dom.minidom +from defusedxml import minidom as safe_minidom from xml.dom import Node -import logging -from c14n import Canonicalize -from Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI +from . import logging +from .c14n import Canonicalize +from .Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI try: @@ -141,7 +142,7 @@ def connect(self): sock.connect((self.host, self.port)) realsock = getattr(sock.sock, '_sock', sock.sock) ssl = socket.ssl(realsock, self.key_file, self.cert_file) - self.sock = httplib.FakeSocket(sock, ssl) + self.sock = http.client.FakeSocket(sock, ssl) def urlopen(url, timeout=20, redirects=None): @@ -150,7 +151,7 @@ def urlopen(url, timeout=20, redirects=None): scheme, host, path, params, query, frag = urlparse(url) if not scheme in ('http', 'https'): - return urllib.urlopen(url) + raise ValueError('Unsupported URL scheme: %s' % (scheme or '')) if params: path = '%s;%s' % (path, params) if query: path = '%s?%s' % (path, query) if frag: path = '%s#%s' % (path, frag) @@ -163,7 +164,7 @@ def urlopen(url, timeout=20, redirects=None): import M2Crypto except ImportError: if not hasattr(socket, 'ssl'): - raise RuntimeError, 'no built-in SSL Support' + raise RuntimeError('no built-in SSL Support') conn = TimeoutHTTPS(host, None, timeout) else: @@ -183,7 +184,7 @@ def urlopen(url, timeout=20, redirects=None): response = conn.getresponse() if response.status != 100: break - conn._HTTPConnection__state = httplib._CS_REQ_SENT + conn._HTTPConnection__state = http.client._CS_REQ_SENT conn._HTTPConnection__response = None status = response.status @@ -193,7 +194,7 @@ def urlopen(url, timeout=20, redirects=None): location = response.msg.getheader('location') if location is not None: response.close() - if redirects is not None and redirects.has_key(location): + if redirects is not None and location in redirects: raise RecursionError( 'Circular HTTP redirection detected.' ) @@ -305,7 +306,7 @@ def GetSOAPActorNextUri(self, version): NS_XSD_01 : NS_XSI_01, } - for key, value in _xsd_uri_mapping.items(): + for key, value in list(_xsd_uri_mapping.items()): _xsd_uri_mapping[value] = key @@ -428,7 +429,7 @@ def getElement(self, node, name, nsuri=None, default=join): return child if default is not join: return default - raise KeyError, name + raise KeyError(name) def getElementById(self, node, id, default=join): """Return the first child of node matching an id reference.""" @@ -440,7 +441,7 @@ def getElementById(self, node, id, default=join): return child if default is not join: return default - raise KeyError, name + raise KeyError(id) def getMappingById(self, document, depth=None, element=None, mapping=None, level=1): @@ -492,7 +493,7 @@ def getAttr(self, node, name, nsuri=None, default=join): if nsuri is None: result = node._attrs.get(name, None) if result is None: - for item in node._attrsNS.keys(): + for item in list(node._attrsNS.keys()): if item[1] == name: result = node._attrsNS[item] break @@ -508,7 +509,7 @@ def getAttrs(self, node): """Return a Collection of all attributes """ attrs = {} - for k,v in node._attrs.items(): + for k,v in list(node._attrs.items()): attrs[k] = v.value return attrs @@ -612,8 +613,9 @@ def _setOwnerDoc(self, document, node): for child in node.childNodes: self._setOwnerDoc(document, child) - def nsUriMatch(self, value, wanted, strict=0, tt=type(())): + def nsUriMatch(self, value, wanted, strict=0, tt=None): """Return a true value if two namespace uri values match.""" + tt = type(()) if tt is None else tt if value == wanted or (type(wanted) is tt) and value in wanted: return 1 if not strict and value is not None: @@ -632,7 +634,7 @@ def createDocument(self, nsuri, qname, doctype=None): def loadDocument(self, data): """Load an xml file from a file-like object and return a DOM document instance.""" - return xml.dom.minidom.parse(data) + return safe_minidom.parse(data) def loadFromURL(self, url): """Load an xml file from a URL and return a DOM document.""" @@ -643,7 +645,7 @@ def loadFromURL(self, url): try: result = self.loadDocument(file) - except Exception, ex: + except Exception as ex: file.close() raise ParseError(('Failed to load document %s' %url,) + ex.args) else: @@ -679,39 +681,39 @@ def Forget(self, obj): def canonicalize(self): '''canonicalize the underlying DOM, and return as string. ''' - raise NotImplementedError, '' + raise NotImplementedError('') def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'): '''create Document ''' - raise NotImplementedError, '' + raise NotImplementedError('') def createAppendElement(self, namespaceURI, localName): '''create and append element(namespaceURI,localName), and return the node. ''' - raise NotImplementedError, '' + raise NotImplementedError('') def findNamespaceURI(self, qualifiedName): - raise NotImplementedError, '' + raise NotImplementedError('') def resolvePrefix(self, prefix): - raise NotImplementedError, '' + raise NotImplementedError('') def setAttributeNS(self, namespaceURI, localName, value): '''set attribute (namespaceURI, localName)=value ''' - raise NotImplementedError, '' + raise NotImplementedError('') def setAttributeType(self, namespaceURI, localName): '''set attribute xsi:type=(namespaceURI, localName) ''' - raise NotImplementedError, '' + raise NotImplementedError('') def setNamespaceAttribute(self, namespaceURI, prefix): '''set namespace attribute xmlns:prefix=namespaceURI ''' - raise NotImplementedError, '' + raise NotImplementedError('') class ElementProxy(Base, MessageInterface): @@ -756,7 +758,7 @@ def __init__(self, sw, message=None): Base.__init__(self) self._dom = DOM self.node = None - if type(message) in (types.StringType,types.UnicodeType): + if type(message) in (bytes,str): self.loadFromString(message) elif isinstance(message, ElementProxy): self.node = message._getNode() @@ -777,7 +779,7 @@ def evaluate(self, expression, processorNss=None): else: context = XPath.Context.Context(self.node, processorNss=processorNss) nodes = expression.evaluate(context) - return map(lambda node: ElementProxy(self.sw,node), nodes) + return [ElementProxy(self.sw,node) for node in nodes] ############################################# # Methods for checking/setting the @@ -794,7 +796,7 @@ def checkNode(self, namespaceURI=None, localName=None): if localName and self.node: check = self._dom.isElement(self.node, localName, namespaceURI) if not check: - raise NamespaceError, 'unexpected node type %s, expecting %s' %(self.node, localName) + raise NamespaceError('unexpected node type %s, expecting %s' %(self.node, localName)) def setNode(self, node=None): if node: @@ -805,7 +807,7 @@ def setNode(self, node=None): elif self.node: node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None) if not node: - raise NamespaceError, 'cant find element (%s,%s)' %(self.namespaceURI,self.name) + raise NamespaceError('cant find element (%s,%s)' %(self.namespaceURI,self.name)) self.node = node else: #self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None) @@ -835,7 +837,7 @@ def _getUniquePrefix(self): prefix = 'ns%d' %self._indx try: self._dom.findNamespaceURI(prefix, self._getNode()) - except DOMException, ex: + except DOMException as ex: break return prefix @@ -849,19 +851,19 @@ def _getPrefix(self, node, nsuri): if node and (node.nodeType == node.ELEMENT_NODE) and \ (nsuri == self._dom.findDefaultNS(node)): return None - except DOMException, ex: + except DOMException as ex: pass if nsuri == XMLNS.XML: return self._xml_prefix if node.nodeType == Node.ELEMENT_NODE: - for attr in node.attributes.values(): + for attr in list(node.attributes.values()): if attr.namespaceURI == XMLNS.BASE \ and nsuri == attr.value: return attr.localName else: if node.parentNode: return self._getPrefix(node.parentNode, nsuri) - raise NamespaceError, 'namespaceURI "%s" is not defined' %nsuri + raise NamespaceError('namespaceURI "%s" is not defined' %nsuri) def _appendChild(self, node): ''' @@ -869,7 +871,7 @@ def _appendChild(self, node): node -- DOM Element Node ''' if node is None: - raise TypeError, 'node is None' + raise TypeError('node is None') self.node.appendChild(node) def _insertBefore(self, newChild, refChild): @@ -900,7 +902,7 @@ def isFault(self): def getPrefix(self, namespaceURI): try: prefix = self._getPrefix(node=self.node, nsuri=namespaceURI) - except NamespaceError, ex: + except NamespaceError as ex: prefix = self._getUniquePrefix() self.setNamespaceAttribute(prefix, namespaceURI) return prefix @@ -942,13 +944,13 @@ def createDocument(self, namespaceURI, localName, doctype=None): self.node = self._dom.createDocument(None,None,None) return else: - raise KeyError, 'only support creation of document in %s' %self.reserved_ns[prefix] + raise KeyError('only support creation of document in %s' %self.reserved_ns[prefix]) document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype) self.node = document.childNodes[0] #set up reserved namespace attributes - for prefix,nsuri in self.reserved_ns.items(): + for prefix,nsuri in list(self.reserved_ns.items()): self._setAttributeNS(namespaceURI=self._xmlns_nsuri, qualifiedName='%s:%s' %(self._xmlns_prefix,prefix), value=nsuri) @@ -991,7 +993,7 @@ def setAttributeNS(self, namespaceURI, localName, value): if namespaceURI: try: prefix = self.getPrefix(namespaceURI) - except KeyError, ex: + except KeyError as ex: prefix = 'ns2' self.setNamespaceAttribute(prefix, namespaceURI) qualifiedName = localName @@ -1112,7 +1114,7 @@ def findNamespaceURI(self, qualifiedName): parts = SplitQName(qualifiedName) element = self._getNode() if len(parts) == 1: - return (self._dom.findTargetNS(element), value) + return (self._dom.findTargetNS(element), parts[1]) return self._dom.findNamespaceURI(parts[0], element) def resolvePrefix(self, prefix): @@ -1147,10 +1149,10 @@ def __setitem__(self, key, item): self.data[key] = item def keys(self): - return map(lambda i: self._func(i), self.list) + return [self._func(i) for i in self.list] def items(self): - return map(lambda i: (self._func(i), i), self.list) + return [(self._func(i), i) for i in self.list] def values(self): return self.list @@ -1168,7 +1170,7 @@ def __init__(self, parent, key=None): def __getitem__(self, key): self.targetNamespace = self.parent().targetNamespace - if type(key) is types.IntType: + if type(key) is int: return self.list[key] elif self.__isSequence(key): nsuri,name = key @@ -1179,21 +1181,21 @@ def __setitem__(self, key, item): item.parent = weakref.ref(self) self.list.append(item) targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace) - if not self.data.has_key(targetNamespace): + if targetNamespace not in self.data: self.data[targetNamespace] = {} self.data[targetNamespace][key] = item def __isSequence(self, key): - return (type(key) in (types.TupleType,types.ListType) and len(key) == 2) + return (type(key) in (tuple,list) and len(key) == 2) def keys(self): keys = [] - for tns in self.data.keys(): - keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values())) + for tns in list(self.data.keys()): + keys.append([(tns,self._func(i)) for i in list(self.data[tns].values())]) return keys def items(self): - return map(lambda i: (self._func(i), i), self.list) + return [(self._func(i), i) for i in self.list] def values(self): return self.list @@ -1247,7 +1249,7 @@ def startElementNS(self, name, tagName , attrs): else: node = self.buildDocument(None, localname) - for aname,value in attrs.items(): + for aname,value in list(attrs.items()): a_uri, a_localname = aname if a_uri == xmlns_uri: if a_localname == 'xmlns': @@ -1303,7 +1305,7 @@ def _clone_node(node, deep, newOwnerDocument): if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE: clone = newOwnerDocument.createElementNS(node.namespaceURI, node.nodeName) - for attr in node.attributes.values(): + for attr in list(node.attributes.values()): clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) prefix, tag = xml.dom.minidom._nssplit(attr.nodeName) @@ -1379,4 +1381,3 @@ def _clone_node(node, deep, newOwnerDocument): return clone xml.dom.minidom._clone_node = _clone_node - diff --git a/wstools/WSDLTools.py b/backend/wstools/WSDLTools.py similarity index 97% rename from wstools/WSDLTools.py rename to backend/wstools/WSDLTools.py index 3dd651a..de7befa 100755 --- a/wstools/WSDLTools.py +++ b/backend/wstools/WSDLTools.py @@ -10,10 +10,10 @@ ident = "$Id$" import weakref -from cStringIO import StringIO -from Namespaces import OASIS, XMLNS, WSA, WSA_LIST, WSAW_LIST, WSRF_V1_2, WSRF -from Utility import Collection, CollectionNS, DOM, ElementProxy, basejoin -from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter +from io import StringIO +from .Namespaces import OASIS, XMLNS, WSA, WSA_LIST, WSAW_LIST, WSRF_V1_2, WSRF +from .Utility import Collection, CollectionNS, DOM, ElementProxy, basejoin +from .XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter class WSDLReader: @@ -82,7 +82,7 @@ def __del__(self): version = '1.1' def addService(self, name, documentation='', targetNamespace=None): - if self.services.has_key(name): + if name in self.services: raise WSDLError( 'Duplicate service element: %s' % name ) @@ -93,7 +93,7 @@ def addService(self, name, documentation='', targetNamespace=None): return item def addMessage(self, name, documentation='', targetNamespace=None): - if self.messages.has_key(name): + if name in self.messages: raise WSDLError( 'Duplicate message element: %s.' % name ) @@ -104,7 +104,7 @@ def addMessage(self, name, documentation='', targetNamespace=None): return item def addPortType(self, name, documentation='', targetNamespace=None): - if self.portTypes.has_key(name): + if name in self.portTypes: raise WSDLError( 'Duplicate portType element: name' ) @@ -115,7 +115,7 @@ def addPortType(self, name, documentation='', targetNamespace=None): return item def addBinding(self, name, type, documentation='', targetNamespace=None): - if self.bindings.has_key(name): + if name in self.bindings: raise WSDLError( 'Duplicate binding element: %s' % name ) @@ -352,7 +352,7 @@ def _import(self, document, element, base_location=None): parent.appendChild(child) child.setAttribute('targetNamespace', namespace) attrsNS = imported._attrsNS - for attrkey in attrsNS.keys(): + for attrkey in list(attrsNS.keys()): if attrkey[0] == DOM.NS_XMLNS: attr = attrsNS[attrkey].cloneNode(1) child.setAttributeNode(attr) @@ -434,7 +434,7 @@ def __init__(self, name, documentation=''): self.parts = Collection(self) def addPart(self, name, type=None, element=None): - if self.parts.has_key(name): + if name in self.parts: raise WSDLError( 'Duplicate message part element: %s' % name ) @@ -683,7 +683,7 @@ def getFaultMessage(self, name): return wsdl.messages[self.faults[name].message] def addFault(self, message, name, documentation='', action=None): - if self.faults.has_key(name): + if name in self.faults: raise WSDLError( 'Duplicate fault element: %s' % name ) @@ -747,7 +747,7 @@ def toDom(self, node): ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type) - if not isinstance(self.message, basestring) and len(self.message) == 2: + if not isinstance(self.message, str) and len(self.message) == 2: ns,name = self.message prefix = epc.getPrefix(ns) epc.setAttributeNS(None, 'message', '%s:%s' %(prefix,name)) @@ -1204,7 +1204,7 @@ def __init__(self, use, namespace=None, encodingStyle=None, parts=None): ) self.encodingStyle = encodingStyle self.namespace = namespace - if type(parts) in (type(''), type(u'')): + if type(parts) in (type(''), type('')): parts = parts.split() self.parts = parts self.use = use @@ -1417,7 +1417,8 @@ def GetWSAActionOutput(operation): return '%s%s/%s' %(targetNamespace, ptName, msgName) return '%s/%s/%s' %(targetNamespace, ptName, msgName) -def FindExtensions(object, kind, t_type=type(())): +def FindExtensions(object, kind, t_type=None): + t_type = type(()) if t_type is None else t_type if isinstance(kind, t_type): result = [] namespaceURI, name = kind @@ -1427,7 +1428,8 @@ def FindExtensions(object, kind, t_type=type(())): and item.name == name ] return [ item for item in object.extensions if isinstance(item, kind) ] -def FindExtension(object, kind, t_type=type(())): +def FindExtension(object, kind, t_type=None): + t_type = type(()) if t_type is None else t_type if isinstance(kind, t_type): namespaceURI, name = kind for item in object.extensions: @@ -1557,12 +1559,12 @@ def callInfoFromWSDL(port, name): addrbinding = port.getAddressBinding() if not isinstance(addrbinding, SoapAddressBinding): - raise ValueError, 'Unsupported binding type.' + raise ValueError('Unsupported binding type.') callinfo.location = addrbinding.location soapbinding = binding.findBinding(SoapBinding) if soapbinding is None: - raise ValueError, 'Missing soap:binding element.' + raise ValueError('Missing soap:binding element.') callinfo.transport = soapbinding.transport callinfo.style = soapbinding.style or 'document' @@ -1579,7 +1581,7 @@ def callInfoFromWSDL(port, name): mime = msgrole.findBinding(MimeMultipartRelatedBinding) if mime is not None: - raise ValueError, 'Mime bindings are not supported.' + raise ValueError('Mime bindings are not supported.') else: for item in msgrole.findBindings(SoapHeaderBinding): part = messages[item.message].parts[item.part] @@ -1593,7 +1595,7 @@ def callInfoFromWSDL(port, name): body = msgrole.findBinding(SoapBodyBinding) if body is None: - raise ValueError, 'Missing soap:body binding.' + raise ValueError('Missing soap:body binding.') callinfo.encodingStyle = body.encodingStyle callinfo.namespace = body.namespace callinfo.use = body.use @@ -1603,7 +1605,7 @@ def callInfoFromWSDL(port, name): for name in body.parts: parts.append(message.parts[name]) else: - parts = message.parts.values() + parts = list(message.parts.values()) for part in parts: callinfo.addInParameter( @@ -1616,22 +1618,22 @@ def callInfoFromWSDL(port, name): try: message = messages[operation.output.message] except KeyError: - if self.strict: + if wsdl.strict: raise RuntimeError( "Recieved message not defined in the WSDL schema: %s" % operation.output.message) else: message = wsdl.addMessage(operation.output.message) - print "Warning:", \ + print("Warning:", \ "Recieved message not defined in the WSDL schema.", \ - "Adding it." - print "Message:", operation.output.message + "Adding it.") + print("Message:", operation.output.message) msgrole = opbinding.output mime = msgrole.findBinding(MimeMultipartRelatedBinding) if mime is not None: - raise ValueError, 'Mime bindings are not supported.' + raise ValueError('Mime bindings are not supported.') else: for item in msgrole.findBindings(SoapHeaderBinding): part = messages[item.message].parts[item.part] @@ -1645,7 +1647,7 @@ def callInfoFromWSDL(port, name): body = msgrole.findBinding(SoapBodyBinding) if body is None: - raise ValueError, 'Missing soap:body binding.' + raise ValueError('Missing soap:body binding.') callinfo.encodingStyle = body.encodingStyle callinfo.namespace = body.namespace callinfo.use = body.use @@ -1655,7 +1657,7 @@ def callInfoFromWSDL(port, name): for name in body.parts: parts.append(message.parts[name]) else: - parts = message.parts.values() + parts = list(message.parts.values()) if parts: for part in parts: diff --git a/wstools/XMLSchema.py b/backend/wstools/XMLSchema.py similarity index 91% rename from wstools/XMLSchema.py rename to backend/wstools/XMLSchema.py index eb5b3fe..dc4248a 100755 --- a/wstools/XMLSchema.py +++ b/backend/wstools/XMLSchema.py @@ -15,9 +15,9 @@ ident = "$Id$" import types, weakref, sys, warnings -from Namespaces import SCHEMA, XMLNS, SOAP, APACHE -from Utility import DOM, DOMException, Collection, SplitQName, basejoin -from StringIO import StringIO +from .Namespaces import SCHEMA, XMLNS, SOAP, APACHE +from .Utility import DOM, DOMException, Collection, SplitQName, basejoin +from io import StringIO # If we have no threading, this should be a no-op try: @@ -68,16 +68,16 @@ def __setImports(self, schema): """Add dictionary of imports to schema instance. schema -- XMLSchema instance """ - for ns,val in schema.imports.items(): - if self._imports.has_key(ns): + for ns,val in list(schema.imports.items()): + if ns in self._imports: schema.addImportSchema(self._imports[ns]) def __setIncludes(self, schema): """Add dictionary of includes to schema instance. schema -- XMLSchema instance """ - for schemaLocation, val in schema.includes.items(): - if self._includes.has_key(schemaLocation): + for schemaLocation, val in list(schema.includes.items()): + if schemaLocation in self._includes: schema.addIncludeSchema(schemaLocation, self._imports[schemaLocation]) def addSchemaByLocation(self, location, schema): @@ -171,51 +171,51 @@ def hasattr(self, attr, ns=None): attr -- attribute to check for ns -- namespace of attribute, by default None """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def getContentList(self, *contents): """returns an ordered list of child nodes *contents -- list of node names to return """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def setAttributeDictionary(self, attributes): """set attribute dictionary """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def getAttributeDictionary(self): """returns a dict of node's attributes """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def getNamespace(self, prefix): """returns namespace referenced by prefix. """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def getTagName(self): """returns tagName of node """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def getParentNode(self): """returns parent element in DOMAdapter or None """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def loadDocument(self, file): """load a Document from a file object file -- """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') def loadFromURL(self, url): """load a Document from an url url -- URL to dereference """ - raise NotImplementedError, 'adapter method not implemented' + raise NotImplementedError('adapter method not implemented') class DOMAdapter(DOMAdapterInterface): @@ -241,8 +241,8 @@ def hasattr(self, attr, ns=None): if not self.__attributes: self.setAttributeDictionary() if ns: - return self.__attributes.get(ns,{}).has_key(attr) - return self.__attributes.has_key(attr) + return attr in self.__attributes.get(ns,{}) + return attr in self.__attributes def getContentList(self, *contents): nodes = [] @@ -251,11 +251,11 @@ def getContentList(self, *contents): if child.nodeType == ELEMENT_NODE and\ SplitQName(child.tagName)[1] in contents: nodes.append(child) - return map(self.__class__, nodes) + return list(map(self.__class__, nodes)) def setAttributeDictionary(self): self.__attributes = {} - for v in self.__node._attrs.values(): + for v in list(self.__node._attrs.values()): self.__attributes[v.nodeName] = v.nodeValue def getAttributeDictionary(self): @@ -281,10 +281,10 @@ def getNamespace(self, prefix): else: try: namespace = DOM.findNamespaceURI(prefix, self.__node) - except DOMException, ex: + except DOMException as ex: if prefix != 'xml': - raise SchemaError, '%s namespace not declared for %s'\ - %(prefix, self.__node._get_tagName()) + raise SchemaError('%s namespace not declared for %s'\ + %(prefix, self.__node._get_tagName())) namespace = XMLNS.XML return namespace @@ -310,7 +310,7 @@ def __str__(self): XMLBase.__rlock.acquire() XMLBase.__indent += 1 tmp = "<" + str(self.__class__) + '>\n' - for k,v in self.__dict__.items(): + for k,v in list(self.__dict__.items()): tmp += "%s* %s = %s\n" %(XMLBase.__indent*' ', k, v) XMLBase.__indent -= 1 XMLBase.__rlock.release() @@ -507,7 +507,7 @@ def __init__(self, parent=None): and not (type(self.__class__.required) == type(XMLSchemaComponent.required)\ and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes)\ and type(self.__class__.contents) == type(XMLSchemaComponent.contents)): - raise RuntimeError, 'Bad type for a class variable in %s' %self.__class__ + raise RuntimeError('Bad type for a class variable in %s' %self.__class__) def getItemTrace(self): """Returns a node trace up to the item. @@ -604,20 +604,20 @@ def getSchemaItem(self, collection, namespace, name): if parent.targetNamespace == namespace: try: obj = getattr(parent, collection)[name] - except KeyError, ex: - raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\ - %(namespace, collection, name) + except KeyError as ex: + raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)'\ + %(namespace, collection, name)) return obj - if not parent.imports.has_key(namespace): + if namespace not in parent.imports: if namespace in BUILT_IN_NAMESPACES: # built-in just return # WARNING: expecting import if "redefine" or add to built-in namespace. return - raise SchemaError, 'schema "%s" does not import namespace "%s"' %( - parent.targetNamespace, namespace) + raise SchemaError('schema "%s" does not import namespace "%s"' %( + parent.targetNamespace, namespace)) # Lazy Eval schema = parent.imports[namespace] @@ -631,17 +631,17 @@ def getSchemaItem(self, collection, namespace, name): # built-in just return return - raise SchemaError, 'no schema instance for imported namespace (%s).'\ - %(namespace) + raise SchemaError('no schema instance for imported namespace (%s).'\ + %(namespace)) if not isinstance(schema, XMLSchema): - raise TypeError, 'expecting XMLSchema instance not "%r"' %schema + raise TypeError('expecting XMLSchema instance not "%r"' %schema) try: obj = getattr(schema, collection)[name] - except KeyError, ex: - raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\ - %(namespace, collection, name) + except KeyError as ex: + raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)'\ + %(namespace, collection, name)) return obj @@ -660,7 +660,7 @@ def getXMLNS(self, prefix=None): if not ns and isinstance(parent, WSDLToolsAdapter): if prefix is None: return '' - raise SchemaError, 'unknown prefix %s' %prefix + raise SchemaError('unknown prefix %s' %prefix) return ns def getAttribute(self, attribute): @@ -668,7 +668,7 @@ def getAttribute(self, attribute): """ if type(attribute) in (list, tuple): if len(attribute) != 2: - raise LookupError, 'To access attributes must use name or (namespace,name)' + raise LookupError('To access attributes must use name or (namespace,name)') ns_dict = self.attributes.get(attribute[0]) if ns_dict is None: @@ -710,25 +710,25 @@ def setAttributes(self, node): with QName. """ self.attributes = {XMLSchemaComponent.xmlns:{}} - for k,v in node.getAttributeDictionary().items(): + for k,v in list(node.getAttributeDictionary().items()): prefix,value = SplitQName(k) if value == XMLSchemaComponent.xmlns: self.attributes[value][prefix or XMLSchemaComponent.xmlns_key] = v elif prefix: ns = node.getNamespace(prefix) if not ns: - raise SchemaError, 'no namespace for attribute prefix %s'\ - %prefix - if not self.attributes.has_key(ns): + raise SchemaError('no namespace for attribute prefix %s'\ + %prefix) + if ns not in self.attributes: self.attributes[ns] = {} - elif self.attributes[ns].has_key(value): - raise SchemaError, 'attribute %s declared multiple times in %s'\ - %(value, ns) + elif value in self.attributes[ns]: + raise SchemaError('attribute %s declared multiple times in %s'\ + %(value, ns)) self.attributes[ns][value] = v - elif not self.attributes.has_key(value): + elif value not in self.attributes: self.attributes[value] = v else: - raise SchemaError, 'attribute %s declared multiple times' %value + raise SchemaError('attribute %s declared multiple times' %value) if not isinstance(self, WSDLToolsAdapter): self.__checkAttributes() @@ -736,14 +736,14 @@ def setAttributes(self, node): #set QNames for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']: - if self.attributes.has_key(k): + if k in self.attributes: prefix, value = SplitQName(self.attributes.get(k)) self.attributes[k] = \ TypeDescriptionComponent((self.getXMLNS(prefix), value)) #Union, memberTypes is a whitespace separated list of QNames for k in ['memberTypes']: - if self.attributes.has_key(k): + if k in self.attributes: qnames = self.attributes[k] self.attributes[k] = [] for qname in qnames.split(): @@ -762,8 +762,8 @@ def __setAttributeDefaults(self): class variable representing attribute is None, then it must be defined as an instance variable. """ - for k,v in self.__class__.attributes.items(): - if v is not None and self.attributes.has_key(k) is False: + for k,v in list(self.__class__.attributes.items()): + if v is not None and (k in self.attributes) is False: if isinstance(v, types.FunctionType): self.attributes[k] = v(self) else: @@ -776,11 +776,10 @@ def __checkAttributes(self): references are not subject to this test. """ for a in self.__class__.required: - if not self.attributes.has_key(a): - raise SchemaError,\ - 'class instance %s, missing required attribute %s'\ - %(self.__class__, a) - for a,v in self.attributes.items(): + if a not in self.attributes: + raise SchemaError('class instance %s, missing required attribute %s'\ + %(self.__class__, a)) + for a,v in list(self.attributes.items()): # attribute #other, ie. not in empty namespace if type(v) is dict: continue @@ -789,10 +788,10 @@ def __checkAttributes(self): if a in (XMLSchemaComponent.xmlns, XMLNS.XML): continue - if (a not in self.__class__.attributes.keys()) and not\ + if (a not in list(self.__class__.attributes.keys())) and not\ (self.isAttribute() and self.isReference()): - raise SchemaError, '%s, unknown attribute(%s,%s)' \ - %(self.getItemTrace(), a, self.attributes[a]) + raise SchemaError('%s, unknown attribute(%s,%s)' \ + %(self.getItemTrace(), a, self.attributes[a])) class WSDLToolsAdapter(XMLSchemaComponent): @@ -842,7 +841,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class Annotation(XMLSchemaComponent): @@ -879,7 +878,7 @@ def fromDom(self, node): #print_debug('class %s, appinfo skipped' %self.__class__, 5) continue else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -915,7 +914,7 @@ def fromDom(self, node): #print_debug('class %s, any skipped' %self.__class__, 5) continue else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -950,7 +949,7 @@ def fromDom(self, node): #print_debug('class %s, any skipped' %self.__class__, 5) continue else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -1064,11 +1063,11 @@ def addImportSchema(self, schema): _imported_schemas """ if not isinstance(schema, XMLSchema): - raise TypeError, 'expecting a Schema instance' + raise TypeError('expecting a Schema instance') if schema.targetNamespace != self.targetNamespace: self._imported_schemas[schema.targetNamespace] = schema else: - raise SchemaError, 'import schema bad targetNamespace' + raise SchemaError('import schema bad targetNamespace') def addIncludeSchema(self, schemaLocation, schema): """for resolving include statements in Schema instance @@ -1077,12 +1076,12 @@ def addIncludeSchema(self, schemaLocation, schema): _included_schemas """ if not isinstance(schema, XMLSchema): - raise TypeError, 'expecting a Schema instance' + raise TypeError('expecting a Schema instance') if not schema.targetNamespace or\ schema.targetNamespace == self.targetNamespace: self._included_schemas[schemaLocation] = schema else: - raise SchemaError, 'include schema bad targetNamespace' + raise SchemaError('include schema bad targetNamespace') def setImportSchemas(self, schema_dict): """set the import schema dictionary, which is used to @@ -1160,8 +1159,8 @@ def load(self, node, location=None): self.setAttributes(pnode) attributes.update(self.attributes) self.setAttributes(node) - for k,v in attributes['xmlns'].items(): - if not self.attributes['xmlns'].has_key(k): + for k,v in list(attributes['xmlns'].items()): + if k not in self.attributes['xmlns']: self.attributes['xmlns'][k] = v else: self.setAttributes(node) @@ -1179,7 +1178,7 @@ def load(self, node, location=None): sl = tp.attributes['schemaLocation'] schema = tp.getSchema() - if not self.getIncludeSchemas().has_key(sl): + if sl not in self.getIncludeSchemas(): self.addIncludeSchema(sl, schema) self.includes[sl] = tp @@ -1192,12 +1191,12 @@ def load(self, node, location=None): for collection in ['imports','elements','types', 'attr_decl','attr_groups','model_groups', 'notations']: - for k,v in getattr(schema,collection).items(): - if not getattr(self,collection).has_key(k): + for k,v in list(getattr(schema,collection).items()): + if k not in getattr(self,collection): v._parent = weakref.ref(self) getattr(self,collection)[k] = v else: - warnings.warn("Not keeping schema component.") + warnings.warn("Not keeping schema component.", stacklevel=2) elif component == 'import': slocd = SchemaReader.namespaceToSchema @@ -1211,24 +1210,24 @@ def load(self, node, location=None): slocd[import_ns] = schema try: tp.loadSchema(schema) - except NoSchemaLocationWarning, ex: + except NoSchemaLocationWarning as ex: # Dependency declaration, hopefully implementation # is aware of this namespace (eg. SOAP,WSDL,?) - print "IMPORT: ", import_ns - print ex + print("IMPORT: ", import_ns) + print(ex) del slocd[import_ns] continue - except SchemaError, ex: + except SchemaError as ex: #warnings.warn(\ # ', %s'\ # %(import_ns, 'failed to load schema instance') #) - print ex + print(ex) del slocd[import_ns] class _LazyEvalImport(str): '''Lazy evaluation of import, replace entry in self.imports.''' #attributes = dict(namespace=import_ns) - def getSchema(namespace): + def getSchema(namespace, slocd=slocd): schema = slocd.get(namespace) if schema is None: parent = self._parent() @@ -1247,10 +1246,10 @@ def getSchema(namespace): else: tp._schema = schema - if self.getImportSchemas().has_key(import_ns): + if import_ns in self.getImportSchemas(): warnings.warn(\ 'Detected multiple imports of the namespace "%s" '\ - %import_ns) + %import_ns, stacklevel=2) self.addImportSchema(schema) # spec says can have multiple imports of same namespace @@ -1258,9 +1257,9 @@ def getSchema(namespace): self.imports[import_ns] = tp elif component == 'redefine': - warnings.warn('redefine is ignored') + warnings.warn('redefine is ignored', stacklevel=2) elif component == 'annotation': - warnings.warn('annotation is ignored') + warnings.warn('annotation is ignored', stacklevel=2) elif component == 'attribute': tp = AttributeDeclaration(self) tp.fromDom(childNode) @@ -1319,7 +1318,7 @@ def fromDom(self, node): contents = self.getContents(node) if self.attributes['namespace'] == self.getTargetNamespace(): - raise SchemaError, 'namespace of schema and import match' + raise SchemaError('namespace of schema and import match') for i in contents: component = SplitQName(i.getTagName())[1] @@ -1327,7 +1326,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) def getSchema(self): """if schema is not defined, first look for a Schema class instance @@ -1343,7 +1342,7 @@ def getSchema(self): if not schema: url = self.attributes.get('schemaLocation') if not url: - raise SchemaError, 'namespace(%s) is unknown' %ns + raise SchemaError('namespace(%s) is unknown' %ns) base_url = self._parent().getBaseUrl() reader = SchemaReader(base_url=base_url) reader._imports = self._parent().getImportSchemas() @@ -1360,7 +1359,7 @@ def loadSchema(self, schema): reader._includes = self._parent().getIncludeSchemas() self._schema = schema - if not self.attributes.has_key('schemaLocation'): + if 'schemaLocation' not in self.attributes: raise NoSchemaLocationWarning('no schemaLocation attribute in import') reader.loadFromURL(self.attributes.get('schemaLocation'), schema) @@ -1397,7 +1396,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) def getSchema(self): """if schema is not defined, first look for a Schema class instance @@ -1467,7 +1466,7 @@ def fromDom(self, node): self.content = AnonymousSimpleType(self) self.content.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class LocalAttributeDeclaration(AttributeDeclaration,\ @@ -1516,7 +1515,7 @@ def fromDom(self, node): self.content = AnonymousSimpleType(self) self.content.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class AttributeWildCard(XMLSchemaComponent,\ @@ -1554,7 +1553,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class AttributeReference(XMLSchemaComponent,\ @@ -1598,7 +1597,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class AttributeGroupDefinition(XMLSchemaComponent,\ @@ -1643,18 +1642,18 @@ def fromDom(self, node): elif contents[indx].hasattr('ref'): content.append(AttributeReference(self)) else: - raise SchemaError, 'Unknown attribute type' + raise SchemaError('Unknown attribute type') content[-1].fromDom(contents[indx]) elif component == 'attributeGroup': content.append(AttributeGroupReference(self)) content[-1].fromDom(contents[indx]) elif component == 'anyAttribute': if len(contents) != indx+1: - raise SchemaError, 'anyAttribute is out of order in %s' %self.getItemTrace() + raise SchemaError('anyAttribute is out of order in %s' %self.getItemTrace()) content.append(AttributeWildCard(self)) content[-1].fromDom(contents[indx]) else: - raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName()) + raise SchemaError('Unknown component (%s)' %(contents[indx].getTagName())) self.attr_content = tuple(content) @@ -1696,7 +1695,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) @@ -1737,9 +1736,9 @@ def fromDom(self, node): fields[-1].fromDom(i) continue else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.fields = tuple(fields) @@ -1759,9 +1758,9 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class Selector(Constraint): """ @@ -1918,7 +1917,7 @@ def getAttribute(self, attribute): parent = self while 1: nsdict = parent.attributes[XMLSchemaComponent.xmlns] - for k,v in nsdict.items(): + for k,v in list(nsdict.items()): if v not in SCHEMA.XSD_LIST: continue return TypeDescriptionComponent((v, 'anyType')) @@ -1928,10 +1927,10 @@ def getAttribute(self, attribute): parent = parent._parent() - raise SchemaError, 'failed to locate the XSD namespace' + raise SchemaError('failed to locate the XSD namespace') def getElementDeclaration(self, attribute): - raise Warning, 'invalid operation for <%s>' %self.tag + raise Warning('invalid operation for <%s>' %self.tag) def getTypeDefinition(self, attribute=None): """If attribute is None, "type" is assumed, return the corresponding @@ -1978,9 +1977,9 @@ def fromDom(self, node): constraints.append(Unique(self)) constraints[-1].fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.constraints = constraints @@ -2030,7 +2029,7 @@ def isQualified(self): return True if form == 'unqualified': return False - raise SchemaError, 'Bad form (%s) for element: %s' %(form, self.getItemTrace()) + raise SchemaError('Bad form (%s) for element: %s' %(form, self.getItemTrace())) class ElementReference(XMLSchemaComponent,\ @@ -2078,7 +2077,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class ElementWildCard(LocalElementDeclaration, WildCardMarker): @@ -2121,7 +2120,7 @@ def getAttribute(self, attribute): return XMLSchemaComponent.getAttribute(self, attribute) def getTypeDefinition(self, attribute): - raise Warning, 'invalid operation for <%s>' % self.tag + raise Warning('invalid operation for <%s>' % self.tag) def fromDom(self, node): self.annotation = None @@ -2133,7 +2132,7 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) ###################################################### @@ -2190,10 +2189,10 @@ def fromDom(self, node): elif component == 'any': content.append(ElementWildCard(self)) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) content[-1].fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -2239,10 +2238,10 @@ def fromDom(self, node): else: content.append(LocalElementDeclaration(self)) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) content[-1].fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -2297,10 +2296,10 @@ def fromDom(self, node): elif component == 'any': content.append(ElementWildCard(self)) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) content[-1].fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content = tuple(content) @@ -2346,10 +2345,10 @@ def fromDom(self, node): elif component == 'sequence' and not self.content: self.content = Sequence(self) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.content.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) class ModelGroupReference(XMLSchemaComponent,\ @@ -2393,9 +2392,9 @@ def fromDom(self, node): self.annotation = Annotation(self) self.annotation.fromDom(i) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) @@ -2439,23 +2438,23 @@ def isMixed(self): m = self.getAttribute('mixed') if m == 0 or m == False: return False - if isinstance(m, basestring) is True: + if isinstance(m, str) is True: if m in ('false', '0'): return False if m in ('true', '1'): return True - raise SchemaError, 'invalid value for attribute mixed(%s): %s'\ - %(m, self.getItemTrace()) + raise SchemaError('invalid value for attribute mixed(%s): %s'\ + %(m, self.getItemTrace())) def getAttributeContent(self): return self.attr_content def getElementDeclaration(self, attribute): - raise Warning, 'invalid operation for <%s>' %self.tag + raise Warning('invalid operation for <%s>' %self.tag) def getTypeDefinition(self, attribute): - raise Warning, 'invalid operation for <%s>' %self.tag + raise Warning('invalid operation for <%s>' %self.tag) def fromDom(self, node): self.setAttributes(node) @@ -2508,8 +2507,8 @@ def fromDom(self, node): elif component == 'anyAttribute': self.attr_content.append(AttributeWildCard(self)) else: - raise SchemaError, 'Unknown component (%s): %s' \ - %(contents[indx].getTagName(),self.getItemTrace()) + raise SchemaError('Unknown component (%s): %s' \ + %(contents[indx].getTagName(),self.getItemTrace())) self.attr_content[-1].fromDom(contents[indx]) indx += 1 @@ -2537,9 +2536,9 @@ def fromDom(self, node): elif component == 'extension' and not self.derivation: self.derivation = self.__class__.Extension(self) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(i.getTagName())) self.derivation.fromDom(i) self.content = self.derivation @@ -2564,13 +2563,13 @@ def isMixed(self): m = self.getAttribute('mixed') if m == 0 or m == False: return False - if isinstance(m, basestring) is True: + if isinstance(m, str) is True: if m in ('false', '0'): return False if m in ('true', '1'): return True - raise SchemaError, 'invalid value for attribute mixed(%s): %s'\ - %(m, self.getItemTrace()) + raise SchemaError('invalid value for attribute mixed(%s): %s'\ + %(m, self.getItemTrace())) class _DerivationBase(XMLSchemaComponent): """, @@ -2650,7 +2649,7 @@ def fromDom(self, node): elif component == 'anyAttribute': self.attr_content.append(AttributeWildCard(self)) else: - raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName()) + raise SchemaError('Unknown component (%s)' %(contents[indx].getTagName())) self.attr_content[-1].fromDom(contents[indx]) indx += 1 @@ -2755,8 +2754,8 @@ def fromDom(self, node): elif component == 'anyAttribute': content.append(AttributeWildCard(self)) else: - raise SchemaError, 'Unknown component (%s)'\ - %(contents[indx].getTagName()) + raise SchemaError('Unknown component (%s)'\ + %(contents[indx].getTagName())) content[-1].fromDom(contents[indx]) indx += 1 self.attr_content = tuple(content) @@ -2824,8 +2823,8 @@ def fromDom(self, node): self.content.append(AnonymousSimpleType(self)) self.content[-1].fromDom(contents[indx]) else: - raise SchemaError, 'Unknown component (%s)'\ - %(contents[indx].getTagName()) + raise SchemaError('Unknown component (%s)'\ + %(contents[indx].getTagName())) content[-1].fromDom(contents[indx]) indx += 1 self.attr_content = tuple(content) @@ -2878,10 +2877,10 @@ def __init__(self, parent): self.content = None def getElementDeclaration(self, attribute): - raise Warning, 'invalid operation for <%s>' %self.tag + raise Warning('invalid operation for <%s>' %self.tag) def getTypeDefinition(self, attribute): - raise Warning, 'invalid operation for <%s>' %self.tag + raise Warning('invalid operation for <%s>' %self.tag) def fromDom(self, node): self.setAttributes(node) @@ -2902,7 +2901,7 @@ def fromDom(self, node): elif component == 'union': self.content = self.__class__.Union(self) else: - raise SchemaError, 'Unknown component (%s)' %(component) + raise SchemaError('Unknown component (%s)' %(component)) self.content.fromDom(child) class Restriction(XMLSchemaComponent,\ @@ -2960,7 +2959,7 @@ def fromDom(self, node): elif component in RestrictionMarker.facets: self.facets.append(contents[indx]) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(contents[indx].getTagName())) self.content = tuple(content) @@ -3000,7 +2999,7 @@ def fromDom(self, node): content.append(AnonymousSimpleType(self)) content[-1].fromDom(contents[indx]) else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(contents[indx].getTagName())) self.content = tuple(content) class List(XMLSchemaComponent, @@ -3052,7 +3051,7 @@ def fromDom(self, node): self.content.fromDom(contents[indx]) break else: - raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) + raise SchemaError('Unknown component (%s)' %(contents[indx].getTagName())) class AnonymousSimpleType(SimpleType,\ @@ -3089,7 +3088,7 @@ class Redefine: if sys.version_info[:2] >= (2, 2): tupleClass = tuple else: - import UserTuple + from . import UserTuple tupleClass = UserTuple.UserTuple class TypeDescriptionComponent(tupleClass): @@ -3101,7 +3100,7 @@ def __init__(self, args): Remove the name's prefix, irrelevant. """ if len(args) != 2: - raise TypeError, 'expecting tuple (namespace, name), got %s' %args + raise TypeError('expecting tuple (namespace, name), got %s' %args) elif args[1].find(':') >= 0: args = (args[0], SplitQName(args[1])[1]) tuple.__init__(self, args) @@ -3112,5 +3111,3 @@ def getTargetNamespace(self): def getName(self): return self[1] - - diff --git a/wstools/XMLname.py b/backend/wstools/XMLname.py similarity index 80% rename from wstools/XMLname.py rename to backend/wstools/XMLname.py index 5961160..5d1f2f4 100644 --- a/wstools/XMLname.py +++ b/backend/wstools/XMLname.py @@ -38,13 +38,13 @@ def _toUnicodeHex(x): elif (hexlen==6): hexval = "00" + hexval elif (hexlen==7): hexval = "0" + hexval elif (hexlen==8): hexval = "" + hexval - else: raise Exception, "Illegal Value returned from hex(ord(x))" + else: raise Exception("Illegal Value returned from hex(ord(x))") return "_x"+ hexval + "_" def _fromUnicodeHex(x): - return eval( r'u"\u'+x[2:-1]+'"' ) + return chr(int(x[2:-1], 16)) def toXMLname(string): @@ -55,26 +55,26 @@ def toXMLname(string): prefix = None localname = string - T = unicode(localname) + T = str(localname) N = len(localname) X = []; for i in range(N) : - if i< N-1 and T[i]==u'_' and T[i+1]==u'x': - X.append(u'_x005F_') + if i< N-1 and T[i]=='_' and T[i+1]=='x': + X.append('_x005F_') elif i==0 and N >= 3 and \ - ( T[0]==u'x' or T[0]==u'X' ) and \ - ( T[1]==u'm' or T[1]==u'M' ) and \ - ( T[2]==u'l' or T[2]==u'L' ): - X.append(u'_xFFFF_' + T[0]) + ( T[0]=='x' or T[0]=='X' ) and \ + ( T[1]=='m' or T[1]=='M' ) and \ + ( T[2]=='l' or T[2]=='L' ): + X.append('_xFFFF_' + T[0]) elif (not _NCNameChar(T[i])) or (i==0 and not _NCNameStartChar(T[i])): X.append(_toUnicodeHex(T[i])) else: X.append(T[i]) if prefix: - return "%s:%s" % (prefix, u''.join(X)) - return u''.join(X) + return "%s:%s" % (prefix, ''.join(X)) + return ''.join(X) def fromXMLname(string): diff --git a/wstools/__init__.py b/backend/wstools/__init__.py similarity index 60% rename from wstools/__init__.py rename to backend/wstools/__init__.py index 5b6f7ef..4b81df0 100644 --- a/wstools/__init__.py +++ b/backend/wstools/__init__.py @@ -3,7 +3,7 @@ ident = "$Id$" -import WSDLTools -import XMLname -import logging +from . import WSDLTools +from . import XMLname +from . import logging diff --git a/wstools/c14n.py b/backend/wstools/c14n.py similarity index 90% rename from wstools/c14n.py rename to backend/wstools/c14n.py index 33305bf..ffd8005 100755 --- a/wstools/c14n.py +++ b/backend/wstools/c14n.py @@ -47,6 +47,7 @@ http://www.w3.org/Consortium/Legal/copyright-software-19980720 ''' +from functools import cmp_to_key import string from xml.dom import Node try: @@ -56,12 +57,12 @@ class XMLNS: BASE = "http://www.w3.org/2000/xmlns/" XML = "http://www.w3.org/XML/1998/namespace" try: - import cStringIO - StringIO = cStringIO + import io + StringIO = io.StringIO except ImportError: - import StringIO + import io -_attrs = lambda E: (E.attributes and E.attributes.values()) or [] +_attrs = lambda E: (E.attributes and list(E.attributes.values())) or [] _children = lambda E: E.childNodes or [] _IN_XML_NS = lambda n: n.name.startswith("xmlns") _inclusive = lambda n: n.unsuppressedPrefixes == None @@ -69,15 +70,20 @@ class XMLNS: # Does a document/PI has lesser/greater document order than the # first element? -_LesserElement, _Element, _GreaterElement = range(3) +_LesserElement, _Element, _GreaterElement = list(range(3)) + +def _cmp_value(left, right): + left = '' if left is None else left + right = '' if right is None else right + return (left > right) - (left < right) def _sorter(n1,n2): '''_sorter(n1,n2) -> int Sorting predicate for non-NS attributes.''' - i = cmp(n1.namespaceURI, n2.namespaceURI) + i = _cmp_value(n1.namespaceURI, n2.namespaceURI) if i: return i - return cmp(n1.localName, n2.localName) + return _cmp_value(n1.localName, n2.localName) def _sorter_ns(n1,n2): @@ -86,7 +92,7 @@ def _sorter_ns(n1,n2): if n1[0] == 'xmlns': return -1 if n2[0] == 'xmlns': return 1 - return cmp(n1[0], n2[0]) + return _cmp_value(n1[0], n2[0]) def _utilized(n, node, other_attrs, unsuppressedPrefixes): '''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean @@ -174,7 +180,7 @@ def __init__(self, node, write, **kw): elif node.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: - raise TypeError, str(node) + raise TypeError(str(node)) def _inherit_context(self, node): @@ -184,7 +190,7 @@ def _inherit_context(self, node): canonicalization.''' # Collect the initial list of xml:foo attributes. - xmlattrs = filter(_IN_XML_NS, _attrs(node)) + xmlattrs = list(filter(_IN_XML_NS, _attrs(node))) # Walk up and get all xml:XXX attributes we inherit. inherited, parent = [], node.parentNode @@ -217,7 +223,7 @@ def _do_document(self, node): elif child.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: - raise TypeError, str(child) + raise TypeError(str(child)) handlers[Node.DOCUMENT_NODE] = _do_document @@ -290,9 +296,10 @@ def _do_attr(self, n, value): W('"') - def _do_element(self, node, initial_other_attrs = [], unused = None): + def _do_element(self, node, initial_other_attrs = None, unused = None): '''_do_element(self, node, initial_other_attrs = [], unused = {}) -> None Process an element (and its children).''' + initial_other_attrs = [] if initial_other_attrs is None else initial_other_attrs # Get state (from the stack) make local copies. # ns_parent -- NS declarations in parent @@ -344,11 +351,10 @@ def _do_element(self, node, initial_other_attrs = [], unused = None): else: prefix = 'xmlns' - if not ns_rendered.has_key(prefix) and not ns_local.has_key(prefix): - if not ns_unused_inherited.has_key(prefix): - raise RuntimeError,\ - 'For exclusive c14n, unable to map prefix "%s" in %s' %( - prefix, node) + if prefix not in ns_rendered and prefix not in ns_local: + if prefix not in ns_unused_inherited: + raise RuntimeError('For exclusive c14n, unable to map prefix "%s" in %s' %( + prefix, node)) ns_local[prefix] = ns_unused_inherited[prefix] del ns_unused_inherited[prefix] @@ -358,7 +364,7 @@ def _do_element(self, node, initial_other_attrs = [], unused = None): # Create list of NS attributes to render. ns_to_render = [] - for n,v in ns_local.items(): + for n,v in list(ns_local.items()): # If default namespace is XMLNS.BASE or empty, # and if an ancestor was the same @@ -376,14 +382,14 @@ def _do_element(self, node, initial_other_attrs = [], unused = None): # If not previously rendered # and it's inclusive or utilized - if (n,v) not in ns_rendered.items(): + if (n,v) not in list(ns_rendered.items()): if inclusive or _utilized(n, node, other_attrs, self.unsuppressedPrefixes): ns_to_render.append((n, v)) elif not inclusive: ns_unused_inherited[n] = v # Sort and render the ns, marking what was rendered. - ns_to_render.sort(_sorter_ns) + ns_to_render.sort(key=cmp_to_key(_sorter_ns)) for n,v in ns_to_render: self._do_attr(n, v) ns_rendered[n]=v #0417 @@ -392,10 +398,10 @@ def _do_element(self, node, initial_other_attrs = [], unused = None): # Else, add all local and ancestor xml attributes # Sort and render the attributes. if not inclusive or _in_subset(self.subset,node.parentNode): #0426 - other_attrs.extend(xml_attrs_local.values()) + other_attrs.extend(list(xml_attrs_local.values())) else: - other_attrs.extend(xml_attrs.values()) - other_attrs.sort(_sorter) + other_attrs.extend(list(xml_attrs.values())) + other_attrs.sort(key=cmp_to_key(_sorter)) for a in other_attrs: self._do_attr(a.nodeName, a.value) W('>') @@ -426,8 +432,8 @@ def Canonicalize(node, output=None, **kw): prefixes that should be inherited. ''' if output: - apply(_implementation, (node, output.write), kw) + _implementation(*(node, output.write), **kw) else: - s = StringIO.StringIO() - apply(_implementation, (node, s.write), kw) + s = io.StringIO() + _implementation(*(node, s.write), **kw) return s.getvalue() diff --git a/wstools/logging.py b/backend/wstools/logging.py similarity index 89% rename from wstools/logging.py rename to backend/wstools/logging.py index 9c33b00..a60dd3d 100644 --- a/wstools/logging.py +++ b/backend/wstools/logging.py @@ -42,24 +42,24 @@ def warning(self, msg, *args, **kw): if self.warnOn() is False: return if BasicLogger.last != self.msg: BasicLogger.last = self.msg - print >>self, "---- ", self.msg, " ----" - print >>self, " %s " %self.WARN, - print >>self, msg %args + print("---- ", self.msg, " ----", file=self) + print(" %s " %self.WARN, end=' ', file=self) + print(msg %args, file=self) WARN = '[WARN]' def debug(self, msg, *args, **kw): if self.debugOn() is False: return if BasicLogger.last != self.msg: BasicLogger.last = self.msg - print >>self, "---- ", self.msg, " ----" - print >>self, " %s " %self.DEBUG, - print >>self, msg %args + print("---- ", self.msg, " ----", file=self) + print(" %s " %self.DEBUG, end=' ', file=self) + print(msg %args, file=self) DEBUG = '[DEBUG]' def error(self, msg, *args, **kw): if BasicLogger.last != self.msg: BasicLogger.last = self.msg - print >>self, "---- ", self.msg, " ----" - print >>self, " %s " %self.ERROR, - print >>self, msg %args + print("---- ", self.msg, " ----", file=self) + print(" %s " %self.ERROR, end=' ', file=self) + print(msg %args, file=self) ERROR = '[ERROR]' def write(self, *args): @@ -140,12 +140,12 @@ def __init__(self, date=None, **kw): def __str__(self): """ """ - from cStringIO import StringIO + from io import StringIO s = StringIO(); n = " " reserved = self.reserved; omitname = self.omitname; levels = self.levels - for k in ( list(filter(lambda i: self.has_key(i), reserved)) + - list(filter(lambda i: i not in reserved, self.keys())) + for k in ( list([i for i in reserved if i in self]) + + list([i for i in list(self.keys()) if i not in reserved]) ): v = self[k] if k in omitname: @@ -178,8 +178,8 @@ def __new__(self, args=None): return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l) - format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x, - unicode:str, GLDate:str, } + format = { int:str, float:lambda x: "%lf" % x, int:str, str:lambda x:x, + str:str, GLDate:str, } def gridLog(**kw): @@ -205,8 +205,8 @@ def gridLog(**kw): scheme = url[:url.find('://')] send = GLRegistry[scheme] send( url, str(GLRecord(**kw)), ) - except Exception, ex: - print >>sys.stderr, "*** gridLog failed -- %s" %(str(kw)) + except Exception as ex: + print("*** gridLog failed -- %s" %(str(kw)), file=sys.stderr) def sendUDP(url, outputStr): @@ -218,7 +218,7 @@ def sendUDP(url, outputStr): socket(AF_INET, SOCK_DGRAM).sendto( outputStr, (host,int(port)), ) def writeToFile(url, outputStr): - print >> open(url.split('://')[1], 'a+'), outputStr + print(outputStr, file=open(url.split('://')[1], 'a+')) GLRegistry["gridlog-udp"] = sendUDP GLRegistry["file"] = writeToFile @@ -271,4 +271,3 @@ def getLogger(msg): ''' return _LoggerClass(msg) - diff --git a/wstools/tests/.cvsignore b/backend/wstools/tests/.cvsignore similarity index 100% rename from wstools/tests/.cvsignore rename to backend/wstools/tests/.cvsignore diff --git a/wstools/tests/README b/backend/wstools/tests/README similarity index 100% rename from wstools/tests/README rename to backend/wstools/tests/README diff --git a/wstools/tests/__init__.py b/backend/wstools/tests/__init__.py similarity index 100% rename from wstools/tests/__init__.py rename to backend/wstools/tests/__init__.py diff --git a/wstools/tests/config.txt b/backend/wstools/tests/config.txt similarity index 100% rename from wstools/tests/config.txt rename to backend/wstools/tests/config.txt diff --git a/wstools/tests/schema.tar.gz b/backend/wstools/tests/schema.tar.gz similarity index 100% rename from wstools/tests/schema.tar.gz rename to backend/wstools/tests/schema.tar.gz diff --git a/wstools/tests/test_t1.py b/backend/wstools/tests/test_t1.py similarity index 96% rename from wstools/tests/test_t1.py rename to backend/wstools/tests/test_t1.py index 5c33899..63c9d23 100644 --- a/wstools/tests/test_t1.py +++ b/backend/wstools/tests/test_t1.py @@ -3,7 +3,7 @@ # See LBNLCopyright for copyright notice! ########################################################################### import unittest -import test_wsdl +from . import test_wsdl import utils def makeTestSuite(): diff --git a/wstools/tests/test_wsdl.py b/backend/wstools/tests/test_wsdl.py similarity index 88% rename from wstools/tests/test_wsdl.py rename to backend/wstools/tests/test_wsdl.py index 5f617b9..cad425f 100644 --- a/wstools/tests/test_wsdl.py +++ b/backend/wstools/tests/test_wsdl.py @@ -6,7 +6,7 @@ ########################################################################### import sys, unittest -import ConfigParser +import configparser import os from wstools.Utility import DOM from wstools.WSDLTools import WSDLReader @@ -21,8 +21,8 @@ def __init__(self, methodName='runTest'): unittest.TestCase.__init__(self, methodName) def setUp(self): - self.path = nameGenerator.next() - print self.path + self.path = next(nameGenerator) + print(self.path) sys.stdout.flush() def __str__(self): @@ -41,7 +41,7 @@ def checkWSDLCollection(self, tag_name, component, key='name'): for node in DOM.getElements(definition, tag_name, nspname): name = DOM.getAttr(node, key) comp = component[name] - self.failUnlessEqual(eval('comp.%s' %key), name) + self.assertEqual(eval('comp.%s' %key), name) def checkXSDCollection(self, tag_name, component, node, key='name'): for cnode in DOM.getElements(node, tag_name): @@ -56,7 +56,7 @@ def test_all(self): self.wsdl = WSDLReader().loadFromFile(self.path) except TimeoutError: - print "connection timed out" + print("connection timed out") sys.stdout.flush() return except: @@ -94,9 +94,9 @@ def test_all(self): raise try: - for key in self.wsdl.types.keys(): + for key in list(self.wsdl.types.keys()): schema = self.wsdl.types[key] - self.failUnlessEqual(key, schema.getTargetNamespace()) + self.assertEqual(key, schema.getTargetNamespace()) definition = self.wsdl.document.documentElement version = DOM.WSDLUriToVersion(definition.namespaceURI) @@ -114,8 +114,8 @@ def test_all(self): raise if self.wsdl.extensions: - print 'No check for WSDLTools(%s) Extensions:' %(self.wsdl.name) - for ext in self.wsdl.extensions: print '\t', ext + print('No check for WSDLTools(%s) Extensions:' %(self.wsdl.name)) + for ext in self.wsdl.extensions: print('\t', ext) def schemaAttributesDeclarations(self, schema, node): self.checkXSDCollection('attribute', schema.attr_decl, node) @@ -132,13 +132,13 @@ def schemaTypeDefinitions(self, schema, node): def setUpOptions(section): - cp = ConfigParser.ConfigParser() + cp = configparser.ConfigParser() cp.read(cwd+'/config.txt') if not cp.sections(): - print 'fatal error: configuration file config.txt not present' + print('fatal error: configuration file config.txt not present') sys.exit(0) if not cp.has_section(section): - print '%s section not present in configuration file, exiting' % section + print('%s section not present in configuration file, exiting' % section) sys.exit(0) return cp, len(cp.options(section)) diff --git a/wstools/tests/test_wstools.py b/backend/wstools/tests/test_wstools.py similarity index 89% rename from wstools/tests/test_wstools.py rename to backend/wstools/tests/test_wstools.py index 0e0f958..9f1ea30 100644 --- a/wstools/tests/test_wstools.py +++ b/backend/wstools/tests/test_wstools.py @@ -5,15 +5,15 @@ # See LBNLCopyright for copyright notice! ########################################################################### -import unittest, tarfile, os, ConfigParser -import test_wsdl +import unittest, tarfile, os, configparser +from . import test_wsdl SECTION='files' CONFIG_FILE = 'config.txt' def extractFiles(section, option): - config = ConfigParser.ConfigParser() + config = configparser.ConfigParser() config.read(CONFIG_FILE) archives = config.get(section, option) archives = eval(archives) diff --git a/wstools/tests/test_wstools_net.py b/backend/wstools/tests/test_wstools_net.py similarity index 95% rename from wstools/tests/test_wstools_net.py rename to backend/wstools/tests/test_wstools_net.py index 880cff3..187fdb9 100644 --- a/wstools/tests/test_wstools_net.py +++ b/backend/wstools/tests/test_wstools_net.py @@ -5,7 +5,7 @@ # See LBNLCopyright for copyright notice! ########################################################################### import unittest -import test_wsdl +from . import test_wsdl def makeTestSuite(): suite = unittest.TestSuite() diff --git a/wstools/tests/xmethods.tar.gz b/backend/wstools/tests/xmethods.tar.gz similarity index 100% rename from wstools/tests/xmethods.tar.gz rename to backend/wstools/tests/xmethods.tar.gz diff --git a/conf/requirements-development.txt b/conf/requirements-development.txt deleted file mode 100644 index d8fc06d..0000000 --- a/conf/requirements-development.txt +++ /dev/null @@ -1,2 +0,0 @@ -ipdb==0.8 -ipython==2.2.0 diff --git a/conf/requirements-testing.txt b/conf/requirements-testing.txt deleted file mode 100644 index 363a54c..0000000 --- a/conf/requirements-testing.txt +++ /dev/null @@ -1,3 +0,0 @@ -coverage==3.7.1 -unittest-xml-reporting==1.9.0 -unittest2==0.5.1 diff --git a/docs/DEFCOIN_P2POOL_OPERATIONAL_NOTES.md b/docs/DEFCOIN_P2POOL_OPERATIONAL_NOTES.md deleted file mode 100644 index b7f27f1..0000000 --- a/docs/DEFCOIN_P2POOL_OPERATIONAL_NOTES.md +++ /dev/null @@ -1,102 +0,0 @@ -# Defcoin P2Pool Operational Notes - -## Server fee wallet - -The dc903 P2Pool server fee wallet is configured in the systemd service, not in -`p2pool/networks/defcoin.py`. - -On the server, inspect it with: - -```bash -systemctl cat p2pool-defcoin -``` - -The active service command is: - -```bash -/usr/bin/python2.7 /home/dfcpool/p2pool-defcoin/run_p2pool.py --net defcoin --allow-obsolete-bitcoind -a DBbKV7upy41hV42dU895m4NcXn9AvHXUz9 -n 50.116.19.40 --bitcoind-p2p-port 10332 --fee 1.5 -``` - -For this deployment: - -- `-a DBbKV7upy41hV42dU895m4NcXn9AvHXUz9` sets the node operator/default payout - address. -- `--fee 1.5` sets the public worker fee to 1.5%. -- In `p2pool/work.py`, the worker fee is applied by occasionally assigning a - worker share to the node operator address instead of the miner-submitted - username address. -- The worker fee can be checked from the web/API endpoint: - -```bash -curl http://127.0.0.1:13372/fee -``` - -This server fee is separate from P2Pool's legacy `DONATION_SCRIPT` / developer -donation output. The legacy donation-script issue is a share-template and -coinbase-compatibility issue; changing `-a` or `--fee` does not remove that dust -output. - -## Version 36 donation dust fix - -Old Defcoin P2Pool shares inherited JP's P2Pool developer donation script. In -this fork it resolves to the Defcoin address -`DQ8AwqR2XJE9G5dSEfspJYH7Spre85dj6L`. The private key for that historical -destination is not available, so the one-satoshi rounding outputs are effectively -lost. - -This repository fixes the issue with Defcoin P2Pool share version `36`. - -- `p2pool/data.py` adds `DonationDustFixedShare`, keeps old shares verifiable, - removes the spendable legacy donation output from new share templates, and - adds a zero-value OP_RETURN padding output so P2Pool's coinbase hashlink still - has a stable tail. -- `p2pool/work.py` stops recording author-donation weight once the active share - type no longer pays the legacy donation output. -- `p2pool/data.py:get_expected_payouts` stops showing the lost-key donation - address as the expected destination once the best share is version `36`. - -This is not a Defcoin blockchain hard fork. It is a P2Pool share-template and -share-version change. Operators sharing the same Defcoin P2Pool network should -coordinate a restart/update window so their P2Pool nodes agree on version `36`. -The parent-chain Defcoin blocks remain ordinary Defcoin blocks. - -For a normal gradual P2Pool upgrade, leave -`DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY` unset and let version `36` activate after the -ordinary successor-vote threshold. On the current very small Defcoin P2Pool -network, that can take too long, so coordinated operators can set: - -```bash -DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY=1 -``` - -with the restart. This allows version `36` shares to follow version `35` shares -immediately. Operators not using the flag-day build should not remain connected -to the same P2Pool sharechain once version `36` shares are being mined. - -Suggested operator note: - -```text -I am updating the Defcoin P2Pool fork to remove the old JP P2Pool developer -donation script from newly mined templates. The on-chain address affected is -DQ8AwqR2XJE9G5dSEfspJYH7Spre85dj6L. This is not a Defcoin hard fork; it is a -P2Pool share-template/share-version update. Please pull the version that adds -DonationDustFixedShare in p2pool/data.py. Because the Defcoin P2Pool share rate -is currently tiny, we should restart during the same window with -DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY=1 instead of waiting for normal share voting. -Keep your Defcoin parent-chain node in dual-magic compatibility mode until older -wallets have mostly upgraded. -``` - -## P2Pool peer handshake logging - -The P2Pool peer network is separate from the Defcoin Core parent-chain peer network. A small Defcoin sharechain may have only one or two useful P2Pool peers, so peer safety is more important than aggressively reducing connection attempts. - -The peer handshake logging policy is: - -- Keep accepting sockets long enough to read the P2Pool `version` message and peer nonce. -- Do not reject a peer only because another connection from the same IP address already exists. -- Keep the normal established-peer log line because it records the live peer set. -- Log invalid handshakes such as too-old protocol versions, repeated version messages, or self-connections. -- For duplicate peer nonces, disconnect the duplicate after identification and rate-limit the log message to one line per host per five minutes, with suppressed-message counts summarized on the next emitted line. - -This keeps useful abnormal events visible while preventing normal duplicate-connection churn from filling logs. It also avoids accidentally isolating a valid P2Pool peer on a very small network. diff --git a/docs/DEFCOIN_P2POOL_PROVENANCE_REPORT.md b/docs/DEFCOIN_P2POOL_PROVENANCE_REPORT.md deleted file mode 100644 index 1fa19be..0000000 --- a/docs/DEFCOIN_P2POOL_PROVENANCE_REPORT.md +++ /dev/null @@ -1,223 +0,0 @@ -# Defcoin P2Pool Provenance and Technical Comparison Report - -Date: 2026-05-22 - -## Executive Summary - -The live `defcoin.dc903.org` p2pool service has two different provenance layers: - -1. Direct Git source for the server checkout: the server's `.git/config` points at the old `charlesrocket/p2pool-defcoin` URL, which GitHub now redirects to the canonical `hellbyte/p2pool-defcoin` repository. -2. Older upstream code lineage: that Defcoin p2pool repository appears to be derived from the Python 2 / `jtoomim/p2pool` era of P2Pool, based on protocol/share-version markers and module layout. - -The live server checkout identifies its immediate upstream remote as: - -- Upstream Defcoin fork: `https://github.com/charlesrocket/p2pool-defcoin` -- GitHub redirect/current owner: `https://github.com/hellbyte/p2pool-defcoin` -- Upstream commit used by the server checkout: `dc1b4af980cb6d662069fd302651b50997a8aa8c` -- Commit subject: `cleared up CPU pool instructions to use USB` -- Upstream default branch: `master` -- Upstream tags: none found in the server checkout - -That repository is not marked by GitHub as a formal fork, so GitHub cannot prove a formal fork relationship to `jtoomim/p2pool`. By code lineage, however, it is a Defcoin adaptation of the P2Pool Python 2 lineage and most closely matches the `jtoomim/p2pool` era rather than the current `p2pool/p2pool` tree. The strongest version markers are: - -- P2Pool protocol version: `3501` -- Current share format: `PaddingBugfixShare.VERSION = 35` -- SegWit share support: `SegwitMiningShare.VERSION = 34` -- Live server p2pool sub-version style: `/P2Pool:dc1b4af-dirty/` before these changes are committed - -For GitHub traceability, `turnkit/p2pool-defcoin` is intended to carry the current dc903 live-server implementation as a normal fork-style repository. The first Turnkit commit after the upstream baseline records the live server changes plus this report, so GitHub can show the difference between the original Defcoin p2pool code and the currently deployed dc903 implementation without asking the archived/original upstream to accept a pull request. - -## Lineage Block Overview - -### 1. Original P2Pool Lineage - -`p2pool/p2pool` is the original project lineage for peer-to-peer mining pool software. It provides the core architecture: a decentralized p2pool sharechain, peer protocol, share validation, work generation, and a small web/status UI. - -### 2. jtoomim-Era Python 2 P2Pool - -The Defcoin fork's core files align much more closely with `jtoomim/p2pool` than with the current `p2pool/p2pool` repository. The matching markers include protocol version `3501`, share versions `35/34/33/32/17`, SegWit-aware share handling, and the same broad module layout. This is a code-lineage finding, not the server's direct Git remote. - -### 3. hellbyte/charlesrocket Defcoin Fork - -`hellbyte/p2pool-defcoin` adds Defcoin as both: - -- a parent blockchain network in `p2pool/bitcoin/networks/defcoin.py` -- a p2pool sharechain network in `p2pool/networks/defcoin.py` - -It changes coin/network constants, ports, block explorer links, bootstrap nodes, and worker port selection for Defcoin mining. - -### 4. dc903 Live Server Branch - -The dc903 live branch adds operational fixes and the 2026 Defcoin network transition work: - -- dual legacy/new p2pool magic support -- per-peer reply magic selection -- Defcoin Core Nu `getblocktemplate` rule negotiation compatibility -- current `defcoin.dc903.org` explorer links -- selected ASIC worker pool settings -- pidfile guard in `run_p2pool.py` -- a small p2pool bug fix in ban-score decay -- customized web UI assets - -## Detailed Modular Overview - -### Repository and Versioning - -The upstream Defcoin p2pool repository does not use a semantic release tag. Runtime versioning comes from `p2pool.__version__`, which calls `git describe --always --dirty`. On the live server, local changes make the runtime identify as `dc1b4af-dirty` until those changes are committed. - -The committed Turnkit tree is intended to remove that ambiguity: it records the live server changes and lets future builds identify by a real repository commit hash instead of an untracked dirty state. - -### Parent Blockchain Network: `p2pool/bitcoin/networks/defcoin.py` - -This module teaches p2pool how to talk to Defcoin Core / defcoind as the parent blockchain. - -Defcoin-specific behavior from upstream Defcoin fork: - -- `SYMBOL = 'DFC'` -- scrypt proof-of-work through `ltc_scrypt.getPoWHash` -- `BLOCK_PERIOD = 150` -- address version `30` -- P2SH version `50` -- default p2p port `1337` -- default RPC port `1335` -- Defcoin genesis/block-header checks -- Defcoin subsidy and difficulty constants - -Current dc903 additions: - -- Defines `LEGACY_P2P_PREFIX = fbc0b6db`. -- Defines `NEW_P2P_PREFIX = defc014e`. -- Selects preferred outbound p2pool magic through `DEFCOIN_P2POOL_USE_NEW_MAGIC`. -- Accepts both legacy and new prefixes during the transition. -- Updates block/address/transaction explorer links to `https://defcoin.dc903.org/explorer/...`. - -### P2Pool Sharechain Network: `p2pool/networks/defcoin.py` - -This module defines the Defcoin p2pool sharechain rules and public mining endpoints. - -Defcoin-specific behavior from upstream Defcoin fork: - -- parent network is `defcoin` -- p2pool peer port is `1337` -- share period is `45` seconds -- chain length is one day of shares -- Defcoin p2pool identifier and prefix -- SegWit-related share rules -- optional pool tiers for CPU, USB, and ASIC miners - -Current dc903 additions: - -- Enables the ASIC worker port `13372`. -- Uses bootstrap address `135.148.43.189`. -- Points explorer URLs at `defcoin.dc903.org`. - -### P2P Wire Protocol: `p2pool/util/p2protocol.py` - -This is the generic packet framing layer used by p2pool peers. - -Upstream behavior: - -- One network prefix is expected. -- Incoming stream scanning waits for exactly that prefix. -- Replies naturally use that same configured prefix. - -Current dc903 addition: - -- The protocol can accept a tuple/list of prefixes. -- On inbound data, it detects which accepted prefix was actually used by the peer. -- It stores that prefix as the active per-connection `_message_prefix`. -- Replies on that connection are serialized with the same prefix the peer used. - -This is important because accepting both old and new magic is not enough. A legacy peer must receive legacy replies, while a new Defcoin-magic peer must receive new Defcoin-magic replies. - -### Parent Chain P2P: `p2pool/bitcoin/p2p.py` - -This module handles p2pool's direct connection to the parent daemon's p2p interface. The dc903 changes are minimal but support the multi-prefix behavior by passing the parent network prefix configuration into the generic protocol layer. - -### Parent Chain Work RPC: `p2pool/bitcoin/helper.py` - -This module requests parent-chain work from Defcoin Core / defcoind. - -Current dc903 addition: - -- Calls `getblocktemplate` with both `segwit` and `mweb` in the rule list. - -Plain English impact: this does not activate a new consensus rule or hard fork Defcoin. It only acknowledges rule names the modern Defcoin Core Nu daemon may include in `getblocktemplate`, preventing the old P2Pool code from failing against the newer backend. - -### Share Data and Serialization: `p2pool/data.py` - -The Defcoin server remains on the jtoomim-era share formats: - -- current/padding bugfix share: version `35` -- SegWit mining share: version `34` -- new share: version `33` -- pre-SegWit share: version `32` -- legacy share: version `17` - -Current dc903 addition: - -- Documents and patches the legacy donation-script situation. Share version `36` - removes the spendable lost-key donation-address output from newly mined - templates while preserving validation for older shares. - -### Peer Management: `p2pool/p2p.py` - -Current dc903 bug fix: - -- Corrects `forgive_transgressions()` from `self.banscore` to `self.banscores`. - -Plain English impact: the old code referenced the wrong attribute while decaying peer ban scores. The fix makes ban-score forgiveness operate on the actual dictionary used elsewhere in the class. - -### Launcher: `run_p2pool.py` - -Current dc903 operational addition: - -- Adds `/tmp/p2pool.pid` guard. -- Refuses to start a second copy when the pidfile exists. -- Removes the pidfile on normal exit through `finally`. - -Plain English impact: the systemd service is less likely to accidentally run duplicate p2pool workers against the same sharechain and ports. - -### Web UI: `web-static/`, `web-static-orig/`, and `p2pool-ui-punchy/` - -The live server replaces the stock p2pool web files with a customized UI. - -Current dc903 UI changes include: - -- preserving original stock files under `web-static-orig/` -- replacing `web-static/index.html` -- adding Bootstrap/Highcharts-style assets under `web-static/css/`, `web-static/js/`, and `web-static/img/` -- adding `p2pool-ui-punchy/` as a staged UI source/reference directory -- deleting old stock `graphs.html`, `share.html`, and bundled `d3.v2.min.js` from the active web root - -Plain English impact: the p2pool web surface is operator-facing and customized for the Defcoin pool rather than stock P2Pool. - -## Technical Comparison Summary - -| Area | Original/jtoomim P2Pool | hellbyte Defcoin fork | dc903 live branch | -| --- | --- | --- | --- | -| Parent chain | Bitcoin/Litecoin/etc. adapters | Adds Defcoin parent adapter | Updates Defcoin explorer links and magic migration behavior | -| Mining network | General p2pool sharechain networks | Adds Defcoin sharechain constants and pool tiers | Enables ASIC worker port and dc903 bootstrap behavior | -| Wire magic | Single configured prefix | Defcoin legacy prefix `fbc0b6db` | Dual prefix support: `fbc0b6db` and `defc014e` | -| Per-peer reply magic | Not needed with one prefix | Not implemented | Replies with the same prefix the peer used | -| Work RPC | Legacy `getblocktemplate` rules | Legacy `getblocktemplate` rules | Declares `segwit` and `mweb` rules for Defcoin Core Nu compatibility | -| Version identity | Dynamic git hash | `dc1b4af` upstream hash | Previously dirty on server; branch commit documents changes | -| Web UI | Stock P2Pool UI | Some Defcoin README/UI references | Customized active UI with preserved stock backup | -| Runtime guard | Direct run script | Direct run script | pidfile guard against duplicate process starts | - -## What Is Not Changed - -The dc903 p2pool branch does not change Defcoin consensus rules. It does not -change Defcoin block validation, transaction validation, or wallet rules. It -does change P2Pool share-template behavior in version `36` by removing the -legacy donation-address dust output, so cooperating Defcoin P2Pool operators -should update together. - -## Evidence Captured - -Local comparison artifacts were used to prepare this report and are intentionally -not published in the repository. - -Server source path used for comparison: - -- `/home/dfcpool/p2pool-defcoin` diff --git a/docs/TECHNICAL_GUIDE.md b/docs/TECHNICAL_GUIDE.md new file mode 100644 index 0000000..a885522 --- /dev/null +++ b/docs/TECHNICAL_GUIDE.md @@ -0,0 +1,416 @@ +# Defcoin P2Pool Technical Guide + +This guide is the public technical reference for the Defcoin P2Pool Python 3 +fork. It consolidates the previous operational, provenance, Python 3 resource, +and Defcoin-specific change notes into one document. + +## Overview + +P2Pool is decentralized mining-pool software. Instead of trusting one central +pool database to track shares, P2Pool miners cooperate on a separate sharechain. +When the pool finds a Defcoin block, the coinbase transaction pays miners based +on recent valid P2Pool shares. + +This fork keeps that P2Pool model and updates the Defcoin deployment path: + +- Python 3 runtime and dependency auditing. +- Defcoin Core Nu compatibility. +- Dual parent-chain message magic during migration. +- Defcoin User-Agent filtering for legacy-magic parent-chain address gossip. +- Share version `36` to remove the old lost-key P2Pool donation dust output + from new share templates. +- Bounded deterministic caches for repeated conversion work. +- A backend/frontend split so operators can build their own web frontends. + +The recommended Defcoin full-node wallet is +[Defcoin Core Nu](https://github.com/defcoincore/Defcoin-Core-Nu). + +## Repository layout + +The repository is split by responsibility: + +- `backend/` contains the Python P2Pool backend, Defcoin network rules, + Stratum work generation, P2P protocol code, tests, requirements, and helper + scripts. +- `frontend/` contains static web UI assets. The backend mines and serves + miners without depending on a specific frontend design. +- `docs/` contains this guide and public images used by the README. +- `run_p2pool.py` is a compatibility launcher that preserves the historical + root command while loading `backend/run_p2pool.py`. + +The backend serves `frontend/web-static` by default. Operators can supply a +custom frontend with `--web-static /path/to/web-static`. + +## Lineage and provenance + +The live Defcoin pool code was originally derived from the Python 2 P2Pool era. +Its immediate upstream was the old `charlesrocket/p2pool-defcoin` repository, +which GitHub redirects to `hellbyte/p2pool-defcoin`. The code lineage also +matches the `jtoomim/p2pool` generation of P2Pool, based on protocol/share +version markers and module layout. + +Important lineage markers: + +- P2Pool protocol version: `3501`. +- Defcoin share format before this fork: version `35`. +- SegWit share support: version `34`. +- New donation-dust-fixed Defcoin share format: version `36`. + +The goal of this repository is not to ask an archived upstream to accept a pull +request. It is to publish the current Defcoin P2Pool implementation in a clean, +auditable form so other Defcoin pool operators can compare, run, and adapt it. + +## Defcoin-specific network behavior + +Defcoin is configured in two places: + +- `backend/p2pool/bitcoin/networks/defcoin.py` describes the Defcoin parent + chain: scrypt proof of work, address versions, block period, RPC/P2P ports, + genesis markers, and parent-chain P2P message magic. +- `backend/p2pool/networks/defcoin.py` describes the Defcoin P2Pool sharechain: + share period, P2Pool ports, bootstrap peers, worker ports, and P2Pool network + identifiers. + +Common Defcoin operator ports: + +| Purpose | Typical port | +| --- | ---: | +| Defcoin Core P2P | `1337` | +| Defcoin Core RPC | `1335` | +| Defcoin Core Nu backend P2P compatibility port on dc903 | `10332` | +| P2Pool peer network | `1337` | +| Stratum worker port used by the public ASIC pool | `13372` | + +Operators should open only the ports required for their deployment. + +## Dual parent-chain magic + +Defcoin inherited a legacy Litecoin-family parent-chain message header: +`fbc0b6db`. Modern Defcoin wallets can use the Defcoin-specific header +`defc014e`. + +This fork supports a transition model: + +- Outbound parent-chain P2P prefers `defc014e` when + `DEFCOIN_P2POOL_USE_NEW_MAGIC=1` is set. +- Compatibility mode can still accept legacy `fbc0b6db`. +- The first valid header from a peer selects that peer's reply magic. +- Each peer is answered with the same magic it used. + +This is not a Defcoin blockchain hard fork. The magic bytes are a P2P packet +boundary check, not a consensus rule. The purpose is to let modern Defcoin +wallets reduce unrelated Litecoin-family traffic while preserving a migration +path for older Defcoin wallets. + +## User-Agent and address-gossip filtering + +Legacy-magic parent-chain peers can include unrelated Litecoin-family nodes. To +reduce address-table pollution, legacy-magic peers must identify with a +Defcoin-prefixed User-Agent before their gossiped addresses are accepted. + +The documented valid prefix is: + +```text +/Defcoin +``` + +`/DefcoinCore:1.0.0/` is valid because it starts with `/Defcoin`. + +The filtering goal is to drop non-Defcoin legacy peers before their `addr` +messages can seed address tables or be rebroadcast. This avoids poisoning the +small Defcoin network with unrelated peer addresses while still allowing valid +Defcoin peers on nonstandard ports when they identify as Defcoin. + +## Share version 36 donation dust fix + +Old Defcoin P2Pool shares inherited JP's P2Pool developer donation script. In +Defcoin it resolves to: + +```text +DQ8AwqR2XJE9G5dSEfspJYH7Spre85dj6L +``` + +That historical destination is treated as a lost-key address for Defcoin +operations. Earlier P2Pool templates could send tiny rounding outputs there. + +This fork adds `DonationDustFixedShare` as share version `36`: + +- Old shares remain verifiable. +- New version `36` templates remove the spendable legacy donation output. +- A zero-value OP_RETURN padding output preserves the P2Pool coinbase hashlink + shape needed for share validation. +- Spendable remainder that formerly landed in the legacy donation output is + routed back into the normal payout construction. + +Code locations: + +- `backend/p2pool/data.py` defines `DonationDustFixedShare`, + `DUSTFIX_PADDING_SCRIPT`, donation address handling, coinbase payout + construction, and expected payout calculation. +- `backend/p2pool/work.py` stops recording author-donation weight once the + active share type no longer pays the legacy donation output. +- `backend/p2pool/main.py` reports the disabled developer donation output at + startup for operators. + +This is not a Defcoin blockchain hard fork. It is a P2Pool share-template and +share-version change. Operators sharing the same Defcoin P2Pool network should +coordinate the update. On a tiny network, coordinated operators can set: + +```bash +DEFCOIN_P2POOL_DUSTFIX_FLAG_DAY=1 +``` + +so version `36` can follow version `35` immediately instead of waiting for a +normal P2Pool upgrade-vote window. + +## Backend operation + +Run this pool next to a fully synced Defcoin Core or Defcoin Core Nu node. + +Install: + +```bash +python3 -m venv .venv +. .venv/bin/activate +python -m pip install --upgrade pip +python -m pip install -r backend/requirements.txt +python -m pip install -e backend/litecoin_scrypt +``` + +Public node example: + +```bash +DEFCOIN_P2POOL_USE_NEW_MAGIC=1 \ +python run_p2pool.py \ + --net defcoin \ + --allow-obsolete-bitcoind \ + -a YOUR_DEFCOIN_OPERATOR_ADDRESS \ + -n YOUR_PUBLIC_IP \ + --bitcoind-address 127.0.0.1 \ + --bitcoind-p2p-port 10332 \ + --fee 1.5 +``` + +`-a` sets the operator/default payout address. `--fee` sets the public worker +fee, applied by occasionally assigning worker shares to the operator address +instead of the miner-submitted username address. This fee is separate from the +legacy P2Pool developer donation script fixed by share version `36`. + +UPnP is disabled by default in this Defcoin fork. Use `--enable-upnp` only for +consumer NAT deployments where automatic router port mapping is intentionally +wanted. Hosted pool servers should keep UPnP disabled and manage exposed ports +explicitly with the host firewall and reverse proxy. + +Historical upstream crash reports are disabled by default. Operators who +explicitly want to send caught exception traces to the old upstream p2pool +error endpoint can opt in with `--enable-bugreport`. Public pool deployments +should normally leave this disabled so operational details stay on the host. + +The fee can be checked from the API: + +```bash +curl http://127.0.0.1:13372/fee +``` + +Mining endpoint example: + +```text +stratum+tcp://YOUR_POOL_HOST:13372 +``` + +Use the miner payout address as the Stratum username and any password. + +## Frontend operation + +The backend defaults to: + +```text +frontend/web-static +``` + +Custom frontend example: + +```bash +python run_p2pool.py --net defcoin --web-static /path/to/custom/web-static ... +``` + +The active frontend calls the backend HTTP endpoints for pool status, payouts, +hashrate, graph data, and peer information. Frontend authors can treat those +endpoints as the integration boundary and replace the static UI without changing +mining logic. + +## Performance caches + +This fork adds bounded `functools.lru_cache` usage only where the function is +deterministic and repeatedly called with the same values: + +- `target_to_average_attempts` +- `average_attempts_to_target` +- `target_to_difficulty` +- `difficulty_to_target` +- `pubkey_hash_to_address` +- `address_to_script2` +- `address_to_pubkey_hash` +- `donation_script_to_address` + +The caches are intentionally small and avoid peer state, sharechain mutation, +timestamps, random choices, and any value whose correctness depends on current +network state. + +Local benchmark command: + +```bash +python backend/dev/cache_benchmark.py +``` + +Current repeated-calculation benchmark results: + +| Function | Uncached | Cached | Speedup | +| --- | ---: | ---: | ---: | +| `target_to_average_attempts` | 0.075015s | 0.017260s | 4.35x | +| `target_to_difficulty` | 0.078973s | 0.014797s | 5.34x | +| `difficulty_to_target` | 0.091125s | 0.016866s | 5.40x | +| `pubkey_hash_to_address` | 0.717119s | 0.011649s | 61.56x | +| `address_to_script2` | 0.084987s | 0.010155s | 8.37x | +| `donation_script_to_address` | 0.005286s | 0.000376s | 14.05x | + +The dispatcher that guesses a script type is deliberately not cached. It is +pure in normal operation, but tests and review tools commonly monkey-patch the +specific parser helpers; caching only the lower-level deterministic conversions +keeps the optimization useful without hiding those correctness checks. + +## Python 3 migration and resource comparison + +The live dc903 service was sampled with the saved Python 2 service and this +Python 3 port on 2026-05-25. + +| Runtime | Samples | Avg CPU | CPU range | Avg RSS | Avg cgroup memory | +| --- | ---: | ---: | ---: | ---: | ---: | +| Python 2 | 30 | 8.96% | 4.00% to 31.40% | 230,129 KB | 236,736 KB | +| Python 3 | 30 | 9.30% | 3.90% to 33.40% | 202,083 KB | 188,193 KB | + +CPU was effectively similar within the quality of this measurement. Python 3 +used less memory in this sample and is materially safer to maintain because +Python 2.7 is end-of-life. + +The Python 3 port keeps the existing Defcoin P2Pool sharechain behavior while +allowing current dependency audits, linting, and security hardening. + +## Dependency and security policy + +Runtime dependency files live under `backend/`: + +- `backend/requirements.txt` +- `backend/conf/requirements-testing.txt` +- `backend/conf/requirements-development.txt` + +Audit commands: + +```bash +pip-audit -r backend/requirements.txt +pip-audit -r backend/conf/requirements-testing.txt +pip-audit -r backend/conf/requirements-development.txt +npx --yes retire --path frontend/web-static --outputformat text +bandit --severity-level medium -r backend/p2pool backend/run_p2pool.py run_p2pool.py -x backend/p2pool/test +``` + +The current quality environment reported no known vulnerabilities for runtime, +test, or development Python requirements, and no vulnerable bundled web assets +after the frontend dependency refresh. Bandit reported no medium or high +findings in runtime code. Package updates should remain conservative: P2Pool +consensus and share validation code should favor stable, tested dependencies +over unnecessary churn. + +Vendored compatibility packages such as `SOAPpy` and `wstools` are legacy code +kept for compatibility with optional NAT traversal and historical P2Pool code. +UPnP is opt-in, XML parsing paths use `defusedxml`, and remote WSDL loading is +scheme-restricted. Linting is therefore focused on fatal Python errors, porting +risks, security-sensitive patterns, and changed code rather than blindly +restyling old vendored modules. + +The repository includes a GitHub Actions CI workflow that runs the compile +check, fatal-error Ruff gate, selected Twisted tests, `pip-audit`, Bandit +medium/high checks, and a Retire.js audit for bundled static frontend assets. + +## Tests and quality gates + +Recommended local checks: + +```bash +python backend/dev/python3_port_compile_check.py +ruff check --select E9,F63,F7,F82 backend/p2pool backend/run_p2pool.py run_p2pool.py +cd backend && python -m twisted.trial p2pool.test.test_data p2pool.test.test_node p2pool.test.bitcoin.test_data +cd .. +python backend/dev/cache_benchmark.py +git diff --check +``` + +Use live deployment testing carefully. The Defcoin P2Pool network can be very +small, so a pool operator should confirm that Stratum miners reconnect, shares +are accepted, the web API responds, and the parent-chain node stays synced +after changes. + +## Operational hardening checklist + +A public Defcoin P2Pool server should use explicit operating-system boundaries +instead of relying on the Python process to protect itself: + +- Run P2Pool under an unprivileged service account. +- Keep Defcoin RPC bound to loopback only. +- Expose only required public ports: web, Defcoin parent-chain P2P, P2Pool peer + P2P, and Stratum. +- Use a default-drop firewall policy. +- Put public HTTP endpoints behind nginx or another reverse proxy with security + headers, CSP, request limits for API paths, and ordinary TLS renewal. +- Run P2Pool with UPnP disabled on hosted servers. +- Disable upstream bug reporting unless the operator intentionally opts in. +- Cap journal and application log growth so bad peers cannot fill the disk. +- Monitor service state, web/API health, open ports, disk pressure, memory + pressure, certificate expiry, and Defcoin RPC block count. +- Keep local backups and restoration notes. Restore tests are valuable, but + should be done deliberately with the operator present because this stack is a + live mining service. + +The dc903 deployment uses a small systemd timer named +`defcoin-ops-health-check.timer` for non-invasive checks. It writes compact +status lines to journald and does not restart services automatically. + +## P2Pool peer handshake logging + +The P2Pool peer network is separate from the Defcoin Core parent-chain peer +network. On a tiny sharechain, valid peers are valuable, so this fork avoids +over-aggressive duplicate-host rejection. + +Policy: + +- Accept sockets long enough to read the P2Pool `version` message and peer + nonce. +- Do not reject a peer only because another connection from the same IP address + exists. +- Keep established-peer log lines because they record the live peer set. +- Log invalid handshakes such as too-old protocol versions, repeated version + messages, and self-connections. +- For duplicate peer nonces, disconnect the duplicate after identification and + rate-limit the log message by host. + +This preserves useful abnormal-event logging without filling logs with ordinary +duplicate-connection churn. + +## License and attribution + +This repository follows the inherited P2Pool license: GNU General Public +License version 3. See `COPYING`. + +Bundled third-party or vendored code remains under its inherited terms as +provided by the upstream P2Pool tree and its dependencies. Operators who +redistribute modified binaries or services should review GPLv3 obligations and +provide corresponding source. + +## AI-assisted development note + +This Defcoin P2Pool port and documentation cleanup were developed with AI +assistance for source migration, documentation consolidation, code review, +testing guidance, benchmark scripting, and repetitive polish work, specifically +OpenAI Codex using GPT-5.5 Extra High reasoning settings. Human review, +live-service verification, reproducible tests, and open-source auditability +remain required. diff --git a/docs/assets/defcoin-p2pool-hero.svg b/docs/assets/defcoin-p2pool-hero.svg new file mode 100644 index 0000000..4f83ae9 --- /dev/null +++ b/docs/assets/defcoin-p2pool-hero.svg @@ -0,0 +1,39 @@ + + Defcoin P2Pool + A dark Defcoin P2Pool banner with a gold coin mark, peer graph lines, and the words decentralized mining infrastructure. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defcoin P2Pool + decentralized mining infrastructure for Defcoin + Python 3 port • dual magic support • v36 donation dust fix • separable backend and frontend + + diff --git a/docs/assets/network-peers.png b/docs/assets/network-peers.png new file mode 100644 index 0000000..7fcef0d Binary files /dev/null and b/docs/assets/network-peers.png differ diff --git a/docs/assets/pool-overview.png b/docs/assets/pool-overview.png new file mode 100644 index 0000000..2479a49 Binary files /dev/null and b/docs/assets/pool-overview.png differ diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..1e6806b --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,18 @@ +# Defcoin P2Pool Frontend + +This directory contains web assets served by the backend. + +- `web-static/` is the active bundled UI. +- `web-static-orig/` preserves the stock P2Pool UI for reference. +- `p2pool-ui-punchy/` is retained as a reference/staging source for alternate + UI work. + +The backend can serve a completely different static frontend: + +```bash +python run_p2pool.py --net defcoin --web-static /path/to/custom/web-static ... +``` + +A custom frontend should treat the backend HTTP/API endpoints as the contract. +The bundled UI is useful as a working example, but it is not required for the +pool backend to mine shares or serve Stratum miners. diff --git a/p2pool-ui-punchy/.editorconfig b/frontend/p2pool-ui-punchy/.editorconfig similarity index 100% rename from p2pool-ui-punchy/.editorconfig rename to frontend/p2pool-ui-punchy/.editorconfig diff --git a/p2pool-ui-punchy/.gitignore b/frontend/p2pool-ui-punchy/.gitignore similarity index 100% rename from p2pool-ui-punchy/.gitignore rename to frontend/p2pool-ui-punchy/.gitignore diff --git a/web-static-orig/d3.v2.min.js b/frontend/web-static-orig/d3.v2.min.js similarity index 100% rename from web-static-orig/d3.v2.min.js rename to frontend/web-static-orig/d3.v2.min.js diff --git a/web-static-orig/favicon.ico b/frontend/web-static-orig/favicon.ico similarity index 100% rename from web-static-orig/favicon.ico rename to frontend/web-static-orig/favicon.ico diff --git a/web-static-orig/graphs.html b/frontend/web-static-orig/graphs.html similarity index 100% rename from web-static-orig/graphs.html rename to frontend/web-static-orig/graphs.html diff --git a/web-static-orig/index.html b/frontend/web-static-orig/index.html similarity index 100% rename from web-static-orig/index.html rename to frontend/web-static-orig/index.html diff --git a/web-static-orig/share.html b/frontend/web-static-orig/share.html similarity index 100% rename from web-static-orig/share.html rename to frontend/web-static-orig/share.html diff --git a/web-static/css/bootstrap-amelia.min.css b/frontend/web-static/css/bootstrap-amelia.min.css similarity index 100% rename from web-static/css/bootstrap-amelia.min.css rename to frontend/web-static/css/bootstrap-amelia.min.css diff --git a/web-static/css/bootstrap-cerulean.min.css b/frontend/web-static/css/bootstrap-cerulean.min.css similarity index 100% rename from web-static/css/bootstrap-cerulean.min.css rename to frontend/web-static/css/bootstrap-cerulean.min.css diff --git a/web-static/css/bootstrap-cosmo.min.css b/frontend/web-static/css/bootstrap-cosmo.min.css similarity index 100% rename from web-static/css/bootstrap-cosmo.min.css rename to frontend/web-static/css/bootstrap-cosmo.min.css diff --git a/web-static/css/bootstrap-cyborg.min.css b/frontend/web-static/css/bootstrap-cyborg.min.css similarity index 100% rename from web-static/css/bootstrap-cyborg.min.css rename to frontend/web-static/css/bootstrap-cyborg.min.css diff --git a/web-static/css/bootstrap-darkly.min.css b/frontend/web-static/css/bootstrap-darkly.min.css similarity index 100% rename from web-static/css/bootstrap-darkly.min.css rename to frontend/web-static/css/bootstrap-darkly.min.css diff --git a/web-static/css/bootstrap-default.min.css b/frontend/web-static/css/bootstrap-default.min.css similarity index 100% rename from web-static/css/bootstrap-default.min.css rename to frontend/web-static/css/bootstrap-default.min.css diff --git a/web-static/css/bootstrap-flatly.min.css b/frontend/web-static/css/bootstrap-flatly.min.css similarity index 100% rename from web-static/css/bootstrap-flatly.min.css rename to frontend/web-static/css/bootstrap-flatly.min.css diff --git a/web-static/css/bootstrap-journal.min.css b/frontend/web-static/css/bootstrap-journal.min.css similarity index 100% rename from web-static/css/bootstrap-journal.min.css rename to frontend/web-static/css/bootstrap-journal.min.css diff --git a/web-static/css/bootstrap-lumen.min.css b/frontend/web-static/css/bootstrap-lumen.min.css similarity index 100% rename from web-static/css/bootstrap-lumen.min.css rename to frontend/web-static/css/bootstrap-lumen.min.css diff --git a/web-static/css/bootstrap-readable.min.css b/frontend/web-static/css/bootstrap-readable.min.css similarity index 100% rename from web-static/css/bootstrap-readable.min.css rename to frontend/web-static/css/bootstrap-readable.min.css diff --git a/web-static/css/bootstrap-simplex.min.css b/frontend/web-static/css/bootstrap-simplex.min.css similarity index 100% rename from web-static/css/bootstrap-simplex.min.css rename to frontend/web-static/css/bootstrap-simplex.min.css diff --git a/web-static/css/bootstrap-slate.min.css b/frontend/web-static/css/bootstrap-slate.min.css similarity index 100% rename from web-static/css/bootstrap-slate.min.css rename to frontend/web-static/css/bootstrap-slate.min.css diff --git a/web-static/css/bootstrap-sortable.css b/frontend/web-static/css/bootstrap-sortable.css similarity index 100% rename from web-static/css/bootstrap-sortable.css rename to frontend/web-static/css/bootstrap-sortable.css diff --git a/web-static/css/bootstrap-spacelab.min.css b/frontend/web-static/css/bootstrap-spacelab.min.css similarity index 100% rename from web-static/css/bootstrap-spacelab.min.css rename to frontend/web-static/css/bootstrap-spacelab.min.css diff --git a/web-static/css/bootstrap-superhero.min.css b/frontend/web-static/css/bootstrap-superhero.min.css similarity index 100% rename from web-static/css/bootstrap-superhero.min.css rename to frontend/web-static/css/bootstrap-superhero.min.css diff --git a/web-static/css/bootstrap-united.min.css b/frontend/web-static/css/bootstrap-united.min.css similarity index 100% rename from web-static/css/bootstrap-united.min.css rename to frontend/web-static/css/bootstrap-united.min.css diff --git a/web-static/css/bootstrap-yeti.min.css b/frontend/web-static/css/bootstrap-yeti.min.css similarity index 100% rename from web-static/css/bootstrap-yeti.min.css rename to frontend/web-static/css/bootstrap-yeti.min.css diff --git a/web-static/css/p2pool.css b/frontend/web-static/css/p2pool.css similarity index 100% rename from web-static/css/p2pool.css rename to frontend/web-static/css/p2pool.css diff --git a/web-static/favicon.ico b/frontend/web-static/favicon.ico similarity index 100% rename from web-static/favicon.ico rename to frontend/web-static/favicon.ico diff --git a/web-static/img/screenshot-graph.png b/frontend/web-static/img/screenshot-graph.png similarity index 100% rename from web-static/img/screenshot-graph.png rename to frontend/web-static/img/screenshot-graph.png diff --git a/web-static/img/screenshot_extended_p2pool.png b/frontend/web-static/img/screenshot_extended_p2pool.png similarity index 100% rename from web-static/img/screenshot_extended_p2pool.png rename to frontend/web-static/img/screenshot_extended_p2pool.png diff --git a/web-static/img/screenshot_stock_p2pool.png b/frontend/web-static/img/screenshot_stock_p2pool.png similarity index 100% rename from web-static/img/screenshot_stock_p2pool.png rename to frontend/web-static/img/screenshot_stock_p2pool.png diff --git a/web-static/index.html b/frontend/web-static/index.html similarity index 95% rename from web-static/index.html rename to frontend/web-static/index.html index 521da8b..f1f0bb5 100644 --- a/web-static/index.html +++ b/frontend/web-static/index.html @@ -10,8 +10,8 @@ DC903 - node stats - - + + @@ -217,7 +217,7 @@