Category: DistributedComputing

  • When do we get a Privacy-Preserving CDN?

    The surveillance-capitalism business model that defines the Internet today is only going to get more imposing. The vast majority of our online requests today are serviced and logged by centralized infrastructure – even more centralized than what we probably expect.

    While our collective hivemind takes rightful pride in the successful pushes that have improved this situation, most notably encryption in transit (HTTPS), we are still very much losing the war on metadata. Even when the payload is opaque, the who, when, and where of data access sheds an unfortunate amount of insight into our social networks and our behavior.

    This isn’t a fundamental tradeoff – but we need to invest and evolve our systems to protect ourselves from second order effects of metadata collection.

    Efficiency & Privacy

    Centralization is not an inherent evil, and it is on the path of least resistance for improved performance. It is the second-order effects that are the main risk.

    Caching data at the “edge”—physically closer to the user— is a natural performance optimization in minimizing the speed-of-light constraints. This should be aligned with our privacy goals – less hops in the network will see requests and traffic in a well designed system. Similar performance outcomes lead to single entities controlling constrained back-haul infrastructure (efficient spanning trees). This itself is not a problem, but it is natural for these powerful entities to then want to leverage the value of data they are transiting from their privileged positions, and especially in cases where the infrastructure providers extend to smarter ‘value added’ services, this secondary effect of value extraction leads to unfortunate designs for collection, logging, and eventually manipulation of traffic.

    With the rise of advanced traffic analysis and machine learning, the “anonymity” we enjoy thinking that our requests aren’t analyzed because of the scale of traffic they are ‘hidden’ within is no longer realistic. As analytical capabilities increase, the power structures exploiting this data will become more effective and will work even harder to embed themselves into core infrastructure.

    What does a better structure look like?

    To build a CDN resilient to modern passive and active surveillance, we need to go quite a bit beyond encryption. We need the infrastructure and system designed to limit metadata leakage. The good news is that there are both good research ideas and deployed systems that chip away at many parts of this problem already.

    Decoupling Identity from Intent (Oblivious HTTP)

    The most immediate path already charted by IETF drafts and Apple’s Private Relay is to have an independent entity relay traffic between the client and content. This can mean that the intermediary will know the user’s IP  but not the piece of data being asked for, and the content provider knows the content served, but not the user’s identity.

    This “de-linking” is important, but it is not by itself the end of the story. In the last decade, we have seen how easy it is to fingerprint the traffic signatures associated with visiting a website (which will involve loading a range of resources, each of a different size). A more effective mental model may be to think about the traffic patterns that would be generated by a series of back-and-forth conversations. Protecting metadata in this ‘repeated game’ scope will yield different systems than limiting scope to a single request. 

    Differential Privacy and Cover Traffic

    These fingerprinting concerns have been the impetus for a range of research looking at defenses. One important piece of intuition that has emerged from this field is that we must be willing to stray from optimal efficiency. There are a number of ways to do this: we could inject ‘fake’ traffic, fit requests into a pre-defined pattern, or increase latency to grow an anonymity set.

    Some examples of systems taking different approaches in this design space include:

    • Nym adds differential cover traffic to make an argument for statistical deniability in its mixnet design, while Tor trades off its resistance to a “global passive adversary” against latency and practicality concerns.
    • Pond was a proof of concept messenger demonstrating usage-agnostic communication patterns.
    • Mullvad offers the ability to add cover traffic to reduce classifiability of individual webpages.

    Private Information Retrieval (PIR)

    Private Information Retrieval” refers to the class of systems that answer a specific question: how can a user retrieve an item from a database (or cache) without the database learning which item was selected? While historically computationally expensive, recent advances suggest that sub-second, privacy-preserving cache lookups can be possible at scale.

    • Kohaku – is an ethereum wallet project demonstrating using PIR for hiding reads
    • Iphone live caller ID is the largest user of PIR currently

    Content Addressing and Blinding

    A variety of more exotic techniques for data transfer have been explored in the contexts of content addressed systems like Bittorrent and IPFS. A number of useful ideas have resurfaced in these contexts:

    • Files and data generally can be thought of as a series of fixed sized ‘chunks’, which helps with speed, and is already pre-requisite for the preceding constructions.
    • By requesting data by its hash, the response becomes verifiable by the client – so we can split who is responsible for ‘availability’ (any other peer) vs what the data is (the source leading us to get data in the first place). It also means that we don’t have to go to a single origin, but are more naturally able to take advantage of caches.
    • We can separate ‘discovery’ (the DNS equivalent of figuring out who might have data) with the transfer of the individual blocks from those peers, and get past a standard client-server model with minimal additional cognitive complexity.

    Reducing Centralization & Segmenting Information

    There have been a number of projects in the last year, mostly riding on the wave of interest in ‘DePIN’ (decentralized physical infrastructure networks) that looked at economic models for how protocols could directly split earnings with participating network nodes. This extends the coordination systems ideas from cryptocurrencies to how things like CDNs could be constructed to incentivize a decentralized group of participants to operate participating caches / parts of the overall network around the world.

    These systems sit somewhat orthogonal to a set of prior research on ‘Sybils’, which indicates there’s an additional coordination system of some sort needed to actually reduce centralization. Conceptually, if you set up incentives so that there are more rewards (and an incentive) for many small participants to form a network rather than a big central player, the large central player can generally split up their resources and make themselves look like multiple smaller entities (called ‘Sybils’). This means there needs to be some mechanism to confirm that different entities are really ‘independent’ if that is a desired property. A number of mechanisms – using social networks, or various forms of human identity have been proposed for this, though all with caveats.

    What’s next?

    We are missing two important pieces in the story of privacy preserving content delivery. The first is that there is currently no shelling point for this effort. Existing centralized players have been so far disincentivized from investing in this direction, because it is at odds with their business model, and there has not yet been a credible community effort that has emerged. 

    The second is that much of the market is driven by price. The reason there was a substantial shift from Amazon S3 to Cloudflare R2 was not because of a technical innovation, but because Cloudflare was able to leverage their infrastructure position to provide the same service at a cheaper price. The shift that allows for subsequent disruption is likely partially regulatory – that liability around the collection and exploitation of metadata needs to be disincentivized and in so doing leads customers to switch to a ‘safer’ or more privacy-preserving alternative.

    There is hope! Code is becoming cheaper to generate and deploy, so the marginal cost of building is dropping. On the flip side, the value of a Shared Private CDN will grow with usage. – This feels like a situation where the trick will be to get enough excitement and activation energy.

    We don’t just need better protocols; we also need the coordination, but there is hope and increasing incentives that make me optimistic that a better system here will emerge.

  • On Trust

    There has been a fair amount of effort on UCAN (User Controlled Authorization Networks), and other types of ‘decentralized credentials’ over the last couple years. These efforts perpetuate the same control structures that exist today, with delegated trees of hierarchical control. This is in contrast to a personal or ‘decentralized’ trust we might hope for in peer to peer networks. It is difficult to use DIDs, UCANs, or other proposed mechanisms for reputation and network formation without finding ourselves back trusting an authority – they are both easily captured and naturally lend themselves to centralization of control. We need a fundamentally different trust infrastructure in order to build resilient, peer to peer networks.

    On non-hierarchical models for trust

    The main barrier is not a technical one – we have seen technical implementations (e.g. the GPG web of trust) for decades. There is an intuitive design for how a flat trust model can be implemented. The problem lies in a dis-satisfaction from the emergent properties of that naive network structure. This tension has been framed in a couple different ways. One perspective is that the user experience in bootstrapping trust is overly cumbersome, and this friction leads to an insufficiently dense trust network. A different perspective on the same tension is that a user-driven trust system is at-odds with transitive / automatic trust relations, and that actions to ‘ease’ the user experience are fundamentally reducing user control.

    We can find a space for exploration, by calling out this tension as a false dichotomy. The choice is not between a single authority vs user-directed trust links, but about distributing trust structures. There is a space for organic / automatic way to generate and allow for the reflection and evolution of trust that is neither user-directed nor rooted in a single authority. The bit-torrent tit-for-tat mechanism is one form of this, where protocol-compliant behavior leads to an increasing buffer for data transfer within the protocol.

    Trust or Reputation

    There is a related notion that is more regularly referred to in protocols as a concept of ‘reputation’. Reputation can be viewed as a property of a node in a system rather than one of an edge. (e.g. reputation is often constructed as a metric that is transitive, or where a node has a single consensus value. This is different from how we normally think of our personal trust in another user.)

    What then exactly are we trying to capture in a measure for ‘Trust’? In the hierarchical systems of web 2, it’s meant to provide some assurance that “someone is who they say they are”. It isn’t an indication that there are ‘aligned beliefs’, but rather that the expected entity is behind a given identifier. The properties that come from systems like TLS / CAs look very similar to reputation in this sense. While each individual can over-ride and manually configure which authorities to trust, that definition of trust is meaning a confidence in adherence to protocol and of coherence between expectation and reality.

    Scoping trust

    A challenge we sometimes run into when talking about trust as it relates to technical networks is that our expectation of scope is typically much more limited in digital or transactional contexts than they are in real life. When you refer to a person as a “trusted individual”, the implication is not only that this is not an ‘imposter’, but also that the person has some level of altruism or aligned / positive motivations. While some formulations use reputation as a stand-in for this additional notion of trust, I would argue that it is perhaps better thought of as an understanding of motivations. The trust is that it is understandable what game someone is playing, what their motivations are, and thus what their rational behavior will be.

    Narrow interactions, like those scoped in technical protocols, are intentionally limited to exclude externalities, but this also makes it difficult to understand if other nodes have ulterior motives in participating in the protocol. The analysis of what can be learned by a participant, and the other uses that can be derived from participation is not always easy to analyze, and the lack of completeness is unsatisfying. In contrast, the design of protocols to not leak information is difficult-to-impossible, and difficult to justify. Even the determination and understanding of risk present in a system is an expensive proposition.

    Categorizing mechanisms

    How do we build distributed notions that reflect this notion of confidence that another participant is also playing the same game as us?

    If we take the narrower view of actions within the protocol, we can get to a somewhat useful taxonomy of work in this space.

    • The bit-torrent tit-for-tat algorithm uses the demonstration from the other participant that they’re following the protocol as a signal to continue the conversation.
    • A set of protocols use a proof of work, or computational puzzle as a way for participants to demonstrate that it is worth something to them to participate.
    • Protocols like TLS have added revocation lists, and things shaped like “proofs of bad behavior” as ways to share knowledge of identities that have misbehaved. If the cost of creating an identity is high, and your misbehavior causes “reputational damage”, your rational behavior becomes more incentivized to follow the protocol.
    • Finally, there is emerging growth of validation-based protocols. Cryptographic proofs are increasingly able to provide an assertion that computation has been performed per the expected protocol, and reduces the space of valid-but-not-compliant actions that can be taken.

    The complement to this category are protocols that make use of external costs. In many cases the cost is difficult to quantify, which leaves modeling of the strength of the protocol trust levels equally difficult to pin down. At the same time, it means that there is the ability for costs to be higher relative to what could be built into a protocol in isolation.

    • Protocols which involve a validation of ‘real name’ (linking an ID, bank account, cell phone, etc) are able to retaliate for misbehavior using the legal system.
    • Protocols involving social graphs use the potential of negative impact to your standing with your friends.
    • Protocols requiring registration with a phone number, or who distribute their app only for mobile devices are leveraging the cost of those assets as part of the account cost.

    Increasing trust

    From the previous categories we can see that there are two ways that they end up leaning on for increasing this notion of trust.

    The first is increasing the cost of defection. Increasing the costs tied to creating or re-creating an account increase this cost. Impacting a reputation or decreasing utility likewise are ways to increase the cost of not following a protocol

    The second way that trust is increased is by increasing a user’s confidence that they will be able to succeed in getting resolution when another user defects. In most of the ‘in protocol’ cost models, resolution occurs as part of the protocol itself. Bit-torrent won’t continue rewarding peers that aren’t honoring the tit-for-tat agreement. Submitting a computation without a valid proof transcript will be ignored. It is the out of protocol actions where this subjective confidence is most at issue. Actions like Facebook suspending Cambridge Analytica (and publicized moderation actions more generally) demonstrate to users that enforcement is taking place.

    Full circle

    How do we provide decentralized notions of trust that can be dense and mesh with protocol needs for automatic establishment?

    By ensuring that the risk associated with a trust link is less than what can be mitigated when trust is broken. This can be done in one of three ways:

    1. The benefit of breaking trust can be reduced
    2. The cost associated with punishment can be increased
    3. Regularity (or user perception) of breaking trust leading to punishment can be increased

    Concretely, the hesitancy to form a mesh network comes most often from the lack of a concretely defined threat model. When a protocol comes with a well scoped definition of misbehavior, it is typically much easier to enforce compliance and to frame the protocol in a way that provides comfort to participants.

    It’s worth noting that we are often concerned with one of the hardest forms of this scenario – which is balancing the ease of participation in a system with the indirect and difficult to identify surveillance risks. Concrete examples of this tension are nation-state identification of Tor users, RIAA identification of bit-torrent users, or IRS identification of crypto currency users. In all of these cases, a user joining the protocol may behave as normal, but may also record network identifiers of other participants they encounter. An unaccountable out-of-protocol leaking of these known identifiers then leads to repercussions to other participants. I don’t know if the preceding discussion is the best framing in this specific case. I think it can be used as a lens still, but the interesting question here is mostly around the first point of reducing the benefits around breaking trust, and in reducing the signal that such an attack gets in the initial level of participation in the protocol.

  • Retrieval Constraints

    A couple months ago I wrote up some of the edges that I’ve encountered in thinking about how to structure decentralized data transfer systems. These are an extension of the limitations that were initially encountered in bittorrent style tit-for-tat exchanges, and have now matured into a much more extensive field looking at incentives and other mechanisms that can be leveraged to create robust systems.

    See the long-form essay on mirror

    My top take-away from this line of thought is that it does seem like within our initial framing of how data transfer might happen we end up still relying on reputation as a way to estimate transferability of experience, and in estimating trust for whether past behavior will continue to subsequent performance.

  • Building Decentralization

    Building Decentralization

    I talked earlier this week on some of the current problems in decentralization at the rc3 event. It’s easy to be pessimistic about the current silo’d technological landscape, but decentralized platforms are continuing to make progress and there’s reason to be hopeful. At the same time, there’s a green field of many more decentralized protocols to discover and define beyond the current notions of DHTs and Consensus protocols.

    The RC3 event was a great commemoration of the traditional chaos congress. The extent of culture and community that was brought into the 2d virtual world managed to capture some of the essence of the in-person event. Like the real events, it was a great opportunity for mixing whimsy and technical learning. In that spirit, I rehashed some measurement work to generate the following statistics about the event:

    • The most common character accessory was wearing a mask, which were donned by 30% of participants.
    • The badge shown on the most user profiles was ‘On Webcam‘, a badge I awarded to a scraped list of usernames on the 2nd day of the event. It was about 3x more popular than the second most popular badge, received for visiting the CERT, which only functioned near the end of the event.
    • A total of 385 badges were awarded and publicly displayed on user profile pages.
    • A total of 334 distinct pronouns were used by users. Only 5 of them were attempts at cross-site scripting attacks.
    • The user population was approximately that of the recent in-person events. Of those, my measurement estimated about 1/3rd participated in the 2d virtual world portion of the event.
    • There were only 2 users who used the same description of themselves on their profiles: ‘Moin!’

    These statistics come from a fairly simple script that measured user pages near the end of the event. User IDs were largely sequential and could be enumerated without issue. This was needed as a step in awarding badges, which could only be done with the non-enumerable “usernames”, rather than these User IDs. One of the things that makes the CCC events unique is their transience, which allows for a safer form of expression than our more usual permanently logged and recorded online experience. In that spirit I have subsequently deleted my collected list of usernames and saved only these summary statistics.

  • Stunning

    I’ve started to dive once again into the mess of connection establishment. Network address translation (NAT) is a reality today for most Internet users, and poses a significant hurdle in creating the user-user (or peer-peer) connections. NAT is the process used by your router to provide multiple internal (192.168.x.x) addresses that are all only visible as a single external address on the Internet. The challenge caused by this device is that if someone outside wants to connect to your computer, they have to figure out how to get the router to send their traffic back to you, and not just drop it or send it to another computer on your network.

    Without configuring your router to add a ‘port forwarding’ rule, it isn’t supposed to do this, so many of the connection establishment procedures are really ways to trick your NAT into forwarding traffic without realizing what’s happening.

    There are two main protocols on the Internet today: UDP and TCP. UDP is stateless, each “packet” of data is its own message, and is self contained. In contrast, TCP is a representation of a longer “stream” of data – many messages are sent with an explicit ordering . TCP is much harder to trick routers into establishing, and there has been little work there.

    The current generation of p2p systems are led by high-bandwidth applications that want to offload traffic from central servers in order to save on bandwidth costs. Good examples of these are Google’s hangouts and other VOIP (video over IP) traffic.

    These systems establish a channel to send UDP traffic between two computers both behind NAT routers using a system called ICE (interactive connectivity establishment). This is a complex dance with multiple sub-protocols used to try several different ways of establishing connectivity and tricking the routers.

    One of the key systems used by ICE is a publicly visible server that speaks a protocol called STUN. STUN servers provide a way for a client to open a UDP connection through their router to a server that is known to be able to receive messages, and then learn what that connection looks like outside of its router. It can then provide that external view of how it’s connected to another peer which may be able to send messages to the same external address and port and have them forwarded back to the client.

    One of the unfortunate aspects of this situation is that the complexity of these systems has led to very few implementations. This is unfortunate, since the existence of libraries making it easy to reuse these techniques can allow more p2p systems to continue working in the modern Internet without forcing users to manually configure their routers.

    I’ve started work on a standalone go implementation of the ICE connectivity stack. Over the weekend I reached the first milestone – The library can create a STUN connection, and learn the external appearance of the connection as reported by the STUN server.

  • proxy2p


    A quick screenshot of what I’m doing for my distributed computing final project. I’m calling it friend.s for now, although I’m not totally satisfied with that name. It’s a cross-platform piece of software that brings elements of peer-to-peer communication into your web browser. The goal is to be able to eventually offer a completely decentralized social network that can offer the same services as Facebook while guaranteeing privacy.

  • Distributed Computing so far

    I gave a half-hour presentation on my research at the admitted students weekend earlier.  I think I was able to convey some sense of the opportunities that Mudd offers for research, and presented a reasonable face of what it could look like.

    The talk was an explanation of the concepts behind distributed hash tables, and an introduction to the work I’ve been doing with bitTorrent.

    These are the slides I used: Admitted Students presentation

  • Experimenting with 802.11s

    The purpose of this document is an explanation of what is defined in the IEEE 802.11s standard, and the states of current implementations based on this standard. 802.11s is the standardization of mesh networking. That is to say that it defines a protocol for mobile devices where they can communicate amongst themselves even when not directly connected, and can route data beyond their immediate environment.
    This work has been ongoing for close to a decade, and has been progressing as a single proposal for the last four. The standard is for a complete system, explaining the MAC level standard that data will be transferred. This includes how clients can securely create connections, and how and when they should resend packets they receive which are meant for other devices in the mesh. As a result, this standard has become effectively all encompassing, as it defines standards from the hardware signal levels all the way up to complex software routing and security.
    Even today, the standard is not formalized, meaning that nothing is focalized, and implementers are really very cautious to begin implementing mesh networking, because it may change and they would then have to re-write or design their implementation (it means specifically that wireless cards are not being built with mesh networking in mind, since chip design is more expensive and less changeable then software drivers.) The lowest level changes are made to the wireless frames in order to allow hops within the mesh, and would benefit from hardware changes to make those changes quickly implemented, however they will still work even when those changes are processed entirely in software, which is the current choice implementations are making until the standard is formalized.
    Routing can be specified either explicitly, as the tree that the source is aware of that will extend to the root (or final destination in the mesh) or ad-hoc, where intermediate nodes make their own decisions on how to route the packet. However, routing is done using a QOS-esque process, where the route is first established, and subsequent packets can use the same path until it needs to be recalculated due to topological changes. In addition there is a periodic discussion about which node in the mesh should act as a root, and the ordering of nodes, which is based upon which node has wired access to other networks, and tie-broken by the MAC addresses. Beyond this there are different levels of structure that these networks can take on, similar to the differences we see today in ad-hoc networks and networks with access-points. These are called meshes with and without registration. Without registration, any node can come and go, and the rest of the mesh is unaware of any topology beyond that directly adjacent to it. In registration mode, the root is aware of the entire tomography of the network, and can make informed choices about how routes should be created.
    While the major protocol specification seems to not be changing much at the present, there is still enough flux in details that implementations are not compatible with each other, and are still very rudimentary. I looked at three different implementations, none of which are inter-compatible, and all claim to be based off of the standard.
    The first is the implementation of mesh networks used in the OLPC. This was one of the first implementations of mesh networking, and is not compatible with any widely used implementation outside of those devices. It works in OLPC clusters, and is a technical feat, although since the central points that were intended to ground the mesh networks have not yet materialized, it is quite underutilized as I understand it. Instead, in the situations where OLPCs have been deployed, a standard 802.11b network typically works well since all of the machines are close enough to the central access point.
    The second is the open 802.11s project, which is designing a software driver for the Linux kernel. This version works currently for a limited set of wireless cards, whose Linux drivers are sufficiently open to allow the needed modifications. It is not included as part of the standard kernel distribution, which is a fairly powerful comment on the state of it’s development, since the kernel is typically thought of as including everything and the kitchen sink. It is simply the reference implementation being created as part of the development of the standard.
    The third implementation is available in the latest version of FreeBSD. This version is included in the distribution, and notes that it does not work with the Linux version due to how primitive they are. I was unable to test this implementation as I was hoping to, because the emulated lab I was using didn’t allow the permissions that the code wanted to make to the wireless drivers. However, this code promises to be one of the most practical current versions of mesh networking. Setup is performed through the standard ifconfig linux tool. Where one specifies the access point in other protocols, here they specify the mesh they wish to use, and the parameters associated with it. Once the mesh is specified, routes are automatically formed, and users can manually specify nodes they wish to block or favor using included implementations.
    I think the important takeaway from this exploration is into the state of mesh networking. I think the IEEE process here has been a hindrance to the development, and that it has trouble keeping up with the technological developments that are going on in this area. Enough new research keeps coming in that the standard needs to be constantly updated to keep from being outdated, and in so doing means that vendors are hesitant to implement inoperable devices, and keeps the whole field from the popularity it needs to really succeed. I think that we have had the opportunity to settle on an imperfect draft of this standard and actually have widespread mesh networking, but due to the fact that it can become useful only if everyone does the same thing, we have been very hesitant to do so.
    Hopefully as smart phones continue to evolve we will begin to see mesh networking standardized in those devices, as the potential it envelops becomes increasingly important to our communication. Given the issues we’ve seen in recent years with cell companies growing troubles keeping their access point bandwidth in line with the consumer demand feels unsustainable, and will hopefully result in an increasing desire for truly distributed communication for both better reliability and bandwidth.

  • on p2p in the browser

    The final project I want to accomplish this semester in my distributed computing independent study, is to come up with a way to access p2p capabilities from within the browser. I was originally hoping to do this with JavaScript API that relied behind the scenes on the new flash p2p protocol, rtmfp. The protocol has been around since last spring, but development for it is not exactly optimal. You need to be using flash to make the movie, and you need a proprietary and expensive piece of server software to coordinate data transfers. The protocol itself is still proprietary, meaning that Adobe won’t actually tell you how to make a server that can work with it, or how data is sent across the wire.

    They finally have started advertising it at least, and so it will gain some prominence, and eventually the details will come to light, but for now it is unrealistic to attempt to use flash for a general server agnostic service. (http://www.ietf.org/proceedings/10mar/slides/tsvarea-1.pdf)

    Instead, my plan is to modify the open source privoxy software and add p2p capabilities at that layer. My eventual goal is to make a communal grease-monkey system, where pages can be modified by the user through pieces of JavaScript, and those scripts can then be shared to friends. With the right level of abstraction, I think that this can produce a very powerful system. Starting next week, I’ll begin reading and hacking privoxy to find out how to integrate new code into that project.

  • Torrent Auditor

    I have now migrated the python torrent client that I’ve been working on to a google code project.

    It lives at torrentauditor and now has basic support for actually downloading torrent files.

    I researched the bittorrent extension protocols this week, but was somewhat frustrated by what I found. Most of the interesting ones are implemented on a per-client basis, and aren’t well documented outside of that client. The Vuze client it turns out switches to an entirely different application specific protocol when it meets another client of the same time. The libtorrent based clients do much the same thing, although they send their additional messages over the existing connection.

    However, the good news is that the basic protocol is friendly enough that it can be implemented without major trouble. I chose to focus on in-order reading for now simply for simplicity sake, although it is highly inefficient.

    One goal that I’m going to try to focus on a bit in the next weeks as I have time, is to be able to extract frames of videos from downloaded data. For my digital animation class I would like to make an automated program that stitches together frames / short clips of videos entirely automatically – a visual representation of the swarm.