protoschool.github.io icon indicating copy to clipboard operation
protoschool.github.io copied to clipboard

Feature: Add support for libp2p validation

Open terichadbourne opened this issue 5 years ago • 11 comments

@jacobheun I heard you mention on a call today that the blocker for you to creating meaningful lessons on libp2p in ProtoSchool is that a libp2p node isn't created and you therefore can't do the validation you want to in exercises. I'm sure I'm phrasing that poorly, but I'd love it if you could say more about what would be needed to make the system work for you so that we could potentially add some functionality and turn your content into a ProtoSchool tutorial lesson after IPFS Camp. Thanks!

terichadbourne avatar Jun 05 '19 16:06 terichadbourne

So, we have a few types of interactive lessons that we've put together. Thinking more through this I think we could workaround some of these things. I'll write this out so we can talk through potential options/improvements.

The first type of lessons, are basic configuration lessons like adding transports, discovery services, stream muxers, etc. These should be fairly straightforward to check in the result of validate. An example of this configuring TCP and Websockets might look like:

const run = async () => { /* globals TCP, Websockets */
  // Return libp2p configuration
  return {
    modules: {
      // Add transports here
    },
    config: {}
  }
}
return run

The second type, are directly calling libp2p methods. For example, adding a protocol handler. This would require us being able to check the libp2p instance they used to verify the correct things were added. We can technically get the libp2p instance from ipfs, ipfs.libp2p, but I worry that could just cause confusion. If we modify the libp2p instance, do we get that back in the verify code? If so, instead of checking the result (undefined) we could do some checking on the libp2p instance to make sure it had the protocol registered.

const run = async () => { /* globals ipfs, CustomProtocol */
  // Add the CustomProtocol to libp2p
  ipfs.libp2p.handle(CustomProtocol.protocolTag, CustomProtocol.handler)
}
return run

The third type involves communicating with other nodes. For protoschool, I think we'd need to be able to mock out some of the code. I don't think it makes sense to have actual dial or discovery code running, but mocking those methods would make it easy for us to verify they're doing the correct thing.

const run = async (peerInfo) => { /* globals libp2p, dialHandler */
  // If we could mock/stub `dial` we'd be able to validate it was called with the correct values 
  libp2p.dial(peerInfo, dialHandler)
}
return run

I think the main challenge with the libp2p lessons right now is that a significant part of the learning is in customizing libp2p itself, as that's the nature of how libp2p is designed (bring what you need). I think there are plenty of lessons we could build around using the libp2p apis (provided we could mock certain things to avoid actual network calls), but I think it's valuable they also start with configuring the specific portion of libp2p needed for that.

If we created a lesson where we could have a build progression, that would be helpful. While we wouldn't use the users results from the previously lesson, starting with the previous lessons solution code could be helpful.

A full example could be something such as working with pubsub. It could involve:

  1. Configuring libp2p to use pubsub
  2. Subscribing to topics (starts with the pubsub enabled node from previous step)
  3. Publishing to topics

jacobheun avatar Jun 06 '19 08:06 jacobheun

@mikeal Since you built the internal workings of ProtoSchool originally and are more familiar with libp2p than I am, would you mind taking a look at @jacobheun's suggestions above? Does this proposal look feasible? Any technical challenges you expect we'd encounter?

terichadbourne avatar Jun 13 '19 18:06 terichadbourne

As part of our mid-quarter scoring, and in anticipation of a reduction in folks available, we're deprioritizing this to a P2 and don't expect to get to it this quarter unless any volunteers pop out of the woodwork.

terichadbourne avatar Aug 16 '19 16:08 terichadbourne

@codynhat I believe we chatted about this issue while at Offline Camp. It's something the core ProtoSchool team won't have time for this quarter but we're very open to having others start working on it if it's something that interests you. (I think there was one other person discussing this with us. Was it Tim S.?)

terichadbourne avatar Oct 08 '19 15:10 terichadbourne

@jacobheun just circling around to see if there's interest from the libp2p team in building out this validation support in the near future. The core ProtoSchool team doesn't have the technical experience to make it happen independently in Q1, but we'd be happy to support the libp2p team in understanding the structure of the project if someone there is able to spend some time on it.

As a reminder, the currently lack of ability to create a libp2p node under the hood is a block to creating validated code challenges for libp2p in ProtoSchool, but we could currently create either text-only or multiple-choice lessons on libp2p concepts.

terichadbourne avatar Dec 16 '19 20:12 terichadbourne

@terichadbourne we'd definitely like to get something integrated. We're working on finishing up the async refactor for libp2p. Once that's done, the Getting Started guide we're created would, I think, translate nicely into a ProtoSchool lesson/lessons.

