(Update: this code is not updated for Holochain RSM, it was for holochain-rust / redux, so it will no longer be appropriate for RSM)
(disclaimer: for anyone who is still unaware, I am no longer an employee of Holo, since August 1, 2019. I currently run a business in which we specialize in developing Holochain applications)
It can be tempting, and “intuitive” to use hdk::AGENT_ADDRESS
in validation rules, but most of the time, you probably shouldn’t.
If what you are trying to do is match a field, like entry.address
to the agent who is committing the entry…
validation: | validation_data: hdk::EntryValidationData<Profile>| {
match validation_data{
hdk::EntryValidationData::Create{entry,..}=>{
if entry.address!=AGENT_ADDRESS.to_string() {
Err("only the same agent as the profile is about can create their profile".into())
}else { Ok(()) }
},
_ => { Ok(()) }
}
},
This only works in the context of the original author. Entries that pass the original authors validation rules will fail when it gets gossiped to other nodes because hdk::AGENT_ADDRESS
will be equal to their agent address, and thus will produce the Err case.
Instead, the true agent that you likely want to reference is the one found here, in the validation_data
struct that wasn’t previously being used:
validation: | validation_data: hdk::EntryValidationData<Profile>| {
match validation_data{
hdk::EntryValidationData::Create{entry,validation_data}=>{
let agent_address = &validation_data.sources()[0];
if entry.address!=agent_address.to_string() {
Err("only the same agent as the profile is about can create their profile".into())
}else {Ok(())}
},
_ => { Ok(()) }
}
},
To help make sense of this, it’s helpful to check the source code of sources()
function on validation_data
https://docs.rs/hdk/0.0.40-alpha1/hdk/struct.ValidationData.html#method.sources
impl ValidationData {
/// The list of authors that have signed this entry.
pub fn sources(&self) -> Vec<Address> {
self.package
.chain_header
.provenances()
.iter()
.map(|provenance| provenance.source())
.collect()
}
}
It accesses the ChainHeader in the ValidationPackage that’s associated with the validation callback, in order to access its “provenances”. The People/Agents who committed the entry and chain header.
A provenance is a fancy word for the original author of an entry/chain_header…
it includes their Crypto Signature, and their Agent Address
pub struct Provenance(pub Address, pub Signature);
calling .source()
on a Provenance returns the Address.
Really, in most cases, there are not multiple sources… so just take the first source.
validation_data.sources()[0]
This is something I think the Holochain project needs much better documentation about. I hope this is helpful to others.