Introduction
Particle types describe the qualitative aspects of a Particle's state machine, which are a combination of the content structure of an instance and the lifecycle and content state transitions that are permitted. The Particle type further defines the data its Particle instances must contain and what constraints they must abide to be accepted and stored. Particle types often share common properties that require their constraints to work a certain way, such as the property that a Particle instance of a type can be uniquely identified. These distinct, common properties of Particles are called Quarks.
In summary, the two defining qualitative aspects of a Particle type are:
-Quarks: distinct properties this Particle type implements
-Constraints: the constraints that are applied to Particle instances to be accepted
Quarks
The fundamental, distinct properties a Particle can have are called Quarks. They are the foundation for all Particles and the interface to the underlying Tempo engine. Particle types can implement these Quarks and thereby take on the constraints offered by them.
Quark name | Meaning | Constraints |
---|---|---|
Identifiable | Particle instances are uniquely identifiable | Can only be one Particle instance with the provided identifier, has to be a valid Radix Resource Identifier |
Fungible | Particle instances are fungible and mutually interchangeable | Transactions involving Particle instances have to add up |
Accountable | Particle instances can reside in a Radix account | Particle instances must be stored in a Radix account |
Ownable | Particle instances can be owned by a Radix account | Only owner of Particle instance can invalidate (i.e. consume) it |
Constraints
In addition to the fundamental constraints provided by Quarks, Particle types can implement their own constraints. These constraints are implemented using the Constraint Scrypt Language. Constraint Scrypts are Scripts that register constraints for a certain Particle type.
Constraint Structure
A constraint is a requirement placed on a Particle type that all Particle instances of that type have to meet to be accepted and stored alongside an Atom. The constraint is validated against a single particle instance and can be based on:
-just the Particle instance with "require",
-all Particle instances with the identifier of the Particle instance (for Indexables) with "requireIndexed",
-all Particle instances with the same content with "require.
The structure of a Constraint is defined as:
on()
require | requireIndexed | require
where >requirement is the requirement that the constraint imposes on >. The output (i.e. return value) of the requirement must be of type Result, which is an enum of
-success (no message)
-error (with message).
Although a return value is required, the final success statement can be omitted for brevity as it is an implicit default.
Example
Consider an example Constraint Scrypt that enforces that MyParticle's symbol must
-exist and be non-empty
-all uppercase
-between a certain range in length (MIN_SYMBOL_LENGTH and MAX_SYMBOL_LENGTH)
As this Constraint Scrypt only requires the Particle instance in question, it is implemented as a stateless requirement with require().
on(MyParticle)
require(myParticle -> {
String symbol = myParticle.symbol
if !symbol
error "Symbol: no or empty provided."
if symbol.chars().anyMatch(isIllegalSymbolChar)
error "Symbol: must be all uppercase."
if !symbol.length in MIN_SYMBOL_LENGTH..MAX_SYMBOL_LENGTH
error "Symbol: invalid length, must be between + MIN_SYMBOL_LENGTH + " and " + MAX_SYMBOL_LENGTH + " but is " + symbol.length()
success // can be omitted
})
Particle Instance
Particle instances describe the quantitative aspects of a Particle state machine, i.e. the actual instance state. They are an instance of a certain Particle type and must therefore abide by its Particle types constraints and lifecycle state machine to be accepted. The Particle instance stores all quantitative state (i.e. instance state) required by its Particle type and can transition into any state - lifecycle state and data state - permitted by the Particle type. A Particle instance does not carry any qualitative information with it - the qualitative aspects defined by the Particle type are "stored" in the Atom Model. Consider the following example of a Particle type defining the Particle Finite State Machine (FSM) and two instances of that FSM:
In this example, a Particle type with the lifecycle Unique and Mortal and two toy constraints is defined. Remembering that the Particle lifecycle Unique and Mortal enforces unique, invalidatable Particle instances, it can be observed that instances violating the lifecycle state machine are rejected. Similarly, Particle instances violating the toy constraints for instance data (instance data is all uppercase if it's letters, positive if it's a number) are rejected. Particle instances without violations are accepted.
User-Defined Particle Types
Currently Particles are hardcoded in the Radix Core and libraries, that is, no new Particle types can be added without modifying the source code. The building-block-like design of the Atom Model will enable us to support user-defined Particle types, and even Particle types defined as Particle instances on the Radix ledger. This will require all relevant pieces of a Particle type to be adapted into a data-driven format, including the definition of the Constraint Scrypt Language. As such, this expansion necessitates significant work in planning, design, implementation and testing and is therefore a long-term feature.
Join The Radix Community
Telegram for general chat
Discord for developers chat
Reddit for general discussion
Forum for technical discussion
Twitter for announcements
Email newsletter for weekly updates
Mail to hello@radixdlt.com for general enquiries
Top comments (0)