jacobheun avatar Dec 16 '19 21:12 jacobheun

@raulk has confirmed that the async refactor for libp2p is complete. @zebateira will update us tomorrow on what he's learned about the limitations of the in-browser JavaScript implementation of libp2p so we can continue the conversation with the team about what under-the-hood setup will best unlock the creation of useful content in ProtoSchool.

terichadbourne avatar May 14 '20 17:05 terichadbourne

Thank you @terichadbourne!

So after my convo with @vasco-santos I learned that the libp2p team is still working out the issue of peer discovery in the browser without a server. The current solution right now is to use a signaling server. I think that would work for us since the server would be very low maintenance and low infra requirements. And in the future we would be able to remove it. But let me know if this is an option for us.

zebateira avatar May 15 '20 10:05 zebateira

So, we have a few types of interactive lessons that we've put together. Thinking more through this I think we could workaround some of these things. I'll write this out so we can talk through potential options/improvements.

The first type of lessons, are basic configuration lessons like adding transports, discovery services, stream muxers, etc. These should be fairly straightforward to check in the result of validate. An example of this configuring TCP and Websockets might look like:

const run = async () => { /* globals TCP, Websockets */
  // Return libp2p configuration
  return {
    modules: {
      // Add transports here
    },
    config: {}
  }
}
return run

The second type, are directly calling libp2p methods. For example, adding a protocol handler. This would require us being able to check the libp2p instance they used to verify the correct things were added. We can technically get the libp2p instance from ipfs, ipfs.libp2p, but I worry that could just cause confusion. If we modify the libp2p instance, do we get that back in the verify code? If so, instead of checking the result (undefined) we could do some checking on the libp2p instance to make sure it had the protocol registered.

const run = async () => { /* globals ipfs, CustomProtocol */
  // Add the CustomProtocol to libp2p
  ipfs.libp2p.handle(CustomProtocol.protocolTag, CustomProtocol.handler)
}
return run

The third type involves communicating with other nodes. For protoschool, I think we'd need to be able to mock out some of the code. I don't think it makes sense to have actual dial or discovery code running, but mocking those methods would make it easy for us to verify they're doing the correct thing.

const run = async (peerInfo) => { /* globals libp2p, dialHandler */
  // If we could mock/stub `dial` we'd be able to validate it was called with the correct values 
  libp2p.dial(peerInfo, dialHandler)
}
return run

I think the main challenge with the libp2p lessons right now is that a significant part of the learning is in customizing libp2p itself, as that's the nature of how libp2p is designed (bring what you need). I think there are plenty of lessons we could build around using the libp2p apis (provided we could mock certain things to avoid actual network calls), but I think it's valuable they also start with configuring the specific portion of libp2p needed for that.

If we created a lesson where we could have a build progression, that would be helpful. While we wouldn't use the users results from the previously lesson, starting with the previous lessons solution code could be helpful.

A full example could be something such as working with pubsub. It could involve:

  1. Configuring libp2p to use pubsub
  2. Subscribing to topics (starts with the pubsub enabled node from previous step)
  3. Publishing to topics

@jacobheun going through your ideas for types of lessons, I think they look great and feasible. So if we go with the strategy to mock libp2p api methods that require network operations, I don't see any limitations on what we can teach at Protoschool.

Now the only concern I have is that we really wanted the libp2p tutorial code challenges to actually run code (not mocks), but since we have tech limitations (if we don't use a sig server), I think it is reasonable. We just need to be careful about making sure the code we present to the user is as close as possible to a real code example.

zebateira avatar May 20 '20 14:05 zebateira

@terichadbourne @raulk @vasco-santos and me had a call today to discuss where to go from here.

  1. libp2p node transport/discovery:

    • after some thoughts on it, we don't believe mocking is a good sustainable solution: it is a fragile approach with regards to future maintenance of the validation code. A simple major release upgrade is already a lot of work, so on top of that supporting unofficial changes to the internals is not something we can afford to do.
    • @raulk mentioned two other ideas to explore (besides the signalling server): window.postMessage and Service Workers
  2. Content: Tutorial Ideas and others

  3. Next:

    • I'll proceed with investigating if it is possible to have local discovery with either window.postMessage or Service Workers (with the help of @vasco-santos if needed) by creating a custom transport.

zebateira avatar Jun 16 '20 15:06 zebateira

🔄 Update on this:

  • I'm almost done creating a memory transport for js: https://github.com/zebateira/js-libp2p-memory
  • So instead of using window.postMessage or Service Workers we can just have two nodes connect to each other in-memory
  • You can see the latest work on the branch libp2p-memory.

zebateira avatar Feb 18 '21 15:02 zebateira