Read default server list from file. Update list with 1.1 servers. Remove nolnet option.
This commit is contained in:
parent
dd2b7e4d89
commit
8c5b6bdaf3
5
electrum
5
electrum
|
@ -355,11 +355,6 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
if config.get('testnet'):
|
if config.get('testnet'):
|
||||||
bitcoin.set_testnet()
|
bitcoin.set_testnet()
|
||||||
network.set_testnet()
|
|
||||||
|
|
||||||
if config.get('nolnet'):
|
|
||||||
bitcoin.set_nolnet()
|
|
||||||
network.set_nolnet()
|
|
||||||
|
|
||||||
# run non-RPC commands separately
|
# run non-RPC commands separately
|
||||||
if cmdname in ['create', 'restore']:
|
if cmdname in ['create', 'restore']:
|
||||||
|
|
|
@ -28,6 +28,7 @@ import base64
|
||||||
import re
|
import re
|
||||||
import hmac
|
import hmac
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
import ecdsa
|
import ecdsa
|
||||||
import pyaes
|
import pyaes
|
||||||
|
@ -37,6 +38,14 @@ from . import version
|
||||||
from .util import print_error, InvalidPassword, assert_bytes, to_bytes
|
from .util import print_error, InvalidPassword, assert_bytes, to_bytes
|
||||||
from . import segwit_addr
|
from . import segwit_addr
|
||||||
|
|
||||||
|
def read_json_dict(filename):
|
||||||
|
path = os.path.join(os.path.dirname(__file__), filename)
|
||||||
|
try:
|
||||||
|
r = json.loads(open(path, 'r').read())
|
||||||
|
except:
|
||||||
|
r = {}
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
# Bitcoin network constants
|
# Bitcoin network constants
|
||||||
TESTNET = False
|
TESTNET = False
|
||||||
|
@ -48,6 +57,9 @@ XPRV_HEADER = 0x0488ade4
|
||||||
XPUB_HEADER = 0x0488b21e
|
XPUB_HEADER = 0x0488b21e
|
||||||
HEADERS_URL = "https://headers.electrum.org/blockchain_headers"
|
HEADERS_URL = "https://headers.electrum.org/blockchain_headers"
|
||||||
GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||||
|
SERVERLIST = 'servers.json'
|
||||||
|
DEFAULT_PORTS = {'t':'50001', 's':'50002'}
|
||||||
|
DEFAULT_SERVERS = read_json_dict('servers.json')
|
||||||
|
|
||||||
def set_testnet():
|
def set_testnet():
|
||||||
global ADDRTYPE_P2PKH, ADDRTYPE_P2SH
|
global ADDRTYPE_P2PKH, ADDRTYPE_P2SH
|
||||||
|
@ -55,6 +67,7 @@ def set_testnet():
|
||||||
global TESTNET, HEADERS_URL
|
global TESTNET, HEADERS_URL
|
||||||
global GENESIS
|
global GENESIS
|
||||||
global SEGWIT_HRP
|
global SEGWIT_HRP
|
||||||
|
global DEFAULT_PORTS, SERVERLIST
|
||||||
TESTNET = True
|
TESTNET = True
|
||||||
ADDRTYPE_P2PKH = 111
|
ADDRTYPE_P2PKH = 111
|
||||||
ADDRTYPE_P2SH = 196
|
ADDRTYPE_P2SH = 196
|
||||||
|
@ -63,20 +76,9 @@ def set_testnet():
|
||||||
XPUB_HEADER = 0x043587cf
|
XPUB_HEADER = 0x043587cf
|
||||||
HEADERS_URL = "https://headers.electrum.org/testnet_headers"
|
HEADERS_URL = "https://headers.electrum.org/testnet_headers"
|
||||||
GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||||
|
SERVERLIST = 'servers_testnet.json'
|
||||||
def set_nolnet():
|
DEFAULT_PORTS = {'t':'51001', 's':'51002'}
|
||||||
global ADDRTYPE_P2PKH, ADDRTYPE_P2SH
|
DEFAULT_SERVERS = read_json_dict('servers_testnet.json')
|
||||||
global XPRV_HEADER, XPUB_HEADER
|
|
||||||
global NOLNET, HEADERS_URL
|
|
||||||
global GENESIS
|
|
||||||
TESTNET = True
|
|
||||||
ADDRTYPE_P2PKH = 0
|
|
||||||
ADDRTYPE_P2SH = 5
|
|
||||||
XPRV_HEADER = 0x0488ade4
|
|
||||||
XPUB_HEADER = 0x0488b21e
|
|
||||||
HEADERS_URL = "https://headers.electrum.org/nolnet_headers"
|
|
||||||
GENESIS = "663c88be18d07c45f87f910b93a1a71ed9ef1946cad50eb6a6f3af4c424625c6"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
################################## transactions
|
################################## transactions
|
||||||
|
|
|
@ -826,7 +826,6 @@ def add_global_options(parser):
|
||||||
group.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
|
group.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
|
||||||
group.add_argument("--testnet", action="store_true", dest="testnet", default=False, help="Use Testnet")
|
group.add_argument("--testnet", action="store_true", dest="testnet", default=False, help="Use Testnet")
|
||||||
group.add_argument("--segwit", action="store_true", dest="segwit", default=False, help="The Wizard will create Segwit seed phrases (Testnet only).")
|
group.add_argument("--segwit", action="store_true", dest="segwit", default=False, help="The Wizard will create Segwit seed phrases (Testnet only).")
|
||||||
group.add_argument("--nolnet", action="store_true", dest="nolnet", default=False, help="Use Nolnet")
|
|
||||||
|
|
||||||
def get_parser():
|
def get_parser():
|
||||||
# create main parser
|
# create main parser
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
# Electrum - Lightweight Bitcoin Client
|
# Electrum - Lightweight Bitcoin Client
|
||||||
# Copyright (c) 2011-2016 Thomas Voegtlin
|
# Copyright (c) 2011-2016 Thomas Voegtlin
|
||||||
#
|
#
|
||||||
|
@ -35,7 +36,6 @@ import select
|
||||||
import traceback
|
import traceback
|
||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -47,54 +47,6 @@ from .interface import Connection, Interface
|
||||||
from . import blockchain
|
from . import blockchain
|
||||||
from .version import ELECTRUM_VERSION, PROTOCOL_VERSION
|
from .version import ELECTRUM_VERSION, PROTOCOL_VERSION
|
||||||
|
|
||||||
DEFAULT_PORTS = {'t':'50001', 's':'50002'}
|
|
||||||
|
|
||||||
#There is a schedule to move the default list to e-x (electrumx) by Jan 2018
|
|
||||||
#Schedule is as follows:
|
|
||||||
#move ~3/4 to e-x by 1.4.17
|
|
||||||
#then gradually switch remaining nodes to e-x nodes
|
|
||||||
|
|
||||||
DEFAULT_SERVERS = {
|
|
||||||
'erbium1.sytes.net':DEFAULT_PORTS, # core, e-x
|
|
||||||
'ecdsa.net':{'t':'50001', 's':'110'}, # core, e-x
|
|
||||||
'gh05.geekhosters.com':DEFAULT_PORTS, # core, e-s
|
|
||||||
'VPS.hsmiths.com':DEFAULT_PORTS, # core, e-x
|
|
||||||
'electrum.anduck.net':DEFAULT_PORTS, # core, e-s; banner with version pending
|
|
||||||
'electrum.no-ip.org':DEFAULT_PORTS, # core, e-s
|
|
||||||
'electrum.be':DEFAULT_PORTS, # core, e-x
|
|
||||||
'helicarrier.bauerj.eu':DEFAULT_PORTS, # core, e-x
|
|
||||||
'elex01.blackpole.online':DEFAULT_PORTS, # core, e-x
|
|
||||||
'electrumx.not.fyi':DEFAULT_PORTS, # core, e-x
|
|
||||||
'node.xbt.eu':DEFAULT_PORTS, # core, e-x
|
|
||||||
'kirsche.emzy.de':DEFAULT_PORTS, # core, e-x
|
|
||||||
'electrum.villocq.com':DEFAULT_PORTS, # core?, e-s; banner with version recommended
|
|
||||||
'us11.einfachmalnettsein.de':DEFAULT_PORTS, # core, e-x
|
|
||||||
'electrum.trouth.net':DEFAULT_PORTS, # BU, e-s
|
|
||||||
'Electrum.hsmiths.com':{'t':'8080', 's':'995'}, # core, e-x
|
|
||||||
'electrum3.hachre.de':DEFAULT_PORTS, # core, e-x
|
|
||||||
'b.1209k.com':DEFAULT_PORTS, # XT, jelectrum
|
|
||||||
'elec.luggs.co':{ 's':'443'}, # core, e-x
|
|
||||||
'btc.smsys.me':{'t':'110', 's':'995'}, # BU, e-x
|
|
||||||
}
|
|
||||||
|
|
||||||
def set_testnet():
|
|
||||||
global DEFAULT_PORTS, DEFAULT_SERVERS
|
|
||||||
DEFAULT_PORTS = {'t':'51001', 's':'51002'}
|
|
||||||
DEFAULT_SERVERS = {
|
|
||||||
'testnetnode.arihanc.com': DEFAULT_PORTS,
|
|
||||||
'testnet1.bauerj.eu': DEFAULT_PORTS,
|
|
||||||
'14.3.140.101': DEFAULT_PORTS,
|
|
||||||
'testnet.hsmiths.com': {'t':'53011', 's':'53012'},
|
|
||||||
'electrum.akinbo.org': DEFAULT_PORTS,
|
|
||||||
'ELEX05.blackpole.online': {'t':'52011', 's':'52002'},
|
|
||||||
}
|
|
||||||
|
|
||||||
def set_nolnet():
|
|
||||||
global DEFAULT_PORTS, DEFAULT_SERVERS
|
|
||||||
DEFAULT_PORTS = {'t':'52001', 's':'52002'}
|
|
||||||
DEFAULT_SERVERS = {
|
|
||||||
'14.3.140.101': DEFAULT_PORTS,
|
|
||||||
}
|
|
||||||
|
|
||||||
NODES_RETRY_INTERVAL = 60
|
NODES_RETRY_INTERVAL = 60
|
||||||
SERVER_RETRY_INTERVAL = 10
|
SERVER_RETRY_INTERVAL = 10
|
||||||
|
@ -401,11 +353,10 @@ class Network(util.DaemonThread):
|
||||||
return list(self.interfaces.keys())
|
return list(self.interfaces.keys())
|
||||||
|
|
||||||
def get_servers(self):
|
def get_servers(self):
|
||||||
if self.irc_servers:
|
|
||||||
out = self.irc_servers.copy()
|
|
||||||
out.update(DEFAULT_SERVERS)
|
|
||||||
else:
|
|
||||||
out = DEFAULT_SERVERS
|
out = DEFAULT_SERVERS
|
||||||
|
if self.irc_servers:
|
||||||
|
out.update(filter_version(self.irc_servers.copy()))
|
||||||
|
else:
|
||||||
for s in self.recent_servers:
|
for s in self.recent_servers:
|
||||||
try:
|
try:
|
||||||
host, port, protocol = deserialize_server(s)
|
host, port, protocol = deserialize_server(s)
|
||||||
|
@ -510,7 +461,8 @@ class Network(util.DaemonThread):
|
||||||
'''Switch to a random connected server other than the current one'''
|
'''Switch to a random connected server other than the current one'''
|
||||||
servers = self.get_interfaces() # Those in connected state
|
servers = self.get_interfaces() # Those in connected state
|
||||||
if self.default_server in servers:
|
if self.default_server in servers:
|
||||||
servers.remove(self.default_server)
|
servers.remov
|
||||||
|
e(self.default_server)
|
||||||
if servers:
|
if servers:
|
||||||
self.switch_to_interface(random.choice(servers))
|
self.switch_to_interface(random.choice(servers))
|
||||||
|
|
||||||
|
@ -577,7 +529,7 @@ class Network(util.DaemonThread):
|
||||||
self.on_notify_header(interface, result)
|
self.on_notify_header(interface, result)
|
||||||
elif method == 'server.peers.subscribe':
|
elif method == 'server.peers.subscribe':
|
||||||
if error is None:
|
if error is None:
|
||||||
self.irc_servers = filter_version(parse_servers(result))
|
self.irc_servers = parse_servers(result)
|
||||||
self.notify('servers')
|
self.notify('servers')
|
||||||
elif method == 'server.banner':
|
elif method == 'server.banner':
|
||||||
if error is None:
|
if error is None:
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
{
|
||||||
|
"E-X.not.fyi": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"ELECTRUMX.not.fyi": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"ELEX01.blackpole.online": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"VPS.hsmiths.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"bitcoin.freedomnode.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"btc.smsys.me": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "995",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"currentlane.lovebitco.in": {
|
||||||
|
"pruning": "-",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"daedalus.bauerj.eu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"de01.hamster.science": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"ecdsa.net": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "110",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"elec.luggs.co": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "443",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.akinbo.org": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.antumbra.se": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.be": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.coinucopia.io": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.cutie.ga": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.festivaldelhumor.org": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.hsmiths.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.qtornado.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum.vom-stausee.de": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrum3.hachre.de": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrumx.bot.nu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"electrumx.westeurope.cloudapp.azure.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"elx01.knas.systems": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"ex-btc.server-on.net": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"helicarrier.bauerj.eu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"mooo.not.fyi": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50012",
|
||||||
|
"t": "50011",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"ndnd.selfhost.eu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"node.arihanc.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"node.xbt.eu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"node1.volatilevictory.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"noserver4u.de": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"qmebr.spdns.org": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"raspi.hsmiths.com": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "51002",
|
||||||
|
"t": "51001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"s2.noip.pl": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50102",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"s5.noip.pl": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50105",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"songbird.bauerj.eu": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"us.electrum.be": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
},
|
||||||
|
"us01.hamster.science": {
|
||||||
|
"pruning": "-",
|
||||||
|
"s": "50002",
|
||||||
|
"t": "50001",
|
||||||
|
"version": "1.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
'testnetnode.arihanc.com': {'t':'51001', 's':'51002'},
|
||||||
|
'testnet1.bauerj.eu': {'t':'51001', 's':'51002'},
|
||||||
|
'14.3.140.101': {'t':'51001', 's':'51002'},
|
||||||
|
'testnet.hsmiths.com': {'t':'53011', 's':'53012'},
|
||||||
|
'electrum.akinbo.org': {'t':'51001', 's':'51002'},
|
||||||
|
'ELEX05.blackpole.online': {'t':'52011', 's':'52002'},
|
||||||
|
}
|
|
@ -87,8 +87,6 @@ class SimpleConfig(PrintError):
|
||||||
|
|
||||||
if self.get('testnet'):
|
if self.get('testnet'):
|
||||||
path = os.path.join(path, 'testnet')
|
path = os.path.join(path, 'testnet')
|
||||||
elif self.get('nolnet'):
|
|
||||||
path = os.path.join(path, 'nolnet')
|
|
||||||
|
|
||||||
# Make directory if it does not yet exist.
|
# Make directory if it does not yet exist.
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from electrum import set_verbosity
|
from electrum import set_verbosity
|
||||||
from electrum.network import filter_protocol
|
from electrum.network import filter_version
|
||||||
|
|
||||||
import util, json
|
import util, json
|
||||||
set_verbosity(False)
|
set_verbosity(False)
|
||||||
|
|
||||||
|
servers = filter_version(util.get_peers())
|
||||||
servers = util.get_peers()
|
print(json.dumps(servers, sort_keys = True, indent = 4))
|
||||||
|
|
||||||
for k, v in sorted(servers.items(), key=lambda x:x[1].get('version')):
|
|
||||||
print("%40s"%k, v.get('version'))
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue