Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZeroNameCached Plugin #2856

Open
wants to merge 3 commits into
base: py3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions plugins/ZeronameCached/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# ZeroName

Zeroname plugin to connect Namecoin and register all the .bit domain name.

## Start

You can create your own Zeroname.

### Namecoin node

You need to run a namecoin node.

[Namecoin](https://namecoin.org/download/)

You will need to start it as a RPC server.

Example of `~/.namecoin/namecoin.conf` minimal setup:
```
daemon=1
rpcuser=your-name
rpcpassword=your-password
rpcport=8336
server=1
txindex=1
```

Don't forget to change the `rpcuser` value and `rpcpassword` value!

You can start your node : `./namecoind`

### Create a Zeroname site

You will also need to create a site `python zeronet.py createSite` and regitser the info.

In the site you will need to create a file `./data/<your-site>/data/names.json` with this is it:
```
{}
```

### `zeroname_config.json` file

In `~/.namecoin/zeroname_config.json`
```
{
"lastprocessed": 223910,
"zeronet_path": "/root/ZeroNet", # Update with your path
"privatekey": "", # Update with your private key of your site
"site": "" # Update with the address of your site
}
```

### Run updater

You can now run the script : `updater/zeroname_updater.py` and wait until it is fully sync (it might take a while).
290 changes: 290 additions & 0 deletions plugins/ZeronameCached/SiteManagerPlugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
import logging
import re
import time
import os
import json

from Config import config
from Plugin import PluginManager

allow_reload = False # No reload supported

log = logging.getLogger("ZeronameCachedPlugin")

import gevent

from gevent import Greenlet

@PluginManager.registerTo("SiteManager")
class SiteManagerPlugin(object):
def load_cache(self):
if hasattr(self, "zero_cache"):
return

self.cache_file_path = os.path.dirname(os.path.abspath(__file__)) + "/../../domains_cache.json"
if not os.path.isfile(self.cache_file_path):
zero_cache = {
"domains": {},
"update_interval": 180,
"last_updated": 0,
"update_time": 0,
"use_cache": True,
"update_resolvers": True
}
with open(self.cache_file_path, 'w') as f:
json.dump(zero_cache, f, indent=2, sort_keys=True)

with open(self.cache_file_path, 'r') as f:
self.zero_cache = json.load(f)

def update_cache(self):
self.load_cache()
if not self.cache_need_update():
return

zero_names_len = len(self.zero_names)
for i in range(0, zero_names_len):
self.loadZeroName(i)
self.update_cache_resolver(i)

self.update_cache_file()

def update_cache_resolver(self, i):
self.load_cache()

self.zero_cache["domains"].update(self.zero_names[i].db_domains)

domains = self.filter_domains(self.zero_cache["domains"])
self.zero_cache["domains"] = domains
updated = time.time()
self.zero_cache["last_updated"] = updated
self.zero_cache["update_time"] = updated + self.zero_cache["update_interval"]

def update_cache_file(self):
try:
self.load_cache()
with open(self.cache_file_path, 'w') as f:
json.dump(self.zero_cache, f, indent=2, sort_keys=True)
except:
pass

def cache_need_update(self):
self.load_cache()

if not self.zero_cache["use_cache"]:
return True

last_updated = self.zero_cache["last_updated"]
update_interval = self.zero_cache["update_interval"]
if update_interval <= 0:
return True

if last_updated <= 0:
return True

last_updated = last_updated + update_interval
if time.time() >= last_updated:
return True

return False

def get_item_from_zero_cache(self, item):
self.update_cache()
return self.zero_cache["domains"].get(item)

def filter_domains(self, my_dict):
result = filter(lambda x: self.dcr.match(x[0]) and self.acr.match(x[1]) and (x[0], x[1]) or False, my_dict.items())
result = dict(result)
return my_dict

def __init__(self, *args, **kwargs):
super(SiteManagerPlugin, self).__init__(*args, **kwargs)
self.zero_names = []
self.count = 0
self.dcr = re.compile(r"(.*?)([A-Za-z0-9_-]+\.bit)$")
self.acr = re.compile("^[A-Za-z0-9]{26,35}$")
self.load_cache()
# fallback for old ZeroNet versions
self.hasattr_isDomainCached = hasattr(super(SiteManagerPlugin, self), "isDomainCached")
self.hasattr_resolveDomainCached = hasattr(super(SiteManagerPlugin, self), "resolveDomainCached")

if not self.hasattr_isDomainCached:
def _isDomain(domain):
log.debug("ZeroNameCached: call isDomain")
return self.isDomainCached(domain) #or super(SiteManagerPlugin, self).isDomain

self.isDomain = _isDomain

if not self.hasattr_resolveDomainCached:
def _resolveDomain(domain):
log.debug("ZeroNameCached: call resolveDomain")
return self.resolveDomainCached(domain) #or super(SiteManagerPlugin, self).resolveDomain

self.resolveDomain = _resolveDomain

# Return: Site object or None if not found
def fast_get(self, address):
return self.sites.get(address) or self.sites.get(address.lower())

# Return or create site and start download site files
def fast_need(self, address, all_file=True, settings=None):
from Site import Site
site = self.fast_get(address)
if not site: # Site not exist yet
self.sites_changed = int(time.time())
if not self.acr.match(address):
return False # Not address: %s % address
self.log.debug("Added new site: %s" % address)
config.loadTrackersFile()
site = Site(address, settings=settings)
self.sites[address] = site
if not site.settings["serving"]: # Maybe it was deleted before
site.settings["serving"] = True
site.saveSettings()
if all_file: # Also download user files on first sync
site.download(check_size=True, blind_includes=True)

return site

def load(self, *args, **kwargs):
super(SiteManagerPlugin, self).load(*args, **kwargs)
# gevent.joinall() make sure that self.loaded == True in order to prevent a self.need/get loop >-< collect the greenlets here
#def waitForLoaded():
# while not self.loaded:
# continue
#
#self.is_loaded = Greenlet(waitForLoaded)
self.load_cache()
self.count = self.count + 1
log.debug("ZeroNameCachedPlugin bit_resolver count: " + str(self.count))
if not self.zero_names:
self.zero_names = []
def get_zero_name_obj():
zero_name_obj = {
"site_zeroname": None,
"site_zeroname_modified": 0,
"db_domains": {},
"db_domains_modified": 0,
"bit_resolver": None,
"loaded": False
}
class ZeroNameObj(object):
def __init__(self, *args, **kwargs):
self.__dict__.update(zero_name_obj)
return ZeroNameObj

self.create_zno = get_zero_name_obj()

#self.is_loaded.start()
#self.is_loaded.join() # workaround for the security hole self.need/get shit
for bit_resolver in config.bit_resolvers:
zno = self.create_zno()
log.debug("ZeroNameCachedPlugin bit_resolver: " + bit_resolver)
zno.bit_resolver = bit_resolver
zno.site_zeroname = Greenlet(self.fast_need, bit_resolver)
zno.site_zeroname.start()
self.zero_names.append(zno)
self.update_cache()

#Return: see resolveBitDomain from the ZeroName Plugin
def loadZeroName(self, i):
zno = self.zero_names[i]

#log.debug("ZeroNameCachedPlugin zno: " + zno)
log.debug("ZeroNameCached: Resolve from : %s" % zno.bit_resolver)
zno.site_zeroname.join()
site_zeroname = None
if not zno.site_zeroname.ready():
zno.site_zeroname = Greenlet(self.fast_need, zno.bit_resolver)
log.debug("ZeroNameCached: Load site site_zeroname : %s" % zno.bit_resolver)
zno.site_zeroname.join()

site_zeroname = None
if zno.site_zeroname.ready():
site_zeroname = zno.site_zeroname
zno.site_zeroname = site_zeroname.get()
else:
self.zero_names[i] = zno
return

zno.site_zeroname_modified = zno.site_zeroname.content_manager.contents.get("content.json", {}).get("modified", 0)
log.debug("ZeroNameCached: test zno.db_domains_modified != zno.site_zeroname_modified ")
if (not zno.loaded) or (zno.db_domains_modified != zno.site_zeroname_modified):
zno.site_zeroname.needFile("data/names.json", priority=10)
log.debug("ZeroNameCached: needFile")
s = time.time()
try:
zno.db_domains = self.filter_domains(zno.site_zeroname.storage.loadJson("data/names.json"))
zno.loaded = True
zno.db_domains_modified = zno.site_zeroname_modified
self.update_cache_file()
log.debug(
"ZeroNameCached: Domain db with %s entries loaded in %.3fs (modification: %s -> %s)" %
(len(zno.db_domains), time.time() - s, zno.db_domains_modified, zno.site_zeroname_modified)
)
except Exception as err:
log.error("ZeroNameCached: Error loading names.json: %s" % err)
zno.loaded = False

zno.site_zeroname = site_zeroname
self.zero_names[i] = zno

# Return: True if the address is .bit domain
# Use the cached funtion in order to have a entry point before the ZeroName plugin is called
def isBitDomainCached(self, address):
log.debug("ZeroNameCached domain to be resolved: " + address)
isDomainZite = bool(self.dcr.match(address))
log.debug("ZeroNameCached: call isBitDomainCached boolean: " + str(isDomainZite))
return isDomainZite

def resolveBitDomainCached(self, domain):
log.debug("ZeroNameCached: call resolveBitDomainCached")
domain = domain.lower()
log.debug("ZeroNameCachedPlugin domain: " + domain)
return self.get_item_from_zero_cache(domain)

# Turn domain into address
# Use the cached funtion in order to have a entry point before the ZeroName plugin is called
def resolveDomainCached(self, domain):
log.debug("ZeroNameCached: call resolveDomainCached")
resolve_domain = self.resolveBitDomainCached(domain)

if resolve_domain:
return resolve_domain

# fallback for old ZeroNet versions
if not self.hasattr_resolveDomainCached:
log.debug("ZeroNameCached: call fallback resolveDomain")
return super(SiteManagerPlugin, self).resolveDomain(domain)

log.debug("ZeroNameCached: fallback to original resolveDomainCached")
return super(SiteManagerPlugin, self).resolveDomainCached(domain)

# Return: True if the address is domain
# Use the cached funtion in order to have a entry point before the ZeroName plugin is called
def isDomainCached(self, domain):
log.debug("ZeroNameCached: call isDomainCached")
resolve_domain = self.isBitDomainCached(domain)

if resolve_domain:
return resolve_domain

# fallback for old ZeroNet versions
if not self.hasattr_isDomainCached:
log.debug("ZeroNameCached: call fallback isDomain")
return super(SiteManagerPlugin, self).isDomain(domain)

log.debug("ZeroNameCached: fallback to original isDomainCached")
return super(SiteManagerPlugin, self).isDomainCached(domain)

@PluginManager.registerTo("ConfigPlugin")
class ConfigPlugin(object):
def createArguments(self):
group = self.parser.add_argument_group("ZeronameCachedPlugin")
group.add_argument(
"--bit_resolvers", help="ZeroNameCached: ZeroNet sites to resolve .bit domains",
default=["1Name2NXVi1RDPDgf5617UoW7xA6YrhM9F", "1SitesVCdgNfHojzf2aGKQrD4dteAZR1k", "1E97TpiDiCj1WGhZWxoKjBV9KkVty1PFsq"], nargs='+', metavar="0net_addresses"
) # zeronet resolver, # zeronetx resolver # zeronet is nice resolver

log.debug("ZeroNameCached has created the arguments for you!")
return super(ConfigPlugin, self).createArguments()
1 change: 1 addition & 0 deletions plugins/ZeronameCached/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import SiteManagerPlugin
5 changes: 5 additions & 0 deletions plugins/ZeronameCached/plugin_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "ZeronameCached",
"description": "Suppport from multiple resolvers and use the cached functions resolveDomainCached in order to have a entry point before Zeroname plugin is called",
"default": "enabled"
}
Loading