mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-01 23:30:53 +00:00
derive permutation seed from pubkey/server_id
This commit is contained in:
parent
386edeb405
commit
8cf53d2d12
@ -687,28 +687,56 @@ The ``storage`` dictionary takes keys which are server-ids, and values which
|
|||||||
are dictionaries with two keys: ``ann`` and ``connections``. The ``ann``
|
are dictionaries with two keys: ``ann`` and ``connections``. The ``ann``
|
||||||
value is a dictionary which will be used in lieu of the introducer
|
value is a dictionary which will be used in lieu of the introducer
|
||||||
announcement, so it can be populated by copying the ``ann`` dictionary from
|
announcement, so it can be populated by copying the ``ann`` dictionary from
|
||||||
``NODEDIR/introducer_cache.yaml``. Static servers which use the node's
|
``NODEDIR/introducer_cache.yaml``.
|
||||||
default connection handlers only need a few keys:
|
|
||||||
|
|
||||||
* the server ID, which can be any string
|
The server-id can be any string, but ideally you should use the public key as
|
||||||
* a nickname, which is the string that is printed on the web interface
|
published by the server. Each server displays this as "Node ID:" in the
|
||||||
* the ``anonymous-storage-FURL``, which is where the server lives
|
top-right corner of its "WUI" web welcome page. It can also be obtained from
|
||||||
* ``permutation-seed-base32``, which controls how shares are mapped to
|
other client nodes, which record it as ``key_s:`` in their
|
||||||
|
``introducer_cache.yaml`` file. The format is "v0-" followed by 52 base32
|
||||||
|
characters like so::
|
||||||
|
|
||||||
|
v0-c2ng2pbrmxmlwpijn3mr72ckk5fmzk6uxf6nhowyosaubrt6y5mq
|
||||||
|
|
||||||
|
The ``ann`` dictionary really only needs one key:
|
||||||
|
|
||||||
|
* ``anonymous-storage-FURL``: how we connect to the server
|
||||||
|
|
||||||
|
(note that other important keys may be added in the future, as Accounting and
|
||||||
|
HTTP-based servers are implemented)
|
||||||
|
|
||||||
|
Optional keys include:
|
||||||
|
|
||||||
|
* ``nickname``: the name of this server, as displayed on the Welcome page
|
||||||
|
server list
|
||||||
|
* ``permutation-seed-base32``: this controls how shares are mapped to
|
||||||
servers. This is normally computed from the server-ID, but can be
|
servers. This is normally computed from the server-ID, but can be
|
||||||
overridden to maintain the mapping for older servers which used to use
|
overridden to maintain the mapping for older servers which used to use
|
||||||
Foolscap TubIDs as server-IDs.
|
Foolscap TubIDs as server-IDs. If your selected server-ID cannot be parsed
|
||||||
* more important keys may be added in the future, as Accounting and
|
as a public key, it will be hashed to compute the permutation seed. This is
|
||||||
HTTP-based servers are implemented
|
fine as long as all clients use the same thing, but if they don't, then
|
||||||
|
your client will disagree with the other clients about which servers should
|
||||||
|
hold each share. This will slow downloads for everybody, and may cause
|
||||||
|
additional work or consume extra storage when repair operations don't
|
||||||
|
converge.
|
||||||
|
* anything else from the ``introducer_cache.yaml`` announcement, like
|
||||||
|
``my-version``, which is displayed on the Welcome page server list
|
||||||
|
|
||||||
For example, a private static server could be defined with a
|
For example, a private static server could be defined with a
|
||||||
``private/servers.yaml`` file like this::
|
``private/servers.yaml`` file like this::
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
my-serverid-1:
|
v0-4uazse3xb6uu5qpkb7tel2bm6bpea4jhuigdhqcuvvse7hugtsia:
|
||||||
ann:
|
ann:
|
||||||
nickname: my-server-1
|
nickname: my-server-1
|
||||||
anonymous-storage-FURL: pb://u33m4y7klhz3bypswqkozwetvabelhxt@tcp:8.8.8.8:51298/eiu2i7p6d6mm4ihmss7ieou5hac3wn6b
|
anonymous-storage-FURL: pb://u33m4y7klhz3bypswqkozwetvabelhxt@tcp:8.8.8.8:51298/eiu2i7p6d6mm4ihmss7ieou5hac3wn6b
|
||||||
permutation-seed-base32: w2hqnbaa25yw4qgcvghl5psa3srpfgw3
|
|
||||||
|
Or, if you're feeling really lazy::
|
||||||
|
|
||||||
|
storage:
|
||||||
|
my-serverid-1:
|
||||||
|
ann:
|
||||||
|
anonymous-storage-FURL: pb://u33m4y7klhz3bypswqkozwetvabelhxt@tcp:8.8.8.8:51298/eiu2i7p6d6mm4ihmss7ieou5hac3wn6b
|
||||||
|
|
||||||
.. _YAML: http://yaml.org/
|
.. _YAML: http://yaml.org/
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ the foolscap-based server implemented in src/allmydata/storage/*.py .
|
|||||||
# 6: implement other sorts of IStorageClient classes: S3, etc
|
# 6: implement other sorts of IStorageClient classes: S3, etc
|
||||||
|
|
||||||
|
|
||||||
import re, time
|
import re, time, hashlib
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.application import service
|
from twisted.application import service
|
||||||
@ -289,8 +289,18 @@ class NativeStorageServer(service.MultiService):
|
|||||||
assert m, furl
|
assert m, furl
|
||||||
tubid_s = m.group(1).lower()
|
tubid_s = m.group(1).lower()
|
||||||
self._tubid = base32.a2b(tubid_s)
|
self._tubid = base32.a2b(tubid_s)
|
||||||
assert "permutation-seed-base32" in ann, ann
|
if "permutation-seed-base32" in ann:
|
||||||
ps = base32.a2b(str(ann["permutation-seed-base32"]))
|
ps = base32.a2b(str(ann["permutation-seed-base32"]))
|
||||||
|
elif re.search(r'^v0-[0-9a-zA-Z]{52}$', server_id):
|
||||||
|
ps = base32.a2b(server_id[3:])
|
||||||
|
else:
|
||||||
|
log.msg("unable to parse serverid '%(server_id)s as pubkey, "
|
||||||
|
"hashing it to get permutation-seed, "
|
||||||
|
"may not converge with other clients",
|
||||||
|
server_id=server_id,
|
||||||
|
facility="tahoe.storage_broker",
|
||||||
|
level=log.UNUSUAL, umid="qu86tw")
|
||||||
|
ps = hashlib.sha256(server_id).digest()
|
||||||
self._permutation_seed = ps
|
self._permutation_seed = ps
|
||||||
|
|
||||||
assert server_id
|
assert server_id
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import hashlib
|
||||||
from mock import Mock, patch
|
from mock import Mock, patch
|
||||||
from allmydata.util import base32
|
from allmydata.util import base32
|
||||||
|
|
||||||
@ -74,6 +75,40 @@ class TestStorageFarmBroker(unittest.TestCase):
|
|||||||
self.assertIdentical(s2, s)
|
self.assertIdentical(s2, s)
|
||||||
self.assertEqual(s2.get_permutation_seed(), permseed)
|
self.assertEqual(s2.get_permutation_seed(), permseed)
|
||||||
|
|
||||||
|
def test_static_permutation_seed_pubkey(self):
|
||||||
|
broker = StorageFarmBroker(True)
|
||||||
|
server_id = "v0-4uazse3xb6uu5qpkb7tel2bm6bpea4jhuigdhqcuvvse7hugtsia"
|
||||||
|
k = "4uazse3xb6uu5qpkb7tel2bm6bpea4jhuigdhqcuvvse7hugtsia"
|
||||||
|
ann = {
|
||||||
|
"anonymous-storage-FURL": "pb://abcde@nowhere/fake",
|
||||||
|
}
|
||||||
|
broker.set_static_servers({server_id: {"ann": ann}})
|
||||||
|
s = broker.servers[server_id]
|
||||||
|
self.assertEqual(s.get_permutation_seed(), base32.a2b(k))
|
||||||
|
|
||||||
|
def test_static_permutation_seed_explicit(self):
|
||||||
|
broker = StorageFarmBroker(True)
|
||||||
|
server_id = "v0-4uazse3xb6uu5qpkb7tel2bm6bpea4jhuigdhqcuvvse7hugtsia"
|
||||||
|
k = "w5gl5igiexhwmftwzhai5jy2jixn7yx7"
|
||||||
|
ann = {
|
||||||
|
"anonymous-storage-FURL": "pb://abcde@nowhere/fake",
|
||||||
|
"permutation-seed-base32": k,
|
||||||
|
}
|
||||||
|
broker.set_static_servers({server_id: {"ann": ann}})
|
||||||
|
s = broker.servers[server_id]
|
||||||
|
self.assertEqual(s.get_permutation_seed(), base32.a2b(k))
|
||||||
|
|
||||||
|
def test_static_permutation_seed_hashed(self):
|
||||||
|
broker = StorageFarmBroker(True)
|
||||||
|
server_id = "unparseable"
|
||||||
|
ann = {
|
||||||
|
"anonymous-storage-FURL": "pb://abcde@nowhere/fake",
|
||||||
|
}
|
||||||
|
broker.set_static_servers({server_id: {"ann": ann}})
|
||||||
|
s = broker.servers[server_id]
|
||||||
|
self.assertEqual(s.get_permutation_seed(),
|
||||||
|
hashlib.sha256(server_id).digest())
|
||||||
|
|
||||||
@inlineCallbacks
|
@inlineCallbacks
|
||||||
def test_threshold_reached(self):
|
def test_threshold_reached(self):
|
||||||
introducer = Mock()
|
introducer = Mock()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user