Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderPavlenko committed Dec 2, 2024
2 parents 0ea391f + 9258910 commit 866363e
Show file tree
Hide file tree
Showing 18 changed files with 375 additions and 323 deletions.
6 changes: 3 additions & 3 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ unittests_task:
- pip install pytest-cov
- pip install coveralls
- pip install Sphinx
# deps for e-x itself
- pip install -r requirements.txt
- pip install "python-rocksdb>=0.6.9"
# e-x itself
- pip install 'Cython<3.0' # for rocksdb
- pip install ".[rocksdb]"
# hashes and other altcoin-specific stuff
- pip install tribushashm
- pip install blake256
Expand Down
2 changes: 1 addition & 1 deletion contrib/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# example of Dockerfile that installs spesmilo electrumx 1.16.0
# ENV variables can be overriden on the `docker run` command
# ENV variables can be overridden on the `docker run` command

FROM python:3.9.16-bullseye AS builder

Expand Down
2 changes: 0 additions & 2 deletions docs/HOWTO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Python3 ElectrumX uses asyncio. Python version >= 3.8 is
**required**.
`aiohttp`_ Python library for asynchronous HTTP. Version >=
2.0 required.
`pylru`_ Python LRU cache package.
DB Engine A database engine package is required; two are
supported (see `Database Engine`_ below).
================ ========================
Expand Down Expand Up @@ -443,7 +442,6 @@ You can then set the port as follows and advertise the service externally on the
.. _`daemontools`: http://cr.yp.to/daemontools.html
.. _`runit`: http://smarden.org/runit/index.html
.. _`aiohttp`: https://pypi.python.org/pypi/aiohttp
.. _`pylru`: https://pypi.python.org/pypi/pylru
.. _`dash_hash`: https://pypi.python.org/pypi/dash_hash
.. _`contrib/raspberrypi3/install_electrumx.sh`: https://github.com/spesmilo/electrumx/blob/master/contrib/raspberrypi3/install_electrumx.sh
.. _`contrib/raspberrypi3/run_electrumx.sh`: https://github.com/spesmilo/electrumx/blob/master/contrib/raspberrypi3/run_electrumx.sh
32 changes: 27 additions & 5 deletions electrumx/lib/coins.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ def interpret_name_prefix(cls, script, possible_ops):
# Script structure: https://git.io/fjuRu
added, template = cls._add_data_placeholders_to_template(ops[i:], template)
offset += added - 1 # subtract the "DATA_PUSH_MULTIPLE" opcode
elif type(op) == str:
elif isinstance(op, str):
template.append(-1)
named_index[op] = i + offset
else:
Expand Down Expand Up @@ -439,7 +439,7 @@ def _read_data_placeholders_count(cls, opcodes):
data_placeholders = 0

for opcode in opcodes:
if type(opcode) == tuple:
if isinstance(opcode, tuple):
data_placeholders += 1
else:
break
Expand Down Expand Up @@ -971,6 +971,23 @@ class BitcoinSegwitSignet(BitcoinSignet):
NAME = "BitcoinSegwit" # support legacy name


class BitcoinTestnet4(BitcoinTestnet):
NAME = "Bitcoin"
NET = "testnet4"
GENESIS_HASH = ('00000000da84f2bafbbc53dee25a72ae'
'507ff4914b867c565be350b0da8bf043')
PEERS = [
'blackie.c3-soft.com s57010 t57009',
'testnet4-electrumx.wakiyamap.dev',
]
TX_COUNT = 1
TX_COUNT_HEIGHT = 1


class BitcoinSegwitTestnet4(BitcoinTestnet4):
NAME = "BitcoinSegwit" # support legacy name


class BitcoinNolnet(BitcoinCash):
'''Bitcoin Unlimited nolimit testnet.'''
NET = "nolnet"
Expand Down Expand Up @@ -1200,14 +1217,19 @@ class Namecoin(NameIndexAuxPoWMixin, Coin):
TX_PER_BLOCK = 10
RPC_PORT = 8336
PEERS = [
'188.167.144.126 s50002',
'198.50.223.25 s50002',
'46.229.238.187 s57002',
'82.119.233.36 s50002',
'198.50.223.27 s50002',
'electrum-nmc.le-space.de s50002',
'ex.lug.gs s446',
'electrumx2.nmc.dotbit.zone s50002',
'electrumx4.nmc.dotbit.zone s50002',
'nmc.bitcoins.sk s50002',
'nmc2.bitcoins.sk s57002',
'ulrichard.ch s50006 t50005',
'h6qrnwxtwiaahsw4qhk2nbutswwb54vnqso6jrxeuk6nwtfbos7jkoqd.onion s50002',
'mqhok2edqcxdpklwovquuvvl2q5or4g2o777qwrinydgzfxjbixq76yd.onion s50002',
'wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion s50002',
'quuzpffsddq3aim3gk4oiczzyt5okjjzf4zpe6okzo6qidao6rshynqd.onion s50002',
]
BLOCK_PROCESSOR = block_proc.NameIndexBlockProcessor
NAME_EXPIRATION = 36_000
Expand Down
181 changes: 181 additions & 0 deletions electrumx/lib/lrucache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# The MIT License (MIT)
#
# Copyright (c) 2014-2022 Thomas Kemmer
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# -----
#
# This is a stripped down LRU-cache from the "cachetools" library.
# https://github.com/tkem/cachetools/blob/d991ac71b4eb6394be5ec572b835434081393215/src/cachetools/__init__.py

