A Microsubjective Blockchain is a linked list of nostr events, with the most recent event containing the current state in full. Client implementations use a Web of Trust in combination with proof verification to determine which fork to follow and/or append on.
The tip of the MSB is a replaceable event (kind 31108
) that contains the current state and the event ID of the previous state (most relay implementations provide the previous versions of replaced events if requested by ID).
Instead of verifying the entire history of the MSB, clients MAY allow users to consume the current state directly from the latest 31108
event signed by pubkeys they trust. This allows meaningful interoperability with regular nostr clients that do not want to implement validation.
- The project creator publishes a
kind 31108
event to create a new MSB. This is called theignition
event. - Anyone can fork and modify the state of the MSB by publishing a replacement
31108
event with the new state and proof(s) that the modification follows the protocol ruleset indicated by theignition
event. - A replacement
31108
event (i.e. all except theignition
event) MUST provide the ID of theignition
event at the root of this MSB, AND the ID of the most recent31108
event that this builds upon. - To find the current state of the MSB, we request the latest
31108
events that have tagged theignition
event (from pubkeys we trust), and OPTIONALLY perform validation on the entire MSB back to theignition
event. - To signal that we are following a particular MSB tip, we publish a
31108
event toshadow
it.
The following tags are indicated for use in kind 31108 events.
RFC 2119 | Description | Spec or Example |
---|---|---|
MUST | Ruleset identifier - the ruleset(s) that this MSB validates against. | ["ruleset", <hex>] |
MUST | Pointer to the kind 31108 ignition event for this MSB, or "this" if it itself is the ignition event. |
`[ "ignition", <event ID |
MUST | Pointer to the ID of the last kind 31108 that this replacement is updating (MUST be the same pubkey), or "this" if it itself is the ignition event. |
`[ "parent", <event ID |
MUST | The name or identifier of this MSB. | [ "d", <name of this MSB> ] |
OPTIONAL | This is to signal that we agree with a specific 31108 event. If this is the first 31108 published by a new participant in the MSB it MUST include a pointer to the latest valid state of this MSB from which the new member will begin updating. |
["shadow", <ID of 31108 event> ] |
SHOULD | Current block, mostly for convenience. | [ "bitcoin", "<current bitcoin height>:<hash>" ] |
Some state changes MAY require a proof so that others can verify it if they wish. This can either contain the event ID of a proof, arbitrary data as a proof, or a full event as stringified JSON. A single update MAY contain multiple proofs.
[ "proof_id", <event ID of proof>, <relay hint> ]
[ "proof_full", <stringified JSON of full event> ]
[ "proof_raw", <proof type>:<proof data> ]
MSB Rules define how to handle inputs (events that cause a state change), and how to modify the current state based on them.
Rulesets are a way to compose these Rules and allow experimentation in a way that is clear and simple to reason about, and does not introduce non-determinism (i.e. does not encounter the halting problem).
We can think of a Ruleset as a portable set of atomic transaction validation rules that can be mixed and matched between any MSB. Like Bitcoin, MSB transaction execution does not encounter the halting problem because inputs are discrete and atomic requests to modify specific state(s).
Instead of allowing arbitrary inputs, we pre-state what inputs are allowed (as part of the ruleset), and we modify the ruleset to allow novel states and inputs. This allows MSBs to have infinite state possibilities and arbitrary mechanisms for validating state changes, but without invoking the fundamentally insecure and unpatchable "Turing complete" paradigm in use by "smart contract" platforms. This is important because doing so would make it impossible to perform full recognition of inputs prior to execution, and the lack of this capability is what makes things like the DAO hack possible.
Rulesets are identified with a hexadecimal code, for example 334000
for the first attempt at a ruleset for Nostrocket.
Verification is not strictly required, participants may choose to simply trust the current 31108
event published by someone they trust, or the MSB creator.
If participants wish to verify the full state, they may do so by fetching any proofs contained in the event, and fetching the parent
event. Applying the proof events to the parent
event in the context of the parent's ruleset
should result in the same state as the current event. The process should be repeated until the ignition
event is reached.
If the participant's pubkey has power over consensus (based on the current ruleset in the context of the current state), the participant SHOULD publish a shadow
of the most recent 31108
event.
To prevent the accidental or intentional replay of proofs, we include a bloom filter array and validate that the candidate proof has not yet been included in this MSB. This will sometimes cause legitimate proofs to be rejected but client implementations can re-create them with a new ID if so.
The Microsubjective Blockchain architecture utilizes replacable nostr events rather than a traditional blockchain. It is not intended to be used as money or a "smart contract" platform and doing so would be silly.
However, a nice way to think about how state transitions work in this paradigm is to compare it to the existing paradigms used by Bitcoin, and the EVM.
Bitcoin handles the halting problem through limitations on state transitions - the different states that Bitcoin can enter after executing a valid transaction is finite.
In order to handle novel types of state or execution, the Bitcoin VM must be modified, but Bitcoin is explicitly designed such that these modifications are impossible without near-unanimous agreement between the time-bounded rolling-set of participants who recieve Bitcoin as a form of payment.
The EVM handles the halting problem with a fee consumption model that limits opcode execution. The different states that the EVM can enter after executing a valid transaction is infinite.
This allows pseudo-Turing-completeness (it has halting guarantees) at the transaction level.
The major benefit is we don't need to modify the consensus rules to implement novel functionality because all possible computations can be accomplished with the set of opcodes available.
However this this turing complete set of opcodes precludes full recognition of valid or expected inputs, hence the (predicted) DAO hack etc. Oops.
A Microsubjective Blockchain state change request is a Nostr event that complies with the protocol/ruleset and satisfies all rules in the context of the current state.
To avoid language theoretic security vulnerabilities, state change requests are explicit, atomic, and known to halt (the same model as Bitcoin). This enables full recognition of valid or expected inputs prior to execution, which is not possible with "smart" contract platforms.
However, a Microsubjective Blockchain has the same level of flexibility as a Turing complete environment such as the EVM. Any type of execution that can be done on the EVM can be done by a Microsubjective Blockchain.
Instead of this flexibility being invoked by "transactions", it is prestated in the codebase/client that a user executes (leveraging their web of trust) and invoked by explicit and atomic state change requests.