Sarva is a hub-and-spoke compute grid — a FastAPI backend, a Next.js 14 dashboard, and a Python node agent that runs on contributor machines. This post is not about the hub-and-spoke pattern (that one is well-trodden). It's about the one piece of business logic I was most worried about getting right: the moment a job is assigned, how do you decide what it costs the submitter, what the node earns, and how do you make sure the audit log captures enough state to reconstruct any disagreement after the fact.

I am writing this after the third time I rewrote submit_job and complete_job. The first two versions diverged — they used different gr() lookups, different rounding, and a "credit" abstraction that quietly lost precision. This is the version that has been live on Railway for the last few weeks, and it is the one I am willing to defend.

The formula is the same on both sides, but the inputs differ

There are two multiplier functions, both tiny:

GPU_MULT = {