# README
This is a simple example showing case how to use the chainark
library.
Understanding the data and the chain structure
Suppose we have a chain structure:
data0 <- data1 <- data2 <- data3
Following the rule:
$id_{n+1}$ = SHA256($id_n$ || "chainark example")
Each data is simply composed by below two elements concatenated together hash || string_literal
, where:
hash
is hash value of 32 bytes, which is the SHA256 hash of its predecessor data;string literal
ischainark example
.
Now the LinkageID
is the hash
value. In the supplied data file, the first hash
is generated by running this command:
echo 0000000000000000000000000000000000000000000000000000000000000000 | xxd -r -p | openssl sha256 -hex
It outputs hash value 66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
.
Then data0
, or the first line of the data file is simply
66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925636861696e61726b206578616d706c65
with 636861696e61726b206578616d706c65
as the hex encode of chainark example
.
Going forward we may have the ID corresponding to data0
from running the command:
echo 66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925636861696e61726b206578616d706c65 | xxd -r -p | openssl sha256 -hex
and its value is 843d12c93f9079e0d63a6101c31ac8a7eda3b78d6c4ea5b63fef0bf3eb91aa85
. This is then the genesis ID
or id0
. Usually a genesis ID is publically known and recognized.
Now data1
becomes 843d12c93f9079e0d63a6101c31ac8a7eda3b78d6c4ea5b63fef0bf3eb91aa85636861696e61726b206578616d706c65
, and we can compute id1
, and so on.
The proving task
Now we want to prove that following the above hashing computation rule, a hash value of a1ac83d0e18e0845ced8bcd71be011c011c8cde038b3aa98e4407fe5584acd7e
could be computed starting from the data identified by the genesis ID
of 843d12c93f9079e0d63a6101c31ac8a7eda3b78d6c4ea5b63fef0bf3eb91aa85
.
To do this, we first need to generate all the unit
proofs, that is, we need a ZK-proof from a data item (hash || "chainark example"
) to an ID (hash
) for all the IDs from genesis to the one under question. UnitCircuit
is implemented in the app_types.go. Besides unit circuit definition, a main function is defined to generate the unit proofs.
Then we also need to create main functions to output the genesis and recursive proofs. The genesis circuit verifies the first two unit proofs, building the initial chain structure starting from the chosen genesis ID. The recursive circuit verifies first a genesis proof or a recursive proof, then a unit proof. The proof generated from the recursive circuit could be used to verify the existence of a chain from the genesis ID to the one under question.
Under the hook
Please refer to the general doc.
Running the example
generate verification keys
Note that the fingerprints of all verification keys have been hardcoded in the example codes. Usually you don't need to worry about it. But if you have modified some of the circuits, or if you are planning to build your own application based on this example, here are general procedures to follow:
- Go to the
unit
folder, build the application, run./unit --setup
to generate proving key and verification key for the unit circuit; - Go to the
fp_unit
folder, run./fp_unit
to compute the fingerprint of the verification key, and update the result to the implementation of functionGetUnitFpBytes()
; - Since the genesis circuit hardcodes the fingerprint of the unit circuit verification key, this has to happen after the step 2: go to the
genesis
folder, build the application, run./genesis --setup
to generate proving key and verification key for the genesis circuit; - Go to the
fp_genesis
folder and run./fp_genesis
, update the result to the implementation of functionGetGenesisFpBytes
; - Go to the
recursive
folder, build the application, run./recursive --setup
to generate proving key and verification key for the recursive circuit; - Go to the
fp_recursive
folder and run./fp_recursive
, update the result to the implementation of functionGetRecursiveFpBytes
;
compute the proofs
Now setup is complete. Run below commands to compute the proof:
- Go to the
unit
folder, run./unit_script.sh
; - Go to the
genesis
folder, run./genesis_script.sh
; - Go to the
recursive
folder, run./recursive_script.sh
.
Now you have exactly one proof for each and every id: the genesis id is recognized, its successor is proved with a unit
proof, the next is proved with a genesis
proof, and the rest with a corresponding recursive
proof.