Providing some thoughts on what's needed for adoption of lean-imt in TLSNotary.
TLSNotary needs to support multiple hash functions which have varying length digests. Having a public trait for hasher implementations would do the trick.
The tree data structure should not contain any generics as this prevents us from deserializing without knowing its exact type at compile time, or relying on type tagging workarounds.
I would suggest the core tree structure to simply look something like this:
#[derive(Serialize, Deserialize)]
struct Tree {
// Serialized node data
data: Vec<Vec<u8>>,
}
impl Tree {
// Hasher implementation is passed in.
fn push<H>(&mut self, hasher: &mut H, leaf: H::Hash) where H: Hasher {}
}
This could be wrapped in a higher level structure for ease of use. The deserialization implementation would need to perform checking on the inner tree data.
#[derive(Serialize, Deserialize)]
struct TypedTree<H> {
inner: Tree,
// Hasher should probably be owned to support dynamic dispatch and stateful algorithms
hasher: H,
}
impl<H> TypedTree<H> where H: Hasher {
fn push(&mut self, leaf: H::Hash) {}
}
Not trying to be too prescriptive here, but trying to convey the level of flexibility we need.
Requirements
Providing some thoughts on what's needed for adoption of lean-imt in TLSNotary.
TLSNotary needs to support multiple hash functions which have varying length digests. Having a public trait for hasher implementations would do the trick.
The tree data structure should not contain any generics as this prevents us from deserializing without knowing its exact type at compile time, or relying on type tagging workarounds.
I would suggest the core tree structure to simply look something like this:
This could be wrapped in a higher level structure for ease of use. The deserialization implementation would need to perform checking on the inner tree data.
Not trying to be too prescriptive here, but trying to convey the level of flexibility we need.
Requirements