Open slowli opened 7 years ago
@boguslavsky @defuz @gisochre Are you OK with this interface? Maybe, ListView
or MapView
need to have other methods? As for JSON for constructors, I see it slightly more verbose than it is currently, in order to be parseable within generic Exonum type spec:
ListView (3 items, proofs for 1st and 3rd):
{
"root": {
"@type": "branch",
"left": {
"@type": "branch",
"left": {
"val": ...
},
"right": {
"stub": "abcdef..."
}
},
"right": {
"@type": "sprout",
"child": {
"val": ...
}
}
},
"length": 3
}
MapView (proof for key 01101...
; the bits
field is embedded into variants):
{
"@type": "branch",
"bits": "",
"left": {
"@type": "branch",
"bits": "0",
"left": {
"stub": {
"bits": "01",
"hash": "..."
}
},
"right": {
"val": {
"bits": "1101...",
"item": ...
}
}
},
"right": {
"stub": {
"bits": "1",
"hash": "..."
}
}
}
This assumes that oneOf
can be encoded either as {<tag>: <value>}
or {"@type": <tag>, ...<value>}
.
As for implementation, it could be first implemented with custom JSON parsing logic, and then integrated into the Exonum type system.
I've implemented a PoC for type defs, which includes possibility of tree implementation, among other things. Very rough, but you probably get the general idea.
Merkle (Patricia) tree proofs essentially prove that a certain element (or several elements) belongs to a certain data collection (list in the case of Merkle trees; map in the case of MPTs). Essentially, a MTs and MPTs are views of lists or maps, in which some elements are unknown. So, it could be logical to implement them as such.
Interface
Thus, it could be logical to have the following interface for MTs and MPTs:
constructor(json)
: creates an MT or MPT based on JSON retrieved from the server. Verifies the internal structure of the tree (see below) and throwsTypeError
if the provided JSON is invalidhash()
: returns the hash of the collection, calculated as per the current algorithmlength
(read-only property): returns the length of the underlying collectionget(index)
: gets the element at the specified index (integer for MTs,Hash
in the case of MPTs). Returnsundefined
if the element was not in the provided JSONhas(index)
: returnstrue
if the requested index is in the collection view,false
otherwisemaybeHas(index)
: returnstrue
if the specified index may be present in the collection (not necessarily in the current view). Hence, the proof of absence forindex
is!view.maybeHas(index)
.Symbol.iterator
andentries()
: returns the iterator for[index, value]
pairs in the view, like the JSMap
(maybe, pull other methods fromMap
too, e.g.,forEach
,keys
andvalues
).Internal construction
Merkle tree
Recursive definition:
Consistency checks:
length
left
child in any branch cannot be asprout
branch
cannot have bothstub
childrenMethods:
get(index)
can be implemented by traversing the tree from the roothash()
can be implemented by traversing the tree from the leavesMerkle Patricia tree
Recursive definition:
bits
may be woven into all type variants if deemed necessary.Consistency checks:
bits
may be empty only for the root nodeleft.bits
must start with0
andright.bits
with1
branch
cannot have bothstub
childrenMethods:
get(index)
andmaybeHas(index)
can be implemented by traversing the tree from the roothash()
can be implemented by traversing the tree from the leaves