berty / weshnet

Async Mesh Network Protocol for Extreme Communication -- Innovative, Resilient, and Decentralized
https://wesh.network
Other
151 stars 26 forks source link

Blockchain network on top of Weshnet? #64

Open stanbar opened 1 year ago

stanbar commented 1 year ago

Asking a question, not reporting a bug

Is there an existing issue for this?

Question

Hello, I'm building a p2p voting system and found Weshnet to ideally match my network assumptions. However, in our voting protocol, we have to assume that some nodes are malicious and want to manipulate the voting results. As a result, we need some byzantine fault-tolerant consensus mechanisms (ideally something like blockchain).

You mentioned why you don't need Blockchain for Berty app. But for the voting protocol, it's essential to determine the order of the messages, AFAIK Conflict-Free Replicated Data (https://berty.tech/docs/protocol/#conflict-free-replicated-data-type) won't help with byzantine nodes.

We need to achieve a consensus on the order of messages over participants of a group. Something like PBFT/Tendermint/Stellar Consensus Protocol (FBA) would work best. Can you suggest me some approach? Or maybe someone else tried to do that?

Context

The context has been described in the field above.

jefft0 commented 1 year ago

I'm not an expert on Byzantine nodes. The Wesh protocol is designed for delay-tolerant networks which only need eventual consistency among nodes. But they will reach consensus on the order of messages when all of them have arrived. But I don't know enough to suggest an approach for your use case.

Without implementing consensus directly in the Wesh protocol, you could use it as the lower messaging layer of some consensus system. Does that work?

stanbar commented 1 year ago

they will reach consensus on the order of messages when all of them have arrived.

The problem is when a (malicious) node sends two messages with the same lamport's clock time. How can other nodes determine which one is valid and which one is not? Consensus is needed to agree on one of many conflicting versions.

I did some research and found a paper Making CRDTs Byzantine Fault Tolerant. The author promises:

This paper shows how to adapt existing non-Byzantine CRDT algorithms and make them Byzantine fault-tolerant. The proposed scheme can tolerate any number of Byzantine nodes (making it immune to Sybil attacks), guarantees Strong Eventual Consistency, and requires only modest changes to existing CRDT algorithms.

Here is a discussion on Hacker News about making CRDT byzantine fault tolerant.

Building a consensus mechanism on top of Wesh would be the best option. However, I'm not sure how to do it using Wesh. Your tutorials don't cover sending messages. I'm sure you are working on it, but could you please sketch how would implementing consensus protocol on top of Wesh look like? It would save me a lot of time 🙏

stanbar commented 1 year ago

Since you use orbit-db underneath I also asked them for more information https://github.com/orbitdb/orbit-db/issues/1073

jefft0 commented 1 year ago

The Lamport clock uses a counter and the public key of the sender. A malicious user can send a message with the same Lamport clock (public key) as another group member, but the message signature will fail and will not become part of the message log, because the malicious user doesn't have the corresponding private key. (I'm pretty sure about this, but I could verify with our cryptographers.) The signature failure will prevent the problem you mentioned, right?

stanbar commented 1 year ago

The problem is a bit different.

AFAIK the structure of messages in Wesh is like this:

{
  payload: "A",
  lamportClock: {
    time: 1,
    id: "0x123zxcv..."
  },
  signature: Ed25519(privkey, this.payload, this.lamportClock)
}

I'm ignoring the symmetric ratchet protocol as it doesn't change anything.

The problem is that a (malicious) user can create two conflicting messages:

const voteForA = {
  payload: "A",
  lamportClock: {
    time: 1,
    id: "0x123zxcv..."
  },
  signature: Ed25519(privkey, this.payload, this.lamportClock)
}

// and

const voteForB = {
  payload: "B",
  lamportClock: {
    time: 1,
    id: "0x123zxcv..."
  },
  signature: Ed25519(privkey, this.payload, this.lamportClock)
}

They are both equally valid. Then the user broadcasts voteForA to half of the network and voteForB to the other half. Now the problem is, how the whole network can agree on one message. Nodes can not accept both because they are using the same time: 1.

jefft0 commented 1 year ago

I see. Thanks for the clarification. I thought it was one malicious user trying to displace another user's message, but you are talking about one malicious user abusing the protocol with two conflicting messages. I have to ask about whether the Wesh protocol has a consideration for this.

jefft0 commented 1 year ago

Hi @stanbar. I did a quick read of the paper Making CRDTs Byzantine Fault Tolerant. One of its recommendations is to use the hash of an entry. Go-orbitDB is based on go-ipfs-log. It does use the entry hash in case two Lamport clocks are the same. So, there should not be the ability to replace one entry by another with the same Lamport clock. I know this doesn't fully implement the recommendations, but it is at least something. See the code: https://github.com/berty/go-ipfs-log/blob/master/entry/sorting/sorting.go#L66

bitnom commented 1 year ago

@stanbar I'm in a similar boat as you for an MVP. Check this out: https://github.com/jackyzha0/bft-json-crdt

GitHub
GitHub - jackyzha0/bft-json-crdt: 🏰 the first JSON-like Byzantine Fault Tolerant CRDT
🏰 the first JSON-like Byzantine Fault Tolerant CRDT - GitHub - jackyzha0/bft-json-crdt: 🏰 the first JSON-like Byzantine Fault Tolerant CRDT
jefft0 commented 1 year ago

We are looking at working with some blockchain/smart contract projects but no details yet. We will keep this issue open and update when we know more.

stanbar commented 1 year ago

@bitnom any update on that? How is your MVP going? Did you figure out how to do it?

jefft0 commented 1 year ago

The blockchain project is moving along, but we haven't gotten to the part where we will use Wesh for off-grid communication. Be aware that the project is not to implement a blockchain on top of Wesh, but to use Wesh for some of the operations in the existing blockchain system which can be done off-grid. For example, to access a device offline to sign a transaction. Or to update a message list (with Wesh) which will later be synced with the blockchain (not using Wesh).