Validation needs to be deterministic: same result no matter who runs it and when.
After an action is committed, it is transformed into different DHT Operations (DHT Ops)
Then, those DHT Ops are published to the different neighborhoods in the DHT
When those nodes receive that publish, they add it to their validation queue
If the validation fails, those nodes produce warrants that get gossiped throughout the network
All other nodes can verify that the bad agent is behaving badly
They then disconnect from the bad agent
If the validation succeeds, the node starts to serve that record to DHT queries (get, get_links, etc.)
Validation callback function context
The function validate is called in two contexts
The author validates
All prospective hosts of the DHT Op validate
DHT Ops
System validation
Does not depend on your application code
Holochain enforces some system level validations across all apps
Actions
Source chains can’t be forked
All actions must be signed by their author
Timestamp and sequence number for the actions must be incremental
If the action is accompanied by an entry, the entry hash in the action is correct
Entries
The entry byte array can be deserialized to the appropriate struct
App validation
Validation rules for a given entry or link type must go in the same zome as the type definition
Private entries cannot be validated
Callback:Â validate(dht_op: Op)
#[hdk_extern]pub fn validate(op: Op) -> ExternResult<ValidateCallbackResult> { // Right now there is bunch of boilerplate here that's going to be replaced in the next version }
Three results possible:
Valid
Invalid: it specifies the reason why it failed
Unresolved dependencies: Not enough data to complete the validation
Validation challenges
Non-deterministic queries can’t be considered during validation
get and get_details are forbidden
They attempt to return a current list of updates and deletes
get_links is forbidden
get_agent_activity is forbidden unless bounded by action hashes
Deterministic alternatives:
must_get_entry
Only returns the entry, not its action
Never returns None, rather the validation has unresolved dependencies
must_get_action
Only returns the action
Never returns None, rather the validation has unresolved dependencies
must_get_valid_record
Returns the record
Never returns None, rather the validation has unresolved dependencies
let role = PublicationRole::new("editor", author); let role_entry_hash = hash_entry(&EntryTypes::PublicationRole(role))?; let entry = must_get_entry(role_entry_hash); match entry { Ok(_) => Ok(ValidateCallbackResult::Valid), Err(_) => Ok(ValidateCallbackResult::Invalid(String::from( "Only editors can create posts", ))), }
Genesis self-check
Callback executed when the cell is instantiated
If it fails, the app for that cell will fail to install