*** General notes and instructions. 0: We are breaking up this specification into a tree of specifications, 1: The word “lodge” should not be used in the spec or the code. This is specific to a specific application. The generic term is “room.” Do not update the code yet, but always use "room" in new 2: In docs, create a new directory new-state/ to handle all state specifications within the new state system. We will be splitting it into kernel and derived subspects. In this directory, 3: Create a new directory new-state/derived to specify all the derived state specifications 4: Create a new directory new-state/kernel to specify all the kernel state specifications 5: Put all specification issues that are not a description of derived or kernel state in new-state/overview.md. Remove the original new specification document, making sure that no new content *** Notes on derived state “And their results” is incorrect. Derived state contains the current queries, not the query results, which are delivered in events. Each query has a unique ID which is in the result structure sent back to the task when the query produces data. In the file new-state/derived/presentation.md, in Typescript structures, define and describe the complete presentation state of the system. This is all the information needed to render the whole UI. React will react to changes in this state. In the file new-state/derived/hd.md, in typescript structures, define the state of all keys derived from the master secret for all urbits. Be sure to include the HD paths we are using in comments. In the file new-state/derived/blockchain.md, define the BlockchainQuery structure we are using. Go over the existing code to make sure it represents all the queries that the existing code is currently sending. In the file new-state/derived/web.md, define an HTTP query structure that will support any reasonable API request. *** Notes on kernel state: 1. Put the specification for the Secrets interface in new-state/kernel/secrets.md. Describe how this contract works. Describe the way the system handles secrets. One important point is the handling of passkey encryption and blockchain secrets. To the user, we store the master secret "in" the passkey. This is not real. Actually, we store the master secret on the blockchain If the browser supports the PRF passkey encryption extension, Put the specification for both blockchain and HTTP queries in new-state/kernel/queries.md. Describe the set of queries we make to what service providers. Consider the cold-start case where we have to compose a backstory for an existing urbit. Put the specification for the Task interface in new-state/kernel/tasks.md. Here is some stuff about tasks: There is some interaction state that is not derived. Put the specification for it in new-state/kernel/interaction.md. TASKS: Because we are saving and restoring this state, we are trying to keep it JSON-shaped. However, it is basically an object-oriented system, although built with discriminated unions and switch statements rather than method dispatch, and unique IDs not pointers. A task may be of arbitrary complexity and include arbitrary subtasks, some of which may be performed serially. Every task has a unique identity. Typically the unique identity is known only by the parent task and used to respond to success or failure reports by the child task. The task identity is a list of numbers. The last number in the list is the event number, since every task is created by one event. When we do multiple things inside a task, we prepend a counter to this list. Every task type is created by a corresponding event type. Some of these tasks complete in their initialization function without leaving any persistent state. We never block in task processing, not even to perform network operations. Every task has two kinds of data: static data from the event that starts the task, and intermediate data (typically some kind of state machine) that it needs while running. Task requests are not only requests we send to the network. They are also user interaction flows. For example, the signup / invite acceptance flow is a task. In various task states, it presents a UI. TASK FUNCTIONS: setters: process_event: React to any event (or void for initialization). May mutate the present task. Results: 0 if the task continues, 1 if it has completed, [2 "message"] if it has failed; list of new events to push on stack getters: list all current blockchain queries list all current http requests (GET only). HTTP request can be one-time or repeated (polling) list current UI modal screen if any EVENTS: Put a complete event system design in new-state/kernel/events.md. Here is some stuff about events. An event is anything that passes through the main event loop. Some events are processed immediately as actions. Some are sent to tasks. Events include: Commands / source transactions A command always initializes a new task. Results of HTTP requests Results of task completion Results of blockchain queries (one-time or ongoing). Includes all tracking of transactions. User input responses Timers Raw actions: submit blockchain transaction set timer BLOCKCHAIN STATE: Blockchain state has four parts: operation state, address state, mirror state, and ambient state. Ambient state is public state that is not actually blockchain state but in practice might as well be. For now the only ambient state is exchange rates and gas costs. Ambient state APIs report Operation state tracks our attempts to get our transactions on chain. Only transactions in process are tracked by operation state. The transaction is followed from when it is sent to the network, to when it is either finalized or dropped. Address state is the all-important index counter that tells us which HD wallet addresses we have used on what networks. This lets us create new per-transaction addresses, which we really like to do. We have to restore all this data when we cold boot. And these addresses should be in order, so that we can perform this query. This state is literally just one number per network. Mirror state endeavors to maintain a local image of the state of the general-purpose blockchain. Mirror state falls in two categories: token and contract. All mirror state is described by a path. The questions we can ask about mirror state, for any given path: - if it is final, just the value - if it is not final, how stable is it? return the old value, the new value, and the stability level 1-3 (prepared, acknowledged, incorporated). - how fresh is it? return the number of seconds since this value was valid on the blockchain, or 0 if not incorporated Token paths are direct: /$NETWORK/token/$ADDRESS or indirect (only works if $URBIT is us) /$NETWORK/token/$URBIT/index/$NUMBER Token state is ERC20 qnd ERC721 tokens. These are indexed by query providers (eg Alchemy). We can use Alchemy web hooks to track all ERC20 balances. Contract state is state in all the contracts on all the networks that we track. On Ethereum, this is Azimuth, PlanetDispenser, NexusHub, and Secrets.