BlockchainGirl || Web3/ZK enthusiast || #Onbecoming...👸💻

Joined June 2020
53 Photos and videos
Pinned Tweet
Happy Monday, back to studying ZK and staying locked in.
7
3
31
1,494
Marvy retweeted
Kick off @gooddollarorg buildathon 🎉 We selected 20 teams to take 7-day challenge before selecting the top ones to enter the next GoodBuilders Season 👀 Thanks @zintarh_dev & @ImmanuelOlivia1 for inspiring the next generation and killing the past season with their projects!
6
9
41
1,923
Marvy retweeted
Proov. A habit tracking app designed to help you stay consistent, build better routines, and turn daily actions into lasting progress. With a simple, structured experience, Proov helps you track what matters and stay committed to your goals. One day at a time.
1
3
38
Marvy retweeted
We received 80 applications and selected 20 teams Congrats for those selected!
GoodBuilders 7 Day Buildathon|2-8 June 🤝 20 teams pre-selected for building 🏆 $3K prizes fast track into a funded 3-month program for top 2 Past dev3pack projects went from 0 → 800 users with @gooddollarorg incubation program. Apply by May 31 👇 ubi.gd/buildathon
3
4
35
1,788
Marvy retweeted
Registration is OFFICIALLY OPEN 🎉🔥 Cohort XV students it’s time! 🚀 In a few months, you could be: → Building real-world Web2 products → Diving deep into Web3 → Writing powerful Rust code → Exploring the future with Zero Knowledge (ZK) Or… still watching from the sidelines. Choose your path. web3bridgeafrica.com/registe… 👆Apply now. Spots won’t wait. ⏳ #Web3 #Web2 #RustLang #ZK #TechCareers
8
36
66
3,070
Day 33/100 of ZK 🔐 Everything started to connect: how ZK moves from computation → structure → algebra → proofs. It began with barycentric evaluation. When a polynomial is in evaluation (point-value) form, you don’t need to convert back to coefficients to work with it. You can evaluate it at new points directly and efficiently. That matters because in ZK, we often stay in this “evaluation world”, it’s faster and fits how modern proof systems operate. That showed a distinction: A function is just a mapping. A polynomial is a structured function. And over finite fields, different polynomials can represent the same function on a given domain. So what really matters isn’t the exact polynomial, it’s the behavior it satisfies over that domain. Now connect that to programs: Every program defines a structure. Constraints that describe how inputs relate to outputs. In ZK, the verifier doesn’t see the inputs (the witness), but it does know the structure. So the goal becomes clear: prove that your hidden values satisfy the same structure. But how do we trust that structure algebraically? This is where Reed–Solomon codes come in. They add redundancy so we can check that something behaves like a low-degree polynomial, catching errors and enforcing consistency. And that’s the bridge: We take computation → express it as constraints → encode it as polynomials → use algebraic checks to verify correctness. That entire process is arithmetization. Whether it’s: • R1CS • PLONKish systems • Algebraic Intermediate Representation • or newer frameworks They’re all doing the same thing: Turning programs into algebra so they can be proven. #ZK #ZeroKnowledgeProof #BuildingInPublic
7
117
Marvy retweeted
Apr 19
me in every universe
1
725
2,622
40,756
Day 32/100 of ZK 🔐 Today was on Sumcheck. It lets a prover convince a verifier that the sum of a multivariate polynomial over the entire boolean hypercube equals some claimed value, without sending the whole polynomial. Suppose we have a multilinear polynomial f(x₀, x₁, …, x_{k-1}) over a finite field. We want to prove: ∑{x₀=0,1} ∑{x₁=0,1} … ∑{x{k-1}=0,1} f(x₀, …, x_{k-1}) = claimed_sum Naively, the prover would need to send all 2^k evaluations — exponential and impossible for large k. Sumcheck reduces this to just O(k) communication and O(2^k) work on the prover side (which is still much better when combined with other techniques). How Sumcheck works (step by step) The protocol is interactive and runs in k rounds (one per variable): 1. Round 1 (for x₀) Prover sends a univariate polynomial g₀(x) = ∑{x₁…x{k-1}} f(x, x₁, …, x_{k-1}) Verifier checks that g₀(0) g₀(1) equals the claimed total sum. 2. Challenge Verifier sends a random field element r₀. 3. Round 2 (for x₁) Prover now proves that g₁(x) = ∑{x₂…x{k-1}} f(r₀, x, x₂, …, x_{k-1}) Verifier checks g₁(0) g₁(1) = g₀(r₀) 4. Repeat for each variable until the last round. 5. Final check In the last round, the verifier evaluates the final univariate polynomial at the last random point and checks it matches the actual evaluation of f at all the random points chosen so far. If all checks pass, the verifier is convinced the original sum is correct. Why Sumcheck is so useful * Turns exponential sums into a short interactive (or Fiat-Shamir non-interactive) protocol. * Works beautifully with multilinear polynomials (which we saw in Day 27). * Forms the backbone of many modern SNARKs and STARKs. * When combined with KZG or other commitments, we get succinct proofs for huge computations. #ZK #BuildingInPublic #ZeroKnowledgeProof
2
20
625
Day 31/100 of ZK 🔐 Today we tackled arithmetization, the crucial bridge that turns any computation (code, logic, circuits) into something a zero-knowledge proof system can actually work with: polynomials and algebraic constraints. Arithmetization is the process of converting a computational statement (like “I know a secret x such that some function f(x) = public output y”) into a set of polynomial equations over a finite field. Why do we need this? ZK proof systems (especially SNARKs) are extremely good at proving properties about polynomials, evaluating them, summing them, checking degrees, etc. But real-world programs use if-statements, loops, comparisons, and bitwise operations. Arithmetization “flattens” all that complexity into pure addition and multiplication over numbers in a finite field. How it usually works (high-level) 1. Represent the computation as a circuit Break the program into gates: addition gates, multiplication gates, and sometimes custom gates. 2. Turn gates into constraints Each gate becomes one or more polynomial equations that must equal zero if the computation is correct. Common arithmetization schemes we discussed: * R1CS (Rank-1 Constraint System) — Classic and widely used (Groth16). Every constraint looks like: (A · w) × (B · w) = C · w where w is the witness vector (private public inputs). * Plonkish (used in PLONK and friends) — More flexible. Uses selector polynomials and custom gates so you can express complex operations with fewer constraints. * AIR (Algebraic Intermediate Representation). Used in STARKs, focuses on transition constraints over execution traces. Once the computation is arithmetized into polynomials, we can: * Commit to those polynomials (e.g., using KZG from the last few days) * Use sum-check or other protocols to prove the polynomials satisfy all the constraints * Prove the public output is correct without revealing the private inputs Why this step is so important Without good arithmetization, the proof would be huge or extremely slow. Efficient arithmetization keeps both the proof size and verification time small, which is the whole point of succinct ZK proofs. #zk #BuildingInPublic #ZeroKnowledgeProof
15
446
Day 30/100 of ZK 🔐 Presentation day. We walked through a complete, working KZG polynomial commitment implementation in Rust using the arkworks library. Here’s what we built and discussed: 1. Trusted Setup We generate a secret random τ and compute the Structured Reference String (SRS): * g1_powers: [τ⁰]₁, [τ¹]₁, …, [τ^max_degree]₁ in G₁ * [τ]₂ in G₂ (needed for verification) This SRS is public and can be reused for any polynomial up to the chosen max degree. 2. Commitment For a polynomial f(x) = 3 2x x² (in the demo), the commitment is: C = Σ coeff_i · [τ^i]₁ = [f(τ)]₁ It’s just a linear combination of the precomputed powers — resulting in a single group element. 3. Opening (Proof Generation) To prove f(a) = b at a point a: * Compute value = f.evaluate(a) * Build quotient q(x) = (f(x) - b) / (x - a) * Proof π = [q(τ)]₁ (again, one group element) 4. Verification A single pairing check: e(π, [τ - a]₂) == e(C - [b]₁, [1]₂) If it holds, the proof is valid. If not, it’s rejected. Demo Highlights * Max degree = 10 * Simple polynomial f(x) = 3 2x x² * Commitment computed * Open at point = 5 → returns value and proof * Verify correct value → true * Try wrong value → false (correctly rejected) The beauty of KZG is that both the commitment and the proof are constant size (one group element each), and verification requires only one pairing, this is extremely efficient. In ZK, this lets us commit to large polynomials (e.g., circuit constraints) and prove specific evaluations succinctly, which is foundational for many zk-SNARK constructions. #ZK #BuildingInPublic
1
1
26
702
Still here…
2
1
7
151
Day 29/100 of ZK 🔐 Today we finished the core of KZG polynomial commitments by walking through the last two steps: proving an evaluation and verifying it. Quick recap from yesterday: * Trusted setup gives us the structured reference string (SRS): powers [τ⁰]₁, [τ¹]₁, …, [τ^d]₁ in G₁ and corresponding powers in G₂. * Commitment to a polynomial f(x) of degree ≤ d is C = [f(τ)]₁ — one group element. Step 3: Proving an evaluation Verifier sends a random challenge a (usually via Fiat-Shamir hash of previous messages). Prover wants to show f(a) = b. Compute the quotient polynomial: q(x) = (f(x) - b) / (x - a) Since f is degree ≤ d and (x - a) is degree 1, q has degree ≤ d-1. The proof is simply π = [q(τ)]₁ ∈ G₁ — again, a single group element. Step 4: Verification Verifier checks one pairing equation: e(π, [τ - a]₂) = e(C - [b]₁, [1]₂) This holds if and only if f(τ) - b = (τ - a) · q(τ), which is true exactly when f(a) = b. Pairings are bilinear, so the equality checks the polynomial identity without ever seeing f or q. Why this is so powerful * Commitment = 1 group element * Proof = 1 group element * Verification = 1 pairing check (fast on modern hardware) * Security rests on the q-SDH assumption (q-Strong Diffie-Hellman) — no known attacks when τ stays secret. We also talked about why the random challenge a is essential: without it, a malicious prover could precompute fake proofs for fixed points. Fiat-Shamir turns the interactive challenge into a non-interactive hash, making the protocol secure in the random-oracle model. @Oba_Ddev #ZeroKnowledgeProof #BuildingInPublic
3
2
18
593
Day 28/100 of ZK 🔐 Today we started implementing KZG (Kate-Zaverucha-Goldberg) polynomial commitments — the succinct, pairing-based commitment scheme that powers many zk-SNARKs and is a cornerstone for proving polynomial evaluations efficiently. KZG is built around four main steps. We covered the first two today. 1. Trusted setup (powers of tau) A trusted party (or multi-party ceremony) generates a secret random value τ and computes powers of it: SRS = { [τ⁰]₁, [τ¹]₁, …, [τ^d]₁ , [τ⁰]₂, …, [τ^d]₂ } where [·]₁ means point in G₁ and [·]₂ in G₂ (pairing-friendly elliptic curve groups). These powers are the structured reference string (SRS), which is public and reusable for all polynomials up to degree d. τ is called “toxic waste” because anyone who knows τ can forge proofs. If τ leaks, an attacker can create fake polynomial evaluations that pass verification. So every participant in the ceremony adds their own randomness to τ, then permanently deletes their share. No single person ever knows the final τ. If even one contributor deletes properly, the secret stays safe forever. 2. Commit to a polynomial Given a polynomial f(x) = f₀ f₁x f₂x² … f_d x^d of degree ≤ d, the commitment is: C = f₀[τ⁰]₁ f₁[τ¹]₁ … f_d[τ^d]₁ = [f(τ)]₁ ∈ G₁ This is just a single group element — constant size, no matter how large the polynomial is. The next two steps (coming soon) are: 3. Prove an evaluation 4. Verify Why KZG matters in ZK: * Commitments and proofs are tiny (constant size) * Verification is extremely fast (one pairing) * It enables succinct proofs for arithmetic circuits, lookup tables, and many other building blocks in zk-SNARKs. KZG is like locking a giant spreadsheet into a single tiny safe. You seal it once (commit), then prove “the number in cell B47 is exactly 7” with a tiny proof without ever opening the safe or showing the spreadsheet. The verifier trusts it because the math can’t be cheated unless someone stole a secret that should have been destroyed. #ZeroKnowledgeProof #BuildingInPublic
10
248
Day 27/100 of ZK 🔐 Today we implemented Pedersen commitments, a cryptographic primitive for hiding values while allowing later opening, widely used in ZK for commitments, range proofs, and bulletproof-style arguments. A Pedersen commitment lets you commit to a value m with a random blinding factor r so that the commitment C hides m perfectly (hiding property) and you can’t change your mind later (binding property under discrete log hardness). The math is simple: C = g^m · h^r mod p where g and h are generators of a large prime-order subgroup, and the discrete log between g and h is unknown (h = g^x for secret x). * To commit: pick random r, compute C above. * To open: reveal m and r; verifier checks C == g^m · h^r mod p. Because of the unknown relation between g and h, an attacker can’t extract m from C, and can’t find a different m' and r' that give the same C (unless they solve DL, which is hard). #ZeroKnowledgeProof #BuildingInPublic
1
2
14
178
Day 26/100 of ZK 🔐 Today we focused on multilinear polynomials and implemented a basic multilinear extension (MLE) over a finite field. A multilinear polynomial in k variables is one where each variable appears with degree at most 1. Formally, it looks like: f(x₀, x₁, …, x_{k-1}) = Σ_{w ∈ {0,1}^k} c_w · (x₀^{w₀} x₁^{w₁} … x_{k-1}^{w_{k-1}}) Because each exponent is 0 or 1, the polynomial is completely determined by its values on the boolean hypercube {0,1}^k — exactly 2^k points. We store these 2^k evaluations in a Vec<u64> and treat them as the canonical representation of the MLE. The multilinear extension property means we can evaluate the polynomial at any point in F_p^k (not just {0,1}^k) by interpolating the hypercube values. This is what makes MLEs powerful, they extend discrete table lookups into smooth, algebraic objects that play nicely with sum-check, Fiat-Shamir, and low-degree testing. How evaluation works (bookkeeping method) We start with the full table of 2^k values. For each variable r_i in the point: * Split the table into two halves: low (where x_i = 0) and high (where x_i = 1) * For each low entry, compute: low r_i × (high - low) * This linearly interpolates between the low and high slices * Repeat for the next variable on the now-halved table, until only one value remains This is O(2^k) time but very cache-friendly and constant-factor efficient. The Lagrange method (summing f(w) × χ_w(r) over all w) is slower (also O(2^k)) but useful for verification. How I implemented it * Field: p = 2⁶¹ - 1 (fits in u64, fast reduction) * Inline field ops: fadd, fsub, fmul (with u128 intermediate for mul), fpow (binary exponentiation), finv (a^{p-2}), fdiv * MultilinearPoly holds evals Vec<u64> and num_vars = log₂(len) * evaluate(point) uses the iterative binding loop (bookkeeping) * bind_first(value) fixes the first variable and returns the reduced MLE * add, scale do pointwise operations * sum_over_hypercube() folds all evals (useful for sum-check round 0) * lagrange_basis evaluate_lagrange for alternative interpolation check * Demo shows 2-var and 3-var examples, boolean cube checks, binding, scaling, adding, and field sanity tests In ZK this structure is critical: circuits get arithmetized into multilinear polynomials, sum-check proves sums over hypercubes efficiently, and random evaluation points let verifiers check low degree without reading the whole table. #ZeroKnowledgeProof #BuildingInPublic #Math
2
1
27
709
Day 25/100 of ZK 🔐 Today was presentation and discussion day. Walked through the Merkle tree implementation from yesterday, and discussed the Shamir Secret Sharing implementation. Everyone shared their code, debugged edge cases, and talked about how it fits into ZK workflows. We talked about why Shamir matters in ZK: threshold schemes, distributed key generation, trusted setup ceremonies (powers-of-tau splitting), MPC-friendly protocols. The goal was to implement polynomial-based secret sharing over a finite field: split a secret s into n shares with threshold t (any t shares reconstruct s exactly, fewer than t reveal nothing), using Lagrange interpolation for reconstruction. Most people used GF(p) with p a large prime, some tried small fields for testing. Key parts I built: * A Polynomial struct holding coefficients (secret as constant term t-1 random coeffs mod prime) * split(secret, n, threshold) → generates n shares (x=i, y=poly(i)) for i=1 to n * combine(shares) → uses Lagrange basis polynomials to recover the constant term (secret) Most used num-bigint for arbitrary-precision arithmetic over a large prime field (e.g., 2¹²⁷ - 1 or a safe prime). Common choices included modular inverse via Fermat’s little theorem (a^{p-2} mod p) or extended Euclidean. #ZeroKnowledgeProof #BuildingInPublic
1
1
12
244
Marvy retweeted
1/ The STRK20s Technical Paper is now live. It outlines the design, architecture, and core ideas behind STRK20s, a privacy capability for any ERC-20. If you’re bullish on privacy as crypto’s next major unlock, this paper is for you 🧵
59
119
391
166,075
ZK is for privacy ZK is for scale ZK is for security ZK is for lifting barriers and expanding what blockchains can do
46
30
213
6,812
Day 24/100 of ZK 🔐 Today we implemented a Merkle tree in Rust, a binary tree where each leaf is the hash of a data item and each non-leaf node is the hash of its two children. The root hash becomes a compact commitment to the entire dataset. Built one that supports arbitrary power-of-2 capacity (2^depth leaves), allows adding leaves sequentially (index 0 to n-1), updating any leaf by index, getting the current root hash, and generating a Merkle proof for any leaf (sibling hashes needed to recompute the root). I used SHA-256 via the sha2 crate for hashing, with a prefix byte to distinguish leaves (0x00) from internal nodes (0x01). The tree is stored in a flat Vec with standard binary-heap indexing: root at index 1, left child of i is 2i, right is 2i 1, leaves start at 2^depth. Core functions: * new(capacity: usize) — creates an empty tree with 2^depth capacity, pre-filled with sentinel hashes * add(data: &[u8]) — appends a new leaf and updates the path to root * update(index: usize, data: &[u8]) — replaces leaf and updates path to root * root() — returns current root hash * get_proof(index: usize) — returns vec of sibling hashes path directions * verify_proof(leaf_data, proof, root) — recomputes root from leaf proof and checks match In ZK, Merkle trees are everywhere: proving inclusion/exclusion in large datasets, stateless clients, rollups, verifiable data structures. You commit to the root once, then prove a leaf belongs without revealing the whole tree. #ZeroKnowledgeProof #BuildingInPublic
1
15
426
Day 23/100 of ZK 🔐 Today we covered hash functions. A hash function takes an input of any length and outputs a fixed-size value called a digest (or hash). Simple hash functions (like those in hash tables) only guarantee that identical inputs produce identical outputs. Because the output space is finite and inputs are infinite, collisions (different inputs → same output) are unavoidable. Cryptographic hash functions are much stronger. They must satisfy three core security properties: Preimage resistance (one-wayness): Given a digest h, it's computationally infeasible to find any input m such that hash(m) = h. Easy to hash forward, extremely hard to reverse. Second preimage resistance: Given a message m, it's infeasible to find a different m' ≠ m where hash(m) = hash(m'). Collision resistance: It's infeasible to find any two distinct messages m ≠ m' such that hash(m) = hash(m'). These properties enable avalanche effect: changing even one bit in the input causes roughly half the output bits to flip unpredictably, making small changes hard to control. In practice we talk about attacks instead: preimage attack — find input for given hash second-preimage attack — find alternate message for given input hash collision attack — find any colliding pair We also touched on major families: SHA-1 — once standard, now broken for collision resistance (practical collisions found in 2017). Deprecated for signatures and most uses. SHA-2 family (SHA-256, SHA-512, etc.) — still secure, widely used (Bitcoin, TLS, etc.). No practical breaks on full versions. Keccak / SHA-3 — winner of NIST's SHA-3 competition (2015). Uses a sponge construction (absorb input → permute → squeeze output). Offers a different design from SHA-2, strong security margins, and good resistance to side-channel attacks. SHA3-256 is the 256-bit version. In ZK, cryptographic hashes are everywhere — Merkle trees for data integrity, commitment schemes, Fiat-Shamir heuristic to make interactive proofs non-interactive, proof compression, and random oracles in many protocols. #ZeroKnowledgeProof #BuildingInPublic
1
1
21
562
Marvy retweeted
Today we celebrate the women who wakes up every day and decides to try. The ones who opened their first GitHub account. The ones who asked questions when they felt lost. The ones who stayed up late debugging code. Web3 is still being built, and we’re glad women are helping shape what it becomes. Happy International Women’s Day from Web3Bridge. #InternationalWomensDay
1
9
59
1,007