# ZK Playground Homework 0 Link: https://hackmd.io/@ChiHaoLu/ZKPlayground-HW0 ## Prerequisite ```bash npm i -g eth-cli ``` ## Problems ```bash eth address:random > test_account.json export ETH_CLI_PRIVATE_KEY=(cat test_account.json | jq '.privateKey' -r) ``` ### Problem 1 ```bash eth transaction:send --to 0x847FB490b9255758738c1DBddD9E3049E9bC86c8 -n goerli --value 1000000000000000 ``` ### Problem 2 ``` MACI ``` ### Problem 3 ```bash eth method:hash 'claim(uint256)' # => 379607f5 # generate test ABI with solc solcjs test.sol --abi # Encode the argument with ABI eth method:encode --goerli test_sol_test.abi 'claim(1)' # => 0x379607f50000000000000000000000000000000000000000000000000000000000000001 eth transaction:send --to 0x847FB490b9255758738c1DBddD9E3049E9bC86c8 -n goerli --data 0x379607f50000000000000000000000000000000000000000000000000000000000000001 ``` ### Problem 4 ```bash eth abi:add zk test_sol_test.abi ``` :::info #### :bulb: 關於 contract read public arrray variable 原本是寫 `eth contract:call -n goerli zk@0x847FB490b9255758738c1DBddD9E3049E9bC86c8 'hashes(0)'` 一個一個拿,原因是 solidity 自動產生的 getter 會避免 gas costs(array 元素可能很多) > If you have a public state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism exists to avoid high gas costs when returning an entire array > https://docs.soliditylang.org/en/v0.8.4/contracts.html#getter-functions > 也可以直接算就好了 https://emn178.github.io/online-tools/keccak_256.html ::: ```javascript const keccak256 = require('keccak256'); const txs = [ 'zkpenguin', // 0 'zkpancake', // 1 'zkpolice', // 2 'zkpig', // 3 'zkplayground', // 4 'zkpigeon', // 5 'zkpoison', // 6 ]; const simpleHash = (a, b) => { // compare string hex value const intA = parseInt(a, 16); const intB = parseInt(b, 16); const concatedString = intA < intB ? a + b : b + a; return keccak256(Buffer.from(concatedString, 'hex')).toString('hex'); }; const hashes = txs.map((tx) => keccak256(tx).toString('hex')); // hash(hash(zkpig) <-> hash(zkpigeon)) const a = simpleHash(hashes[3], hashes[5]); // hash(zkpoison) const b = hashes[6]; const c = simpleHash(a, b); // hash(hash(zkplayground) <-> hash(zkpenguin)) const d = simpleHash(hashes[4], hashes[0]); // hash(hash(zkpancake) <-> hash(zkpolice)) const e = simpleHash(hashes[1], hashes[2]); // d + e const f = simpleHash(d, e); const root = simpleHash(c, f); // making proof path for zkplayground const proof = [ hashes[0], // zkpenguin // zkpancake <-> zkpolice e, c, ]; console.log('proof', proof); console.log('root', root); // generate function argument console.log(JSON.stringify(proof.map((hash) => '0x' + hash))); // root should be e2de7e936cd2e3b398a5b5b89726a8d72148b93050d271cf91ffec3cc5598577 if ( root === 'e2de7e936cd2e3b398a5b5b89726a8d72148b93050d271cf91ffec3cc5598577' ) { console.log('root is correct'); } else { console.error('root is incorrect'); } ``` ```bash eth contract:call -n goerli zk@0x847FB490b9255758738c1DBddD9E3049E9bC86c8 'merkleProof(["0x2098ddd01d6035049de112333af26442bb3009ea06b6df66fccfadf8adee9914","0xb4435d3d2bb4863bffe2dd7c4a217641efe9da99b177cef8693fe26910a2bf04","0x7c8d8e6486e95d2eaff942ec8eb9b732d53596cb06548b62ff4841438a25a5d4"])' ``` 好! ![](https://i.imgur.com/I6jJeYL.png) ## Test contract for generating ABI ```bash npm i -g solc # skip if already installed solcjs test.sol --abi eth abi:add zk test_sol_test.abi # if created eth abi:update zk test_sol_test.abi ``` 16 年開始接觸到以太坊,研究智能合約, 曾主導 NFT 項目發行與架構設計,本業是 Sass 新創軟體工程師,因為很喜歡研究 Computer Science,之前透過網路資源學習過 ZKP 相關理論知識,也自學 circom 相關知識與撰寫程式經驗,但尚有許多理論和技術細節並不熟悉,也想透過這次過程,研究更多 ZKP 相關的知識。 ```solidity // test.sol // SPDX-License-Identifier: MIT pragma solidity 0.8.16; contract test { bytes32[] public hashes; function claim(uint256 _amountInFinney) public payable {} function merkleProof(bytes32[] memory proof) public {} } ``` ### JS code of HW4 - [merkle-tree-practice/index.js at main · moojing/merkle-tree-practice (github.com)](https://github.com/moojing/merkle-tree-practice/blob/main/index.js)