• 11 Posts
  • 695 Comments
Joined 3 years ago
cake
Cake day: July 2nd, 2023

help-circle
  • In some cases, the game server’s IP address is actually anycasted, which is an approach that (very carefully) breaks the notion that a network identity belongs to a single machine. Instead, that one IP address would actually be routed to a nearby machine which is authorized to assume the identity of the game server, and will thus handle the game traffic for that region. So long as all regions handle their traffic identically and the results are consistent as if there were one giant machine that were handling all the traffic, this can work. An example where the seams are visible are how YouTube’s view counters will momentarily not match up across all geographies, because the backend servers don’t sync up to each other instantly or even quickly; and few people require that precision anyway, so they just don’t bother engineering it to do that. When you’re providing a global service, that is exactly the sort of engineering tradeoff that must be considered, because even they do not have unlimited money.

    In other situations, the game server IP address really is for a single machine, but that machine is a specialized hardware load-balancer that is situated in a cloud provider’s network. All that this machine does is to be the frontend for the 5-tuple, and will create a new conversation/connection 5-tuple with a cluster of game servers within the cloud provider’s network. There might be some superficial comparisons between a load-balancer and NAT, but the latter works by fraudulence whereas a load-balancer is a subcontractor.


  • The other commenters have provided many disparate answers that do reply to parts of your question, but allow me to approach the question holistically and thoroughly.

    my basic understanding is that computer networking relies on constructs like IP addresses and port numbers to direct data packets to the correct device and application.

    This is substantially correct. An IP address is a network identity of some “node” machine that participates on the network. A port number is a protocol-specific number for how to interact with a given node. For gaming, we are almost always talking about UDP as the protocol, so the port number will be a UDP port number; the same logic applies for TCP, but I’m going to gloss over that unless you specifically want details about this.

    In the case of Legacy IPv4, an IP address is a 32-bit number that is usually presented as four decimal bytes separated by dots (eg 203.0.113.67). Or for modern IPv6, it will be a 128-bit number presented as hexadecimal groups of double bytes that are colon-separated, but where zeros can be abbreviated (eg 2001:db8::67). A TCP port number is any value between 1 and 65535 inclusive; 0 is technically usable but most software will not allow its use.

    So, if I’m playing an online game like Minecraft or Counter-Strike, I am able to connect to the dedicated game server using the server’s IP address … and port number

    Correct. Your client aims at the server’s IP address, and the UDP port number on that server. And on your end, you will have your own client IP address and client UDP port number. Implicit to the internet, we know that this must be using IP (v4 or v6 does not matter in this scenario) and the client and server only know how to speak UDP. Thus, there are five pieces of information which capture the entire connection: the source IP, source port number, destination IP, destination port number, and the protocol (UDP). In the networking parlance, we call this as the 5-tuple, because it captures the notion of a single conversation between two applications across the network.

    Note that I’m specifically using the word “conversation” and not “connection” because the latter has a specific meaning in the business. A connection means that we’re holding a resource open – like a telephone line --for the entire duration that data is being exchanged. But UDP doesn’t reserve resources like that, and is more like sending a post card and hoping for a reply.

    The 5-tuple concept is important because like an IRL conversation, it’s entirely possible to send data in the reverse direction, and while the source IP/port and destination IP/port will be reversed, it’s easy to see that this is functionally the same “conversation”, just in reverse. The network doesn’t really care if the tables have turned: it just passes packets around. So I will simplify and say that if a 5-tuple reverses its source and destination values, then that’s functionally no change at all.

    I can now answer your question with technical precision: a game server can distinguish multiple game clients by using their unique 5-tuple. The rest of your question is answered by a brief explanation of various workarounds that are needed for the post-1995 Legacy IPv4 world, but which were fixed in the modern IPv6.

    In some cases, each client will be connecting from their own network modem, with their own IP address assigned to them dynamically or statically by their ISP. In that case, I would imagine that the server could just keep a list of client connections and route relevant data back to each client.

    This is exactly what existed pre-1995 when the end-to-end principle was alive-and-well on the public Legacy IPv4 Internet. As I mentioned before, an IP address is a network identity, and in the original conception of IP going back to ARPANet, an identity was not meant to be shared amongst multiple machines. Instead, every machine was expected to have its own IP address. However, during the 1995 explosion of dial-up users, network operators could not (or would) not) obtain new tranches of IP addresses to hand out to users, so they began using NAT as a workaround, to reduce their need for public IP addresses. But the keyword was “reduce” not “eliminate”, and by 2012, the world had officially run out of available IP addresses to hand out to ISPs.

    But in other cases, you might have a multiple clients playing a game behind one modem (like housemates or a LAN party where multiple players join the same remote/internet server), or a newer problem, multiple different networks sharing an IP address due to CG-NAT at the ISP level.

    All of these workarounds (NAT/NPAT, CG-NAT, etc) all work by mutilating the 5-tuple and then unmutilating it for return traffic. When a home router performs NAT, it replaces the client’s source IP (eg 192.168.3.42) with the router’s (eg 203.0.113.67), and usually also replaces the client’s UDP port (eg 12345) with a random one available on the router (eg 45467). The resulting 5-tuple is what the game server will receive. NAT must save the mapping (12345 -> 45467) for future reference.

    When the game server wants to reply, it will – exactly the same as the case with the end-to-end principle – reverse the source/destination fields in the 5-tuple, and send the packet. This means the destination is now the home router’s IP (203.0.113.670 and UDP port (45467). What NAT will now do is to again modify the source IP (to restore the original value of 192.168.3.42) and then use its stored mapping to restore the original UDP port number of 12345.

    From the client’s perspective, it receives a reversed 5-tuple of the one it sent to earlier. Thus, it’s perfectly happy to receive that traffic and nobody is the wiser.

    In which case, from the perspective of the server, multiple players would be playing from the same IP address and communicating over the same port, right?

    Recall that NAT on the router will: 1) generate a random, new UDP port number, and 2) store the mapping of the originator’s port number. So if there are two clients at home playing Minecraft, the router will have generated a different random UDP port number for each, meaning the 5-tuple that arrives to the game server will match 4 out of 5 parts, but not all five. The crucial – and only – distinction between these two clients at the same house are that they present a different source UDP port number to the server. And that is also how the game server will treat those two clients separately.

    If the home router were to spontaneously reboot – thus forgetting the NAT mapping table for UDP port numbers – then both clients cannot recover the conversation at all, even after the home router is back online: the mappings are lost, and nothing can be done but to reconnect to the game server as a new 5-tuple. The end-to-end scenario does not have this problem, and pre-1995, routers did in-fact crash more often than they do now. Genuinely, today’s Legacy IPv4 service is poorer than it was in the past, and certainly poorer than what modern IPv6 can deliver.

    So how does the server differentiate between >2 players connecting from the same IP address and communicating over the same port?

    As long as the home router has available UDP port numbers, NAT can continue to randomly generate a unique UDP port number for each client that is behind the NAT. Since UDP port numbers can be as large at 65535, that’s a lot of clients. Though practically, no home router would ever see that many Minecraft clients. Even CG-NAT tends to only support approximately 64-128 clients on a single Legacy IPv4 address.

    As for why, all this mutilation of packets takes a little bit longer than just passing the packet through the internet. It is not fun for the ISP to have to build CG-NAT infrastructure. It is not fun to build home router firmware that will get blamed for the user’s bandwidth or firewall problems. Also, NAT would require a (relatively large) table in memory store lots of mappings, and so they just don’t do that for consumer routers.

    In the USA, AT&T’s fibre internet modem/router is known to max out after a critical number of UDP conversations or TCP connections, because the NAT feature has run out of memory. This is precisely why some people bypass the modem/router (so they can use their own high-end router) or will use IPv6 for their connection-intensive workloads, like sharing Linux ISOs.

    Or does it not even try, and instead just broadcast all of the relevant game data to every client?

    Game servers definitely do not do this, because broadcast is not permitted on the public Internet whatsoever, whether on Legacy IPv4 or modern IPv6. The original conception of the internet did describe “multicast” which can target a group of IPs on a network, but this was never well-implemented for IPv4 and is only implemented on LANs for IPv6. The public internet does not support multicast, for a number of historical and bandwidth/security reasons.

    If a game server wanted to send the same data to each client, one after another, it can. But it still must know the 5-tuple that identifies each client. Fortunately, the game server’s OS will have taken care to record this info (eg BSD sockets).

    And if that’s the case, how do huge games like battle royales or MMOs handle sending game state to a large number of users?

    The way that MMOs deal with 100k+ clients goes deep into the realm of clustering, load-balancing, and network engineering. The only things that get more complex than that are high-bandwidth applications involving hundreds of thousands of clients (eg Netflix) or are massive hyper-scaler cloud providers (eg Azure, Alibaba).

    That said, the fundamentals are still there: clients are identified by their 5-tuple, and all the engineering done to spread that load must still end up producing a reply that has the reversed 5-tuple.

    (cont)


  • This and the comment it replies to make the categorical error which is to assume that NAT exists as part-and-parcel to firewalling. This is not the case. Many American university and corporate networks do still adhere to the end-to-end principle by giving every device a public IP address. They can do this because they are among the few legacy entities that actually have enough for their needs, such as a Class A (aka /8) subnet on Legacy IP. At the same time, these entities employ firewalls that don’t allow unsolicited inbound traffic (and sometimes also block disallowed outbound traffic).

    NAT is not a firewall, and the OP correctly points out that by using NAT or CGNAT, the end to end principle is demolished, with no way for the victims to recover. OP mentions “firewalls” exactly twice, to compare how they are not firewalls and are still necessary in spite of NAT. Nobody is credibly suggesting that everyone should switch to IPv6 without a firewall. Every single domestic router for the past two decades has included a firewall, and that would not change in an all IPv6 world.

    I wish to reiterate an example I’ve used in the past, which is that the most famous address in the USA is 1600 Pennsylvania Ave, Washington DC. Anyone can send letters and parcels directly to this address as-written, with no need to rewrite the address to first arrive at the Secret Service. And yet, all such parcels and letters will be thoroughly scrutinized by the Secret Service anyway at an off-site facility, and some indeed will be let through to the occupants of the residence. NAT is address mutilation, and the United States Postal Service does not require nor allow that.


  • I wish to be abundantly clear that I wasn’t attacking your position, but that folks on the fence about “what makes a proper English word” should have some examples where English does the thing that makes the language fairly incomprehensible unique.

    Not sure if this was intentional

    I absolutely intended that and I’m glad you noticed! The doppelkupplungsgetriebe example is also a reference to an episode of Top Gear (UK). I meant to hyperlink both to their respective YouTube videos but entirely forgot.


  • Is this really a problem though? Compound words in English can be spaced, hyphenated, and sometimes even parenthesized. German has the word “doppelkupplungsgetriebe” which means “dual clutch gearbox” but whether the first pair is hyphenated or not, these three words in English together refer to a single object, a type of automobile transmission.

    Separating the word into its parts is no different than splitting “hypoglycemia” (hypo meaning low, glyco meaning sugar, and -emia meaning presence in blood) into its parts: useful for understanding, but cannot substitute for the original compound word. The difference between the English and German word is a matter of spelling and punctuation.

    Meanwhile, English has a genuine lack of a word for joy from the misfortune of others, that we borrow the word verbatim from English. The vacuum of a word meant we looked farther afield. And while that word was imported, I imagine there’s a similar challenge finding an English word for “the warm feeling of sand between ones toes at the beach”. The need for words is solved by usage, not by prescribing rules that prohibit importation.


  • What are these “built in listeners” that you speak of, and which OS’s can I find this on?

    Also TCP will work before UDP. For whatever reason firewalls and such do weird things with UDP traffic.

    This doesn’t really explain why troubleshooting is more difficult, but rather that firewalls often cause trouble for UDP. My question was “why would diagnosing a UDP problem be harder than anything else?”, not “why is UDP more problematic?”. I’m fully aware that some firewalls are configured with absurd parameters, like blocking ICMP, QUIC, or even TLS in some bizarre situations. But my tools for debugging network troubles have always been the same: tcpdump for passive tracing, nc to coerce an active response, and icmp/icmp6 ping for basic connectivity and MTU verification.

    Whether it’s UDP or anything other protocol, those tools have proven sufficient for me. Do you use something else?


  • I’ll add some color to this post.

    The original FTP is, frankly, a monster of a protocol. Very useful, but an anomalous protocol that even without NAT breaking the end-to-end principle, it is unlikely to have survived modern corporate firewall rulesets in any case. The fact that FTP was even ported for TCP is its own historical quirk.

    BTW, that is the term which this post is missing: the end-to-end principle is the design philosophy that the network itself should not have to perform work on payloads transmitted, except to carry it towards the destination. This also implies that no fields or bits should be modified in transit, once it leaves the sender; encap/decap restores the fields so that the receiver is none the wiser.

    NAT breaks end-to-end in two respects: corruption of the original sender, and corruption of L4 port numbers. Note that Legacy IP also violated end-to-end, when packets are fragmented due to MTU issues. With IPv6, fragmentation by the network is disallowed outright, and the technical case for NAT is non-existent.

    There’s something to be said about adopters of NAT, that they were facing a Hobson’s choice: use NAT so that they could connect early dial-up users to the emerging Internet, or reinvent the 20 year experiment of the Internet so that it could scale properly. In 1995, IPv6 did not exist so they made the only real choice available.

    In the year 2026 though, that argument doesn’t hold water: it is a choice to continue to ignore the dual-stack and IPv6-only internet. There’s a quote that all sufficiently complex technical problems are in-fact political, and this is that: the modern case for Legacy IP and NAT is rooted in inertia, resource scarcity (eg hyperscale cloud companies buying up IP subnets), and recalcitrance by professionals that abdicate their responsibility to their clients to pursue the available technology.

    There is no colorable technical rationale for why IPv6 best practices cannot be adopted today for most organizations, when all network hardware, all major consumer and enterprise OS’s, and all mobile phones support v6. Note that I said “best practices”, because a minority of orgs such as certain American ISPs have undertaken truly bonkers decisions that are putting us on track for the very same sins as Legacy IP.

    The fact that some ISPs assign nothing but a single /128 via DHCP6 is absurd: this malpractice perpetuates the same problem as NAT44, except that there’s no good excuse for it. Even the most delusional of ISPs will never run out of /128 addresses in their assigned /32. Per best practice, even handing out /48’s to customers is not a problem either, because that’s 65536 customers and if that’s really a problem, just ask the RIR for another /32, which they can do as RIR dues-paying members. There is no practical limit, except that some people just cannot math properly to see that there’s no practical limit. When a technical solution to a technical problem fails because of innumeracy by those tasked with implementing it, then that’s so much worse than any 1990s workaround.

    I’ve harped a lot about IPv6 because its strength today is that it’s technically competent, future-proofed, and most importantly, practitioners that saw the first travesty of NAT will not allow a redux to play out with IPv6. The technical reasons to deploy NAT66 are non-existent: it is always a workaround for political issues.

    I can (just barely) accept NPTv6 as a like subnet-for-subnet mapping that does not harm L4, but that’s still glossing over a political issue. IPv6 gave network engineers real choices in numbers and administering their networks, and while some will squander it, I will be encouraging people to not let that happen.


  • Why would UDP be any more difficult than TCP (or anything else) for troubleshooting? If nothing else, it should be easier because there are no stateful connections and every packet is “fire and forget”. Now, as a tunneling technology, WG might be more difficult than a simple client/server socket-driven application, but that just means some routing tables need to be inspected and you have to understand IP subnets. In any case, you’d still want to obtain packet traces from both ends of the WG tunnel.


  • The thing is, if you don’t wish to port-forward on Legacy IP nor open firewall ports for IPv6, then the only other option is to reach out to some sort of relay server. But whether your own VPS fulfils that role or you use Tailscale’s DERP/TURN relays, the same class of latency and bandwidth issues will still erupt. So you’d still have to debug them, although you presumably would have better visibility into diagnosing issues with your VPS relay.

    Generally speaking, if Tailscale isn’t working for you, then all other solutions will increase in complexity, not decrease.

    Answering the ultimate question, I operate and secure my SSH server, with port 22 open only for IPv6 inbound. There’s no NAT, so I don’t have to deal with debugging odd port mangling. The SSH server only allows key auth, and all password attempts are logged and blocked, because there can’t be any legitimate traffic like that. On this SSH server would be my mounts for backups.


  • The case "eBay Domestic Holdings, Inc. v. Craig Newmark, et al." in Delaware’s Court of Chancery does not support the assertion at all. What the two corporate officers did wrong was to dilute a minority stakeholder’s shares for an impermissible reason under Delaware law. One permissible reason to justify such dilution would be if the change was “reasonable to promote shareholder value” (page 49). The two officers could not prove that their actions were reasonable, nor could they prove any other permissible reason, so they lost the case.

    At bottom, the major question in that case was whether the corporate officers can conspire with the majority stakeholders to harm a minority stakeholder. It was about two corporate officers that were acting out of self preservation (page 59):

    Jim and Craig simply disliked the possibility that he Grim Reaper someday will catch up with them and that a company like eBay might, in the future, purchase a controlling interest in craigslist.

    The minor question (whether shareholder value would be promoted) could have been answered in the affirmative and those two would still have lost the case, because Delaware law also doesn’t allow harming a stakeholder, violating their fiduciary duty to eBay in this case (page 61):

    If Jim and Craig were the only stockholders affected by their decisions, then there would be no one to object. eBay, however, holds a significant stake in craigslist, and Jim and Craig’s actions affect others besides themselves.

    The court only looked at the minor question to appeal-proof the ruling, because the two corporate officers had tried to match their argument to an earlier DE Supreme Court ruling.

    For the purposes of my point in this discussion, the distinction doesn’t matter.

    I disagree. Drawing the correct conclusion from the wrong cause is pure sophistry (ie “arbitrary, inauthentic, or deceptive styles of reasoning” -Wikipedia). It is intellectually dishonest to state a conclusion but then decline to support your basis, dismiss your own basis as irrelevant, and then circularly assert that the conclusion stands on its own.


  • I can agree that corporations are immoral, but no one has ever offered a citation for “legally required to maximize profit”. Many corporations have failed in spectacular fashion and yet where are the lawsuits or criminal prosecutions for leaders that fail this supposed obligation?

    What does exist is the fiduciary duty to be frank with shareholders, and many corporate officers have been sued for lying by omission. I believe that a corporate officer can choose to prioritize something else besides profit/value, so long as they inform the shareholders. In turn, the shareholders can fire the officer and replace them.

    It’s no surprise that most officers won’t stick out their neck for non-financial causes, but let’s be honest if it’s simply self preservation rather than some oft-cited but wrong assertion of the law.




  • The CS job market is very location specific, so I don’t have much advice in that regard.

    I’ve got quite a bit of experience with Linux and I manage a home server, but that probably doesn’t differentiate me much.

    That said, I have been on my company’s rotating interview panel for about a decade now, and while my company’s line of work involves a lot of Linux development, I can say that most of our college hires do not possess very much Linux background at all. Sure, they might have used Linux machines for school projects, but rarely do any of them assert to be “experienced” with Linux.

    By that, I mean deeper knowledge than just using Bash. If a candidate can tell me why they prefer csh over Bash, or any syntax difference between POSIX sh compared to Bash, that is definitely a distinguishing quality. It speaks of an operator who has enough usage under their belt that they’re annoyed by the typical distro’s defaults, and more importantly, assessed the available tools, and picked the right tool that works for them.

    I cannot understate how valuable it is to us to find a candidate that understands their tooling, especially right out of college. Considering that we assume most new hires have to be brought up to speed over the first few months, a candidate that saves us that effort is at least one rank above their peers.

    Deeper functional knowledge comes in other forms as well. It’s one thing to know how a C program’s main() function is invoked by an OS, but anything which shows a fuller understanding of, say, system architecture and how a timer interrupt leads to a context switch in an assembly ISR, to a returned service call to load an ELF, to a CPU privilege ring change, to crt0, to main(), that is another level entirely.

    I’ve interviewed candidates that had side projects involving retro game disassembly. So maybe they couldn’t give me the above level of detail for x86, they could describe the same for MIPS. And that’s good enough, because most architectures do roughly the same thing, with a few different semantics and names.

    Circling back to managing a server, if you had to deal with PAM, NAT and port forwarding, tunnels and VPNs, compiling from source, or abything like that which is non-trivial, do not sell yourself short. All that stuff is resume material, because if you can relay to an interviewer that you’ve dealt with real network or machine security tasks, it is distinguishing.

    The best part is that you have all of college to learn the CS curriculum, but it’s also time that you have to pursue any particular focus that excites you. I’ve written earlier about how embedded engineers don’t really get caught in the hype cycle, so jobs don’t suddenly appear then disappear a few years later. If you wanted to do that route, getting started with any microcontroller (eg Arduino, STM32) would help, with a goal to understand all the “magic” that the IDE and compiler are doing. Maybe instead you like das blinkenlights and find yourself drawn to hardware design. It wouldn’t be too late to consider a switch to the Computer Engineer (CE) major, so you have a small taste of the EE life.

    CS as a field is so large that there are many routes between “I want to work with computers” to a declared major and to a career thereafter. Fortunately, time is on your side; this would be a very different conversation if you were a 4th year college student.




  • IIRC, the IAU’s definition of planet – infamously applied so that Pluto fell off the list of Solar System planets – requires that a candidate planet be large enough that its own gravity is strong enough to force it into a rough sphere, whatever it might be made of.

    So a disc-shaped planet could not ever meet this criteria, because if it were made of something strong enough to remain a disk, then it’s too small to be a planet. And if it did exceed the critical size for gravity to make a sphere, then it wouldn’t be disc shaped anymore.

    But setting that definitional quibble aside, we will focus on sizes and materials that allow a disk shape object to exist and be large enough for humans (or Mario) to visit. So no Wensleydale cheese. If we say that this object is mostly uniform in its mass distribution, then it would have to be the case that for any disc shape (including cylindrical), different points along the surface will be farther or closer to the center of gravity. Thus, inhabitants would experience gravity differently depending on where they are.

    Note that we haven’t even considered whether the disc is rotating. If it is, then there’s a chance that the centrifugal acceleration at some points will completely negate the gravitational acceleration. At such points, one could hop up and off the surface, linger for a bit, and then get pulled back down once the disc has rotated to a position where there’s a net force upon you again. Or if the centrifugal acceleration is too strong, it might repel visitors on the surface altogether.

    Alternatively, there would be a danger of playing on a trampoline that accidentally crosses into a net-zero gravity region. Here, a double bounce could send someone very high up, only to then plummet back down to their death when re-entering a downward gravity zone.

    I have almost no citations for the above, but I thank you for posing an interesting question.


  • I agree that RPM isn’t the primary quality to assess here, but I think angular momentum doesn’t really matter either. As a quantity, momentum describes a conserved capacity to store kinetic energy. As in, it could tell us how long the fan would stay in motion when the wind stops blowing. But that’s not the objective for a wind turbine, which is supposed to convert lift from the wind to do some work.

    At bottom, none of these quantities are the useful metric for what makes a good wind turbine. And that’s expected, because we have few details about the fan itself: the blade pitch, stall speed, and fan diameter, to list a few parameters. The only firm detail we can see is the blade count from the picture.



  • Given that FOSS licenses are premised on copyright, yes, the same ails would still exist: 1) AI washing of licenses (including transforming one license into another), and 2) the vagueness of whether LLM outputs can be copyright, which threatens the validity of a FOSS license upon that output.

    The first ail can be seen even without LLMs: the BSD variants have gone through great pains to remove GPL-licensed code from their base repositories. This basically involves reimplementing utilities and functionality from scratch, using only the ideas that are in common with the equivalent GPL code, but never copying that code directly. This is properly considered a reimplementation, which can then be licensed permissively (eg MIT license).

    If an LLM were to train on GPL code but the output were licensed with MIT, then that could be a GPL violation because GPL mandates that remixes continue to keep the GPL license.

    Maybe you could avoid this fate by limiting the LLM to only train on permissively licensed code. So that it would be permissive licenses going in, and permissive licenses coming out. No GPL problems here. But that brings us to ail #2.

    Some jurisdictions have rules against granting copyright for computer-generated works, in the same vein as works generated by non-humans (eg a macaque). If this LLM fell into this situation, then the output is not copyrightable. And if there is no copyright, a license like MIT or GPL simply cannot apply, because its terms couldn’t be enforced.

    Well, to be clear, the copyright parts of those licenses would be unenforceable. Some parts of the license may still be enforced under a contracts claim. But in any case, the things we refer to as “FOSS licenses” cannot attach to uncopyrightable works (with the possible exception of the CC0 license, which is essentially the absence of any license whatsoever).

    EDIT: you did say “consenting projects” and consent is key. If such consent came in the form of a license grant, then yes, that would be enthusiastic consent for the LLM to generate output, which solves ail #1. But for most multi-person projects, getting consent from everyone is difficult or impossible. The Linux kernel is one such example, having so many contributors that some of them are already dead. Death means they cannot consent, but their copyright grant lives on. And so practically speaking, obtaining enthusiastic consent for whole projects is a challenge, which drastically limits the prospects for such an LLM from the very beginning.