diff --git a/01_host/02_state/state_storage_trie.adoc b/01_host/02_state/state_storage_trie.adoc index 53a82fe6b..3a75e46a2 100644 --- a/01_host/02_state/state_storage_trie.adoc +++ b/01_host/02_state/state_storage_trie.adoc @@ -211,7 +211,7 @@ the following concatenated data: [stem] ++++ -"Node Header|Partial Key|Node Subvalue" +"Node Header"||"Partial Key"||"Node Subvalue" ++++ Formally noted as: @@ -229,59 +229,47 @@ defined in <>, <>, <> and [#defn-node-header] .<> ==== -The *node header* of node stem:[N], stem:["Head"_N], consists of stem:[l + 1 >= 1] -bytes stem:["Head"_(N,1),...,"Head"_(N,l+1)] such that: - -[cols="2,2,4,4,.^1,4"] -|=== -|Node Type |pk length | pk length extra byte 1 |pk key length extra byte 2 1.2+|...| pk length extra byte stem:[l] -|stem:["Head"_(N,1)^(6-7)] | stem:["Head"_(N,1)^(0-5)] | stem:["Head"_(N,2)] |... | stem:["Head"_(N,l+1)] -|=== - -In which stem:["Head"_(N,1)^(6-7)], the two most significant bits of the first -byte of stem:["Head"_N] are determined as follows: +The *node header*, consisting of stem:[>= 1] bytes, stem:[N_1...N_n], specifies +the node variant and the length of the partial key length (<>) in +4-bit nibbles. Both pieces of information can be represented in bits within a +single byte, stem:[N_1], where the amount of bits of the variant, stem:[v], and +the bits of the partial key length, stem:[p_l] varies. [stem] ++++ -"Head"_(N,1)^(6-7) := {(00,"Special case"),(01,"Leaf Node"),(10,"Branch Node with " k_N !in cc K),(11,"Branch Node with " k_N in cc K):} +v = { + (01,"Leaf",p_l = 2^6), + (10,"Branch Node with" k_N !in cc "K", p_l = 2^6), + (11, "Branch Node with" k_N in cc "K", p_l = 2^6), + (001,"Leaf containing hashes", p_l = 2^5), + (0001,"Branch containing hashes", p_l = 2^4), + (0000 0000,"Empty",), + (0001 0000,"Reserved for compact encoding",) + :} ++++ -where stem:[cc K] is defined <>. +If the value of stem:[p_l] is equal to the maximum possible value the bits can +hold, such as 63 (stem:[2^6-1]) in case of the stem:[01] variant, then the value +of the next 8 bits (stem:[N_2]) are added the the length. This process is +repeated for every stem:[N_n] where stem:[N_n = 2^8-1]. Any value smaller than +the maximum possible value of stem:[N_n] implies that the next value of +stem:[N_(n+1)] should not be added to the length. + +The variant stem:[0001] can be distinguished from stem:[0001 0000] due to the +fact that the following 4 bits of the first variant never equal zero. -stem:["Head"_(N,1)^(0-5)], the 6 least significant bits of teh first byte of stem:["Head"_N] are defined to be: +Formally, the lenght of the parital key, stem:["pk"_N^l], is defined as: [stem] ++++ -"Head"_(N,1)^(0-5) := {(||pk_N||_(nib),||pk_N||_(nib) < 63),(63,||pk_N||_(nib) >= 63):} +"pk"_N^l = p_l + N_n + N_(n+x) + ... + N_(n+x+y) ++++ -In which stem:[||"pk"_N||_(nib)] is the length of stem:["pk"_N] in number nibbles. -stem:["Head"_(N,2),...,"Head"_(N,l+1)] bytes are determined by the algorithm as -defined in <>. +as long as stem:[p_l = m], stem:[N_(n+x) = 2^8-1] and +stem:[N_(n+x+y) < 2^8-1], where stem:[m] is the maximum possible value +that stem:[p_l] can hold. ==== -[#algo-pk-length] -===== Partial Key Length Encoding -**** -Algorithm: stem:["Partial-Key-Length-Encoding"("Head"_(N,1)^(6-7),pk_N)] - -. stem:["if " ||pk_N||_(nib) >= 2^16] -. stem:[" " "return Error"] -. stem:["Head"_(N,1) larr 64 xx "Head"_(N,1)^(6-7)] -. stem:["if " ||pk_N||_(nib) < 63] -. stem:[" " "Head"_(N,1) larr "Head"_(N,1) + ||pk_N||_(nib)] -. stem:[" " "return Head"_N] -. stem:["Head"_(N,1) larr "Head"_(N,1) + 63] -. stem:[l larr ||pk_N||_(nib) - 63] -. stem:[i larr 2] -. stem:["while " (l > 255)] -. stem:[" " "Head"_(N,i) larr 255] -. stem:[" " l larr l - 255] -. stem:[" " i larr i + 1] -. stem:["Head"_(N,1) larr l] -. stem:["return Head"_N] -**** - [#sect-merkl-proof] ==== Merkle Proof @@ -340,7 +328,6 @@ where the first variant is a leaf node and the second variant is a branch node. ++++ "StoredValue"_("SC") := {("Enc"_("SC")("StoredValue"(k_N)),"if StoredValue"(k_N) = v),(phi,"if StoredValue"(k_N) = phi):} ++++ -==== stem:[N_(C_1) ... N_(C_n)] with stem:[n <= 16] are the children nodes of the branch node stem:[N] and stem:["Enc"_("SC")], stem:["StoredValue"], stem:[H], and @@ -351,6 +338,19 @@ respectively. The Trie deviates from a traditional Merkle tree where node value (<>), stem:[v_N], is presented instead of its hash if it occupies less space than its hash. +==== + +[#defn-node-hashes] +.<> +==== +To increate performance, a merkle proof can be generated by inserting the hash of +a value into the trie rather than the value itself (which can be quite +large). If merkle proof computation with node hashing is explicitly executed via +the Host API (<>), then any value larger than +32 bytes is hashed, resulting in that hash being used as the subvalue +(<>) under the corresponding key. The node header must +specify the variant stem:[001] respectively stem:[0001] (<>). +==== [#defn-merkle-value] .<> diff --git a/ab_host-api/storage.adoc b/ab_host-api/storage.adoc index 02f4c7db7..e3ccc6fd7 100644 --- a/ab_host-api/storage.adoc +++ b/ab_host-api/storage.adoc @@ -131,6 +131,27 @@ value to be appended. Compute the storage root. +[#sect-ext-storage-root-version-2] +===== Version 2 - Prototype +---- +(func $ext_storage_root_version_2 + (param $version i32) (return i32)) +---- + +Arguments:: +* `version`: a 32-bit pointer to the state version of the following format: ++ +[stem] +++++ +v = {(0, "state version 1"),(1, "node hashes"):} +++++ +where stem:[0] behaves like version 1 (<>) of +this function and stem:[1] makes use of "node hashes" when calculating the +merkle proof (<>). +* `return`: a 32-bit pointer to the buffer containing the 256-bit Blake2 storage +root. + +[#sect-ext-storage-root-version-1] ===== Version 1 - Prototype ---- (func $ext_storage_root_version_1 diff --git a/ac_runtime-api/modules/core.adoc b/ac_runtime-api/modules/core.adoc index dc5a8bbfa..733d6461e 100644 --- a/ac_runtime-api/modules/core.adoc +++ b/ac_runtime-api/modules/core.adoc @@ -18,18 +18,13 @@ Return:: |Name |Type |Description | `spec_name` | String | Runtime identifier - | `impl_name` | String | Name of the implementation (e.g. C++) - | `authoring_version` | Unsigned 32-bit integer | Version of the authorship interface - | `spec_version` | Unsigned 32-bit integer | Version of the Runtime specification - | `impl_version` | Unsigned 32-bit integer | Version of the Runtime implementation - | `apis` | ApiVersions (<>) | List of supported APIs along with their version - | `transaction_version` | Unsigned 32-bit integer | Version of the transaction format +| `state_version` | Unsigned 32-bit integer | Version of the trie format |=== .ApiVersions