Tlon builds Urbit, a secure peer-to-peer network of personal servers, built on a clean-slate system software stack. You can learn more about it here https://urbit.org/#learn
We’re hiring developers up and down the stack to work on systems, storage, languages, crypto, and front-end. It’s an entire operating system, so there’s a lot of work to do.
Tlon builds Urbit, a secure peer-to-peer network of personal servers, built on a clean-slate system software stack. You can learn more about it here: https://urbit.org/#learn
We’re hiring developers across the stack to work on systems, storage, languages, crypto, and front-end. It’s an entire operating system, so there’s a lot of work to do.
Unfortunately I wouldn't expect a lot of substantive technical discussion for a post like this on HN -- this post will expire before anyone has time to read it properly and produce thoughtful responses.
(Which is broadly the problem with posting enormous applied CS-research braindumps to HN. Don't know a better place to do it, though. And I see people are upvoting you. Also, the absence of thoughtless responses is itself a great response.)
The key point here, as far as I can tell, is really building a CRDT system as a true platform layer, rather than as a one-off solution for a special-purpose app. I think it's fairly clear that generic sync is a pretty essential part of a modern decentralized computing environment, and I don't think it's clear at all what the best way to solve it is.
But... it seems to me that you've solved a large piece of the problem but not the whole thing. Because the most important document sync and collaboration platform is, of course, source code control. If you have a document sync and collaboration model that doesn't at least generalize to classic revision control, why not?
Now, there's a sensible reason to separate these problems -- CRDT and OT solutions tend to specialize in the zero-maintenance case where a user-resolved merge is just impossible. Whereas if it was possible to build a zero-maintenance revision-control system, which automatically resolved all merges and conflicts, someone would have done so already.
This certainly suggests that the two are different problems. But generalizing across slight differences is what system software does. Maybe one is a special case of the other?
A generalized layer for lightweight collaboration is pretty powerful. But it certainly seems like the case that if you could generalize across lightweight collaboration and heavyweight revision control, you would have something that would be incredibly powerful.
Or is this too ambitious? I don't know so I'm asking you.
I suspect you could build such a thing if you could more rigidly define edit operations on source code files. The way we edit code now is roughly "insert/edit/delete string <x> at position <y>", which doesn't really carry enough context to auto-merge.
If edits carried all the semantic information of what they were doing to the source: "rename symbol <x> to <y> everywhere" "perform step <x> after step <y>", then we could probably build a zero-maintenance revision-control system.
I've had some thoughts along the same lines, but haven't taken the opportunity to flesh them out nearly as far.
A git repository is nearly a CRDT that represents a file system hierarchy -- the only thing that's missing is a deterministic merge algorithm. If you allow files to be committed in a conflicted state that gets resolved by a later edit, you have a full CRDT that automated systems can work freely with.
The catch, of course, is that despite pushing the resolution to an arbitrary point in the future, these conflicts still have to be resolved by hand eventually.
Definitely not dead -- it got stalled for a while because Urbit tends to use deep stacks and both Graal and the JVM seem to favor shallow ones. The author (not me) came up with a "meta-stack" design that may mitigate this issue and will go back and try it soon.
But the performance seen on a trivial Ackerman function was very good -- Nock via Graal got close to C performance. That's impressive for what's basically a Lisp.
Here's a more optimistic take which is unavoidably a plug.
Urbit is maybe a sort of "extreme langsec." "Immune" is a dangerous word. Urbit is "premitigated" against Spectre for the following reasons, some cool and others stupid:
(1) The Nock VM has no O(n) data structures, ie, arrays. This was not anything to brag about till now.
(2) Urbit events are interpreted in their own process, which is one trust domain (one process, one "personal server").
(3) A personal server isn't a browser and doesn't habitually run code its owner doesn't trust.
(4) Urbit is purely functional, so you only know the time if someone passes you the time.
(5) Top-level event handlers are passed the time of the event. This is easy to fuzz.
(6) If you are running untrusted foreign code, it is probably just a function. Giving this function a measured time interval from top-level event times would be strange. And it would need another channel to exfiltrate the stolen data.
Never say never, but this combination of premitigations makes me worry about Spectre very little. Although, when we do have a less-trusted tier of applications (walk before run), ain't nobody is going to be telling them the time.
Besides the plug, the lesson there is that one of the reasons Spectre is a problem is that langsec is an imperfect bandaid.
Urbit is premitigated because it was designed as a functional system from the ground up. The JS environment is functional lite -- it allows typeless functional programming, but it also retains many mutable/imperative systems design tropes.
It's these tropes that have become clever attack vectors. If you don't want to get Spectred, build systems that are formal and functional all the way down.
>(5) Top-level event handlers are passed the time of the event. This is easy to fuzz.
Therein lies the rub -- if your program does not have access to precise timing information, it is by definition not operating at the full capability of the hardware which runs it. That's a hard sell to many domains.
Consider gaming. At 144Hz w/ 4K resolution you have 6ms to render a frame: that's about 1.3ns per pixel. If for a moment we imagine that it takes approximately 1 machine cycle per pixel to render a scene: that means you need to be operating at 1.3GHz just to meet the deadline for drawing to the frame buffer. -- That's before you consider memory & cache latency, or the fact that your multitasking OS is stealing resources for itself & other competing processes.
So no, one cannot just fuzz performance counters in the name of security. Any soft-realtime or hard-realtime domain is going to expect the machine to actually perform as advertised.
One possible answer: maybe the right system would use "ambient authority" (ACLs, etc) for the common case, but scale up to true capabilities for interesting corner cases.
Creating capability UIs that compete, in the common case, with the normal ambient-authority design, is ferociously hard. This seems to be where most capability systems falter. The hardest UI problem in the leading modern capability OS, Sandstorm, is certainly the capability "powerbox."
Think about all the places you can type a filename or a URL. If the designator and the authorization have to travel together, and the pair is an unforgeable capability, then user-entered designators (like paths or URLs) are not practical. Designators can't travel through unsecured paths, through the human mind, etc. This is a painful limitation.
That said, the OP is the best explanation of capabilities I've ever seen. Everyone really should read it.
> The hardest UI problem in the leading modern capability OS, Sandstorm, is certainly the capability "powerbox."
Heh, I'm not sure I'd describe Sandstorm as "leading" anything right now, but thanks. :)
I think Sandstorm made the problem more difficult for itself by not just trying to solve this UI problem, but trying to do it in a way that can be integrated into existing codebases that were never designed with capabilities in mind. This is the really difficult part: dealing with legacy code. The powerbox itself is otherwise "just a picker", a fairly straightforward concept.
For example, the standard file-open dialog box in everyone's browser, when invoked from an upload button on a web site, is actually a powerbox: the web site itself is given no access to any files except the one that the user chooses, but the file-open dialog is able to see everything.
But imagine trying to graft this approach onto an existing native app, that is used to being able to read the hard drive directly and already has its own custom file picker UI built in. You have to convince the developers of that app to remove their nice custom UI and instead invoke the system's UI. Moreover, when they invoke the file picker, they now don't get back a file name, but rather an already-open file descriptor. So their code has to be adjusted to not expect a name. This could be hard, depending on how the code is organized: maybe it uses a bunch of libraries that expect to open a file by name, etc.
Sandstorm is trying to graft this model onto apps that are used to making HTTP API requests to each other directly.
We had designs figured out to make this work, and even make most of the process look like an OAuth request, so that existing OAuth-based apps might not need to change very much... some of this is implemented, but mostly we just didn't get there before running out of money. (I am still working on it in my spare time, though!)
Protip: if no one's ahead of you, you're leading :-)
This is a great answer. I think the impedance-mismatch question is a big part of the problem. Personally I prefer to boil the ocean rather than drowning in the impedance-mismatch tarpit. Both of these strategies are, of course, profoundly insane.
It's true that a file-open dialog box easily becomes a powerbox. But of course, you are using the ambient authority of the user's login session to ascribe authority to the path that gets typed. So in a way it's the exception that proves the rule. And does a URL bar easily become a powerbox? What about a command-line shell?
Perhaps we're both just agreeing that there is always trivial ambient authority, and the right way to scale up to nontrivial cases is a capability model.
I just worry that when too many people discover the beautiful screwdriver that is capabilities, they decide that everything should be a screw. But the world has nails. It may even be true that the world should have nails. And then you find yourself pounding in nails with the butt of your screwdriver.
Have you considered an ICO? Asking for a friend :-)
I agree that capability people tend to get too extreme, and this tends to lead to failure. With Sandstorm we've tried to be more pragmatic, but still careful not to do anything that breaks the whole model in the long run.
Whether or not the URL bar of a browser is a kind of powerbox depends on how extreme you want to get. In a pure capability model, yes, it would have to be. And hypertext would no longer be plain data -- it would be data with embedded capabilities (for each link), and would have to be transmitted via a protocol that can track capabilities. Obviously that kind of stuff, even though it would be amazingly powerful in a lot of ways, is not practical. :/
> Have you considered an ICO? Asking for a friend :-)
People keep asking me that, often citing Urbit as an example to follow. :) At the moment I'm having too much fun at my day job building Cloudflare Workers (an unusually practical project by my standards!), and want to focus my outside-of-work time on coding Sandstorm rather than fundraising for it. In the future, who knows.
If I can distill my objection to the pure capability model: there are two different statements of the capability manifesto, one strong and one weak.
The weak capability position is that it should be possible to construct an opaque combination of designator and authority, ie, a capability. The strong capability position is that designator and authority must always follow the same path.
So in the "pure capability model," you are actually subtracting a feature from the system. Now, of course, it's often the case that subtracting a feature makes a system better. But one needs to be really clear about confusing this with the positive virtues of just having capabilities.
Also, while I agree that capabilities are really great (Arvo has a somewhat capability-like internal communication model), it's important to point out that (a) capability vs. identity is a duality; and (b) it's cheating to compare a good capability system to a bad identity system.
For (a), note that identity systems can implement capability features like delegation and revocation; they just have to do it actively rather than passively. If I am willing to act as your deputy, I can delegate my power to act to you. Or some restricted subset thereof. Tell me what to do and I'll do it.
For (b), if you put a decent capability system next to the Internet, a network whose identity model is a burning-tire dumpster fire. If your identity system actually works and makes sense, competing is harder for the capability design.
I do think Urbit should have some kind of capability model. However, this has the feel of a 2.0 or even 3.0 feature. I hate to solve a problem until it is actually in my way. I feel we have come nowhere near the limits of the common case. A simple map from identity to privilege is certainly that.
And while capability UIs may be doable, identity UIs are trivial. This would not be the first case of humans being funky, hence screwing up our elegant architectural logic.
If you have a system software project and it can advance without being lashed to a company, definitely do it that way! It's always a poor fit -- they have to succeed on different timelines.
One thing I know: once we all have personal servers, today's cloud will look pretty lame in retrospect...
Can you explain that more? Do you mean that both caps and ACL systems are ways to organize an access-control matrix, either by rows or by columns? Because I think that idea over-abstracts the reality.
OK. For anyone else reading, the idea is a matrix "access(row, column)" where 'row' names an agent and 'column' names a resource, telling us whether the agent has permission to access the resource. A cap system breaks it out by rows: an agent has a list of capabilities; while an ACL system groups by columns: a file has a list of who can access it. This point of view seems to stand above either approach and make them look complementary.
The most important things left out of that view I think are the way an agent expresses its intent (vs. ambient authority) and the way the whole system changes over time. I started writing some more, but it's late and http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf goes into this at length, so I'll just leave that here.
(You're probably already much more familiar with it than I am, but if not:)
Your example of the file open dialog box is identical to what Apple did on MacOS when they implemented sandboxing. Rather than using regular paths in NSString objects, they return you an NSURL with a "security scope" - a capability. These can be saved and reused across process terminations.
Unfortunately, the concept of "taming", where ambient-authority systems are used to implement functionality in capability-safe systems, is often a sad and frustrating path due to massive impedance mismatch. Like you say, paths are not caps, which means that capability-safe languages on UNIX-like systems are constantly dancing to tame the OS.
As usual, it would be great if you made your VM cap-aware, so that we may eventually get over this hump.
It's worth noting that WebAssembly should go nicely with capability systems. Mark S. Miller started a thread on the mailing lists recently about making sure it stays that way.
Wadler's criticisms of jets are pretty common and not super hard to respond to.
Nothing at all stops any jet-based interpreter from using normal standards practices to specify a standard jet profile. We can even expect aggressive vendors to "embrace and extend" that profile.
But, in practice as well as theory, this isn't going to cause incompatibilities, monopolies, etc. Your semantic compatibility is perfect.
In fact, jet competition should have excellent effects on performance across a healthy market. If Google hosts a jet-propelled interpreter, it's natural for it to both offer a tensor processing library, and hook that library up to a jet that talks to a hardware TPU. Your code will work the same if you move off Google -- you're not physically locked in.
What we just got rid of: the bureaucratic overhead of standardizing a TPU opcode. Look at all the crypto algorithms you have to run in JS on the browser, when half the time there's a hardware instruction on the chip. It's technically trivial to connect these two things -- but not politically. Politically, you need a committee to standardize the builtin.
It's true that performance disparities are absurd if you don't jet-propel basic arithmetic. But no one would do that. If a system works both in theory and in practice, it works. You can't really say that in theory, it doesn't work in practice.
(Disclaimer: jet inventor here. But Simplicity's jets are much more badass because of the Coq equivalency proofs.)
On first glance, Cell feels like a very serious effort and I wouldn’t be surprised if it has an impact.
The embedding model is a nice and thoughtful touch. I think a lot of imperative systems could benefit by converting their semantic cores into code in an engine that’s reactive, structurally typed, transactional, and functional-lite (Cell appears to not even have generalized higher order programming, a bold but defensible choice). The relational automata (actors?) are also quite interesting.
Urbit is a clean-slate system software stack defined as a single frozen function. We're looking for:
- Systems generalists who are comfortable at every layer of the stack and want to build beautiful code. Experience in functional programming, compilers, kernels, etc, is nice.
- Designers who can code, or frontend devs with an attention to detail.
The first question (economics) is one we've thought a bit about. Not affiliated with Filecoin/IPFS/Protocol Labs, so these answers may be wrong:
Filecoin creates a market for storage. The price of B2 is an important variable in this market, because it creates an arbitrage opportunity where you can use B2 to mine Filecoin.
But why not just use B2 directly? Three reasons.
One, B2's replication isn't perfect (at least, not as perfect as S3), and both B2 and S3 have nonzero political risk (a sovereign could order them to destroy your data). B2 plus a layer of blockchainy replication could be quite attractive to some low-price-sensitivity customers.
Two, to work with B2, you need a business relationship with B2. This is obviously no big deal in the normal world of multiuser, single-server apps that we live in today.
However, if we can somehow migrate to a world in which users have their own servers, it's much easier for those personal servers to have simple, maintenance-free automated relationships with decentralized token-based services. Think about how many centralized service providers a typical startup has relationships with (and how much they cost). This design can't really be scaled down from industrial computing to personal computing.
Three, Filecoin has an interesting consensus design in which the word "miner" is used in two senses: "miners" participate in storage transactions, and also receive block rewards based on proof of stake, where stake is defined as the storage of the whole system. The effect of this on the economics of Filecoin is extremely hard to predict, but it can only be positive.
The one point that seems unresolved about the economics of Filecoin is this interesting interaction between FC as a cryptocurrency and FC as a payment mechanism in a storage market. It does seem that you could take FC's storage market and port it to an existing blockchain. But there may be more subtle technical requirements from a blockchain -- a storage market is certainly a demanding application.
Tlon builds Urbit, a secure peer-to-peer network of personal servers, built on a clean-slate system software stack. You can learn more about it here https://urbit.org/#learn
We’re hiring developers up and down the stack to work on systems, storage, languages, crypto, and front-end. It’s an entire operating system, so there’s a lot of work to do.
Sound interesting? Get in touch: apply@tlon.io