import collections
import collections.abc


class _DefaultSize:

__slots__ = ()

def __getitem__(self, _):
return 1

def __setitem__(self, _, value):
assert value == 1

def pop(self, _):
return 1


class Cache(collections.abc.MutableMapping):
"""Mutable mapping to serve as a simple cache or cache base class."""

__marker = object()

__size = _DefaultSize()

def __init__(self, maxsize, getsizeof=None):
if getsizeof:
self.getsizeof = getsizeof
if self.getsizeof is not Cache.getsizeof:
self.__size = dict()
self.__data = dict()
self.__currsize = 0
self.__maxsize = maxsize

def __repr__(self):
return "%s(%s, maxsize=%r, currsize=%r)" % (
self.__class__.__name__,
repr(self.__data),
self.__maxsize,
self.__currsize,
)

def __getitem__(self, key):
try:
return self.__data[key]
except KeyError:
return self.__missing__(key)

def __setitem__(self, key, value):
maxsize = self.__maxsize
size = self.getsizeof(value)
if size > maxsize:
raise ValueError("value too large")
if key not in self.__data or self.__size[key] < size:
while self.__currsize + size > maxsize:
self.popitem()
if key in self.__data:
diffsize = size - self.__size[key]
else:
diffsize = size
self.__data[key] = value
self.__size[key] = size
self.__currsize += diffsize

def __delitem__(self, key):
size = self.__size.pop(key)
del self.__data[key]
self.__currsize -= size

def __contains__(self, key):
return key in self.__data

def __missing__(self, key):
raise KeyError(key)

def __iter__(self):
return iter(self.__data)

def __len__(self):
return len(self.__data)

def get(self, key, default=None):
if key in self:
return self[key]
else:
return default

def pop(self, key, default=__marker):
if key in self:
value = self[key]
del self[key]
elif default is self.__marker:
raise KeyError(key)
else:
value = default
return value

def setdefault(self, key, default=None):
if key in self:
value = self[key]
else:
self[key] = value = default
return value

@property
def maxsize(self):
"""The maximum size of the cache."""
return self.__maxsize

@property
def currsize(self):
"""The current size of the cache."""
return self.__currsize

@staticmethod
def getsizeof(value):
"""Return the size of a cache element's value."""
return 1


class LRUCache(Cache):
"""Least Recently Used (LRU) cache implementation."""

def __init__(self, maxsize, getsizeof=None):
Cache.__init__(self, maxsize, getsizeof)
self.__order = collections.OrderedDict()

def __getitem__(self, key, cache_getitem=Cache.__getitem__):
value = cache_getitem(self, key)
if key in self: # __missing__ may not store item
self.__update(key)
return value

def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
cache_setitem(self, key, value)
self.__update(key)

def __delitem__(self, key, cache_delitem=Cache.__delitem__):
cache_delitem(self, key)
del self.__order[key]

def popitem(self):
"""Remove and return the `(key, value)` pair least recently used."""
try:
key = next(iter(self.__order))
except StopIteration:
raise KeyError("%s is empty" % type(self).__name__) from None
else:
return (key, self.pop(key))

def __update(self, key):
try:
self.__order.move_to_end(key)
except KeyError:
self.__order[key] = None
20 changes: 13 additions & 7 deletions electrumx/lib/tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,12 @@ def _read_tx_parts(self):
orig_ser += self.binary[start:self.cursor]
vsize = (3 * base_size + self.binary_length) // 4

return TxTimeSegWit(
version, time, marker, flag, inputs, outputs, witness, locktime),\
self.TX_HASH_FN(orig_ser), vsize
return (
TxTimeSegWit(
version, time, marker, flag, inputs, outputs, witness, locktime),
self.TX_HASH_FN(orig_ser),
vsize,
)

def read_tx(self):
return self._read_tx_parts()[0]
Expand Down Expand Up @@ -734,9 +737,12 @@ def _read_tx_parts(self):
vsize = (3 * base_size + self.binary_length) // 4
orig_ser += self.binary[start:self.cursor]

return TxTimeSegWit(
version, time, marker, flag, inputs, outputs, witness, locktime),\
self.TX_HASH_FN(orig_ser), vsize
return (
TxTimeSegWit(
version, time, marker, flag, inputs, outputs, witness, locktime),
self.TX_HASH_FN(orig_ser),
vsize,
)

def read_tx(self):
return self._read_tx_parts()[0]
Expand Down Expand Up @@ -925,7 +931,7 @@ def _is_anon_input(self):
self.script[1] == self.OP_ANON_MARKER)

def is_generation(self):
# Transactions comming in from stealth addresses are seen by
# Transactions coming in from stealth addresses are seen by
# the blockchain as newly minted coins. The reverse, where coins
# are sent TO a stealth address, are seen by the blockchain as
# a coin burn.
Expand Down
Loading

0 comments on commit 866363e

Please sign in to comment.