Call for help - Limitations with js-ipfs #2093
Description
Hello everyone!
This is a call for help 🙏. As some of you know, I'm going to give a workshop about IDM and Nomios in IPFS Camp. In a glimpse, IDM is a concept and specification for an Identity Wallet, based on DIDs, Verifiable Credentials and DID-Auth. Nomios is a Identity Wallet based on IDM, but anyone can build their own.
One of Nomios' goals is to work within the browser, without requiring users to install or setup external tools, such as IPFS Companion or JS/GO daemons. This doesn't mean that Nomios will be usable solely in the browser. In fact, the closer to the OS the better as it gives us a better user-experience, more capabilities and increased performance. Though, asking users to install something "native" - like an Electron based app - will yield better results after they are "sold" into the product.
This is where I need help. Here's a list of things I use from IPFS that must work within the browser:
The js-ipfs route
ipfs.dag.get
& ipfs.dag.put
We are using OrbitDB to store and replicate data amongst wallets, which in turn uses ipfs-log
. That module uses the DAG API to build a immutable log based on a Merkle DAG. Moreover, the DAG API is also being used by did-ipid
to store DID Documents.
❌ Using the latest version of IPFS in the browser, I'm unable to do ipfs.dag.put
in one browser and fetch it using ipfs.dag.get
in a different browser. The promise takes forever to resolve and eventually times out. The behavior is the same when attempting to resolve from the ipfs.io public gateway. My understanding tells me that this should work without any tinkering since preload
is enabled by default, making the content available to bootstrap nodes faster. Here's a codepen for everyone to try: simply open that URL in Chrome and Firefox and try to resolve the CIDs from each other.
✅ You will notice there's some commented code in index.js
file of the codepen, which defines a Swarm
value pointing to a Websocket Star server. This makes things work but isn't this a bit centralized since all discovery and traffic goes into it? I'm ok in using this for the workshop, but I'm interested in hearing alternatives. Shouldn't preload
make things work "magically"? Shouldn't WebRTC help here?
ipfs.add
& ipfs.get
The FILES API is used to store blobs, such as the identities images.
❌ The problems exhibited here are the same as ipfs.dag.get
& ipfs.dag.put
.
✅ By using a custom Swarm
pointing to a Websocket Star server, fetching files are pretty fast.
ipfs.keys
, ipfs.name.publish
and ipfs.name.resolve
One of the first DID methods we are supporting is ipid
.
(ipid) is and implementation of the DID (decentralized identifiers) specification over the IPFS (Interplanetary File System) network using the IPNS (Interplanetary Name Service) cryptographic namespace resolution service.
IPID based DIDs have the following shape: did:ipid:<ipns-name>
. To resolve these DIDs to DID Documents, we need to resolve the IPNS record. Moreover, to both create or update a DID Document, we need to publish the IPNS record to point to a DID Document's CID.
The IPNS key is not the IPFS node identity. Therefore, we need to be able to temporarily import the key using ipfs.keys
to publish the IPNS record. After the publish succeeds, the key is removed. This makes the republishing impossible but this will later be solved with improvements to IPNS that allow for third-party republishing. For now, we are setting a high lifetime
(1 year) to circumvent this limit, but we don't know if it's being respected.
❌ Publishing of IPNS records succeed but then I'm unable to resolve them in a different browser, failing immediately saying that it's unable to resolve the record. The issue I think is that we don't have DHT enabled yet and it's blocked until #1984 is fixed.
✅ I'm inclined to use the work that @hugomrdias did on a tiered IPNS approach where he used CloudFlare workers (or wait for the DNS based approach). I haven't yet fully tested it in the browser but it seems to work within the JS daemon. This is indeed a bit centralized but it works reliably if we have an internet connection.
PubSub
PubSub is used by OrbitDB to replicate data between wallets.
Swarm
value pointing to a WebSocket Star server. This is a similar requirement than the one mentioned in ipfs.dag.get
& ipfs.dag.put
, but I would prefer peers to connect directly via WebRTC or similar than using a WebSocket Star to relay traffic.
The external daemon / go-ipfs
route
Besides the solutions mentioned above, I tried to explore other ways, including ones that go against the original goal of not requiring setting up or installing external tools:
- IPFS Companion with an external daemon
❌ ipfs.name.publish
and ipfs.keys
are not yet supported, see ipfs/ipfs-companion#452.
- IPFS HTTP Client with an external daemon
❌ Doesn't support PubSub in browsers yet, see: ipfs-inactive/js-ipfs-http-client#518.
This was a summary of my investigation. Please keep in mind that this thread is not to blame anyone but to improve the project for use-cases such as mine. I count with everyone's experience to find solutions other than the ones I mentioned. 🙏
//cc @alanshaw @daviddias @pgte @vasco-santos @hugomrdias @jsoares
Feel free to mention anyone relevant to this discussion.