Does my publishing platform design make sense to you?

Hi there!

I’m trying to build a censorship resistant publishing platform on Ethereum. I have a general idea of how to build it with Nitro/ForceMove and I would love some feedback on whether my idea makes any sense, and where in your code I should look to start building. It’s a long post so I appreciate even a cursory glance and a little feedback!

Features

The platform only needs a few features:

  1. Subscribers must be sure they have correctly received any message sent by a publisher
  2. Publishers must be sure all subscribers can receive their messages
  3. If someone wants to subscribe to a publisher, the publisher must be able to find out, approve the subscription, and receive payment
  4. Publications must be encrypted such that only they and the subscribers can read them

The challenge here is that publishers and subscribers shouldn’t have to be online all the time. The solution I’ve though of, is to have a set of high-uptime intermediaries who, in a sense, create a virtual asynchronous channel between publisher and subscriber.

This post will focus on my solution for features 1 and 2.

Publishing

So how do we publish a message? Basically we give our new post to a group of intermediaries who are incentivised to tell subscribers about the post, and highly disincentivized to lie.

Protocol

  1. Send/Acknowledge. A publisher connects to a group of staked intermediaries, and gets them each to acknowledge the post.
  2. Distribute Receipts. The publisher makes sure every intermediary can prove that the others have acknowledged the post.
  3. Receive. The subscriber connects to any intermediary at any time, and asks for the post.
  4. Verify. The subscriber tells other intermediaries what they received.
  5. Challenge. If an intermediary gives false information about what was published and the another intermediary finds out, this other intermediary receives the entire stake.

Example

Setup

Say, for example, that publisher P has a single subscriber S , and there are mutually known intermediaries {I1, I2 … In}, whose IP addresses are published on chain and are assumed to be highly available. If P wants to publish M , they should encrypt M using S 's key, giving ciphertext C.

Send/Acknowledge

P then establishes a state channel with each Ii, and pays them a small fee to receive a signed receipt Ri saying they have received C.

I think this can be a simple two state ForceMove channel. The channel is probably virtual, so that the publisher only has to establish a deposit with a single intermediary. (aside: is it reasonable to establish n virtual channels using one deposit in a short period of time?)

Distribute Receipts

Then, P sends each receipt Ri to every other intermediary Ij!=i. Now we can be sure that every intermediary has received the encrypted message, and every other intermediary knows every intermediary has received the message.

I don’t think this needs to be done over a state channel, since there is an incentive on either side: Ij!=i wants the receipt for the chance to win Ii's stake, and P wants Ij!=i to get the receipt to keep Ii honest.

Receipts

Now, when S comes online and wants receive posts from P, they can connect to any intermediary (let’s say I0), and pay them for the messages from P via a state channel.

This should be a similar two state ForceMove virtual channel as in Send/Acknowledge.

Verify

Now, in order to verify that the intermediary can go to any other intermediary (let’s say I1) and tell them what I0 sent them.

Challenge

If there is any inconsistency between I0's receipts, and what I0 sent to S, I1 can retrieve all of I0's stake on chain. If there is an on-chain challenge, S can be sure they were given false information, and they should ask a different intermediary. If there is no on chain challenge, they can be fairly certain they were given the right information (assuming P correctly gave all appropriate receipts to all intermediaries).

Timing Receipts

Receipts should specify that I knows about certain messages at a given time, not in general.

Suppose, in the scheme I described, I has not received a message from P, then I is asked for P’s latest messages by S and I says there are none. Now if P publishes a message I will be forced to acknowledge it, and now their stake is at risk, given they have already declared that there are no messages.

I believe this can be solved by I’s receipts only declaring that a given message was known at a certain time. This can probably be done by having a receipt apply from the current block onwards (or perhaps the next or the one after that etc to offer some leeway).

Publisher trickery

The protocol described assumes that P and S are cooperating to ensure I relays the message faithfully. However, P might try to get S’s payment without giving them the appropriate message. Some kind of hash based commitment scheme could be used here to help S verify that P’s message is correct and there are no missing messages.

Subscribing

Subscribing will hopefully be able to work via a similar asynchronous channel mechanism. Basically, the subscriber will give a payment to an intermediary, on the condition that it’s transferred to the publisher, along with the subscriber’s address. The publisher will acknowledge this more or less at their leisure, and will subsequently be forced to include messages to the new subscriber in any publication.

There is more game theory to be worked out here though. We should make sure the publisher must acknowledge (or reject) new subscribers before making a new post so they can’t hold a subscriber’s payment in limbo without posting to them.

