smartin015 / peerprint

A distributed system allowing for sharing and running of 3D printing jobs
Apache License 2.0
2 stars 0 forks source link

Cross-network (WAN) 3D print queues #2

Open smartin015 opened 2 years ago

smartin015 commented 2 years ago

Is your feature request related to a problem? Please describe.

With the advent of peerprint, printers can now share work over a network. But there's additional benefit to being able to establish a "trusted" network of printers across multiple networks, not just the LAN.

Describe the solution you'd like

Connecting to a WAN queue should be almost as easy as with a LAN queue - however this will likely require some kind of credential / auth step to ensure things remain secure.

There should be a way to perform the same functions as defined in LANPrintQueueBase:

Additionally there should be a batteries-included file hosting option, like the Fileshare class but permitting global access to the file.

File sync

IPFS seems to make a lot of sense here, but the design should allow for an arbitrary URI to permit file hosting in whatever way is easiest. IPFS does seem to require running a server in order to push files (link) so overhead may be an issue on less performant OctoPrint hosts (e.g. older generation raspberry pi's)

Additional context

35 is the parent issue.

smartin015 commented 2 years ago

Update: IPFS was very easy to integrate. Smart contracts took some learning, but I now have an implementation that costs around $0.002 per transaction - yep, 1/5 of a cent.

I've still got bugs to shake out and safeties to add, then it's time to plug back into continuous print and see what breaks.

smartin015 commented 2 years ago

Had some more discussion / did some more research on this today.

A few thoughts:

Trusted WAN (baby steps)

Before moving to fully anonymous / decentralized setups, it makes sense IMO to take one step at a time and add authentication to the existing stack. Blockchain has a high config barrier to entry, so perhaps we save untrusted distributed printing for a later time.

Discovery

Use DNSLink (e.g. on continuousprint.net) to link one or more CIDs containing an IPFS file that is a mutable queue registry. The registry contains a list of WAN queues and "bootstrap" IP addresses available to make a connection for direct P2P style communication. To prevent lock-in, users can specify other IPNS CIDs or DNS names to get their own registry.

An alternative would be to use IPNS, but that has a TTL / requires constant republishing which basically requires reinventing DNS hosting.

Future decentralized domain ownership could be done via handshake.

An example registry schema in YAML form:

version: 0.0.1
queues:
  - name: "test queue"
    description: "a description of what the queue is used for goes here"
    url: "a URL for additional context"
    bootstrap_list: 
      - 111.111.111.111
      - 222.222.222.222

On moderation

Further decentralization requires basic auth/moderation. Accounts should not require a third-party (especially not cloud) authority. This puts us in 'web of trust' / GPG style territory, meaning we'd need to mint a key (or have the user provide one) for each user they wish to have act on the queue (add pubkey to the peers dict object).

Initial implementation: In the registry, trusted peers have the ability (i.e. the signing key) to distribute an allow-list of keys over IPNS to gatekeep inbound peers. Credentials are detached from octoprint instances (e.g. a single instance of octoprint could publish things signed with various keys). In OctoPrint, credentials can be associated with users but don't necessarily have to be (think "service accounts" / "bots").

The IPNS keylist may also link to other IPNS files, allowing for delegated authority and/or sharding. Example schema:

version: 0.0.1
allow_list:
  - PUBKEY1
  - PUBKEY2
  - PUBKEY3 etc.
delegates:
  - /ipns/delegatefile1
  - /ipns/delegatefile2
  - /ipns/delegatefile3 etc

Continue using pysyncobj

PySyncObj is great for consensus and state agreement - but it is not sufficient since it lacks authentication.

go-libp2p-pubsub is a pubsub implementation using the same IPFS distributed systems that has some of this auth stuff already. As a transport layer, it makes some sense.

Combine the two - implement a pubsub-based Transport class that backs pysyncobj's RAFT consensus log, that then gets passed in on init. That changes very little about the overall algorithm, which means we have minimal code paths to maintain.

smartin015 commented 1 year ago

Checkpointing progress so far - it turns out that pysyncobj was harder to integrate with than initially anticipated, so we now have a standalone binary in golang that uses the same go-libp2p and libp2p-pubsub modules that drive other projects like IPFS and go-eth.

Clients (i.e. OctoPrint) interface with this golang binary via a wrapper python script that manages the process and connects to it via zeromq.

smartin015 commented 1 year ago

Changes are now tested and all piled into a pending v0.2.0 release. Next work to be done in https://github.com/smartin015/continuousprint/pull/140.