HNHacker News
TopNewBestAskShowJobs

haadcode

46 karma · joined October 17, 2016

submissionscomments
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
Can you elaborate why you think Rust is a better choice?
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
No, on both. See above.
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
> How do you know that? It's not inferrable from the DAG. Is sequencing also provided "a layer up"?

I jumped the gun there and made an assumption that the value of a node is the LWW ordering :) Ok, so without that assumption, the DAG

  1 --> 2 --> 3 --> 4 
         `--> 5 --> 6
...are the values of the operations that the DAG represents, ie. values of a key, so we need to look at the Lamport clocks (or Merkle Clocks when the operations are hashed as a merkle dag) of each operation, represented here as ((ts, id), key, value):

  ((0, x), a, 1) --> ((1, x), a, 2) --> ((2, x), a, 3) --> ((3, x), a, 4)
                                   `--> ((2, y), a, 5) --> ((3, y), a, 6)

which one is the latest value for key a? Which updates, semantically, were lost? In a non-CRDT system, which value (4/x or 6/y) is or should be displayed and considered the latest?

> This is a problem! If you claim to be a CRDT and offline-first or whatever, then as a user, I expect that the operations I make while I'm disconnected aren't just going to be destroyed when I reconnect, because someone else happened to be using a computer with a lexicographically superior hostname (or however you derive your vector clocks).

You're conflating the data(base) model with the log and we can't generalize that all cases of data models or merge conflict are cases of "I expect all my operations to be the latest and visible to me". They are semantically different. If the writes are on the same key, one of them has to come first if the notion of "latest single value" is required. If the writes are not on the same key, or not key-based, multiple values appear where they need to. What we can generalize is that by giving a deterministic sorting function, the "latest value" is the same for all participants (readers) in the system. From data structure perspective this is correct: given same set of operations, you always get the same result. For many use cases, LWW works perfectly fine, and if your data model requires a "different interpretation" of the latest values, you can pass in your custom merge logic (=sorting function) in orbitdb. The cool thing is, that by giving a deterministic sorting function for a log, you can turn almost any data structure to a CRDT. How they translate to end-user data model will depend (eg. I wouldn't model, say, "comments on a blog post" as a key-value store).

If you're curious to understand more, I think the model is best described in the paper "OpSets: Sequential Specifications for Replicated Datatypes" [1]. Another two papers, from the same author, that may also help are "Online Event Processing" [2] and "Moving Elements in List CRDTs" [3] which show how by breaking down the data model to be more granular than "all or nothing", composing different CRDTs give arise to new CRDTS, which I find beautiful. Anything, really, that M. Kleppmann has written about the topic is worth a read :)

[1] https://arxiv.org/pdf/1805.04263.pdf [2] https://martin.kleppmann.com/papers/olep-cacm.pdf [3] https://martin.kleppmann.com/papers/list-move-papoc20.pdf

haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
almost! :) let me elaborate on few points.

> you have to reference all of the current concurrent root nodes of the data structure, in effect becoming the new single root node

correct, and more precisely the union of heads is the current "single root node". in practise, and this is where the merge strategy comes in, the "latest value" is the value of the event that is "last" (as per LWW sorting).

> and your event data, which must be a CRDT, gets merged with the CRDTs of those root nodes.

the event data itself doesn't have to be a CRDT, can be any data structure. the "root nodes" (meaning the heads of the log) don't get merged with the "event data" (assuming you mean the database/model layer on top of the log), the merge strategy of the log picks the "last/latest event data" to be the latest value of your data structure.

> It's time to write a new value, so I create a new tuple with references to 4 and 6, and merge their CRDT values.