What I don’t yet understand

Gas issues

One critical issue here is gas. Since I’ll be implementing this as a set of ForceMove channels, one participant can always become non-reactive to make their opponent force a move on chain. In short, how do you analyse these system’s without making the " Simple Transition Rule" assumption?

Libraries

It looks like the nitro-protocol in the statechannels repo is the right place to go to get started building. Is that about right? I have read the nitro whitepaper and believe I understand it, and am currently reading ForceMove (having read the state channels blog about it). Is there anything else you think I should look at for this project?

Thanks :wink:

Thank you to anyone who took the time and effort to read through and understand this! I appreciate the work you guys have done and I think this will be super critical to scaling Ethereum in the future.

Cheers,
Blake McAlevey-Scurr

1 Like

Hi Blake!

You’re a few days shy of a (hopefully) more accessible introduction to virtual channels. I’ll forward you a blog post soon that might help, but I’m not sure that virtual channels are exactly what you’re looking for in this case.

The main benefit of virtual nitro channels is that the intermediary is involved in the setup (funding) and teardown (defunding) of an “application channel”, but:

  • the intermediary does not need to know about the application logic used by the app channel
  • the intermediary is not involved in updates to the app channel
    In other words, virtual Nitro channels allows the intermediary to be application-agnostic.

In your case, the intermediary plays an important role in the application itself! So, you might want a 3-party state channel. (The virtual funding protocol may still make sense, but it’s different from the use case so far.) I need a bit more time to parse your post, and this week is a bit of a crunch for me, so we can get back to you more on this next week.


Now, 3-party nitro channels today are probably quite awkward: nitro currently supports “round robin” turn taking, ie: Alice updates, then Bob updates, then Charlie updates, then Alice, then Bob, then Charlie, etc. It also supports “multi-sig” style state channels, where every participant must sign every state update for the update to be valid.

It does not currently support more interesting turn taking, like:

  • from a “consensus” state, signed by everyone, any participant can make an update
  • no participant can make more than one update between two “consensus” states

We’ve been thinking through the implications of “dynamic” turn taking like this. Your use case may benefit from this relaxation of the base Nitro protocol!

Again, you’re a few days early, but I hope to explain this idea in more detail in an upcoming blog post. If you leave me your email, I can share a draft with you when it’s ready.


Now, I’ll answer some specific questions.

We’ve got a protocol tutorial that might be a perfect fit for you! It may be a bit out of date, so if you run through it and find some issues, don’t hesitate to let us know. (In fact, please leave us feedback in any form, if you do the tutorial.)

Keep in mind through this that we are currently investigating some protocol changes that will allow for more flexible application designs. So, you may find it difficult to express what you want to do in a 3-party state channel, but it might get A LOT easier in the short-term.

I’m not sure I understand the question. What’s the “Simple Transition Rule” assumption?

What aspect of the system do you want to analyse? Do you want to understand the gas cost of the sad path, where a participant becomes non-reactive or acts maliciously?

1 Like

Hi Andrew!

Thanks for getting back to me, your feedback is super helpful.

I think my protocol idea is a little half baked, I’ve already changed my mind a lot about the implementation over the last few days, so I wouldn’t want you spending too long chewing on it! The goal of making a publishing platform will remain though. I think the main challenge will also remain, which is that Alice and Bob want to create and advance a state channel without being online at the same time, since they’ll both be using a short lived client like a webpage, and I don’t want to route them through a centralised server.

I’m working on a more carefully thought out solution and I’ll post on this forum again when I think it all makes sense.

You’re totally right that the intermediary in my system plays a role in the application! I’d actually like to change that, and just have them act as communication channel between Alice and Bob, over which a state channel can be run. The PubSub stuff would be run over that asynchronous channel.

I think you’re right to point out that this isn’t really like a Nitro virtual channel though, however I’m not sure a 3-party state channel will work either, since it would presumably require all three parties to be online at the same time.

Great I’d be interested in any relaxation in the protocol! It’s blakemscurr@gmail.com.

Great, I’ll give it a go!

Yes exactly, I wondered whether a participant could force a lot of gas fees on another by being non-reactive all the time. But I actually realised that (at least in the 2 party case), even if they’re making their opponent spend gas on force-move, they have to spend gas on respond, so they have a strong incentive to cooperate in the first place. Although, I don’t quite understand how this would happen in an 3+ party channel: if Alice is non responsive and Bob calls force-move, it’s Charlie who has to pay gas to respond.