Skip to content

Commit

Permalink
work on final
Browse files Browse the repository at this point in the history
git-svn-id: svn://forre.st/undns@1212 470744a7-cac9-478e-843e-5ec1b25c69e8
  • Loading branch information
forrest committed Mar 29, 2011
1 parent a45cc0d commit 14a514a
Show file tree
Hide file tree
Showing 6 changed files with 1,259 additions and 33 deletions.
40 changes: 40 additions & 0 deletions notes2
@@ -0,0 +1,40 @@
clients can't hold all updates
clients could garbage collect old updates _but they still have to initially receive them_

store data in blockchain just as a hash
get actual data over DHT
avoids versioning requirements



two steps
publishes create some proof-of-work that can't be quickly replicated (and the domain claimed) and spread it to nodes
nodes work and create a new block every 10 minutes containing all entries from publishers


decision tree
all clients contain complete block chain
clients contain abridged block chain and use it to verify




actually quite simple

clients hold all headers and keep track of them
DHT returns block from query 'whar google.com'?
client verifies that block is in header chain
to prevent replying with old blocks, to spoof old records
block expiry is measured in blocks - clients can absolutely tell whether a block is valid based on header chain
having to declare an expiration date is annoying - time-critical updates can't happen
expiration could just be smallish

something like a skip list to prevent having to hold all headers
client could initially get every n blocks - each block has a reference to the 1st previous and the nth previous

using only the fact that it's in the block chain relies on trusting the generating nodes to not accept invalid claims such as ones that override past registrations

desired rate - one block every 1000 seconds
- 31556.952 blocks per year
size of headers seems fine - in the range of 1-10 MB/year - (bytes/block / 31.7) MB/year
with a target of 1-10 MB/year that's 32-317 bytes/block
5 changes: 2 additions & 3 deletions p2p.py
Expand Up @@ -36,7 +36,7 @@ def draw():


def do_work(x, difficulty, stop_flag): def do_work(x, difficulty, stop_flag):
d = "[%s, " % json.dumps(x) d = "[%s, " % json.dumps(x)
h = hashlib.sha1(d) h = hashlib.sha256(d)
for i in itertools.count(random.randrange(2**63)): for i in itertools.count(random.randrange(2**63)):
if stop_flag[0]: if stop_flag[0]:
return None return None
Expand Down Expand Up @@ -153,7 +153,6 @@ def __init__(self, port, bootstrap_addresses):
self.port = port self.port = port
self.bootstrap_addresses = bootstrap_addresses self.bootstrap_addresses = bootstrap_addresses
self.id = random.randrange(2**160) self.id = random.randrange(2**160)
self.seen = set()


self.blocks = {} # hash -> data self.blocks = {} # hash -> data
self.verified = set() # hashes of blocks that can be tracked to a genesis block self.verified = set() # hashes of blocks that can be tracked to a genesis block
Expand Down Expand Up @@ -309,7 +308,7 @@ def verified_block(self, block, from_node=None, depth=0):


def add_contact(self, address, remote_id=None): def add_contact(self, address, remote_id=None):
if remote_id is None: if remote_id is None:
RemoteNode(self, address, None).rpc_ping() # response will contain id and add_contact will be called RemoteNode(self, address, None).rpc_ping().addErrback(lambda fail: None) # response will contain id and add_contact will be called
return return
if remote_id == self.id: if remote_id == self.id:
return return
Expand Down
69 changes: 69 additions & 0 deletions packet.py
Expand Up @@ -82,3 +82,72 @@ def get_address(self):


def encode(self, zone_file, rng): def encode(self, zone_file, rng):
return Packet(self._private_key.publickey(), zone_file, self._private_key.sign(hashlib.sha1(zone_file).digest(), rng)) return Packet(self._private_key.publickey(), zone_file, self._private_key.sign(hashlib.sha1(zone_file).digest(), rng))

class TheirIdentity(object):
@classmethod
def from_binary(cls, x):
return cls(util.tuple_to_key(json.loads(zlib.decompress(x))))

def __init__(self, public_key):
if public_key.has_private():
raise ValueError("key not public")

self._public_key = public_key

def to_binary(self):
return zlib.compress(json.dumps(util.key_to_tuple(self._public_key)))

def get_id(self):
return util.hash_address(util.key_to_string(self._public_key))

def verify(self, data, signature):
return self._public_key.verify(util.hash_sign(data), signature)

class MyIdentity(object):
@classmethod
def generate(cls, rng):
return cls(RSA.generate(1024, rng))

@classmethod
def from_binary(cls, x):
return cls(util.tuple_to_key(json.loads(zlib.decompress(x))))

def __init__(self, private_key):
if not private_key.has_private():
raise ValueError("key not private")

self._private_key = private_key

def to_binary(self):
return zlib.compress(json.dumps(util.key_to_tuple(self._private_key)))

def get_id(self):
return util.hash_address(util.key_to_string(self._private_key.publickey()))

def to_binary_public(self):
return zlib.compress(json.dumps(util.key_to_tuple(self._private_key.publickey())))

def sign(self, data, rng):
return self._private_key.sign(util.hash_sign(data), rng)

if __name__ == '__main__':
from Crypto import Random
rng = Random.new().read

h = "hello, world!"

a = MyIdentity.generate(rng)

print repr(a.to_binary())
print repr(a.get_id())
print repr(a.to_binary_public())

print
d = a.sign(h, rng)
print repr(d)

b = TheirIdentity.from_binary(a.to_binary_public())

print repr(b.get_id())
print b.verify(h, d)

0 comments on commit 14a514a

Please sign in to comment.