when a new value is written, correct that the references to 4 and 6 are stored, but the new value doesn't merge the values of the previous events and rather, it's a new value of its own. it may replace the value from one or both of the previous events, but that depends on the data model (layer up from the log).

  1 --> 2 --> 3 --> 4 
         `--> 5 --> 6
> Last Writer Wins, right? So either 4 or 6 dominates the other. Whoever was in the other causal history just... lost their writes?

no writes are lost. the result in your example depends what 4 and 6 refer to. in a log database, the ordered log would be eg. 1<-2<-3<-5<-4<-6, so all values are preserved. in the case of a key-value store, it could be that 4 is a set operation to key a and 6 is a set operation to key b, thus the writes don't effect each other. if 4 and 6 are both a set operation on key a, it would mean that key a would have the value from 6 and the next write to key a would overwrite the value in a. makes sense?

haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
The log described above is this https://github.com/orbitdb/ipfs-log
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
Great comments! Indeed, "sign your log appends" gives everything needed for authority. Re. transactions, from OrbitDB's perspective this would be application specific, so you could hook into traditional, centralized consensus or use a blockchain or other types of decentralized consensus mechanisms. Or, given the core data structure is a log, build a "custom database" on OrbitDB that models and provides an interface for a consensus algorithm, eg. "append 1: head is X" <- "append 2: ack head is X" <- "append 3: ack from me too that head is X" etc.
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
One great piece of writing to think about the use cases and what kind of systems and applications can be built following the concepts applied in OrbitDB is this "Local-first software" https://www.inkandswitch.com/local-first.html (there's prolly a thread somewhere here too on that).
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
Posted this in another reply above, but give this a read: "Merkle CRDTs" (https://arxiv.org/abs/2004.00107).
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
> Last-Writer-Wins is a conflict resolution strategy that can be used by any kind of data type that needs conflicts resolved, CRDTs included. Unfortunately it's not a very good one: even if you use vector clocks instead of wall clocks, it doesn't give you much stronger guarantees than determinism. That is, given two concurrent writes, the winner is essentially arbitrary. LWW is a merge strategy of last resort; if that's the only thing your CRDT system offers, I'm not sure it's really fair to call it a CRDT system.

Can't reply to the comment below, so replying here.

I believe what markhenderson was trying to say is that in OrbitDB, the default merge strategy for concurrent operations is LWW.

The comment above is conflating a lot of things here. 1) determinism is exactly the guarantee one needs for CRDTs, and I'd argue generally is a good thing in distributed system but 2) adding vector clocks (OrbitDB uses Lamport clocks, or Merkle Clocks [1], by default), nor wall clocks, have nothing to do with determinism and in fact there's a good reason to not use vector clocks by default: they grow unbounded in a system where users (=IDs) are not known. In my experience, LWW is a good baseline merge strategy.

I don't think it's at all correct to say that "the winner is essentially arbitrary" because it's not. The "last" in LWW can be determined based on any number of facts. For example "in case of concurrent operations, always take the one that is written by the ID of the user's mobile device", or "in case of concurrent operations, always take the one that <your preferred time/ordering service> says should come first". It'd be more correct say "the winner is based on the logical time ordering function, which may not be chronological, real world time order".

As for the last comment, I'm pretty sure it's a CRDT system :) Want to elaborate your reasoning why you think it's not a CRDT?

[1] "Merkle-CRDTs: Merkle-DAGs meet CRDTs" - https://arxiv.org/abs/2004.00107

haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
There's also a Go implementation at https://github.com/berty/go-orbit-db
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
To clarify here, OrbitDB's core is an append-only, immutable log CRDT. While a mouthful, what is gives, is a distributed (decentralized) database operations log. Almost any type of database, or data structure, can be then built on top of that log. The log in OrbitDB is a Merkle-DAG [1], so, a graph.

Key-Value databases, feeds, and other data model types that OrbitDB supports by default, are all built on that log. You can also create your custom database types, ie. custom data models.

[1] https://discuss.ipfs.io/t/what-is-a-merkle-dag/386/4

haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
The use case is shared, mutable data structures that don't rely on central coordination or control.
haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
> I guess performance and robustness were not a priority.

You'd be surprised how well JS does on both fronts, in addition to being able to run across platforms :)

haadcode··on OrbitDB: Peer-to-peer databases for the decentralized web
> * How did this project get started? What problem is it trying to solve?

OrbitDB got started because we wanted to build serverless applications, especially for the web (ie. applications that run in the browser.) Serverless meaning "no server" and no central authority, ie. something that can't be shut down.

OrbitDB gives tools to build systems and applications where the user owns their data, that is, the data that is not controlled by a service. As a way of simple example, imagine Twitter that doesn't have one massive database for all tweets, but rather you'd have one database for each user.

haadcode··on Mobile Ambients – process calculus for mobile computation (1998) [pdf]
Absolutely! I don't know the exact history and why it hasn't been applied much, and I'd be very curious to learn, but it's definitely a gem.
haadcode··on Mobile Ambients – process calculus for mobile computation (1998) [pdf]
tldr version: https://en.m.wikipedia.org/wiki/Ambient_calculus
haadcode··on Pushing the Limits of IPFS and OrbitDB
To summarize the relevant links and Github repos, they are:

https://tallylab.com/

https://github.com/orbitdb/orbit-db

https://github.com/orbitdb/ipfs-log

https://github.com/ipfs/js-ipfs

https://github.com/ipfs/go-ipfs

https://github.com/ipfs/ipfs

haadcode··on Pushing the Limits of IPFS and OrbitDB
I think it depends on what the use case for IPFS is. Many use it "server-side" to just transfer and store files, so a "native client" makes a lot of sense. The IPFS devs always recognized the importance of the browser though and as such js-ipfs (https://github.com/ipfs/js-ipfs) has always been a first-class implementation of IPFS. With js-ipfs, the IPFS protocol works in the browser and can be embedded to JavaScript applications in a way that doesn't "require a new client".

Highly recommend to read into IPFS and how it works to understand the various use cases and possibilities. A good starting point would be https://ipfs.io/ and https://github.com/ipfs/ipfs.

haadcode··on Pushing the Limits of IPFS and OrbitDB
The ipfs.io url is a public IPFS gateway, ie. bunch of IPFS nodes running on servers and "caching" content to be served through that domain. From that perspective, you're not accessing the content through the IPFS protocol but through http like any website. It's a public service operated by the IPFS community, but underneath it does all the "...get it to look-up some distributed hash table in order to find peers with the content (a la torrents)".

However, if you install the IPFS client (https://dist.ipfs.io/#go-ipfs), you can get the blog post peer-to-peer through IPFS by running `ipfs get QmY2LufsW3v6AfxTTkp6SGqDGa5AeJhSZXH8RSsdiao4Ds`. Note how the hash in the ipfs.io url is the hash of the content stored in IPFS.

Hope this clarifies it!

haadcode··on Pushing the Limits of IPFS and OrbitDB
Not quite. The data structures for the "database" part are more complex than a single json structure. Each update to the database is an "individual json" which get linked together using an append-only log CRDT (https://github.com/orbitdb/ipfs-log) and you'd essentially serve that log. So instead of "one big json", it's "many small jsons" and the state (view) of the database gets calculated from those small jsons.
haadcode··on Pushing the Limits of IPFS and OrbitDB
It's true that availability is not "automatic" as per the software itself (rarely is in P2P networks). To make sure the data stays online (whether IPFS or OrbitDB), one needs to make sure there are enough nodes serving the data. In OrbitDB the replication protocol will make sure the full database is downloaded and served upon opening the database and as all db-data is IPFS-data, the db will be served just like any content on IPFS. So for example, for an application built with OrbitDB and IPFS, one would probably want to run some nodes themselves to "pin" (IPFS parlance) the databases and serve them to the network.

Edit: There's an open issue for a "OrbitDB pinning service" (https://github.com/orbitdb/orbit-db/issues/352), it's in the works atm.

haadcode··on Pushing the Limits of IPFS and OrbitDB
The blog post is accessible through IPFS here https://ipfs.io/ipfs/QmY2LufsW3v6AfxTTkp6SGqDGa5AeJhSZXH8RSs... in case the original link doesn't work.
haadcode··on Antidote: CRDT-based distributed database
This absolutely awesome!

I'm very excited for AntidoteDB, for its use cases but also for the underlying, pioneering work you're doing on CRDTs. Thank you for doing it! <3

haadcode··on IPFS is the Distributed Web
Unfortunately there's no proper demo page :/ We're working on improving the docs (we know this is big issues atm).

There's an old version (from June) of Orbit at http://orbit.libp2p.io which you can try. Much has happened since and we're working on bringing the js-ipfs version Orbit back to a working state.

Re.Pubsub, I'm personally also very excited about it! :) The specs and general info are located here https://github.com/libp2p/pubsub. go-ipfs merged pubsub into master some time ago with this commit https://github.com/ipfs/go-ipfs/commit/e1c40dfa347e38bdc9812... and we're working to get it into js-ipfs here https://github.com/ipfs/js-ipfs/issues/530.

haadcode··on IPFS is the Distributed Web
(IPFS dev here)

js-ipfs, the Javascript implementation of IPFS, has made a lot of progress in the past 6 months. It's still early but totally usable.

We've been working on go-ipfs and js-ipfs interop so that browser nodes can talk to "native" nodes. It's not fully ready yet but soon. This will open a lot of doors for a more advanced network and applications using IPFS.

See https://github.com/ipfs/js-ipfs.

As for your question re. ipfs.io using js-ipfs, the answers is no, it doesn't use js-ipfs implementation yet.

haadcode··on Orbit – Distributed, serverless, peer-to-peer chat application on IPFS
The cool thing about unique hash per message is that it makes that message linkable in other applications, after all it's just an IPFS hash. So for example, if you share a file in Orbit, you can get that file with IPFS just like you would get it normally.

Linked data ftw! :)

haadcode··on Orbit – Distributed, serverless, peer-to-peer chat application on IPFS
Developer of Orbit here. Great to hear all the feedback, thank you!

Most questions have been already answered, but to clarify:

Orbit indeed uses IPFS pubsub (https://github.com/ipfs/go-ipfs/pull/3202) for real-time message propagation, no servers are involved. In addition, it uses orbit-db (https://github.com/haadcode/orbit-db) - a distributed database on IPFS - for the message history, so the messages are not ephemeral and the channel history can always be retrieved. This is a really nice property and allows Orbit to work in "disconnected" or split networks, as well as offline.

Orbit has been a testbed for IPFS applications and orbit-db came out of that work, enabling various types of distributed, p2p applications and use cases: comment systems, votes/likes/starring systems (with counters), feeds, etc. And now with IPFS pubsub, we're finally at a point of being completely serverless and distributed which is hugely exciting and opens so many doors for future work!

I recently gave a talk at Devcon2 about Orbit and developing distributed real-time applications (https://ethereumfoundation.org/devcon/?session=orbit-distrib...) and while the videos of the talk are not out yet (afaik coming very soon!), there's the uncut video of the talk here http://v.youku.com/v_show/id_XMTc1NjU1NzEyNA==.html?firsttim... if you're interested to learn more. Video of the demo I showed in the talk is here https://ethereumfoundation.org/devcon/wp-content/uploads/201....

I'll be hanging out on #ipfs in Orbit if you're interested to try it out. Note that the Electron app and the web version at orbit.libp2p.io don't talk to each other atm (we're working on this), so I would highly recommend to try out the Electron app.

While you're at it, try drag & dropping files and folders to a channel, that's one of the coolest feature of Orbit atm imo :)

We're actively developing Orbit and making a push in the next few months, if you're interested to take part in the design and development, or would like to develop your own apps using the same tech, join us on Github https://github.com/haadcode/orbit/issues.

Thanks for the comments everyone, much appreciated!