mafintosh / hyperdb

Distributed scalable database
MIT License
753 stars 75 forks source link

replication between shared public/private keypair #59

Open saranrapjs opened 6 years ago

saranrapjs commented 6 years ago

I'm curious to implement a hyperdb where the public/private keypair are treated as a "capability" code, where anyone who has them can write to the same hyperdb. Is replication between the same keypair something which should (theoretically) work with hyperdb/hypercore?

I tried something like the following, but the replication doesn't seem to work (totally possible I'm doing this the wrong way):

var db1 = hyperdb('./db1.db', {valueEncoding: 'utf-8'})
// cp -r db1.db -> db2.db (manually in the shell), which copies the keypairs
db1.on('ready', function(err, node)  {
    var db2 = hyperdb('./db2.db', {valueEncoding: 'utf-8'})
    db2.on('ready', function(err, node) {
        db1.put('/hello', 'world', function (err, node) {
            var stream = db1.replicate()
            stream.pipe(db2.replicate()).pipe(stream).on('end', function() {
              db2.get('/hello', function (err, nodes) {
                if (err) throw err;
                console.log('/hello --> ' + nodes)
              })
            })
        })
    })
});

I was looking into the hypercore-protocol code, which has a hook for specifying a stream id to "to detect if you connect to yourself". I'd be happy to dig in further (while admitting that I'm a little out of my depth here!) unless there's some fundamental architectural reason why replicating between identical keypairs shouldn't be supported?

hackergrrl commented 6 years ago

Based on my understanding of how hypercore and hyperdb work, there can only be one feed for a given keypair. The hyperdb internals assume this.

hyperdb doesn't expose hooks for adding your own authorization checks yet. If that gets implemented, it'd be easier to block or ingore writes that don't match your constraint (signed by a certain private key).

Can you say a bit more about what you're trying to do this for? There might be another way of doing what you're after.

saranrapjs commented 6 years ago

Ah, that's clarifying. What I'm after: slightly more permissive peer-replicated hypercores, without losing the crypto verification/signatures. I like how the Dat key is used as a capability token for reading feeds, and was hoping to build something where: having the public key grants you "write" access to a hypercore or set of hypercores, without requiring explicit authorization by the original "owner" of the hypercore. It seems like I might just need to cook something up with vanilla hypercore, or just think this thru a little further first at a minimum...

hackergrrl commented 6 years ago

Maybe you could implement this by putting a layer over the hyperdb replication stream:

  1. The hyperdb creator generates a keypair and inserts an initial message that's signed with it, to prove they are in possession of it.
  2. Write a module that replaces the hyperdb replication duplex stream with another duplex stream that wraps it with an initial handshake: both parties need to prove they have the keypair from (1) by sending a signed nonced message to each other. Once that's confirmed, the replication proceeds as per hyperdb default (the party /w existing hyperdb access could do an inline db.authorize() sometime during this handshake).