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:
- Subscribers must be sure they have correctly received any message sent by a publisher
- Publishers must be sure all subscribers can receive their messages
- If someone wants to subscribe to a publisher, the publisher must be able to find out, approve the subscription, and receive payment
- 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
- Send/Acknowledge. A publisher connects to a group of staked intermediaries, and gets them each to acknowledge the post.
- Distribute Receipts. The publisher makes sure every intermediary can prove that the others have acknowledged the post.
- Receive. The subscriber connects to any intermediary at any time, and asks for the post.
- Verify. The subscriber tells other intermediaries what they received.
- 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
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