From cea9a99f8baf64a92205c7295b1a03f6bac9841b Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 15 Aug 2023 23:27:28 +0000 Subject: [PATCH] Deploy thogiti/thogiti.github.io to thogiti/thogiti.github.io:gh-pages --- .DS_Store | Bin 0 -> 6148 bytes 404.html | 203 ++ about/index.html | 235 ++ assets/.DS_Store | Bin 0 -> 6148 bytes assets/Unbounded-Black.woff2 | Bin 0 -> 106504 bytes assets/Unbounded-Bold.woff2 | Bin 0 -> 112724 bytes assets/Unbounded-ExtraLight.woff2 | Bin 0 -> 91800 bytes assets/Unbounded-Light.woff2 | Bin 0 -> 99064 bytes assets/Unbounded-Medium.woff2 | Bin 0 -> 107040 bytes assets/Unbounded-Regular.woff2 | Bin 0 -> 95936 bytes assets/apple-touch-icon.png | Bin 0 -> 1077 bytes assets/favicon-16x16.png | Bin 0 -> 1441 bytes assets/favicon-32x32.png | Bin 0 -> 2281 bytes assets/favicon.png | Bin 0 -> 15204 bytes assets/js/disqusLoader.js | 10 + atom.xml | 2898 +++++++++++++++++ .../index.html | 404 +++ .../index.html | 301 ++ .../index.html | 308 ++ .../index.html | 320 ++ .../index.html | 256 ++ fonts.css | 1 + index.html | 316 ++ intro-zkps/index.html | 335 ++ main.css | 1 + .../index.html | 665 ++++ .../index.html | 691 ++++ page/1/index.html | 6 + page/2/index.html | 276 ++ .../index.html | 349 ++ .../index.html | 371 +++ .../index.html | 335 ++ .../index.html | 428 +++ robots.txt | 4 + sitemap.xml | 379 +++ tags/ai-for-cardiology/index.html | 224 ++ tags/ai-for-cardiomyopathy/index.html | 224 ++ tags/ai-for-imaging/index.html | 224 ++ tags/ai/index.html | 234 ++ tags/algebraic-coding-theory/index.html | 220 ++ .../index.html | 225 ++ .../index.html | 225 ++ tags/bn254-elliptic-curve/index.html | 212 ++ tags/bn254/index.html | 212 ++ tags/cardiology/index.html | 224 ++ tags/cardiomyopathy/index.html | 224 ++ tags/caulk/index.html | 214 ++ tags/circom-circuits/index.html | 213 ++ tags/circom/index.html | 228 ++ .../index.html | 224 ++ .../index.html | 224 ++ tags/coefficient-extraction/index.html | 212 ++ tags/constraint-system/index.html | 214 ++ tags/danksharding/index.html | 239 ++ tags/data-extraction/index.html | 212 ++ tags/data-interpolation/index.html | 212 ++ tags/decision-tree/index.html | 214 ++ tags/diagnostic-markers/index.html | 224 ++ .../index.html | 213 ++ tags/discrete-logarithm-problem/index.html | 221 ++ .../index.html | 218 ++ tags/ecadd/index.html | 223 ++ tags/ecdbl/index.html | 223 ++ tags/ecdh/index.html | 223 ++ tags/ecdsa/index.html | 223 ++ tags/ecne/index.html | 213 ++ tags/efficient-zkp/index.html | 214 ++ .../index.html | 221 ++ tags/elgamal-key-generation/index.html | 221 ++ tags/elgamal/index.html | 221 ++ tags/elliptic-curve/index.html | 212 ++ tags/enhancing-elgamal-security/index.html | 221 ++ .../index.html | 223 ++ tags/error-correction/index.html | 212 ++ .../index.html | 223 ++ tags/ethereum-s-scalability/index.html | 212 ++ tags/ethereum-scalability/index.html | 241 ++ tags/ethereum/index.html | 258 ++ tags/executive-summary/index.html | 228 ++ tags/explanation-of-the-concept/index.html | 213 ++ tags/frobenius-automorphism/index.html | 212 ++ .../generalized-reed-solomon-codes/index.html | 212 ++ tags/greedy-algorithm/index.html | 225 ++ tags/halo2/index.html | 218 ++ tags/index.html | 2701 +++++++++++++++ tags/karp-reduction/index.html | 225 ++ tags/kzg/index.html | 214 ++ tags/lookup-arguments/index.html | 214 ++ .../index.html | 225 ++ tags/mathematical-software/index.html | 225 ++ tags/missing-value-analysis/index.html | 212 ++ tags/ml-for-cardiomyopathy/index.html | 224 ++ tags/ml/index.html | 234 ++ tags/multiscalar-multiplication/index.html | 223 ++ tags/noir/index.html | 218 ++ tags/non-linear-constraints/index.html | 214 ++ tags/optimization-algorithms/index.html | 225 ++ tags/paper-review/index.html | 234 ++ tags/point-addition/index.html | 223 ++ tags/point-doubling/index.html | 223 ++ tags/point-operations/index.html | 223 ++ tags/poseidon/index.html | 213 ++ .../index.html | 214 ++ tags/privacy/index.html | 214 ++ tags/problem-solving-techniques/index.html | 225 ++ tags/product-code/index.html | 220 ++ tags/public-key-cryptography/index.html | 221 ++ tags/r1cs/index.html | 214 ++ tags/radiomics/index.html | 224 ++ tags/rate-limiting-nullifier/index.html | 213 ++ tags/reed-solomon-codes/index.html | 212 ++ .../index.html | 225 ++ tags/rln/index.html | 213 ++ tags/rust/index.html | 238 ++ tags/sagemath-implementation/index.html | 221 ++ tags/sagemath/index.html | 285 ++ .../index.html | 221 ++ .../index.html | 223 ++ tags/security-audit/index.html | 213 ++ tags/sublinear-lookup-arguments/index.html | 214 ++ tags/technology-applications/index.html | 225 ++ .../index.html | 222 ++ tags/weighted-set-cover-problem/index.html | 225 ++ tags/writing-zero-knowledge-proofs/index.html | 226 ++ tags/yacademy/index.html | 225 ++ tags/yaudit-zk-fellowship/index.html | 225 ++ .../index.html | 214 ++ .../index.html | 214 ++ tags/zero-knowledge-proofs/index.html | 233 ++ tags/zk-fellowship/index.html | 225 ++ tags/zk/index.html | 268 ++ tags/zkml/index.html | 214 ++ tags/zkp-dotproduct/index.html | 218 ++ tags/zkp-security-audit/index.html | 213 ++ tags/zkp/index.html | 273 ++ .../index.html | 269 ++ .../index.html | 340 ++ .../index.html | 369 +++ .../index.html | 540 +++ 139 files changed, 35332 insertions(+) create mode 100644 .DS_Store create mode 100644 404.html create mode 100644 about/index.html create mode 100644 assets/.DS_Store create mode 100644 assets/Unbounded-Black.woff2 create mode 100644 assets/Unbounded-Bold.woff2 create mode 100644 assets/Unbounded-ExtraLight.woff2 create mode 100644 assets/Unbounded-Light.woff2 create mode 100644 assets/Unbounded-Medium.woff2 create mode 100644 assets/Unbounded-Regular.woff2 create mode 100644 assets/apple-touch-icon.png create mode 100644 assets/favicon-16x16.png create mode 100644 assets/favicon-32x32.png create mode 100644 assets/favicon.png create mode 100644 assets/js/disqusLoader.js create mode 100644 atom.xml create mode 100644 different-types-of-zero-knowledge-proofs/index.html create mode 100644 efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/index.html create mode 100644 enhancing-ethereum-scalability-with-product-codes-and-danksharding/index.html create mode 100644 error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/index.html create mode 100644 explanation-of-the-concept-of-zero-knowledge-proofs/index.html create mode 100644 fonts.css create mode 100644 index.html create mode 100644 intro-zkps/index.html create mode 100644 main.css create mode 100644 mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/index.html create mode 100644 mastering-rank-one-constraint-system-r1cs-with-circom-examples/index.html create mode 100644 page/1/index.html create mode 100644 page/2/index.html create mode 100644 paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/index.html create mode 100644 paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/index.html create mode 100644 paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/index.html create mode 100644 rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/index.html create mode 100644 robots.txt create mode 100644 sitemap.xml create mode 100644 tags/ai-for-cardiology/index.html create mode 100644 tags/ai-for-cardiomyopathy/index.html create mode 100644 tags/ai-for-imaging/index.html create mode 100644 tags/ai/index.html create mode 100644 tags/algebraic-coding-theory/index.html create mode 100644 tags/block-transaction-fee-optimization/index.html create mode 100644 tags/blockchain-transaction-fee-optimization/index.html create mode 100644 tags/bn254-elliptic-curve/index.html create mode 100644 tags/bn254/index.html create mode 100644 tags/cardiology/index.html create mode 100644 tags/cardiomyopathy/index.html create mode 100644 tags/caulk/index.html create mode 100644 tags/circom-circuits/index.html create mode 100644 tags/circom/index.html create mode 100644 tags/classification-of-cardiomyopathy/index.html create mode 100644 tags/classification-of-hypertrophic-cardiomyopathy/index.html create mode 100644 tags/coefficient-extraction/index.html create mode 100644 tags/constraint-system/index.html create mode 100644 tags/danksharding/index.html create mode 100644 tags/data-extraction/index.html create mode 100644 tags/data-interpolation/index.html create mode 100644 tags/decision-tree/index.html create mode 100644 tags/diagnostic-markers/index.html create mode 100644 tags/different-types-of-zero-knowledge-proofs/index.html create mode 100644 tags/discrete-logarithm-problem/index.html create mode 100644 tags/dotproduct-of-two-vectors-in-zkp/index.html create mode 100644 tags/ecadd/index.html create mode 100644 tags/ecdbl/index.html create mode 100644 tags/ecdh/index.html create mode 100644 tags/ecdsa/index.html create mode 100644 tags/ecne/index.html create mode 100644 tags/efficient-zkp/index.html create mode 100644 tags/elgamal-encryption-and-decryption/index.html create mode 100644 tags/elgamal-key-generation/index.html create mode 100644 tags/elgamal/index.html create mode 100644 tags/elliptic-curve/index.html create mode 100644 tags/enhancing-elgamal-security/index.html create mode 100644 tags/ensuring-data-integrity-with-digital-signatures/index.html create mode 100644 tags/error-correction/index.html create mode 100644 tags/establishing-secure-connections-with-ecc/index.html create mode 100644 tags/ethereum-s-scalability/index.html create mode 100644 tags/ethereum-scalability/index.html create mode 100644 tags/ethereum/index.html create mode 100644 tags/executive-summary/index.html create mode 100644 tags/explanation-of-the-concept/index.html create mode 100644 tags/frobenius-automorphism/index.html create mode 100644 tags/generalized-reed-solomon-codes/index.html create mode 100644 tags/greedy-algorithm/index.html create mode 100644 tags/halo2/index.html create mode 100644 tags/index.html create mode 100644 tags/karp-reduction/index.html create mode 100644 tags/kzg/index.html create mode 100644 tags/lookup-arguments/index.html create mode 100644 tags/machine-learning-feature-selection/index.html create mode 100644 tags/mathematical-software/index.html create mode 100644 tags/missing-value-analysis/index.html create mode 100644 tags/ml-for-cardiomyopathy/index.html create mode 100644 tags/ml/index.html create mode 100644 tags/multiscalar-multiplication/index.html create mode 100644 tags/noir/index.html create mode 100644 tags/non-linear-constraints/index.html create mode 100644 tags/optimization-algorithms/index.html create mode 100644 tags/paper-review/index.html create mode 100644 tags/point-addition/index.html create mode 100644 tags/point-doubling/index.html create mode 100644 tags/point-operations/index.html create mode 100644 tags/poseidon/index.html create mode 100644 tags/privacy-preserving-machine-learning/index.html create mode 100644 tags/privacy/index.html create mode 100644 tags/problem-solving-techniques/index.html create mode 100644 tags/product-code/index.html create mode 100644 tags/public-key-cryptography/index.html create mode 100644 tags/r1cs/index.html create mode 100644 tags/radiomics/index.html create mode 100644 tags/rate-limiting-nullifier/index.html create mode 100644 tags/reed-solomon-codes/index.html create mode 100644 tags/resource-allocation-optimization/index.html create mode 100644 tags/rln/index.html create mode 100644 tags/rust/index.html create mode 100644 tags/sagemath-implementation/index.html create mode 100644 tags/sagemath/index.html create mode 100644 tags/secure-communication-with-elgamal/index.html create mode 100644 tags/securing-communications-with-ecc/index.html create mode 100644 tags/security-audit/index.html create mode 100644 tags/sublinear-lookup-arguments/index.html create mode 100644 tags/technology-applications/index.html create mode 100644 tags/understanding-zero-knowledge-proofs/index.html create mode 100644 tags/weighted-set-cover-problem/index.html create mode 100644 tags/writing-zero-knowledge-proofs/index.html create mode 100644 tags/yacademy/index.html create mode 100644 tags/yaudit-zk-fellowship/index.html create mode 100644 tags/zero-knowledge-decision-tree-accuracy-tests/index.html create mode 100644 tags/zero-knowledge-decision-tree-predictions/index.html create mode 100644 tags/zero-knowledge-proofs/index.html create mode 100644 tags/zk-fellowship/index.html create mode 100644 tags/zk/index.html create mode 100644 tags/zkml/index.html create mode 100644 tags/zkp-dotproduct/index.html create mode 100644 tags/zkp-security-audit/index.html create mode 100644 tags/zkp/index.html create mode 100644 understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/index.html create mode 100644 unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/index.html create mode 100644 unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/index.html create mode 100644 writing-zero-knowledge-proofs-and-circuits-in-four-languages/index.html diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c32883842752acf742ff9e4a68f0123bb24f31f0 GIT binary patch literal 6148 zcmeHKISv9b4733uBpOP}e1RWC2wuPkI6EYYg?=mE#nTuc1!$pz0yJJZlQ^ENc8Yi{ zB09h9XCf038Nm(ZYD3p--@IeJj3^L}GtScNo857HIvqRNuLH&%%0?PIhey6`(5L_v zpaN8Y3Q&QME0862H2(O>Jdg@dfnQg^?uP<5tch))UmX~{1pp2ZcEj9z31G1RuqL*F zh`==`Eo-SGgIZ^>C@T@>TmJ_T0OZc1q z|Cz)U6`%rtrGO3=tHm6jl(n_ + + + + + + +404 | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

404: Page not found

+
+

+ Oops! We can't seem to find the page you are looking for. Let's + head back home. +

+

+
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/about/index.html b/about/index.html new file mode 100644 index 00000000..7ceb3deb --- /dev/null +++ b/about/index.html @@ -0,0 +1,235 @@ + + + + + + + + + +Nagu: A Seasoned Innovator in AI, Blockchain, and Infrastructure | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Nagu: A Seasoned Innovator in AI, Blockchain, and Infrastructure

+
+

Nagu is a distinguished professional with over 20 years of experience in developing data-driven products and platforms in the realms of Artificial Intelligence & Machine Learning (AI/ML), Blockchain, and Infrastructure. His solid foundation in mathematics and science, combined with his expertise in Cryptography, sets him apart as a thought leader in the industry.

+

A proud alumnus of prestigious institutions, Nagu holds degrees from MIT's FinTech program, University of Southern California (USC), and the Indian Institute of Technology (IIT). His vast experience in data-driven AI/ML systems design and data-intensive applications development has been instrumental in delivering cutting-edge solutions across various industry sectors (Healthcare, Finance, Leisure Travel, Technology and Infrastructure).

+

Nagu's unique ability to merge technology, data, and business operations has led to the creation of innovative products in Marketing Technology, Advertising Technology, Digital Transformation, Strategic Growth, and Cross-Border Team Building. His work has been recognized and published in top-tier scientific journals, showcasing his commitment to excellence.

+

Throughout his illustrious career, Nagu has held executive positions at renowned organizations such as TeamViewer, Viking Cruises, and PCM. This experience has honed his leadership skills, enabling him to drive success for both his teams and the companies he has served.

+

Nagu's passion for innovation is evident in his three primary areas of interest:

+
    +
  1. +

    Artificial Intelligence & Machine Learning: Nagu's expertise in AI/ML has been instrumental in designing advanced data-driven systems and applications, pushing the boundaries of what is possible in the field.

    +
  2. +
  3. +

    Blockchain: Nagu's knowledge of cryptography and blockchain technology has enabled him to develop secure, decentralized solutions that revolutionize the way businesses operate.

    +
  4. +
  5. +

    Infrastructure: Nagu's experience in infrastructure development has provided him with the ability to create robust, scalable platforms that support the ever-evolving needs of today's digital landscape.

    +
  6. +
+

In summary, Nagu is a seasoned innovator and leader with a proven track record in AI, Blockchain, and Infrastructure. His extensive experience, combined with his passion for cutting-edge technology, positions him as a valuable asset in the rapidly advancing world of digital transformation.

+

Publictions

+
    +
  • Successful real-world application of an osteoarthritis classification deep-learning model, Journal of Orthopedic Research, https://doi.org/10.1002/jor.25415
  • +
  • Deep Transfer Learning for Classification of Common Skin Cancers in Asian Ethnicities Using CNNs with Ensemble Schemes (under review with JAMA Dermatology & JAA Dermatology).
  • +
  • Privacy Preserving Brain Tumor Segmentation using Federated Learning and Differential Privacy (under review with Applied Sciences & Journal of Neuro-Oncology)
  • +
  • Acoustic Psychometry using Machine Learning Methods for mental states identification, http://apsystems123.com/#t-2
  • +
+

You can contact me at +telegram +or +mail.

+ +
+ + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c12c4b1275625b6800e1a6370892e4e41268648a GIT binary patch literal 6148 zcmeHK%}T>S5Z<-5-BN@e6nb3nTClAYD_%mZFJMFuDm5Xc2GeY5T5~9cob`o#5}(JJ z-OV9b@FrqsVE3DypWVy{*&oIjcUNJLu@+-YKttrHY!NhXb?w<;M6TzUur$chc@V2$ z%S37$=o>k^8{pBik{lz_wZj_3H zLidB)Xp)UvhnFf@`cX1j=!7VoK*+;gl!PjC)hY>7o$DEgXo$wR)n2cA-C;)#hMSID z_xh*j9eFnBZ#E5abbNAgJ${L2iFz|ca^PIcfyDyeK`GVr>MfF3B~!2$IYlfXF+dCu z1H{1YF<{RE(cHb#sbXS)82Et!+#e(~M8{%oP;VX3;q@8)RYVlf@hyQUEjku+gWv(- zCKb@6a{I*KCLQe3#yJ*qgC?DEy)w*WS1ukeT(1sxslyp}3{p=F5CdffDrVTi^ZyEd znXQlfate)z0b<~vF~F-MZ{$Kz_H6xD9-g%l+7mPsjLT600ljnyfC26!ZS6FEi8{nN X7IT9*3)*!$AYBABA=D8Azres3IY&$p literal 0 HcmV?d00001 diff --git a/assets/Unbounded-Black.woff2 b/assets/Unbounded-Black.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..6bf337eee9d521563c46325b230d968d66452980 GIT binary patch literal 106504 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 literal 0 HcmV?d00001 diff --git a/assets/Unbounded-Bold.woff2 b/assets/Unbounded-Bold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..add77ee4f2b89d13c93f4cc520a4910443c087af GIT binary patch literal 112724 zcmaI7V~}RS*0%YSyKLLGZQHhO+qT_h+g-M8qsz82eNKGuI};NVbN|>GxnoC0=30?! zU5V{3FUAA_0ssI&?J5AoeezjtEUuiCaFueG(69Hod^1QKsZi7F)G z3MoSxB17PC_{`pNeQdXnl)k`x)Nbxe0R~wovj+{ZaXg) z`>1jB6Kw2@^FBCK3lDEtLI9~HHXfEHuxEc9{8aiWCE8OSkTd~yvJ$W-LCZWa7VbBa5VmcWz zufK5Lj_#RNC}|fxaDp_#HE<8_XgaGeP8>;3j~r4^#*y5ab&-%CL&WX15~|ZfiO{={ zE%PD8kc5^?V(3)LYMGTsaP${NC0_J~;F@h-6rI?gK%x_{L_J>l`N$q39OC$

)Le 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%0DmliR)7K!0Ih(8-J%&0nT!UP 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≀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 U{`YtN&ljZ1f1KuOpt%760P+KjIsgCw literal 0 HcmV?d00001 diff --git a/assets/Unbounded-Light.woff2 b/assets/Unbounded-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..f998903444e4913b2d3a150cc745c601377f70d3 GIT binary patch literal 99064 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 z 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 E04l&K{{R30 literal 0 HcmV?d00001 diff --git a/assets/Unbounded-Medium.woff2 b/assets/Unbounded-Medium.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b16d92b1162e146fae550d6447635d6310837aab GIT binary patch literal 107040 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 IV2jy5XdKTwf(}Vpf!8p+o2)gnPgsOii6r ztFY+8lrUZ;G&*l&<3roMTcL2HL%Q9CQ2L*cO`>c1Py^J`=9vY3v&9K3D(xpwH0X=J zlmXgL#DMfbmnZ;Z*?J}c?=##5sf~#e*3HK>knHo!sbD?iv=FIK~KQ!?` z-FkvLAZM)hdLHu(XB0usH}&B;aiWde2mRwH`3*sHuSVtkQG zf&=o1)pImhti7{XhgIE2cTiWYPY0U($Tm&Z#3-9DlQ`-zUtYwBb+>??j<#+WS1aXq z4`k)q3*5pt97^C(fmW4B6VJXv(4eyVk^hPHExdv3(om8U_9B60Ks)Z95Ja`E)-EKS z0Q-ckeFV8dfoY1DP1RYg{l~0795MLC1fw}>PgC221&t)-X{GGW_L4fPT*NTB2sbNz z##Q>zIj(bG-xL(`zNo!ZkfZ7OY%IvP00(k z@E2s7`$l4)16vsHq6j8RR28Um%7=_g0bSSIy~(s4i&F;?ewlY2zm`xozwiavVbb8H z<(FY$M~XJ7^t;^gE?Pd*mrimvOknD1DKc9wcWf>9vzfP=WDid$jhA*$O|$bT|2k&d z{GmK@!df>#$ogbf{d(r%Ud<;h={D#!l$~pTRZ!|eXCE+Tr#7oUYbLs1Qdu@e~ zCO`M`hq#NRUahIx4${qsdT&wNR1XG;BSsh8KFVgf{G%y93rVB8Sw~=~5m(vIxoSSNMB!P=RT_ZfGdd$yu(VfHs=gUTyaELm8HZ(5bpkckrDn1Ar3raQYou zE-eb+R0Wp>0mAXf=K`WNR=N+1)cs&c`FU=SIWe$lmAZ7=l~kiz=4i$2BpR;jY*DgV zjPA@fq>FhqN;Y^?LiCWv)VN{rs*eIM#hJ46t*l|rMANo7Pjd>39oLI4#9o2F4dk?e zs<$Y7E47TR6xU_F$~=#S44L<=e|3vb!S{RBY|h{a_E`iMUH)zm#A+MfLNgvLwWw}U~}d|`d1WUMTHXm;D=o6gej((OR3ULVQU%03iB z=5vXNSmC;|a913zuv%^#a7*Gpl^L5Tws%E0B?V-ZhGbNK#(lql1ccRsCmkfmwqb%p zp^V4$#tcvjhHlFF0oR_k#p?tllu9Q#)p#)NH?Pkv~@g%0Zs*L^!nzNE@cM}8lEqS3_jj)iDU>8(AHd(RT7E9oU6JqMkJC4`Eg!^~c4tf=36@-Ex zTr7Ry(_0j8mo*ZwZ+FGt(ut2LS981w0*WO{=mRRweMdsw#%0K*bJFHSy`Ug=2)UvT3$7n=l8A#d zMv++PLx+$pE!W)E^KjfTsWSi#j3w$2a)iCLJ!c5Zz?q48D#e8juIAsD+uRqPHG$&$ zm-*b#`E7YFNRrU1$ebz5N-x(x_R|!{Q?$cus?4uxFS-|w7I?50=+QZ0sMY~|Y5cn{ z;u<%3^yAH57O2C}=&_mz<`>2eO~a@JR3{NcQ+pZ98__ zFeIfORo57$VO^(&k$fU&tYj!ihmSM|7)es8}S4E<$%hyp+ld2i$AYhvUZt4c^JT z{p>Z%sb87pP2d`lwcKy7N~d2ATw|Y93x(;h<~TdPVjRFuJv_uXq4hs_Q%X;42u^j& zYRo=r-ta$$J>bzskqVJ7|^SDp>V-@f;H5Y zrI!v<_t8GdbJNX==UxZO_=res~pug=A;K%KHocPbGTDm{`_4@sJXVX4pg)Pu&%xZ?iiEN#{+zvJ*?wzS~5sYjKJ ztPFu@%+x?uu~bQqr=g^<#})eNpQW0CR*HU+Z6D}$0v-TUsQTu-vb98N;lN?Zx|B9I zN4zpNeyN&&=F-F;>+wmPp7!nm*U$gjGSw*0_AKz*h6FdUh%Pza;g|HOouZMBKZ5}a z<%^|(#EJDreya+pRFh%4I#3N8wBYFDL|&6c0(-V`l>6xCSnP^T`4MjUu0 z4*@({0B$kX?6+P0pO|$gThXMM}JwQvzeBn(Z%AZ})lFwXkGIm2I zCdrR(ITl__SMl|k)!6YNXeRQW+f_oyWHY|s70^eeX`Yo+GAvNGRH90h(LKlX77}ZZ z`w|jMVj6IS#=Q$23#3nkw3@7ATGl>f$ceKc*jMnf5T4-S_eMWacfgpanFN3Ey&Ie0 zWJM|k31QEo4ABfeCzmb=<0>%tEBH*avch&POIe&G>q@PGz>>2y7)CipUh5qegDEYL z-`tnVR|H&{Dh8>fnPcUzn2zQd)S1KF7B>IP9?TjtEiyz76wz)Z_#rb|^1@!xBM5-r z59=?6%V;rDNx`j&C7|W*{KD>>-QPQ?v<^|xBY=uyuK>TUdH~BC#Oz(j_N4CqRJgON zG-(yR_?E~Qxl3n0e{qAqjGdILvJzfs*jv_4gyrh8s{+5CFEdn9(xZfR(F{i*Bmyv3a zI^q`pL^U)2xUiNTtsKA{PdxXqNe*je)iNo&~ zWmK-SpeOQ`t{)K;2~$&6!p)TP6_#1M&02jVW>d;jb5>M3<5UfXtOI43t~VF?8rVPUpSbUEa;3U=Q^Ug}%;kRS7;+ojO#;7bR6Qv8;<-vWcQi z*qh&8okcGCHS_4O6Vr+|W1kqMcu>_PSF{cD?KSq=Uha3y-e!vF%x0d(3k{b-1-nBq%LtBMeEEat5FtQZ>}2WY>?_CRd)o)7j^OaW#wYaR%iSjMS?&1s#$^k{9knUfyMANB00A@v+hrYy*w5N} z=Q+kHsMLUl!-gpYiU^P@CtoB47ji+R;rwW|hZG3I;Z7^Ffs_Pcvp1~DXN5O6E<6e0dKL0e(p` z#9!jp?P1ljBm|wKE2Lk6U9T4H-en1Tw)i04Wf^i(bP@B!pf!QkC16+U$epU@QSzqD z)M|G2tq#C4KTmbPu8Wt#D6L6)LREEeD6VTpf9U9pTb|YV{23lB=G~$qxgB}iS=j0< zIYS-6M1jTP?L}>9-7G0#n4tG{{tzYx46J^{Rb_A^WMpw~^C;cr-mKj7<23{!C@{n<$=Ii!#ajIo^ z!;|^MBD8uCguUQS2nY!z1k6~42Q=g`8pIfc&NIT&x@EjkPTkK#cxg>4BFtplfmfn< zuR9Isn;p=bWeI*|y&Os8V{K)7gA+BlF1=u(SSJikT7$(&3m=qw(&S@Ml2P-F^>31t z5-LVEw0C=oSC3#1-oT7rq;+W()F5&n{XqE@iM~?E5N$ouYQ(`j%12HJse-V;qiHUS z4`JR)@#om4!LgoYC7rC<_^qrCMQdj@ur1OfHW%G z9_?l-nP8q8i7g1!s=*n8ZHxf(KXrVHqne$XiaXoI`7YM=7H~di^)7l%>Y7i&ix)b` zroJZumjwJ6!Dzy#h3Q?M)?#rMdv-1N|IJI&-07w*Xg8b&eP(@g$b;-O%oQXSWv;z^ zffDru$c7I%?Y0>yg}pgxw2tPi#fEvV2l?{`*{iz0H<&XAa{%rV+abFM>j@kahV{sK zpr^rVP4&cR%2Km9r2P?$f1+pr>oj#d$d%=Vx}0%=N~mmBFtltTkAWsLYekZ^YYV5pAi!n?WvUObrbWK1zO%nQXh@8>ZlK|m^Z#~1Z6lo5< zg(tm>ZKNeR7qLH2KlOE5JNknS=)z{G>oBoz!)(wY0YPF0(DUl|X#UugWYM!yW5jo% z^6%b2phN~7wOLAuV3E@o8c&i6!YIyg;o5un%Li`8=x=+#&q z#095c$-g6nLn|DG-R=@6NPN1?d0n|UwZnJtvggftYX%nL`I1~G>Kd74dRIwDgtqgxda?3^-q?A5U~Dj*9cPfn;a?> z{u4awXEYLfTdT@f^=UV8uZnP)NV0F}&9C2Z#7ICpmDS2+$&DJ6AH#G{c&yi7d#R&Y zq7pL&BpPk%Ran%FB&6G8VLRgdaiP}->L&A#N&(qtiik8G4FkyPgG%zIB&j)J!o2ub z8?!U%<+|L!i|d9I4ne`qa*VV|etAq_R5z<a_lX>OgO2^OjS~6enD|Ph0U=eZ>+2r z6=meDu+-a&3kd_USyX*YF2!H7@E58xI*)oLr@7q7TC#pACXRPx`9I!7@x8N(90;0P)iz2 z#sUfmu4o^j3pUIB5WSP;HXo zNL?I*|GfYI17$#(zfChVZx)d*TO3?>KS!cry3)Za%Q<7WWp+p|WznVurubb&meVbg z^*cO3<8l+I8MWiVIwPS!$lDjxBo>D;Sb92ddCW#*SKp+sl{+73|o#szp5PtC=ZuZlj9V{6)P= z*YAGAh5`ZNSY0FLc@S3?b%wsXuMvI&*(lEK6omcsBQpkHe&%6vRn|EK~Fq*Js~`*c=ypi{%4dG zwpw(FLMyKIM_-h06hx6M=|)^{*r`UYPXXf}s|U9gZZPE};tS1crR)B8nyYT6)t3&* zJ!(Y8FfWt1T=9(HY7GSdNSi^qa8nhzi`^+fxYRZ~%f^R$S@m|Z%9)TxEJ4hq54xFt z4c>6rZpO5Ur*Wg;gM)}pXi-);-tZts#zD>}p)Q)QepWYfsa-C7foO=Y09E^H;O+oK zvZRh|Gj{U7VGuq}&}2>*tf`5ici#z1x?uMUAQM@V&~bw1e}(kw)8H_;8AivbE{?jZjMLKo|2*|A?_RoK41TX9e$^H5 zA${3zy2d|t#J{BHUWwxtU`vsk_qxI^C0;PUn-w^wkKM4idbc}}SUW=qv(&g@(i%FK z1YK&(=|(tSyu;XEgg?Zz>k_y6qeSE}R}w#ix2O}h8d5cK^Tuo$*!@chJPaO$awq-} zUxOhGpQVd!3i6}#*Bokoj&1e`>);|L3Gvavqqeb=yUurXHzR#M>`bipOEEY4tO+0W z^$Mf3IZJPPFZr~t89V9q+6NAJ1TF4lsD{RVurUT3Wy;e)pR-~NDL1Ieic*WeqxKl> zb@ZI-kE^A}zP|Ijk)glBT2DRrcOn>Ll<^aVX3Qioi&$*SLSJo*5k|lslX-c~1uHQJ z!43;9)6ijegaK|;GpSlwYGcnGxGCI(TRnnlH0)5JF$n=qg2bvUu~UfcEoSJXgRTC z0jFzw9V%s0WL6PF5i-;Wc+8}=78w}18n&9Y1N-bua%~wf0(nA55>mR7(rP56B&0Za zICx~Z__*-_7_&N;!$SItn}>z5#5aFV$q`W$v)C{k2(oWR1MGLpk~+lHTdNc)X&Hd5 zoV)IC04Qw z+FLU*%x+(SLT)Gyf*?{#R8~^T@|u(C+&1h7dcJ@ss?bDnNtK>2t4n?~QsATwYA%8- zx7tRbc1d-hIfl_0@tSaP`!)Q#({02{b=w1vn-@S2vxMIwW|@itPvCmx0OxRhx3#a; z34qgSjo&SueIvlBUO!I&?1HnszL?hsP=ikxJ<_RNbQ=J$zrg^&Jc_|184GZ@$(V2e z5+?atYM~1K3+eZFuy|KpTzK&pD*D{Ei}3{m1`N%b&TAWAG=TM53$WnJ;G6U{8-jTw zAHww8eXFj~;1xmq7e%2{8ZMcLYKo${(QRc+wtvd4)1a7H$MJRzNS8OduJ*BZ3DcqH z&y#)T4H@|w8Dqsfn6)=XShA_j;WxT2S9P5T?h`_A=QSWRATvN`6a~_VKBn4lKmH#^si69 z-1#j7I*Eut5uK1XCa)r4aeL2Mbt_ShH6 zJ7pt7rffNKn_{46orbZL|4E>~KBWJx@_J7Hxo6Ag?qmVL?g4gS<58Xt@XqmTnHO!x z{xc4-{PXD?xf`V$90kq>xQOy89;ryBlnmh08&G z72UvXx`$tc{*}$%Zw>+;*R#B=zw&Pl^R7PT%i+E+4t70sJWtWZg_~+K)JdwWtLbQ( z)y90ai7sWeHn2q}EI%iM(?gMqdjY&_*sVWvlkVWY+^;I^)5AQe=gI2ti~pOudCaGL z9pFF8{%r_uFmSlxrq^)#uKxmwIht)o-joT9Vn(S=;DtCrs|b7#GZ>t9Iy1BE}%E(Y~D&!(3v@!v44 zcllUf@;wLFBm5q{ji?HbZCMx=s*$TiY_;HBUS&dsgbE225)!UapH@1DZMv9VUBgY> zaU7tj;(FYDUoyu#w{*}!p02vlPU$4|Z!9(dBujVSkm{-;;>k{~<3~eQF)^nxQE!3( zp~nxb0GMbaT!@I43dZQYy&qWVc<*Jkx@M@-J^>IVAF93;6rw`-5x*K$E#_Oy5$Et~ zTsrGm$5M2~>LLVKNtwztmGKT*?%F9N_6@0OMuKU;Ee=G z@fmvmX#%KZ%M^vZE@P}p?7~uoGs%B}^jlj~-X=~+y=-F`RKrjTA-b+=s#Opu zVzxn$_ohSs)ip=7A&{c9@5T(IL7R2?*5xjKTiZzFG+=J*(DOiwedmWj|5JjiclIo4eoLp*y)l04hwB?R5s zP(*f&Y)S3;Uyig2d`1K-t^3h->UIj?EIoh=UG6FXBp@i=;}=GOoOV~<+R;P)03d!mevJ}&l)5BDhQ%HJefMRc~`9&m-1!)z{1hSA8vCpme0_I93 ziuQFgJ~Hm!pXDK)Mkyu=p)XT_a6$WnQZfNvP1^>+@K#jZL*VGD1m!pD(_gcaR4g#N zq}OwOHDZIU+%BO=MM|M2o_sw_$tE)Xw1~VR5exFVFkBaG{63p~OdEWintDqj4^Q?Z z_`yP1n4raMd|vwh_#JHuS;w7p+B?pSKI?*u{^pOasy@TuZn~4{MP2Y8eIml^>BVRK zo!~QQ=eE$Uz|GwPwept0p)qL01Y|+RsHL5Ro5fOKw=1VsbTVSeJyg5|f?Jyi@oFZ_ zC-E8^!9dvy63+7=^}LprMB>m)F1GZgLBVjzZbMKVuQ^&n232az{6_ed*Jl2O}ZIP2Cs8SCUw7I*awMbX>uh?PWE(m5t289y0sSUChe@?iiMmd9fiA z)T@5J##*csP&~gT=NQTeCR*Gr;Lon9>lXd^V-LWQXBiL7Hs_^u3$USpp2}TSnl9Kx zCJx(*+g~d*U`${pwnyB8zpPD+uO4G}M-1fUx`66B^l*9dRWHcDtRv(uYjv1V< z!;A^{wA4w^sVhh&zU1pI$_0WBsH}jx!5>c-%D%n*3 zZY8txP^VdcT%iNle-Az6eA?Acr+Ty@3^^W$gV`byAD?X%AF^$g4+%{Ap z=JEG4Qk?8|(zUlgc(u5Cg%B+Qq?0!q{fC)~MAJr6XB)j#$o^|Kxp1jEh{n6^m*al>(8RGD8 z!2Z19p+-oESkhY+TCH{3s4bqd=NfXcngZ%@##{L$CgK`wXpiUQf(MCjprp^tR$iJ( zN)8Pnx#L9&FR2eB5-3FNV9W9Ua}^BN#v=xMEF-PPv9%{L%~!cBE_=v;Mbm zXt!JqjcsL+j+q?()4}F}(Y+???n0-cO>-Ie-5)27nWRfx7X`Xlz~X`C1OdqJQ|+OI zP>9+xhG^E(Ry5f#Zl^uDDDuy#QY7Ph8LrqNe6&;X!hZ(}Pr1{!!da)i(^QXlX1Hwa zl#1{%7}Z#(Zg%W&re__utV2iTyUkSbV&HFop5{sbH-pI$6-I)r5EMy`g%*#bzF$f? za$@jSy_t4p$>+@$`7jSvcQ?BTq*S2AmzbnM}-&(P(vhF$E@!SStj<5KpsZ9)b6QrXP zB9@fE%HddymALyYb<{=URN=g0c7}UcRXT-a?}Y3Ar#9;28*Ftw{bcyStKo<*GJXEh~(O`j5W5_F}gL$V7@lPkuL;pK?-AwhD!d{^+ zbS$#?BeEzgZlZ?fzx#$hMws9@Ph>JP0KS_db;I~g1{YdcnmJqqPzyydNKYuTI_o^a zQm7x29hbZW6o$|$YudP8V7Hh18OAH#@Ow)_(^oq8dDVQZm7D#cF5b9AUr^8LX9E8! z241QwMvVBPvXGE^iBK(C|JoNwK36jT@1rXKP+c_c=}b zquB)#xq()XM=sZIvMX*>>zd;xG$3%nuZXQ5N|Bd8;iW80F>iT4QO(#u6m~~455(0>0 zJeoc+wQ@QWbBKybvv&{`1pCk<9=Gur9x<#eil?I-`%b0;v1O!2_+d$Ik@uQi-OQRwcQFsGX zs3I#W89gsi$bi$yzEcu(%$Z$|l5&ITe`@iwGw#^czU%C5QjS@1|@U8GvSdf>Tq7cPVe81uTL1hCtH?Z0bZ9l zrwV6G9H#Z*R+b?#0aGs~r;1IM_5MOn+uN#2kH8-8Af49Pw2+=N993<5dc2@B6)#)~ zd3LSiXmH!&0dfjeR;s<6*R5vsTz<3OdMTaO`asVdmW*++I<$f^I)X(l`?i%Op&vAS zI5-lc-#OLAm~I!=8;^lLrajqwy6IFMa$ukKYrKoM+79xF_oS(TDb3GJq4s7Bk=ZkM zHU}Vfzs@YG{v6sUa1Lpsm$Z|1+fX`m28XfWMFX+}r{7Um zu-Tvg*j|?gw#&XY#dBTyhuJ^FTg9K)g}G>Ocr#1G`<#|OzWW52;_g+HKLYev`BaU_ zPg=-EPYHDAT{Ui3WHH-%h*4l;!Nscx&SfR*wj!6Svme8|T45L?1GoH8l}ixjFjO`^ zVT;K*Of(wnodkNLA;43M6(8#S@ z7hEbwrxYySTU4Df4jrFRk?g3mvvk_E(P;q*WZZzGS?TE&DlD@8a2!Q*+PKZ^%$tWhDlBJ_=3DhE8-0`Q4xsdq;&fVe$O$kP<5T#M}}&y9JVgb#@F(53o(!h+us zu29AOxPBjZK#vkmt5?gNmq#kEStwk2DA)6jCH8*Lh9ke)d+X%N81ou5L-QH8zdUYL zFnFN0Y)97zn13joTZUTN_o8Gr^!6F%WH0?0u^8lgqV0;nR8&g8F8x4oY9m;ky??*G zTHh-r&kt7~Jk9hBWT|5UInwB5L~P`0Q7hVL6N@TnF~*Rzr!N9Xo$*?Dkjddoixs=!2(y zmRs8%ixsE!QUyuf!^s)}Bu7L+cHbyy3Ns z-Qe)SJ5q2oMepNqsc4VGZTrT(Per!cu^Oi%x#O3Smihc-SiRwEnr5v3*xgC z*n$L67@W#)bYi1_1bYeq5v?up(1hyw>)iKUqy!9F_1sO|j{ky7%_^nl%ss{4>NRD_ zzH0!e?X(}l)VF>U1QL*wN9<)^?km}&hThfp{7;E=iRy_yiN%RiiPuR~y_7%dCEmfK zVUu?3iu+15dhdf}2W|jzl7=v46`z*ffege|NTr(e`Dn$V+pmzh=b3momw4E)p4cMs7+Koolm`KqPK7ZV5f1zqtktWK>2I8XLmd>GgmcQ zMJGjj3L<~+yTo)4db`NOJ_G_{2pn+Y%!Lk!>)z|=*!Srf7`gQfNITHE^&58|;Dlm} zZa4%(6sKDzW_A83mQpRJ3a#zBE%lr|VbgAg&ffWZF<$r=_2u_gkg@F8_!+~M|NAHm3mXi$Lsy-2)~%S34UKb_&a_19 z)}}ea%UhrfV84oz+i(6=SW_XDMY*UJ&7y@kl`vJOKX}aZK8FbnP4c;=idEQbPq@f1bYTr|gd!f-#Nt zI&8x|Ji|M{;T!&u8QGB=`O%x{DVc90obnNkcq*oHszx%>`8BeUPyIAb(+tlD3V;Ye zS#ykD*SN`Db{q5}3Ayfk)@`~0^cZC!Dh$~05F}2PGEE>bW^6d|;44_TXz`Mz%ap57 zsY-8k=riV%1?%>mxuvBu_&v1|9-<>Q;zN^Z+yq>gn?b%uL(Y+yK@8a-#de*eFq0Uz zNsjM1N5d>)L{bv_&e1U&gMMoAKvkv=RaN>(NixT(IvZBfTtsyI1!@j706IZ*LD0hJ z=Aws(UOsdJe9nt61yNEIr6uvTEXpe4+ldgKit;ldI;V$}MgLPaJ)+0-gr3qf%29Dr z)DuX`S>+|8Zy;Zn^D_yY9(!zoh*GolnTx3=@Lmu2u)s zngUH+3#IdW>v8{UhcB;%2f!i^CC;U51PZ%)e>nvQaSPxHx@lJ|B0%RxHO`b??Nu}I z00rcvZDDqlj12$O6J=&_lern(MMDP%`Ki0T#e&(S%C;a&|y20*%Y{}GO z!EZ~R)ecxebxNJ6>~=8kjLr_i3iUB14ZX(&oB#nhIPf&-57h$}OJc-XDj=J5q{NHNh8?ZWX*XkwE{ zPAqlq+sQE}GUzytdgIHr(9}-r-cdp;}dG+cto7j^)xtqA~uGIll zj0@tfZ2YbhU+7d)J9Yp%Tb0mTh5(Qc65rLiXWPG5sytSq`PVgZP5-}-uv#h(I^HdQ zuB37p?nqxh2y$2`;7}{?C(j9g`iqw7B?K$&N&9iDSmpv`tK67%BoB6#Q*?)MHIIfO zL@B{nE&Yg1W3&2yv-_xz`=n3%tU0N#!@A1cFoY`Eg=-aCGeiCnogh*-)gX$vYM8xz zlK~Un(WRx0o{>(odRx%k`?$LmQ*^cKe^y%!c#)@Y2R&V!C z@Ah6Zd%q9TJqR)rTCE{d6qmyrhESSazLxDVGk?Pr6UaNl9if?gQ+<2F3nSf}M?z_S zp#6}73E*pyeiFcO`Nl+Vx-?i{Uc16*S zH?aM~=6tobiBET5^krZ5b#t57{1&v(>e^qQpz78`)1cYv4aq{wf5rdx!B^u}Wvyv# ze^=f=RkW`4meT&}CyBJdLp5xsiap9ziLo9RYH@&zO$Wdo$8G6Rx+{G(#!w`N2tgtP zy#>H=UXRi>uMWN7Nw$xO_UV}d2#3SXfOq~~WB_~i+6JJ60U!VnzCXr*|C3^)djOjR zz(c*i#Z2~K3<6Pc*QBrb_b%l$l0 zUJCOrC86-2PoXuy@jnz%krh>ODLy5r#OLt2|2%3QPnkA7hKxZW;Sia!sJjQLgVt7~hBYp1 zxm~SPtJK8OX6cB*Bwdmh>)!wQm9)IF3pdV5%PXrJnpwH#T+oO1t?G~UWBpzI2c`ac z90jJ+K54%PTJQrmU<{^U8UG;p4`d_RSHDaS-u>)Zd0#s1St2IU+hA-Y@<g`>9`A+WHBa z^2wb~(+&Xar=tP@b_4)+|LCTF@w~mo4=&(D(n&69y66@gH-QbEHTTTrtxH$@1&VL9 zOIJAX27rIUaXVgU(C&<+12jMHM&!)%ki=W{ESWTf(0WIo~(KSKY%UDHyW z4=GD|YQ|#>2RL!V!G>cq@Ua{JF&h0vKagVJi4#BeW3adeHZjA*EYfzsL%FyIhoEra zpkahDHf92YF(_3iE~&;k^DVK)O|Eo}>oj|g#201S{Mh649ezF#0~YM``|TewJOw}q zmm))%DLwj)4}~KJ49T4QAXA#!9H#rBvs=r`SG~F|%xg>0NerE5L@y};C5fm=RAqun zlk+x3&6%4{%e#zBWMw98z4_S5%T~Vjg4-?9RiVx+fPLD`9IV zvSlM(7LsL>*&y-tVp=8X4G>)q$@Nj+2aqi?V6k1+J7BrJAr-~jS>mdbNo6*3ob}va zEk6q7m0vZQF^-}4jg#$5o1op2&~C`890t01R&+pYpdr>y(VCTA-nfPZQ_ z^R&?zsTifkF0%{v5eti2Trgvq`B>V|#Xy6YP6y0-b_@VrjBT~V_70w|MzP$2eJ|W) zQ;~^G$NN_3bZaPckv z#j@Cz@M2x;i(zprp2fMC^O&KGv`chlo!-I-bCGQ_c4|hUdn7?+Or{8B*Z5Y;C+NR` zh=Ofc9FA|(6P1`G&6qW39u*A(9TN)=7l)XFQusE|>A<0&KtADry5nM^GGGN}7Dak# zDOpEy5|Z*<9QH+w%l7@hRqjhKEiO56%MGY7VdW`lNm*;E+LPCqf~G8e&cdg_26M2G zuD;xSE5LEl-xTw0XI&TJM`121go}UvUpn%tP*sDrR_wLmr~_9`Sn39>2Vd{-H$tLO zl1-9ph*&>3cEzb|=5rBY(Yl3@fRTw~vH=NGqLUfIqmhO#(yPbrYXbNB zvC8D}LDzFrx$;!dx@gG%PTI);?AgHRz`gzd+5LT3nSFT5QZq4te7wD|z{H2lW%XhE zbooKQ&9+s*`t$m?$j>)HtnV3e%6K;0KtS0J^LbM^52NwtkhFPTxZ>kGOjli(OTyC; z^^L&yV+B5(B6jhC#?>#+`2|J~VS)7Qp6u}~Afgnl%#F1KH^iQd3P|GMhAe?rU8q4B zV#QXh0NsI1-Z%hAm`{xT_W^H5*A4RX&(exSV~0*z(}c80+fyyMY8RCh60}D;MOqZ6Lso$?h z>NSk6d?^{12x{zf$U2C#UjU24QDb~OIRQa!E0Q}4(tE4ZENKG=G)<-0o+`M6L076Zbe7hD*BanqX+qZ0DV|kE?2BpE z4X}QLL)HXQxG|LuqGPhX(|BvdYR|T5G;+CThfhmlLo%o+V9~M-nk!p=eR?swnU>8Y64j;bxtUgBin9Z&%Bg8M+^B=z61dQEt@(l%Kkm7fm zn){KOV=}Zk9qca0Z@EMoXO7&}`|0Xh)C|0g`bH$(#^N!pnlyOeaVEm3r zOAV#{_L_lH8j(nB{+3klDvLOm;hk@uspK$bY)&wmSWQoWaAMD%M-JthIOmLK0@zZ^ znIRAV8w-!LGD$)P+0a))UZN~(tx#jytF$%xI%9(wU(9d{as9G1>W6P$P_gtfP!i|b ztRiBye8%RHX3N(n&B8fu!o)qKc60+kF>PdQWe(#q9^*3s6EYDKGYRW%Z3VF5t*Db4 zXjjy-#NoiAhdmswY8M$A11&4<9XK(Vq9fxHS7cNlI#M!*qrT@lo?`<$!L~E@O0MeE z*gsVR<$-P10^K$QUTNJr!Z}c2N1j0nJ+i|l1lB(Q@XD5~z3$ui>O2 z9w$R|SC4Y9_1BS9x0Rv9on%6qrn;%ULGfi85El>FVlc_NM%?xnDCW7=GA`>F`5 zR5=h>IY-}^nR;w!mAlIIGe_S3(wS)r@92h1e4+Q?JcK15z(pi0!r?W-w2TM27%O(g z=okc6Xe!z1dSqnuG#fuqIldH?tnf}fA;Ug*a3A;Q>%=sGu{n4OJNJgH7#k`ft2(0d zBCr|`VV4LlAuFk1h}eAYmXhuBTEXC^*HW%=`O)0&dj}cNBu%oW+EnY;l)x#!It~|!nbV3Ja=P!WB(Pcq&T@bIlMYOCziux_U};2{u4^q z{};c+t@ahtSSVOe?~WI1tg0J#ZFDKC&GHj<@u#@As#Y%NE&c(}oIvEHf7WHds>cRb ze7bMnp#`$G7wrXjD4nelDOVxx5-Cx)H4osPDiyGyDNPrdN;lE zf*~H(_cSjomkYEwF1@gZff()gQis|w z7sHyQGE%#V@abuYc#|(-2wEo8meCUK&Pde#lx>i@^tiJQeiN2f zV280;JD}iP(bQz@z((QG>}mn~0d!{RQ3)!8F@kM!YtxSI`&L$Sb~1<2Vmfg-EgU(T zS>3XRfYppxCuJ|2ETz}Y{^gf|pB|0+>uiLzBinyHO#1Orr#Gz!fT>>BX1IQS?&b|0 zJWOK);DA5?7>JNI0B;cHXKv?&*Q*NLOlb7@&^TX+NXks_7TU+A>6MnVw6fLCMUv#? zB0qxPpP<9CzV|_$kEf6<3O%B99c#M0*R0P2n!p|$kK?y^6`W`FM53oKCo&Zl+Q0e= z@ZzEAGqgNLw(D-j8iDbqemdFVyGR7y=?7W1J| zq(YtDrW^c5a>}0s{=pH#B+sW)n3@>&$c7dRt~y`oQ9M6m^$afos{n6~f*_=ZyMj-2 zgwVcd92_`9NRro7cef_g^{iBnNT{WiSq}1g1;h}D^uDWmOVO_~}&1Qd8Bs=UVG zmW9YkaKk0_I7V1$IpWfND6^THQOp#R&#v2Jn@86o(K%CIK?@QNQx?M@ixa;EHP;paX}nx0I&v7 z0GqKJQ09yR0HXr@ad`krM{=$zq3iXk*pZBeh#Hcjjc(+oLUkl)L4-vxW!TN|2uZ%> z0YO%B=h~sRn_?LZa}$%(ljw9f>e3;W0zjv^Z zyzlJH7gwd>+m0xox>;FkLIx2J&6~u2JnE86;!)HqJ_!K}z1KxiedXTbx-#ZCms5PI zAu$&E@AeVE3DGnNo(m0w@YAQB@4D-()mkZ1WC}I{g5{D~J=rh&4ih&8nJ)1qbz=g74W1w`G z*H(DR8!__{OKpMgkLHzKZP2@tLseTkFQ#v?T$TNc@NSi}=wH`E3mfhzHsth!t|UCm z_aebdV=Yodhfjb$nV>*kYUM>4qhqBFCx&Z7hdTZ3m5^oZrd-uNhA{&i)c_0}kNY)pi!lXR3M55c>{$9O9D_Bq;i z%vUIR2(655cGB<}0Tv+FEM-?QB%aJTh^U1fHk~b^QKlBDE(s_ykjr}exaEfF$+*|P zEh>=rfZeHE^<>sqV(Herg^}65eb=Q;B4r-me4LP^MwY(gTOjl0ZP2C((DpoX!C|ps zvM~>LEpn6P*j2o^CsSVCRndX{f~DJrmh1jdz9n^)Bvu`1`xs$k$%~R$R~rpje1sRupocS>QLzNs7=(QoZRq4*tzvuOsm-|i*HhRq5rQek7*Y7)Yg zSk-20JRy@}&pOp~=dGJKg4kx8}Au@%ZUyoWiM@8!n*uu8qP44b>1WZy% zsi2W~doHtOl3{^1(9}Hjvyb)9k=gB*diuG?2N0avg80#GTlbo}K@5vNZf3U$%c+dJ zT^LF#n*~DXE7O+O6kRt#Js+`35-6BTFZtl~i9eJVfaB%hm1>#P?SUP{CK;0yzeqB* z$XWHBGXrDFln3p>-($zx@NRMYpe+Laye2H$`+~8YU{*qQ(pM9I0P;3^mmJ!`Gnai+ ziN9pNCzWbUY57I!d)}nNgI~5IZBQRL{3RtU4@O^7zzcZ=Ni0G0rl70-#70~E6ed{0 ztr?$%%!1Vc^4<)NSS(=6A-c=Q4nY{rWk(sg=~kj5xp5WiFrn~F1z9tBXGVzGH0g#y zig|puVVC=QAD4d#FkAjy`%E7#o(k3p$Hrx#c1t5-T7`d#;Jzk*dvVW z71wCA0K%*U%T-u80Q zbo{=SH`QA7?VVVUr~1L;L}x6)p%e(Sc2r8LWuh*IqDwyl1uQQ4Sjo_8{0c1X5|(Yn z$|dKbBp9%Z;!vr3EJ&~C z6yr52wD=bD1mOaUx#7f8)ENRmTp|TIp+JSS2pW^@LVL#zDhE`Gw&JL8ByN){a>|ro z*3alrKNMFp2KvG@*@b&vmedVqJnpg)2x{A*^4y`JcFFhS6VP%tiLL)a+nwY0l{{-c?!gb|r2DnJdoErHao@U14*9iW8#@v9Z<* z4UEl@;bTi~ep!-sJ}Y^#TFH;n{8o|4r&Hvp#>_m_&@s!E^RAXH4;VwK>6%(iGGaWK zHj{Ex!gBtBJRo09OB>{j@P_<>hSNxk?AhLkS2EsMPOd7`p*6GCVr$Ki`}LpBS`ejp zlaxgu6c|Ike9cHgmBshvtAp=i6+|*qQdXROJH)&Rxi-W%`MD4w1C#lHd{yEJ^na+1 z9c%_sK^G;NXZggsN&@8rH=(~|1GmNIV6eCZc}qSxmvZbrwN|my!tT$pWnxM28)r#& zE7-hywiRIxTAIOfny}0Ym${UbnQhsyfhT9PBLcsGCnew|yT3lDzZ%wYRJGO6b$D!afRS^@1AhB$0?byqBc!@;tt<%MZp3Ah#llForkuV(y_PSsBCKy zl*0Hpz>IjGQZB@@d(tF8o7e z9rklBG>PTh1h-5>Ji_t(rX(sYa;qkE%g~8Q4uc7k081$R;7k!@7jFZ*b>YQiiROI6 ztdaOuM0lHOxh=Db#;`j_u_X!0V4}@mbJL^JJ)y;A1}=Z{fmd0nMm$_K8Z6M@WEP?~ zlmD;4zh|`V&Nfi;lO2^Zhnm<>`R#TbKzQZOl(--bp;UamlugCqlr`qo5EmeUf?xW9 zbyRf5W4(&7VQ#ScLZW2ePD_1Z)I(_@?;vQo^G^H^G3jo7pIdG_EAH+|s_p z!QH@n8uYkuf=i2-@gV9y*38wbJqa@@81J)`!@xAy%sb{Z-_K_@oabE5|7M(>5UY9= zaBr@#r^uL|DYj-sWAKVgWT49Au3NN&pq<2r|G${_CVO?|eCY_K2umchbR6#MuJBMZ zfzfi39M7{Sa3nosOwd)2zG5u9C1gI3**52bGd!6D?MD?AezeCGGCfbb7&SibHxBD; zb65@SVfPc`EhVo^%z-b3G`mEP@{WDmO7H9$B-v7pdz@rGx~72llR9Ll`dGC%%CENYuti}cMs7#01dpiz9Wy5&^GpvT6gOyc`2Hh|14`#s8XhUsbb9mjtoVlD)eyEVoI%xv*hT-gtEhe z0N`41fV+r`u+}M5DHEd&8lx{>%y|35>Lsc1G^&EzQ^;Xl9Vz;)3Rw2oNlxVy)k428 zjGs~|SQnc%ZID9Xcvizs+DxFEwY!roi4xdsuCtDs_qjuIAY zC~8e6sGpXdX*n0YuR!1>YF5}O9kp2KA@xo!+JL=YfjOQ#yO_xz zm5ZnxjnrK7pOU(Y=E77U1k?(iH97s=?YNqtJu%r zD!MPkH-j?4C*sW)r;}Ws7O})jTvzW?S=5Qo4DNkFG$h!3QVGJ3MLkg@r|=aHcQ7&z z5^5C+J-M;U8eHGYZV{gH^OR=2cTJx2+fkiE?n*AuPAGO>BZ@5uc8AWxkyvy7pXa3h zB{mM&!h_ikxU=5qvn70lhvj9pZsq!rAZz*1zxlvy_mAg(QN6OYe8MTPi~xQ5ToI-x z=0TQj)d%V_Sb#El8DVz{&6+;iG9@k|xKF{7Do0)My)P6=C2EGVe<%bTDo{}5 zW&uP*X|h=D2B*)N_o5@+6`NJwI9k-ncE;ci^6p*6$z&@!5^pwc{!2=QF6w1y8c1g? zj$F>_cY!DDD7o@$!IN-%Z)Ys(-AaRVUP^S+|LVXJme3|1guXF{R)9S#J((b!*P;^S{QiKt!+mmxQ{J<->BF*0;BmTU9H@Yql$V2>lcghpQ@ z`GpKq;jYa-hyzLG2g`Hiovx0RpB~sN?__?fda?R>?VXESsrSdCda*CBe4pn|0RW5NWz5Y_Lr1pX+R8Hi!Dpt=CmnOyGncY55m%V93_MbDx9&^^% zM@DC_IJ4{ror&w@_#&{Yn`L%xGs^DlS*8oT-2aE{s+u$pY=l?Jb0V~B-msMRj^-gH0EaxpT-saS1C zINcgsX)G9+TKJ6>;|J^2CIH@m$C#!3b`~>Z9LJV*P|)@8k!$twb5`PNGguD%dNqtL ziuTr*0vv(-Z4Sosv>=v7GH)yz8Cg&M`2sH0bgpO2M zH9brsSi3JBK6Dm_H_RuRH%IRORWX(bY<4)c1(h*XmQkIwJ|Ln^ue}&jX_~eD_uOiL zIn|o)Pj6wjLzi}_9boQkW2f8y)Xuc1mmZAW(CFsM?=cb$qo;;VN`#eKQ1H6K4V^iZ>x{eIxvHC#P{!Jv#x>RMfqVHECx*AexLi zu?d1pF(KI5wJoL1{1X>TOx9?TF(>ILz#UH;pAjnAi<4Np@Ji8BOOgx-+iD^NLArM| znT7(9#sf9U+EGK=4UkmINpm|!Bt`CW?!ULL!Z#d+zb2OdG|Tm=Hc)UP<#9Ub5E0?g zL`9YKU(kK!wk**;6>J~`xedN3B0Ty)`QbsVQ?BGxo0zcbSP_}^`)?WG{L`AArS#T9 z!GH5fo-q(5NzZs&-sTS7eJA+%r61{sO znyzc9yQ5Ci+W|13p-mJXD21PR4Wm`w!R1X2H9>(LFVqAHWu0A*0D!_;r ztxp}iv0b`m;?l2Ba1)lnQK?X^(Xqu;yXlKaC`}R24}&;y%@<(o{OG~>Ha9GU=MCFL zwkhQfj(1bsk*UHQ*UaxoMNZ92w)iwSuQZ-c_qo4?d6LTsP z#aZu#GAauu;#3b<6$y`2NKD2TO3TVaER;l7PX>=HGP((NMa39;Pq$~S;&fD&x)ZGj zC)xo!ibw6f;2qH4vr#MTAM!gv0potOEWCn_{ev8IqC*G6uJ0-i>Q=!Od&9#K``zH+ z;iw%Ji4XcsaEn$o>a!cR{lopB6?wg|ri&hQ28Voxj2&b<34LjJpWg|j-wiI^AGJdj zwL(Va+@px4_ej`5r{Jg)-&AvkmpD6T`6*A8sjo+aBl&ut+Lva^v2zw8%~|Bm_Dm|| z2U3DbC*yKwQmVtBG{_3*yo+{IdAhjHXNBvAq^+mtOsAK`?h8&qa$hpGIcNY1za%*s zd5DGM)fwGR>(x;*Qk#E7(;^nYpK)pbqFcy=_C~8;TcRqr?SsXg@#~Bxspo{Uhht!1 z@p2X!_7Cr&(UJ&8-2fUI7Z}9{kWq?E!b$PVH=5< zF-A(}3NJN_$af|um!4isRbBXHYPue(KQio-DSV@YgZaC~jY?^n=4QoSO=xam)g&2 z__Rgf4Kh1-YV@_aaHm}!pLd!k-q{QdZ#G{4U^eKpClLlDKF2<_5Mec%CV$N53}1kk zdu{BzA}4_l#=nV#xZvXXF02#Qp6PrgM9k)gHNOjOJne9Rcy!f8g8i@RD1dXWb)PiPS7E-m>_ zYu(b9{4dn{O1c5R4rJ&LJcLPKv+uPiqGFn9}z;=m8Gt*9TM2v-ue-Xakd4}{?geV6fX zWdKmK4IpJk`v4Abd+ zbCU*054xzX-IfxIJ|)8!sQw%GsguS|Bk)Y+(ID^`>wyVGnDY3ZYZXI`;+uP*5a2g> zRA9-ZOPB9i_(|Ak5esk+=Lz07Op-kID|@u@Ae!@b^x zQni()B%0?BVaA{(EWlF=7hl*G#0Ab8KU8{sC@OXvsE5apBds&hIxd=CdqDd~yE-+s zbPn8tG`O2eOxbjq@?A?#d?AuNJe+?~9qm7!=)vR%s~S}z@;nJ&(CA%>M&Q`II*V^9 zTfQZ09ROj)VkBI^jgYZgx5MH-c={SYv17Q9vdZE`gXFT)fbd^( zavZp?UX;zFcRP+424>uDou$?vUB$Jc4lZkUU_!~sgW`(4^ImkxFG7Rk6Fi+Ahs9Cb z=OWJTk?CK555CLvI(g{onJUoDzfwPrzG~{_`q9&;&ZEjB-Su21M|+>g($M=M7blGR zYiHO3HGCpN@Igff>S`F=GwTFLU(M6tT$=fJvimB5yp8-aAg_6L%6{#aVp?jmc(1Dy}6- zqLK%xRq!T6FFHjn?45eVf=ECRd0y!{E?QnK;L*v>aVOzjE{P&ddJWKnM4bVUvKf?k zjOomXH+F{pK;Hi?`|*rG`S*aj3v^<1V3fo`%5{()HQpf?KuGs!U<%Not7ihb05G2o z7YYJkCxHvX@tra0TRydZLPoAJc&A5bMF~h2KZC|o_owCEyT2`5V{)q25RbL2cdE4j!Fnesrv9GaXd${9CacO7$2F4d62@7C)eW%X!BcC3r2TUy{r}VWo zF${7HcZC!U5AupH9caeAJH|y&V9+X`5YlxT=$b`bFdx@i$TaCdbidmD*8lkk-3J&t zPdNP6>$IDUJ_Haj%w5yJtEBng8xo;>T#I(rXrb8!+?45!} zp8ns(IWi_~RcOVRvUfhCVOurq^*$u>)EQO@)%8ns|9FU>bjtJG;aRVEIli(* z$gT2T@!y_LHhD^ORzv!uS--%r`c9oeBA=eBh8@_>m}1%6iTOHvG{^+Vny&YEm^8CC z%Tqw4OkWV>@I!s|^Hd|5OsK_UVy20+b3o)W7$JC4FN!E+f5!RKO>~hQ9^CZhI$~hU z_U3lSCVt@GxkK(c7G0CEIjcJ1t9o4d89ZE5S{}Fe+rMEDKRL4So=+P+?yKhKo^5pB zRnDP;3GBAuIMLtBG2MxBp3P&7%N@jj)rc+sep&m!{Te1ovc;?Rj%j8dO&i#lm7n(%hi+WU=ANu@fL~GiLqzMrE60Y`H6UCG+!a=bav#uvOZBH9VV;CF`c}oT#Bm}ar^!P z)wYM_itd*zdK`uC3O4~jf#V!QA+=T>uA?mub+`YHMP^{h!Uis_i!I6{K>C)mi*<14B+f}r=T~b&^XT# zdq|r0H)3EgjNx!}rau=GH>6AZ#3dE$gQ=~^uiwh)&f_-<>*^1@v@~t*0T{Eg5nhp* zc2GU_Xg}OI)VPulNsXwRHFVVZ?b2|yFRhLqQ|XeA3kqGNuIyy zL_nK6nboLF5LDwHkmx*vS!d-k?mLT>5!Sc`y0CIbAMl+MAH_>t3r>q<$ggoG8vii8 zAM{OndgjaMQ1?Wi5k-8voh!CyWl6fMMc^K23D@0XW#KVPe{&#bE@08YsBkX^IUkKa z>~xWGDZqE%WKj6Neqpg@c2?nr;*>x#MZ))Rrq9oWG8J4^9`fts#v=Vg5UGFsg8u5h z=}utXq$hRq0hw>baq2V%1R>}IZkPqk=LE5E)}N+AP9={#R4+8=ZF5kuFGV79+(fHl zutS*?QuU3THAh(+ZU4Yt2>TcBysv=?$QnDNHq1H3N^$*s^QXMHpQW8QeAFGb@Errt z-F33J>wgRf9+O9uKPuhq-0}{pbE?gWh~ipxUVH=&LUnyn>I$`W3&win8|B29Q#QSd zx;}{>Bdriq&i&RMAqbk$!ZO-o%{P5Rg9?b0;WDf4Wj5c7%N(KuTODB8d$N0TqMkB_ zPIJ0QsR9=}gIu3glMk{GH3tPEO)9&N^D_%KqJ7`h9YI^N;)}wWm5{_vhbGt;ikrcj z3Y3p5&N3L&^oiE{I$# z?s!*o4@)Pi@9x7zHsig253T7L8+so-V4gY&r-To)JKg)MSq96lfpIECE>;h4`~L;n zXfUb4c6vgAOpyIo=X~FE>L)9=*&qaQdQ?As^Tej@_wNL?qoSps-I~F`Dxr~vRIJ_j zRaf8oMXzONgWYNfX$*?v#INGk1W~>YOHJK?rI%A@TEbGc%&@YJRqZ+qu{8V$eG?Vv zQH7S2ZzHtArvm8c9k!Sb!ePhM0MV}Gcyg7n)c)Y)f{gM$%w zw8avA*UYwVl*M$o!%m7V&BJ;=!+Xkb~&qCspisf@l|n|*g;mqvkE zpPwfWeVhwzC)~K}-*1ieSaD~bcsu3WPg&~_?%tV!0oV&qu|e6+|1NB$BfkP;xAIEA zhu6NPSwjYZUH|2A9!lRWGzCXRka@MfTvrY~NFz!H={uENJMk(Cs1E2^XvAe= z59Eby^su!3oSd{hjIj2-7mpZMnD}CDJX|EI_RYP~E+|+&<gl+Mkp>rC|8y*?#q8rDB6jk$Ij z5<%p$06-y4{%Jg5b2ThA@?l8*h5$lfSN(clDY9`TH1L$+u7}8LPkstp|`7z^GZsf$3XD$C^vc%U%x5of-uaReuU(FRD&A~Ic_Q6sw#c{bp^+7&>5givOkH9Wu>uX~)ih`-D}Ug6K#jxwVUpFjBOY-B1GLBb40&#V*uJ516C;&%NEYgN z*EQ6`IL7C)yW{>Q3vo<*(gDFf66w~zLsj^p605$s7@t#bK4)Y8Z4 zewLf`dv}#BGP<3!v;Djcgw63)^>y*2IJd%l`DXy0uvX+PQji+haw~uuuGyy5p?AQ1 z>)mqKl3rL!XxqgLug2a{6aT1#`TkaU$HF+o6C)RK?{nM-^7$=TVC|vM28jl+-FAAY zISOefq9oU=3*ruJZW8p4xWtBH>iH@e|V7-81HkD*3HlXw)jOIw6m8#qpzQqZ};q1n_A z2KBwC&pSS%cH=FAvc@S+_v3XHWcsNtFGzC`SXz1*C^fGxgxKcIM-0V8r)H`Hb7lLI ze;iK`hf+<${JWaDquRw+t%-Ec2h4+7zS`L;vl*HhH(%G5RXu}ufET8VeUn9#+}L>< z1H*-yk2Q!N?WxiiTM|pcGlT)#)Jy2;|6|k9nLIk5gM;;jp*EZ65(!AtMDZ?fTQZMU zF)vj)*jatvrs%1oK0oG0I=uF+c64;pEK;o}*U4QB5RC_wMeh07f0TNu*3Ei-m;^k+ zAfgwSMF2d&5#-I~V<<)0k(4jDoQI#6>)qs>G_0QET;S|u zyw3-^78kvRU&F(EJ_b8b9oG23?ZpKj0#%R8Qc{5oPb?pB1WhN62!nc&yLrV_v|)`; zQ%4x&>6>@%_FGT?dk(PVyayh)l8dXg3p!$?uZJIcaRXfyG)}Rno3G(JowFD0iS!f^ zPx?;Imol#GhH*USQoC(t`E?t7#^6khZ%Oai0PLxl=( zD=$)M538VFW>K3CW)v&0%tqTlno^B5+!sxZ3JW7fqubo~$&=MYB0(E1eV*ZEYvug+ zk9M`HQH7jPlUOUucnOueV^P$^RdM~OBzey_Xi{|8VNFB|+o&n3>$E0awd1A3EX@S{ z%c0h$H_?PGx7R^cHoa$_u5nGSH(4$Jjiht>&ZaoE9c!#KXeI<2t-o(RATtsAIu^G^H=N4VWOE-G2Q7_rsBs*eGzYzTwxEq!2cTNSt>tS>K!ImDD3h^ zViO_{##5>{G`fpA8MIoIoB_X*%B=oSdIbY0OaTk$Xy)JTIZ(Bg& zcy}JpORHbYt;wZd8GKK9_0K+lPV|1R10`du95s_x`4=oD zQk6D0fVn^`n6%p*Ahl-d1Kb1P(%r1ww+-|)(`)WOeyq7m|NlSH>uy(91WW&q9US@3 zMSMjC0HqBLxs6$XAA#T(7=-tO8W;$G5fn%O`&S_hb=1nBR{jAG7R(id6N)2mM7rsN z>bMMd1_ofw{lh3^Js9A&=@HG+=K|rMwJ2+40XC2jQtZ(^&alPL68S9z9dj*&5(S^T zIg5@S5NCm`l}Dp$-S$DKeIDu5zEVgUvsIdxVT=TEnJK7|Rm|w&H$2L}3&bSYvttPS z9*Ojneo-kGcYh=l3U_yPs+ER*>5jP2N~~Ab`dZ2Mdb*KKzp&k_qfok1>5Wev)t~09 zfv@~d*bAR;ZXGqYCcfcGB#X|5F#h@JvnfSjGM!8dvf$bAy$YaKG`zL)SX2$OY1=K$ zmm8x%rfq$DTw%+f#PeH-=UZzDI15HravZ(vW@dYOM{<*_GD;Zp&iB#!+~u^6n*Jy& zNMJL4AU@*hkB)LB}M_YQLD>L??sPd zU*z{`>hZcJNsp-O{8Lq2f5jU+eo)|qs_-iA&|7{M^yC*)utB*@IvE|e+{;o^9<6$) zyOt_)U?Xh8H2SS-b`C+hF`ey^8alAYGG=(ss(w+HAr}}Ia*KK+fLnMmx^h$`tMr1glc<)@nAow#Z7Byq=@CcHT1@?Zug@w}x%Ub)z z8>mlewb(%Dey@5GYHt7J{%#K?hgSR8U9VYc{ppXOvAHLc%-|~GmG@ltsqmZaM|8}i z9)V*xM!Z6b9})l@bzlf;_~Z5WWXEa08>V3twaSSTuI6WV-@DhECyHQ-{jJ8ACmV|w z)5mpn6D_ni6A0yvPcXI=%da11&v_Wp7=xze6#vu*?9CjZx@PY)6q;W)6=^F^i~j@f zVdA1~M(@JlR_wDcSJb7q6xtQ7&*gH8Y?f7S4BOK|e;X3;X*3h;H|q9_iLuek34P~1 z)3XX>y#x1Acwdyphoy$c5~WQ4REzYhE;zX6VwpROtho=P>eC-Io#9XEyDb@Dro`X# zv$FiI4X?jG!qG+5Z8An8RTa&V))^Z(W#5vRNkYChN#oMpiS4Oo2Jbd%%1BZRi&Q}y zE@sZ%BWw{qi9Mi^x=Mp>L~Z@7l6Smm_f}b~c30ZV_QY3F?_nrUHp>s`VyUOZSbg#a zR;S1Lm5tw$;1KAASs|>xyYd&;`pXLsmWMyT4}R~Dbx!6vZ%_)^j`!#L(UzH%I`6b& z`Z8RZKELFcTe<`Hy_Yu>2q0{@BQvVHM^ks?C+8+{&8Iiq62#)`yWw!Ynh zc)q>mG8kHl<<^(kRSzTH#-M34eB-c22$$t6LJCR`M%c&;g`w-j|1Y+^So!Bp?#%l^ z)lpgr&XErk+Wz!DqSV;Y*ocbOM9Q2R2Xct={h8?~`u{_rtD&i7E26;<7DQv;o?vCi zZq>6;?^n#o=#wI*C&{KmPVTIZs(Ae42c;Bwtf<`G8EOuZB@xs6q%t!0D+21RIC=f- zi4)P-g-y}m{*~0w!qxx&qv&U*KifR~Ub%(I3tj*E_JaxJ{P(vj{PLpb55au~wUijE z?|%FZF*q8`EM}TP&2ZUse8$hRvW%b4@nzN6sjSS0AmyJ1ct|~aMOdIHvfhhUuDg$> zrgpG&6SB3$TY5ZuxVJcFYvF25yAqwpm6(NOWKxS|iOWc!yr3td$HrwOh+CZ0qCsXB zj4LYz|C{sqVRkzCQbN!nXg{)Z(k*9Um%RrS@1H?smB`09(c09g`qXRDcU6q3A4LV# zwM9ODkk>P~KA^yA)r*;WdyBaZvcJ(^?>nj2fFLL1RMp*_K%@Qc(uz>qQncM$GEV3) znYd#r)hl(@pEMI<>WYhB1O2yG!mlZ_;!I~kRHW2dug2UdGN)7GWCOb!GKx|Xoa__5IHniu! zzT+s&dDJ$O57nl{d~e$0sa!_chKMrq! zhqWH74Zd=Z#;|9R*IQXvEd3ByOPd@SfhKEYhkB-l(6~DvzBIaX#{tG;%R%H9uwh+; zLAw_+BpeFEH3jKmj|+y$S3dg^hQrGF5-DLwi7eA!!Z?%9!JQhHFeY(g#g4qKk~9WP z&sRss!(sn|Hx=I8@w`R6vazSi`CX&!~`VQZ9J!aveOPtSjSj$Ex*L{)0tZBir&6{T$ z)h~La%{JFWZ7N)l5+A0&(o0Sih`HiS^VerH-9;S$#9#o0)o`|vB{T7#=`x2L)l!?75^O4U0^jTqQO2j08pG2<2n9=XJtN@Ly>rgg zLN3DP3SqoJa>4IOqw|nh4#6+pEpJMdU1^R_D5_TDV!}yLY}a$U-JrH^kUcynu(5Fn z{L(@Q+owf;n-(xdh{kgQcG?Ot{{hRSiq@C&mJk?evExgWMiek`6Q8 zP~rC|H=m{i;}Jax<(UXt#>G9_j}ID=g*HN^*AMlSUpe_z$I(IR;;ELi6Bu`<$A8K^ zDMy4^ITbbC4M^v}--8Uzy_sYtccG*&-s^`(%CDTfobQnEAy?7-qDgQjVP}~q@tuvK z#_8HL90~5>;D7USc8rO~y6vDQz0$(2Rl*^@vy-56p_5R7rKOn?HW2d4#{bf^xB;4z zGY(bMEsfO&H9N2i#y{gjo4Y?Qykst(QoTkurF=bxsaK%p$6HI603r*- zeNU5ZR87=T&7n#awBWbTwBSh>%%TGIe6K%F5wC5w1z)mY4%MGxCz#q(VJO#HmTL{t zsXfj?w;3JpnPkgllu_}zwp|mXBMS;}#|_FlSozO4L0Nk}gbTD8klL-|7x34|Abpq{ zF|0w$9;^f8AaPp{A#ni3x=OTMYON;WBHc%w>|tCeS`dXQpzd*`t8@kY%69pAH=+3l zqQ4yUy>svA_qmHn=D1Kd!JSRXpPibC$HsHKL$z-S(`!`2LZLN!a#fD!6iZ0;S zK@UrK|94V%z=MNB`xm>*bE9tHHve-WE4ZtUm~y0-S#You*B5GpsIlscsFMx% zrU%M5Z>Lx!STQ!+WzV&7)99eBd_gB&u`yix8Q1t~*_&3s4vIM6jQ@XEdMmnDtIvuX zJl1+hD+#=FbB5fpvCBWdwIzk;Bjumv)@0;7k?*NU4SR^EUZmhTFRP()KUv10g;y zfJEj8P^%eNFg8ayQndc<_%?TCj=i*cm5cF;jz=Cw0#*u$WWF4%3(d3mJQQ2dakHJ9 zt;bTzw_@(DorbxqS75L@#d>FMfkBFhu5mpZLpyQlQ1_^weQ3XJt|NyUL3~Shq~UV- zdC`lz-^;)N@D1({J*4^ye;wIP%Y*;N*XxrHuqr)1Pw==W(keAiFn`TpmF-1ME^0WB zLz?+YQvGNN*-m9Yt}D3M|J~lM4PU*I^5XG2f1#dI*^z68DkuRAQ+_@D%Qg!T%lrUJ z4dZF_LGOP2DtB1l2!P9|0_X2iyX?(%?$som>!{^f8?PCvEE`i|s%?dL1Rz4&`55QU``~faDWldIos{(TCSG|E>zjyym67@wr)Ra8&X22xrDX zy-BuW%!E1MTv~K3MCOp$3&0+&%@)9YobNxU@AS#tB1Hwp>MKMy? zdn55qeh#A;>(0t-W>k4AthUpvQfaBKs!^T&KeO{KHg6(>Z#-+z_2@uxa$$uGH$-Fw zd#%U-iAKdZBCK-oiTnR#7x*lQk;6V1igyWcm_=9*R%S~f9vUQxQBmylR|#WkJ>$eD zY`sBY*4|A{NCf-w>0Y$LBeoDld(b6LzF~9;u(=?%#whF%q9ghd)pesKlm0AVc4*Sa z?pOXvMc>_>o5wmxSNTEqLVd~0cyH5bWuyzj zISDGCSJXEOvc{YpM-UNr9KoY2t-xp~VNQ0%Fo9hyP=*T3|1!nI(+;!x_t}BJu;O9w zYu~;wft&@otjufcyobWTzne+CxGaBG%*&0R?WOn)M%1?&q`5s1fWn{~z62o^APdDb zfL2ugMftbMEI^v(&n4Bc%%Pww(w*_L1@+#pC98)JLjK-#g>puW_C`C@>faMb)`E>a z`P6PIfim>!w;ADMisV-kQ!zz9^QDB11dGwO3s#S&1v?*UOysk1!9vS!O+=|=ys2|J z$}ZUSPsg{p>I=;>e{;D+k>(T!Gu}=Am6rq&0TZA12`>NO@3o$m>bd?gAUgQGx01-> z6er}Q*a=RroJfT<4h}Dj<0`C?PZdzEFJ%dEDKt`v%sfN)5SYH2nv%3~|giB5}6cHx;r^Aw>3GUq$MfHV+HvTn7)>plC;d%Rkz?8vYdZe0vxp1ODptrQXqHs zEcBC1&6q{E+%H=<-$>fehh9{&4#|J@UV7-LTt?u){C!w3RZG7w&&05tzRdnaGWC zNN_8#`Y0~7HQKD4&-P=!T-8)yaJY%~CAGB8@LV;nkankK>TJr;o=w#Rrwb zGZHs&A@bQjZ7DT1Z5eg7b?AR{U&vOB<8{mL( z!7E$bu=1Gi2xH;g50?LaS^9A+*%=PZiisPnN~%f4Zt{nbS#J;ijL8|sQ=9rm7nb0p z>sZfn9BDpjYum94NYcrin9Ia)SkZ8ACFdc!lZ`1UZC^pYziZ%(X>>D0U+x|RV94|; z#X2h68I;T008$2P-z3>P$6%jwr=eM+mY!ozb-{466`}7YNqBad%924#+l^+uf4`mDt}$zXF&GQM*7hI#MoOL_$fkTzFkd04tr8$sM9A-r7b*B3ypNj* zArSTKo;Er$!w~zqxrjZeoj{jF5S$z=lX27e7pHh^?i^H9U^_zQCi%8Vyp)$5B9-Dn z<*iJK`z&uiEl_V2w%J*-zb(#d_e;1LlzI;}_B=f`0iCb~pEsdG!H+KTx5Z8@76>ba zHOR#%FeMLYn|o$TvYWnsV%_%pcY>yXa^zKVL_>KPVlJ&MSk+HOZkVPvk>~3DhIxhy ze5uH^4cOF4rKEj0!sqEqjr4QkkecdGP8Pu4v{NPvP6BLgNX{X~- z&6HKON&fk7dvAi1{Kam>^8KicBH#3^!~U~7Cx*I;IFlab^DOYa>%|4>EBIccP4(RW zc|<9LVuPrGpmB1%Uzv|*dzjZ}&ooeN{6?v(YOQ=f{}EwTUd-o5n3rmt?ZTZm|HAN* zFQAPLg1{dw1=sKk-R~3UXOF&1M4r1K{bW2t9%xxb4z>B!e!~Ej66L46&2ajTc62jlZ0nDby7~vfq?y1apVS6z zv7kefSY^y0R^@1Lc`KChE!?gCd}k=bJsHaDuicB^6nnpq8i^p4 zG7<&DbblGGPml$W{7%NrR?08nc1nVBUPylho=N3my$Exp%0RvF5!k#_1|GRF-9mA0 zEZ{ahdaTW69j^}l*M7RpUyr{$nE4t1x=8D~07t4e%!XY}wLPYL+AgLHx{Q^C^P6Hy zSh!%p-}JieqQtg~PRCVlIz##bS=&&PIvXlsrKXuK$GuBAHerN#RonpgAx<~XH~ z^z?$EevAl}ZPaR$mXsU~RBUNP#xGhS}z|m;;9Q25Ia`?fQRi-`CW?O3_wGS!|@`rJk z;7Wpe%eJmG4UA|ZCNo?R`azQ}7C|Ms&t!g}XD^ah`c09eZV6BP1eZ#+hNnidVsdh1 zr2Qy-&TCFjiM!zSVV*`5V+{}-AW##OL=f--?^J>WaIo?`AW%&STAF;HTUzswmrBsN zkV+`Kn$m|HNL{8@E2OT4%?6KoDTG~fU{kLyz0WnM(?a{)an|ikF=BHD4GVkNQg;dq zx+@Ji>;}U`)E+kH(D6|+tI-J8YnM7j(+pXh?g>!X%_{7XNB@WZ;HGC+8Br6;oq!|| z%fU**dv)+bqeKXO?Rk-m*?I_0P?OaJg#LO!2KYx`W!XEx@1(KknX^%a<$%&KM)Jo3 zvD=k@P_c>gs|6t|Gu9mfj|3Ow9$s@mtdw4xIk5=@LYtuCGhf0B&$N>43?ev{5MRXu z-%a`)+#mE#BMcmg{6Qp@R|4kLuUy1@z&(CbwgyJD7?ag4%WE}CLa5%3DC(SY$_3L8 z`f%c$>6{+2Xg7yZb2-=CyUV>DBDz`$4){(%s$iy*CHMFWRf>igTqtdmqBRdD(iR%u zAbi8$WD!QKQbMU&0@Au+V3j3cKG@4)hx*tmCQ6v!Dn)M|a2wqq;Euc7q*6J!ZT|{O z;QWkKK^tMm>{#y6CzU@Ftoe?CJ@@D)P1fg+U^roJo*}J&feF5}AfMMx*frlyAfLD3 z@q^?7)Y1D~(@2G>?(@vvkp0O_{qN&FT?`61fIgW56RIkXoN3 zTEYp%@Ea;BXyudOgX!Ml|ei5oCbX1-m#cg;Y0U9LI!@1mAm5eK)zp@V$=?vhj5 zh!dRz9=RW5Ln@oYeFj)2-Xl^gm)QNz$hGRKS`-AyO;VUN^lf#)<8-?d(mZ7e@uH$I z3cV}}p}?MTzNV*Ub-nd#y{tVW1sDczNs|nR*J>2)?yxhW7#ONrI@tuLdU1?0YW((G zm0XkjBMmahlnsmDr(07plbwliHa{fbOXNvRg3m4l&nm3?OR zUWwXKO*LXZR<5|$GEwk(2ix$+L|w>=M4LtfbdQ@m;S)vVaS9jf!`xrhlP)r|hYUbb zlC$FzF>304n2*R`i}qnTX|a`|%nBHy4+apB-O&|c%yQJf@O2aai8As8g^Tr3t}iNy zdl@NnjPy2*#m@~k_(@gvW&7yl75~7sL`23aMnDTmKP0Un0*y)!jZB5ZBU95uQK{V? zZUQ>NwGL+&{nU*`&kZ&z(7XC0h{mkb%11r*%hhK->H#RMr*bQEEiQ6xT-(hTJugjU zr8m-ahHIeN3gU0#-QnR5@QQceb1IkCzX%sdH5It-W11pFn?PB{iXhyryKsevijoOR zo$mZf4{GrX| z-On~xrJVp|K%2i)$CdC-c*xm+{PMNc-rlDx@})pYH}g_ox&p&O*YTr$KZ3-^ggIS1 z$)Eww(MM;>5g}{WATb>E;s0Z1Xp?*XuCn~1n!#+cEuZk|n{ueQq0?J#~WS3+8I6b7mH$45v&*`;``S`>c%bY+TJA0u@0q+B9idW~&Tlmsd)= zl2@5pt#UjmDxUF7FYgHSNQY$1`Df%#I(Ph-fv-}0tB(7aR00eE6;?x z9QEFfZA?dyRR}x%Pbdn{c?MT}2=H7_P4!yWr>f|nbKXkgGjw6zI+i|#ad5aSE=qwy zMJZ)*@Pr~LptMS?P$MSo!?o+CsXSe9UI8ilfwj;ew^#3Nq#|DbTj}-#H78YQDv9{ai>8t z{2#>wnT5e=xr6wHM($2}5TK3(vaAiy!zy$G0=#*((ntD{#hsBncY?)X{;Xwlgt0N_ZkR zy<0YOWwH`KhT^ZUn)U8jGwxuT*J*e#tYEmSf@6x|Xj@8h)1rF7i+%mbQ)ieZ6qACr z$nk-3KexDeQa5)c&NWV5k1dlsVL#FGA%s*(g;96-Z9+rgfq0*NFAiO8Bi}w-V%jT2 z@7%^n3a^JI{HC8hLSEK>m{rt#t&s3-Nh$o;24OPAQg9Pq=QAeHR1@&{oP7$)x@njq z)J1c4%nE)-+P;pkocp`9|%(>X&-(g0nXWC`fyX+()~1NM|Z1gB5lRq$P;l zvG+ELi+LC5*3)~dY1r7HG;2m`)>quKGlX7-z^lO@BNQ!TW35fb7Q}BBlw(fI46rW`;f=_o|K4a+k@iRnH78)GN$VFjsC1fod`*mVjY~X2xlX7J8 z1V}_OoV!%t<0FiVLKG+EmDa-ya2shi?+#GS3+H#{>ze9(OhamOToU_T=dnKhVGyvt5eJ6mD-qJ3f|&i_N-eFs606eUSem6-sJRKm_qs{|YUEbQ9=OfU6A ze_Y2lq|X|A3^?<6EnRv=ck)WG$?|eq^3CKi&|mO%JS&DlrGpm{;jfFuL_MnHbSVXf z&0}Opo6Vg#Ezzq_kFdiX@QouYd@N+y*@n|t-R4`hrCM6LsS2;M1hPvqtU0!+StMpg z(RD=xa!%2sh)EP=vFy^V)5*Xy?Kt(C1U86?t5Km!r0mIp0mGfKk#x{7T`pR>T1_9-lwks)a@cjBBVQYEL!D6p36 zk|zgUz?FqiIYTL(gxZBUTu+`bp+3UA@PoqHe)Zag>f%sDZTb+%A%_o_@A7E9V`e(( z-^c6~XZuIiJmeSZr>IkbO?UQ$g?dbR480tC$FX{qU_1Z|p?j#b3qTBv(skE=`4fV;vc(T~{vy~T7a zEGG0!`p?({2F(Ud27fR3QL$LuRrQyQY`QuBJI!&{!(d|%t?~s(p+1jVOuYQq(-t6? z;=&W3F?9U-@*!rVwh@HI8~SiyI-jZWlWV0Ryk`T7%w6tZ9o_KM&5M%qOB!IC7ob@FSX#tS<*QD)f^R3!cExmjxL<}Nf2^GY+!7M4AlBdLPs^$DLE3!h}sk*i< zMg(qDG`<03cT|Ipy_2#Gpo~(M5!vSV6FpYx^$~|K6}B~QJrW`ZlxoQ zrrAc-dm4t_mQ>uachp%?bsNR^a@pVXH1)2eBZ5ZQ^#v9YQr!kLx^(X#xKf14`VqxM z8x5TDlKnm1AoO_UQ{gljG#dVyq9F?hBAh@nI8;o!QV?fHRJh zl~88j-P7?bxSU}%6_?-jE&18fAY zLajlCT)^F9*bEj2yiryOa=KrQhBwLu{yPH=@b33?t5VW{1XYk>LBYCfN0BPvFIMc? zS>QSG0JW#o!~-55*BQgQ81d|lo5MW0zg|yw-=R$8wNZLWPk(5^cvn5UJj%VUWnLP7Yf&ZU z{W(Sf&ZOW*T>$P0M!jyFA$qj;3l7;A+SE2u~5?PHao{Ddc zp4L}MaMG_SON{yaNbWr~K^7Y0gc>j_eY}NnYvYi;y>z1fH4w3tU0i>`8$Et$GTvwN z+xK2u^0_1OmAbjKGRJmVoC2GWAgz~5sXp@6VkN*;S5HX{p&&m0`t?x8SlvetyS~Br zh|Y#|wqd4&13AdrkMd5hP5@AmIU&T5g0vb@orjW2>y%RybUMOGfsc(*L+dQR3w5)8}oT7NthA z?%o~SC`yOLMyC4xP!x=D**858#WmQez|@0V*e}X`uLnbqrX(*>WO1<*+=&A_-WRwr zso9Qk7)PRW4SpZRqA7@;x!Ns9=Y22&2%@38Y|Ko~xJ3ieJtF^fp&ZT)~@;DUPat*}6LN z)#HkF>`^Y_pGWRj_s@q|QZlv1*ni_Vc#Vs_$CMu&U+lOwnnhoCo*G2GU0dcHX*nVw(wJ|O+zs4~mq7-)VQ%H%;SqtGT zY!uEH!i=HN#qio!VCYm>_b#+B{ez;Tih$+{0E;a1WD%AkDO=YpFFP}d>PK_@kE0uz zkgbsVg!(4=@b=Y|LK4BAJ~V$}RxUyx`d>kOzg1ITTK!GE!1#rv$QyTMGgy!T4i1j$ zyKNDS?I+ zh>|HZS??~2L55|F66>G-DW-K}J>%JCkJuCpW`%`<*$RY(&GXrzVPMuY+1v(QR1?HP zz)W^`Pd92gEN`Rv-CVg&6hpK?=sohIkb^a3285uc z5RY64dNd`5C#(rV`eh0^RQe&xvCccJM`xEj-k;a+(VWp9WtgS3rGMm*K4^76U-cKYYv}JvJcFrH#ioNmM)#lI_k1b#D>{wPdtCqP(?#_>kesIOT2E{6klZ{Erw* zf@HjM!d0T-z&vfZ2BAj0cRsp%bnK zwqs${OKZn;Cnf7YKCHsO<#{X_;Wr-vbr?LH5srXimE`*wjrFdBt!^?F$q315)sDeDx1WH{ zA?G0HS8D+Egm3S4SMzFpEnJI*Weij_y1Eor9b=Gv(ulM2F(A0$w=y5=g_zA9&=31E zsip5e3%MB*o>dx4-SJsi-tA>X+|#Petbt}si)sU&cJEb|g+&Db!`VOq8ow&EI?5@wQv8+eQ4}3(rPbCN$M|ZDVy>wrIKrY* zDcD9O(qM2Kk;#JMe+)u(+IfZob|kr7rPtiVeshTBg2N40Yw~;p-?&gnq8I*+xLhLS zIOwJahQ$s??`&@cdMX>pQEPlbkJ1|-+J7CS8!7PKp z3Fcg)V2-mT)L?Mj*8ptR>;ZFGK~*St{^nq_7Oyg+%iP2`^cbK4Ti)ym+W`Rl61glS z?G%Yzez6CbT~&)$Fq<3voGHMh28NQGJRNBEv{|Ku1`z$_9{KwBf5}s8K=R?9W9`l2 z#M8f#b;ZDQVAq3im1@y7^-M&BV5QqlojvIePH{La8qq57(TP6icuIZegL=~X4~K?v zvH3HjjLCf$P4-wt>}sA=YQi+EMq(``G{rhGC2|bcDdVM zt}ATs!t_m>j>sBX9Tnk`1%pP)`ern%o<0KK+|O81dgpu9rPZ=b(U2q*GGfnn6Bpu& zpb!m+lszPKlwI`jUJVap$4B?5qYn>H5O$@zj}m?(!&qMW5*lZ}m|9fF9tZW>DWG~_ zEY9SWav!szl&~g7HKdSCoV2x`EoFU6ibj4IETM9SxsBTePB}*}zp`S#ySHlZad~sg)veg? z?Sf0+ih)isyY27n1gP|AUp|$Ttcagaf(laB?c?9!1>F&u*E*$<)bX)}WQu_$lhSLP zOn{F`$Us(2DJX(M8>A)1*?*{+X1;?UZFo38Vy@E$e>dUaCbF>TIudnAM8aNOQQ=MG z(+}dn-W8V{4im@YSeaOhBlus+0B$IU*wq3=Zy$cZOs`$A?)Kyx-fbVeNh9-RrbQ;; z&63%&>FTPP`I-tje6(DPQEfzLR4FVL^($mZt6?kZ+X3rfF?b9TiEp-xC18=kcFWrU zD#OJk+Z+dez z?&q%yAM9&?wkO+|PxKlb_NKZ_0N44}aUfDw#y9Gl9V0OxJt<1AJz1(8d-kbOk#Y;S zNzGBd6XoHYd|;O-5Xf1^kUbIBa|qnv)kooP3AQy4insCS4gBfz}NFC&$w8&p#_kKg6Vd!VK5h zjPc46Sjk+jnLfC~7h~fP3)s<%1gYOMTF7)#+rFVC;tV*kQ5iNRx;E5iPgbLork(>^ z@Ke7ZB)SlbO@J(8wGG`4!{(qz5E3w<+`t&93h!~S;_y@ zsF8zzh!>w6X@y=%xaBkVFf;`|_V-zQ4p&g~E)^;Gy6)(mwv*5Q5!LJcgx}Q1(3JD7 zPvWd@*sBxK((UOU7FUm*OVfsC>r<*iuGX%X)Y}2;u=Ta=HLgM-XkvN#ds5rJ=D(E1 zx>h-disGsM9KXIKIYimsjY=kKJx}{UDt=*3U$fb!2f28eBAp_EbK1VuMt;gOa1Jku>a+c zyxzmpk@C+DRVqTA&w&vXN?XKGTL2`M#v2w<%zyBrl;O6v99dEJyKhXET98UgWk(D0 z2!hMUr5YVb!4AJpNaxnE0FicsErwKC{(-^sL_c%(#1d9A$%H%VQNpPeMsed{e$&Hv z;>u5^M^0tkI@M}Yg!X}w@bK5S78e>BCMpP zs3o5$%%umu=gZiaoi8nK-;DH(Djb~InHh8675A1AUmp4_*ZW1Jaz^OozYq%HAJ0r} zn&!?mcZwu#tbL3)E_dp;Yem~MEOfTLy&Dy^#!S*+VM*TAk!EE{ZZMZrw`+Ore0wb3 zHY-;o$x^38rJ|lx?_BNF|ERw4iT;|B5zQ`fX3u=^>V5vauC@>&#Xv zP@SSw7P+#EEi8@iXSLJ<##Y3xMA04gd0B5QinC}d;*UZ0zF}qTI z&Sb3bq($}&1J(bIjvf5tPTM|Xc-?3xRaKA*D>~MyjeEK)^j(lz)M)6ADi(^{``+M5 z`vdm*st~&N>i_!6EAdj(?+efVTvZzv}f%{}9AuPAu7O~jD7KO|Q$ zQAxpH%#2Ye#t?~YrawMrqH;MFiaswcp+AO7HasyRQlTyEORMWg%KNyLt`2VdFUjs- z_f}~!+P~}7QM!!T-l;3hY>i>Pz>g!-O_=fKzUyL&9c~DzU+&aVq=YfVQMZ4$X=e(j z{JuCd<2Ae6hhclq?VNA#^<4FEec>9X%K4?+JNYjgK~qC}t2t@0NrEwkDA_ooy;$vi zk@}p}hhb9Kk|OV?Dkb&8-2ICU@(%;Y`gOt`s@AJtZCBK^-2tz?qOQcn5mcI=pC|p& ziiw72+s%EI6|rq_Y|zx_cs^mS z)-ieeaRh@^h`B0fPvGz9_t(?^qMZh01&=q+Sa|R$625q$(W}v`sjJCGa+)m1E-0*> zN!^Ba`ZqoO{v16!Hz()XEVo!C*zA}Cf3h>xv%wRvf*lP(Z$(;~<_Bf%|IkkSGr>j_ zZEtdB~)}Wn->1^){miG2R_36CTI1{+7kM;=_zC2F^LiI!EV%(N3a)zo0i(f5nxAo(k?Kej@u-`6VZ9U$e? z_#rSS7#k+ofK9nO=3ARWDBq5F;l1|iI6>;x7Fgfx=qrvAnzo}C{BR>GEzRme9>&Le zA{1O44}NLtPt4;qCdhVJW4zYeU6grhk@(MJ6}ekAM$;eB6-^xmHqvq~j3^*z%|ifr z*UEZq%%b1~hG_B~4*!p8{$LYK{R-a=HYIvn#6)G>@U}ARb`o@xaAI`O=}0@XPyj`V ztjx$8F*Q)vVsXJw|A%t$1)Hd8^7PoW17UfwF+mcP_{!y@;8*9Gi2^5KH!&wOE8Lla z04~}#DkjTfGQskqpG=^n2I`~&ZFZQ-&7mqYonIi>_)kK`V~{rU(c0C{k1H_nLNLi@h7W_+%dEd z{Rg{-s$3Y`Q|KrrP7Pm0@pJ3{?!`8T8D1aw?(MUra&7W#>I^Efadh0qk#TQ=h2I1T zFg^ygZ|dTbZMkRP<%bJ4*jN)Fm$=mK2IG{4(sVvk)$Jne)Vl(Cb25 z8pstRl6)9JeOo9uicBwa;4p_{N?4&hK_$IY86@^`1a?)cC&_J*fdprN$V)5syUJj!}i8!9ilkdyhBp&@|!6EeMl{dO_MC7n&}lo^b!+XYUd zNKUOT;D>(j&K|NU(1~%h_jo@7Gg|OG7SfiBpP&5*4ZOB7#~SL@c)p~`#aEe(U zx|{J**ZE(06&#y7s;n$aDa^YVM$ol!kt{9!Zxl)-C{O->SjzRz{kN2-uVC%G{`7Y- zVj`Cxm?tzm^}g%a6^(syVtnUBr++@s@OJyI^P_&qD62z=i5wH`azD`nlQW)>j4aZ1`X>U9pO{1^##K`J9m&#sV`Wy?`bPoIC8{BcB$L!zn$&-|av^r6QDjz?1N)#x zQXD7GBh=|ugxnh_`9&fx6ytoMPL^R7|BTxPjfuj;qPJAM0zF25QBNoL70{QNtPHW-P zFyjc4#9$ts9#}2!R6=v}NJ5Y!1f>&STpw8Gt@ZI&cV!^r&BH7$iU}_TjnesZLq^z&xNH^HkwhURg}i%S|>rawFdm-?G?ZFk8a3o%W^Wdj2NT z=pssjTX?}yi`)q&y&hu;w+GpdwT;|}RJ25y%Q53wnVopE@-KfA;@{`Rz&07jG}xdI z3JDz=_}>Q534^D#8f=)c*ankKb>Ai={};gm*(jA6R|RBC1ZaeJeSWs%191e#?)P||iYQP|G9*R4{RKtFh zoRhd%Y}7B50)%XD$IgRw?$yj)+60gTZ=`fa=!|Q)VBng)^s+$nSsKk8Jrt|6I}o>6skFfI&WS}2f5G?IS{3EU_#zGtaW_epD!~=Z!&~x!fNV{nD2c; zfY&2}9itgh4KX+vjXlU4LNsBXA)mCk$DO}~AB0DP+_5JEh8#MDdv&7|m;=7jlc%Ic zJ#E2sJDf(3!)Z3nZPLq~+t+bK=xV-zYkxuD1kv`FyM5-QtG!N2N5F1C=;%SLbUWV^ zN&0=1Zr>fL3!gzY+QQ13Ks-|U9pm?6)4QYhFT|d7z=1~|iq$!R%7n1aGyXT{z};7E zp0wIIl7_bB{j_ro)tQgB>wQ$ll@hY*C-46Yc9YYHMV9x|P|&#dO5Y{21&FwL5G(!Q zIdJ#wk-Q2j34Bb(c6||2h(J>(qmd&mq4MsyXZrMvz4Iz=2k0u{!he8*YA)L4+7l8RwQzxf}`5$jhdRB75o=J|+72M?6G{Jpa20 zx#?X;4s;d?QQx3VdYRmL4KX65ZJ1M8%KgSqQ z-FrgCbFo991XWt4!iT(9*Zm{7aw#}0d5xX^z(Omp%+Vq4dR?bF)EQ$=p_)BKyQi{E zpcFYus7|Z!1Ino7-MlMbCP;4zglfWS>W-M7e!>#&N1^$n8Bq;I8ezS+u?acK`8lm~ zsGt&Mh`5&_U0w`*Z)>-7L8zBGy8eL4KCD{{Lx~1y6*k8hg?2ajT{rQ9;E#~bUhY;O z`Q7e$5|kq|9jQ{U#sKhU-QD%G&g%8Ej-30qruLbmeEROS33r6FzjDeUfug%+yZ&EK z2d_`B%7GBOA3hPXxsH%fS>1vIJ`$Sxg%An064r6J(OvwAn9-F>mEPlg+1Gw7(Y>Pn z7(%r1_aP;_r87@*)aWks$#aN>COl_I%e8|dH^N(Sc<)wAt3zSaSlI{_+8u9tbn*V? zZ8T0V6Gn#lJJ(7Vs>4~vwkTCDM9v)fd!Z_qR1<1SFdu!w5`Ij-ITYG};0zC>nc;Fg=7Irz5yBpvNWIztZ+@* zgmMAaF>+KPQtignI{RgI_Yq|bjtTd;^XrH0xp5841y8y@cXSH|u`pKZ_dAB0|DvGu zoDaZ~Z$|YO&^7+CzYA-bKBRotO7$;c`By7l(+|h{py>Z<%wSvP@P|iGLP=VkR-sxc z3eAd2b189Geav`C-pG7zlCaBJ)m-hxPw$qX9~l-xo%$he^8o9(ipo%IH%d{VgvPXL zq2-&h`u6jqe@n%{UPfJO^p;9r5wC8%CP#cOv$eUe3kz=vm;<=3We)9?^ zfla7Tjw1bozg)4jS=$oG1KF~>*14CDb!1k3XQh=SZ4wlBFIHs}mShYHI~|psgrcPJ zuavvlw}eZ6^-*?^F6-BYT5MQF&!Pmucw0h6ws)0%MbwveM4?+R&4_)5yQ z1B!i!5>nDC6nZLEvW{Qv2svv0oW4`kk@z2j*MtrJaUTOhOVvE?1(JjX{1heqIjX`$yn1$N$`hDAHg z-G4)Qs`9IAD~+C$#{9Fkjzz9e?X0hT0!{td|Gfi~`@LC`<|i0Bw=((j9qcKQXLYc} zOZpwuvc@k~J?$5S41cC^-lGF4Kd*yvYhOR-e4>wt{umci{SQ|Lx;} zt2;7y%cYfN#S85hHOc+u8>Q*X*=r+N{Fx27fz;JZaDVeUjW(DUAWmikYw^s^8N zakau~6+$i~LMndE$|^!5I{(j8KLkuW|NqZ7GVw*f=|A{E>Wg<`hDm_97F8Oxbo09R zAa7H4agSnYmvKx>swxY?*1A8ec}L&+IM2XR}8QRvDtK04_d{6smcoi$m9Wyv^teR z9%#m6+lMBR1p&(6u^aINjGpWjZxIe6@n7b0q9t1q~KKw`;(Q}Vv zl!&GgztPyJf?kjCj)HpY_>3i}SCZ)k|L8$RSCI6G;V0vj`RhhXl1767y5&K?mSwfu z@WJTfLXfv&xOTcg!Cta(hLs$6BG@Tgh+3f0A8USqdX&XuR@^z2sM=ALJb;Q-?yOKA zKt~I-&tbjM|L@MOv zaj-UJ-Fck#&|10cO^M0KG0p=K)`|*Se7QVy1Tc9X^Mw&3>zy=`-gqE$vC61`$R;@j z8rgt64cEdL_6>SB8Eqawv9Hf63mRj1uv%=xoriL9Ap^h-dj!}39)z(YcuwoB7$)y+ z)#Do-lf&SQPxESxx1ui-tUwQI=Jf-gequO@m_2N-DO!lJ$th)~q$ z0qst3hp=xrMiwMXaZ$$s@LwxNX()}_)7o)agyV4aRPW}`M;gOd$j~ULn5)n;-Dq}X zNQWGg2?i8St322Rm`BX$34SdZ7wEQ5>eok#EkP|jT%nnd{k0CL13@;yVjvkw?dC54 zcSC}^2k;Ju%E!Ac76^QWEExoJi%cT5%O{V|a>SYRYC`YQE$(yyy%peoD0XcIk=Zd= zzEQO@#| ztgM#(vXA%*D+cNvpp5wPSnfwbGS{2Y;|`4qZ%R_8qG5%?QsgN~X7h`(Yhuu1L5fYvH{nH+g$;;lTVDKZ03}ntsHGuFx~pXY6G6uGK{~O zV7o4%T!8)V5#keIL3j|3{epjIKVxQ$OcC$Vagpc%$6NK7PYGj`0&40!wC|)u`6-e~ zK@NXa1rMIp1f&WC3AImBm>5yeT0ABxW&GqcKFty3&|j;7s^~o<|0`;#A>nUpwxvWgY_D>I+r%>Gbh_#0*zZIkryqTogYkRN|e%{L8u=K+o4T*e{$p zDn{5?L%t*BhJpgZcEU)Fm7U<#VQp+|t1v=-9p5a>dE*Z57SF12&E3}V_T!~uX4Qs! z-4OV6Cw23t^TX(7m_>Q}my|Q{ELf&2U=cU9y7{CLE_A-nRsj3@uGj}zyuZh8E3j^V+v+}=_B1CpcxJQ1VY9}t;_F*3j;^krS1H@< zhrQ?(DSgXQI=76md*6RjwU0>hH{YxmGlK&rn*Wmbi!$A|iE?Vm_P;EWhMI(o8WaQM zR53#j1V^F(RlH=tV0)(SXCLKs<3e!|&MU%}TNz-;*IjLEyO)4Y_hEh>(CwL zdx>OBa1$ZVHekml0o?E%$wX^q> z+L)BIj`UkBK&VEIM6LtaGElyxF{!C1{UnI?LH5)I6_rp!!WM7;TrB?_nT`ol+7%hg z4MSRO0H~rb!!mNX?rd#S00dqVO7ZrvgU?zBpwqe$eO_1QCB%iXvl;m$uxnENA!S-% z)Z%rd5msU>B#2z5v@3g~>MAQ(Yx!bH3l9243|*K}h`(@6BDV;-X+dknNEG&#(5Ian zN(q^kU6i@VM%qKW$JHL@e?M1uFOj5Hqz8M*lT~GD7$_icqYqbwbH=>MUbrWFaKP(o zl+Fc(QnL(&3ZZHs!+Y%Vy#v%I$W>U5B}IxYlVPAo@lj5r?q-RnaDDp4d7t6r^mb<0r})*C6uwd|TOZ5y=F=xV&E zAzVW^nShh+2H$i|?Ivy;s%@`{@GzfXGK?`YO#xSz7O<@_ajQwE+Gx3BZct&7CIuIC zZ6FeDfg#r=FVPabD{()+KHe@T)`5{|6|VMiM}Ji3`=ZrP@+U7%EwUqM?ugR2!uFc^BZRZoEYd58#2x|K-z||by`4YB0c?# z8ZDnIi4@C`tCv-|+^R@&?dq{oCMtpm;R`d^Whu^O4*_KbbINSD0zr}tkJC=BnTdFnzeav+c zrJ_%;;OUoKthfsHJgR(C>v9=@u3z|f?-3Wa4Bq+9wwIsYAMCdC-LbdM9X@`YCSg_V ze4ll<)ty~}isbz?iP#6bv1{yZ4uOo3^gDAG}`DJpO zAmr2lU{o(oU$O2eNf6S2}|q>em+ zeEYcb22D(4L}AqWM9Q5>Od14RSc9a`n2?Dw&QfOvvn=_>S|yu-4Ci-0Q0}UN?9|Sn z8M24Zu@Oe@gU|wbFJ?>tN^tvnQ1+QjGJ#5JtyTo^I0hq`Mc{k;*?xo+1J4r_O%n-P zaIJWcbBJ4qt!J!JgHbecgqF3cA+wrBWz;&`&LSS_UxjAA30CqL2t84YO@K5$m zTAkG)^Ws(%m!W;6$D-sA>fy5dn_D;4tJak-BMpd?c|gOOeKgIwfU)NUEc2}bbUHPy zTmIMXqedu9upuW50o}ne05$s1R})|LQp~i0MLxjTm+*d<4GiYO9_NQ*Mvrc1oU6D5 zNYDth%tUaUtzk|r^S)up#ukM4r}l7_waDrWFfsHf9pKF{r|S11)A&X)KF1)9$df{# zl7<1`-U@&T-aL-`cDa()#r3mWJiv$zrb82s3B%AHMi++VR$f9|WF0o>><-~w4BeBb zYdt&Y+z>Kb?u-SgGZliMa%5PrNtC%B-p4hyDRpZ04zguD9?iHbMU@C8M z7onF2+w3ZCHKC?oGRMM@*8TH?eP;HGcQ^8-&Q*>$CgyPV(+2%@p32FR5ZD@iAo zI@;vAV`o$LAT%YL*g?gRV1{J&ef778_0tq8!~OgBT*_oy1gCs7?nwRzyQBWJo7>jR zrQWFDg`5W4+MpH-P|9#Z!%Xe_EM{)(>IUAfyBB?dj+@)2bhFBDQfh}_wKqlJ^nTqf zVOVQu>A3b7D)?Rf5rtzS7y_j+{D^}>&$|kp41I6f6Kc7K_+*QWKtoQ_A?`dtX2szP zA%sEYlwed^a&-7bvOrwCAzC|`5?Df|D=gXS@gQBenn_X2KODl+K&PPy*IedsWT<(l z(jp{%mZ7GQp&W_AyrtqFChT{8%2SSXD~4X<5TO#I_Sw&a4C}%RyDxRDyq&dL@ZkHB zEDXYWK3^i~!%AS6*VdfU`AB1Py|2uNfrd$Kx-l16tJ28yBIM?~tWP!*mYnpq8k)o0 zeG&^!Y0Nr%fv9U9YMHqaW{VP&^bZ4J5M=zW5nb!p%LB9|{JxX>ViMq?4WeWh!Ny&+ z<_0Xr&rhWJRHPnSg(z$86Yf@vDAAEK8{<$aQ5G<=U>OPCNyjySkq2A9GIl^h75O<^ zm6wW+M`|U;av%s?aBMk0mqw|sppepFz6#z_>5tZtJ#wd!MO?U|i-9q01n{9EV6#u+ z1Ls`B`jfqW5@dLexXSIB6R}WzDsy1h*F%NXo$l)Cu3W645?s72EfI!sHKRxwj0>SW zX{#PxD@6G9bUt9vZ4!H>V;X9gVok^h@{7A)%5wK0&%w0#$m7PuWMv{@T8w{qai-BI zT1yBPyseAiTV|vk^(>T9oYl2LAcK=;oLYaQIcKyooTcp~6t1EJ`(nhL#u;U{P^D>5 z{G8N-zQJ7Sog((Gc=br0*7(6(cG;FC2?byhVwNMvM`{~}uW+jor(F{@O&)Zbgx?!c z&~U3P?vj}pd=LqFmN_-6!nLv1>7XX-5eh6O!rIQx zA2^Z?c0O?w*2w>kn!+F`k+#@DSM~(w%A>n7O;|F{pq8&1a_-=V&59RH+YN0G4UB7M z7F!*xp<%p@HV3g9g9^#L{z*W9F}<>Tm-~$H~?PNF_E(z^WRm`UX z0SN^MHk+oSizSww*D=@$1|TAEKqic`PR~Q~OR{K3a(#JQIE1+$M|Qe zyGsNK*jv}lWxGAM?1clBEvZ*~B@DQ`uZp7W>z{hZ5}g!x9%fF-6tb9J^uj^VRh0L( z*ramDA>-GctD=3+7MfuXC-(r_almjd2j#p*!44KAE$jablamx9Lo>eI7!(Y+!D5OW z793BEd!M~rfVBRW_iu9dY~ePLn+{;O6`=Up4i(;6QdVRwJ7}Q*RW4i+Gxk@m!kTmrrL49ww?6f-Sg?Ve`eKVvR2jdd^e)KzoXmN5(+y2 zJHl4YmcBVUYIG1? zIJInph00k)Mq1j&%ral1AK}0C|0&a6hE<~~Dz^VT3h}Bh8EM1YRHW@t9ok2n6F;@Nhu+*gz0jzPr0hT8RGssPwpj-0PC(dj&Mv8j&ow>#B;1Z*hmkjYa>;t9FRS%om2 zvgG7GXlqa0Y(}f4rcKc@0+AV4XHBC#ZP&_dW(4K1s+d{d& zzKXl8q7A&V2wjo6nU$$YMHTP`UyS>}5Qh~^WSx{MDMP{5{C(#R!zbKIdDuYYbO4EM zzzL9piFV0EjlO=e-cyEr?+nM(>H*)v-~CtN+?d5T-qF{gY5Vrqy-$+|QD!)Tbz zC?E|xtd$8&!<@S!0Xl?w`UE(yN7$K7kT*=GxK$7nuMjh5C5|6!rNocBLh{>wcxT(> z&(^$*Wd6%_I+p$FX)-Q-|LELCiJX%NrDs{dn;xFS6a@Fhw$|-|;@CEa#1LjiPKAzQ zzhdW3M#h`&gqW?^K7TnXeL?0U96@+~DeY@+f+Ji?tn6eBkO`%hbvTfgs~o24UvNEV za#5D1oCsvtpJW8$fa2K!r?D(@D^*6aLwIHFXmp3$d`EU4X=QvYgt2!4PDSh9;CA=x z%vD0$-=O3P+rvd|q^~Kz*cvnpyRWbEp?F9(XWUQN$;NHr^#Tdr!C9wrX)w9$2HScS zM14T&QZ#DUr%!^WQ!~bLH1zDyf)Cbyd=Xau@v^^vzP+4|hxR+AzVE4^o(1#{LyyZ&g6|COSfHVHB z_}lyCl(z}=xC4#Tq|S1;)q zLn0}DbFq%dr8&36vyhs{IN5C*S=r^xuT8s;Q zy6B5@!S2RVak09>Kb*Q!w0xa;Dk{XYr<*cGp+X;y*K4^SoYyNDD^h|e#>BUxo|^Ai zrz{uc?M{$}uCD=aUh{NtvCu zbNvQZ>bXy3#*4q!z#zw!m=lK zCtFkI93YN#C>xZMl0T>67dkk%`xX$dn_1M14h0jb7cWJA9E#%K*y~o9K=W^ z5yUaT!9i?+iSR5(Xx4ixCXPb)PW-sxB-66hMtp|ZVOZ9cg?B=Kr}%n`vZ`nsvf*%{!)n9O|0)#qaY8y%Y@*usaMR1^=3njhin zu$Sj8R*zb>Tdt^%Q$@Np`YJbbddddwI4^R>JI~!6y&(Q~O6loxaxXJnQ^RCxF9bsG zZ{;PQbaTmB&spW9xVP|-1>O*-^ornA&%al1gyJAGx+iO7EqN8EKDssk+>VsDsaJaN z%l&pe^$21hus0JzM91SUg&bSM8Mg;_#hz(j zS@dq+!@q81y2J72V$Cu!qh^^pJLK=R54d4XuOr)jwcN3j!+Z90w6Hcylu5P8iAo~& z`a?%;JnkMXamKJ@TqY#TqtQI-j}t(sLp#Rd^${DI`e;+1RDOT$kCVx9B@|OI_?MtB zsrbWn(D^=3EwI0+=L!V3?5vx$-2}i6jYs)~$lbW&%sFf8Y~E$H~GRnHPtVgQZ7L=zrwpu4nSf%d29p1=8e( zm%|M_iwtJW+;R=>2TlY$%?Ds;1DY~kUE`E@I>3a+d&md#9n=}yrI;c!1!1?O1jr>2 z&K?P{ZY9@wJmacL>3Y_mg!KghHjKXn<{hy?AqFNs)k%9&1e;0tMeZQ zdt|ra=s_D|o*}_c;nSd=)xWS{J2FZh|9X~Y5`~sc3&xNls2P0&$>|I*@4q_Xv+)mXmJEn-&gbj=X>o!W-KfwgSC2 zGZ#rs2+0J+^F=G=NZbSZc3MQ1$2cAl9%a5S!d7;G)csh;a}kCmf!xk5-tNz6JRtK# zx<}86E;31zN@DgYB3$#%&%WQ8%)ye!v&Bq zqHYp&%jkf6ir)|55@VVS7xb z*XH(^JSvUdEF-`exA%%|#TpxvGLp}gGh-dcI~w676fan7w4H6kR(CHkgRpcD!_e;Z`o4_={-hr9PS=(2Cj_O))t}PU|d$i>4W~?ql=p7Qvu}=bDR>NT= zS$TeuDGF64m!{6};r-=&TFOB20HOXr5o{F_6_%fw4ebQCMXU~+V{BLhMDlFuk_b_O zdui`obeV9|hQftWhoj6>V~wFsM%rziJ!j|;=Rr@e*-L$0MzoSTSS<<8r;?z)N;)GI ze&Kk5TuAZ~o;t>MpY%sCUO`6VwvOkJ0_R$Lg1X}(`WBpVTk1@o#ayF5kdzR|5c=uS zr}AbM>!wwf1n8_*L4-!jo)G({)9HUMsz&|{^n&++{@u-e9-4wq8RlhYe;P)z)Ho^9 zGk&!maJ-_yR36U)_N=n^<1viaJ7r@U&~{*oEFCcrF0Fu6-K8V$YRsd-)kf_+Mbjpf zp)mz~kS2guNVhT?m|zU4F#MeiKdAVKX2zXe8}(z|>7w1wXpz%AvE)5H36qh|x1BfZ zu{e3M2T|qgWXuf~M?{H0NOG$_<8l!kdXfVOoDVrwOLH`j{PY23%@b&azTvO`aFNGyMBxp@^QDHk(-V*B8jccNo zcSdbN^ZH5CJ1i?qgc+?U@)qMJ@kKE?BUR4hlXl0=dT7&a$xhdVl3cC~FhI1z7w~ag zXuEG-G0A*e&(}4KA*NU=&s3b)^8rwk_|)~#;z4_* zNKE&X6xe(k&w*s0Pd~Nct=9voH4rNt7%Z2{%!0FPG_jvX^chw|n*Aae*<@5GWypAp4PyKYzRp@o(HejP@hz-v6Hc+OH#a>HeoAw zRC*FbP7r(vxYV^29pqT7&F>ZZz z;^wUeK0E^&F&%eBZsXU%Xb3J`4b&Z1nKrcc?A1{4bOMSP$pvnri>=PblSnp2Ul>sl zYACG(-j1Aj4|}QK%M|Q>e%>ri zMlCGctl;+g2BJ+DDK*BT>bcD)=!*mAsYwwc*na`bfco2WPm2l zZ!|64*AzEU$6ioq<3&y6Yh4m!Ds*h%qC|t6e89VO^mJSRqm-AZVFBS9?P7u4WWroD zIIU-Y>9dU$dvz=K*+!!0p1f zHT}AhX~n%5(4rv;6hdhEGsg>_8zdVY4Cf>V`O--S9qAflr25JI=$Y#XY>}*Q7mG_y(1!)f5>HXuCgqS-dooh8)sV)Z&r#?v7UiL zgbw9|38;28Xdhg3IdV^n5bGgBSC$fSDYS$xNaZd=AB|bHztL^Co9>q1MNZ<~#jz#8 zJ*Xej10Ejtq#T@K0#0tS`z}htnvT!92Zk#Zhu!)HC9ME)X zvJ1S&2%w?EA|VbQ-w%gu^9OPKI-g(XnK+!cMlmI;dtr~mEA(jpY>eQ|vp0AFO{z1( z`vukHqc1BCY;^k`?!oubzXh`8x#_@yeF;523v9L+pSslaWLm~uuz{@6(BIM!1vW1_ zHdPOgi9gZR zk;+9#f4ZKBlB#!E)27jDTg|Mvx|FrDwuPHO($+^($2|9AmS9x5U*r=(V!orOOVsgC zUM6X}Yd?3dq#bfXYceWtxN}#MeX(NtggRc^9@?O{eMM;QsipX4z^7o+7@4#z3Fy#K zU1XY|IKD|QAa!j@{zI54jskpy^D*hhPV^M=Xkr1NS#*JCdnrN2dEyNu{}5k^B%gES zk>-R5AqJwwOH0UdvlLdkAu}8?4N=l`;+A8XT8#gXSbB!H zaX>1gKpl`{(57Spke21FNZ^i$yp&%!*`B0IYx@=F3qrPnxR(V~l$?hT(~=vm_{p9N zu!qDjzcYrrpM}|M+&=E`h-u?l^lT(wwHA~$i*`e3*DBTFYcr}rn!G4ffc%e}n;hlD zP%~0sQNC$4a3jrv%?Fo%?kwOLBwuNMBqysKVS^jI)Vjf;?na>_rCHLvMr`{-fJA7r z)m%5SBV8_&iZ;8IrIWNqtqmz-AcV77*ORSgNkhwzh2~z(l9Mp0zCtJ1fk&u+#OmvU zhioXi(j800JI(iINKm2mqBHY#sQ+$oj6?s^8I{Mx-Qykol!Y!iMD11*gFWAv(Qu53 zq6^T)tUo`$KHpxH&@sXv^DylavJmxm*4SO;Lrsx7<6B`ZXYUmAWtk#R*#oiV+oZIkB{L-ap{5kSI3e(13p&orq;D0>5X9KCrG5$az z9u6MXVvnb0+=?U})6-B-rPdmhqaKkHAV)_Wad1bB0J)~nU>EuJJ=)CCw9doIorFhv z4!i4e0t5jR=R?GB6W3F92jTI3_TbSrVopjkk(|`)(|ljCke7oe-;9-&oNP-ga~VmK zpAJ^NI;PaUprTF6X>LxNEZ7hQrt_0FlV)lHG>XkwGb%YH$P!+^9@^5guDYF^=h1oc zzBFw?uXXHmyjJXBozd{G14G83(J*RC;vi=9c#8s>Cghw&Gf!U8-STmy zv|R|t)#x(}l;%n>M&t}YV*Q#Qsvc+F4T5)4RVTTa^h|rrm0f9#RzwTl&02651rYce z*_Mi=O3rb|^F;U9>nbIUbk>0}ne`AXi4ntk(_7C2vfi|uJHTCrD$|T}Q#{nOfGWJR ziKrwnFzwbvrMfZfRqp`kjx4qjQDM_A z+wprZ-zy`BN8;StKiAgS7;_UEQ0F>c-Zh=MrPza>dYG~@dAmzt90=(Hg3tU4PIqac zVm!%g!!!G7$7RLRM;Ycb+H=mJA)I)~cllgvMynGE-f4tmI$AAk_9%{6v$FJd; zB+S%1j;n#tpy}~0!496;p@dzkVsxkQQhGSj<@r3^ zJYxG9=x$@XGg~$_XpX~Kqs#t*G|Kbv_5+HSno-^SuJK;<$8CR}a-mFdVUNMKMIU7kf2=K#8! zY9VL#H~Vh#$D`&U@?bH)-+7ml>)m72Tv=mG%$x9_%;5nbDVW53-mZxdnkvQz0H>mI z;sy?epkFmV%wa*33RQQ7bA~1=lH}G|YUGG2AjH-Z2cpceUZOiJyKJbXVHk)2;gFR< zWQMENo%4FKzTvYNdk0-k1X2Tx_zEx4N39KJvW7#2EU3Q-zF|Dbef1pp;-x)6ddj4p0f;5GkA~! z#}0lA%bJ!7yWW_;%^ZuWkNmmuw~@c-a?Gb@#dE@+*+k3{`#TLM2|gqqC+3L%9m;AG zfKSbI(y;$*;kv(dna^BcJ}T$&&`$U-_|Pnw@Vi~=nAf3!ztl~BAq%4A>KHX=mnP)3 z){)nt*P*M{-CTcfg=c@o@U7pJySh97rAux6OWc>OFWC)j%YDU$pXo|@26FI288;|# zJ@C4hT1_W~Q%HyFynej!srYB>-{Y_A!L2e@m))tp5X#?)d==l==dN#Xpw(qZ;E%;$DT2M{rKsJUUa?US4nyVAppM(Ms01S zksTV04I9l?A5-i~40ECwvG!{eGJS<4wc8nOD?;IeABW@v1x`&tYTAW3nn0|I-{eaH zvgANv%`r8$XYddJ=f(g!9hH45!jU1$sg{Qcq@hr9{x!#&iHQ#ynio$M zb_KIAwPU==Sf5_5Y>kEkKW1EZc)q9#++$1;!l=R5dsl%oA(m&jwM9`}5%QHXmfzegpRZeMw368FuX!k#oq5YHB_S7S3Mtu$Hc9ln zGm^xhMCKkq9!T-yoz}XAq|E%}NoUxBOp+URGUofy0GkgPZCIIP6zAZV8PY3ekL2qx z*?$nQ6Ie@ak~W{v4(QKK(0RX`y|a0mv@mcH(fx~6rMKj7L3nGQ_Mv<5jaR=Q-8^gp zOo0;t!8E8FV7>1#!N76Z59}A9&+CAO$H`Lj7Lpfo!w0+%gEftFab`RRWactrm`uec z0(c}%8ZE%IM-+raokXU%n!*-43+ZWWV5Alp7=GJEV_va2 zWg9Y28v+&sR7mVUH#kp`An13{kJQTQWC@cGdvO<8(-+OyRZfCiwFq!tly~W@z%Lba zqyIxBIplzFvAw9-G*J|FLl1Gx<#U(g4@M>O(M$1TBH(WzYJ{u;jM$Q<73Vk=i=Xd4 z&|fS0kh0}c=5S5PgrCYj)KXFC$O$2lm$kT=C2ugiM{q90-$=$I?cygih#RX$fTj>x zTnP#I&%9TDUrAQ$pQVUB$PRL=sY-wfROx6SG!r)o#cn``kGe$Z+3^cY*@l~8158IL z288UmMC0NHUo|%NLD|D^^UI+6dr#p+~f4dSq0TEMBTJ(8-mUo7=8p z86ki)5%>uyHXe54@oq0xJm4gxI)XKNQD$}d(SI7cG1f%Q{ob;IgBufc(I!lg$4b$) z0KSY&YqZF9={7@GTL)-@MV0e`@V|WRinrrk`sb}2X9kbNBShxH+xFkl_g1?Dx$O^O zzUKu#7BR-FyotspL!;8Yh`ulJCYP2-jMH4i{5S;w=7u0e;SGg^5|Qz2 z8+l6Igqh`D=irwaIFA5D@-kDWHv9$&S^T6*o7y2WKi3@!R|>f;2fSwtPzc4VsLpef zr;E^w%qWlU&2GeQIR^$~bvx;@AD4#@2%dJLN8uTbgcRnB<-DtyUf!)Y9M99<&qK}- znI~~oBi{aF`TuI5f`ZQ(>^WDj zb}806F^mE9<~^KuMxTUQ`G@lY6u6yt(R&5_AVGu|2=8G8L1oXp!+r>{q-+n>Nb?+^ zR4WA=V8Q?$r^L1>zeq>;P)W;1ZPYeSp_L8b%+BISr33IzENaK%tUM&w|D7>Q1GCFLChKtxScRJWQhZ~_MHm9g^FTQm@Sn219&KaKL;m0 zhe}n$AfdvT-^sP={icu7Eix>Q89s!xAq5&b!#{lUZVe{|(o>QY7_A5f9h(p-8OuCjp2w2lFYheF6*csWdB+Gc&9CIzqB(Mew z$7#eZF?(E9OqNPEzjJG(7x7w56Yzk{G=#i$*e-{H?9*;AxD>2*D;%(S9JgyeJrzPAtoF|~X zN}b`nnXLV4&H^|Zqvg^NZT0}X$NNPe2}I zClDmo*>g`d_shv`(~=A4qRes|nL)Lfd)Gs3B@TTkP(#(#^Uc>%CD?wrMxb&w zrz+S{<=PYgn+IR_uS0rddNAiZuldJ26mC=S|Hxtd53&7!VU1#5M);$!Zzt$Y%C3H` zg>W9Sy(!<@yqrlZFYzf>CSvnH#ZQ^BD!^I2 zu%{Em*H%U?j)G^sc*NurOVKvNva~ zq7k~Ow<cyTW$Rnj8EegqVVKNnqm(^za%)FJNaoWWC45?B{@Roue(>o(eOg!^>29Rx<3OB8h zqer@z?+`7P5BEw!3)4*b#;&l7^iMULniDEPXhhL{g)_+5>pXy6)GfKjOa`bi1l}!a zJ*IrhmLT=zsC}aNH%BoylPY?7^}DlY*#~{+32nBWrfGtV4D)GC?FmkwG*f9?$VU;) zb!YRdg_eVPtHnLIk0@qtwDl#kqe6@NsZh7+jFC!p4&021Pxek)$|Bn%%Je}1K3e1q8J>bK+fl=rsh|SkHEx%4-#Me3-E;6b}Wq?oJYFzXmPl8Z$y+ee7I6*oZ;ms%7tTg@eBE-sS!fkCvSmonX zJC$tQskiJtZKdVo;yhJw^vDa^eveb+ih22GHm*|VYbuRmn5lUAg+w}Y)FI**IG}C_ zi=VIOeQUI=ODljkSJk1UNpSf_2YkCC{lR?m@o24 z`P{7N8hS;tUq=V4r;?DL*tI5~k?k1SV>6j$M<4e;R(V^go?dezQ;N438J+`bJm4|s zfb|2&&?Gr6!(-=@d@O0MBaWm|NS6>U39_~RNPXu=yuBO``>xqlM%*wlmB;uDV)V!Wm1@f86aQ7{Y!`pIDY-O-~9RY z9A(d*{)lixosmi!HBJxvd^j+&En%@cJu?UBtG z;)p7qMJhz3+qoxiP|{AVjPgw{Oqd6uP~N@}O~%OSQRR`D+gW|K7z_k~$_s)ole$G~ zKre)xwDJ4L=j&bU#}oI*&H)1Kp1%#D(G=+Qs!-ovH~6=m#1?fzyO5LA2ol|PdZwV* zs-xD%G}ul1e1ExL&;C-3{KAfMq6BmSC*3mUx1?l}e`akO>fMyNyEXN5cxw(Rsh*o< zQ*wXc@p%sFM~^W-)Yi;7?V!opB(|WFR%m5wP7Gd=@MW0pYnU4GFRH@D+vnqU^XqFl z3dN`R976K}ZljMk^j2M82e2Z7jVC_5R6wj@jhEdY1u829^h|=rKu{#iQH}>}SQ6yH zIwhro7$qO+7!;;K;wt-I&^Wi2xB)8TSqn?Ty})wo!!~ddoL+SJhvrPq1CT9Cym(sN z?hEU@2}X6PZmqsaP#5Qdm90y5bt=4&ehruJTuwW*{CPPoAsFO8%&#FdAK{iYN&=0N z1pfr42W!+E$S6=LU&U|eem(Uv^Ev)wf_rq}%{}V88Z!bENf&Y(DrIxG{w`rTMod!Z@$tc%8Xu8@A ztb4ouVq~jL5W%aiSTO4o&QAmFLzEg+u3E~ph?c9Y*<;!Bf*8TxI|Cos%MPaiz>{y`UO&U`iXJ13ga<>7)nSP0i5uJPcb3)PoUBdmjxG zg0|zSCO;@BNWB=iU4ZZ_=V6F|z;^RMhpO-eCLMm5>}d5YuggRfGHvD~(l0CiBq$8D z_5C3n5omk;5(Qy<0fzWM7w3YdQstGvB_DlD{MhK$c{2Jyfbc69V(13wgUs;0tH$<}#p8r#a(M!i2zcV>PT9bbM&Rr+AJ-dEV&KO^F? z`oXp*qrdYARE>;{o9Ca{k)7NMRIr}O=$AV>mW0HC=2r4sqMpWq(?$_y5xbcRZaJQf9XFcQG%X%nGc`}ky?ybA2 z)&?38sV+zih5m4TNS;+;oTRL5&-1Pe`ZYs@CMxQ_YR7lxv$`*LfvrhnBm3S{|E~*5 zG`aC#h_?$hY5Lvi*jiL7GA|%d-BF~?H=!pS31_RFb3#u#Zbt{fuhwXSkrnRS%dn6#M6xgP&Nl%OmV5XU zl?IBD|H@(8II$@;*n5bqTe2JljG|~|Sn45ue?Eq9Yvld_#a=L?ajpJai-N7QVbZtl zeg&QU{!(d=$)bf|Njp_tmBn&PmOIbth;m97u2{tqN0cD@Ak_dNgfgQ_7Jubf%d^=B z5WB3!9DIJ;Qpjy#)VPTR%!7JVskMNw2|Dz=QcGPfv+2+*O=1ANb(gh8h3>=t7~1zd zolM-!F|Z4j=4J2L%$gf#pg#xL8OP&B-E7vKeofG%^F6a}MiSwp+B-4FTGsZhsbg=~ z&JCu=B! zT0n^0Gd6AOfUQ|B#iS%tdc6?u&6rUl*8hBs;L-fOo`c=j)A|DgOdFz`F`-FO-+~Fk zo~L=MbSl|9Ym1WXXd)zPtxgT?Q4g>@B1N0BK~SA?ZR&(j$V~VEUD5PBY{<=Y9$iAG zMu|AJK;PoCsE-)*xvoFc!eM@`vydVv>X3VHg~m>{bV!?J!7y$lf*{E&V3%LG&*R1y zrfh^2taN}aIV_3?o+|ocr@D!AJROrZas5bunW{7WjSnXMF9bf# zqJL-s#IU3G9>c-eakX9ZrbzhQ_;DqYYy5;6`YxX*-$1oNH-&$|`Lj9f>KYTNG?7DF znCdvumdKI5GE_Rz{JRcWz^)_QurQb)N8kESTwWz&h;SH#cwyv!kJ)RAEMhY;u$3mV z1H@b8jI9Y&5)ER8zEB;4Z>+Jq8nej4FBErkXpC*itB<0Us5UCI?hzi%O_u5SDf7J; zV@CUDepv8O6}%Uu6p`#Jng4~QF4yYHpYNTsI!j_6?Y%0Wyj1wNC*;(Ko9z{U;u+6= zmIrxgrhBUeGfchGc*0q-I_2AGA{fLg-7yv~qt@{fP!YQN81!@oBdLT}st1`Kye-h@ z)%HC*Mzs)Fj+(~+qm*ej#!(R;NY-GG#x_BMijAb~PR5!6f|+x=>L|;L@LCw4;%1Gw zP({ynC}e8ax6wOCY`$oEVk17>6IXdGw6y+ajfX&6gve;YVsh2riIS>lX5z&Bso>G2 zIdRb&RonB)MS`((;l9Q~NsjV0m}LYDI^oZuM{Xpd@nUsT8Zmu7vHuEo{-4(rX8#w);2*Ns z?f(C}YBb_rzOMP)efgm3tP6-8ac4xByXGT-8EiIUbi3Y-0P)1`SYhbE#?gqnUa-Jl zvKp(O|ABPCcm43$CvV@pe)a6hgZuaH_TOu5_KHsbWgnm@-f`)aCPL{j0mRWKD@eej z0vEN7D>AmE|6Bqc7rcu9x#17lzlJzL$Mms6qUUldp}a0wmNZ=_U1EFqNLk6Xeu~eP zWd%Nd@%g78-#>eDId$%iUQSxpmItcBeZE-bdBph22>kjY2>huW`?KJyirU&sVaLD&JlT z?#yZDjOOAlyYtQ?^YVCdhf+4xiJcss0Pr@F`Y#uTMWPGm5uz1(4384HE*w@amX0;z zN;@j@FrC#B4_%P*VTB?$zn`Yl@#WRYHVkncQ+*&Knh~5N?*sQt)FkjhF~xurY&z(= z^g`I=&)sQNSDHn;kJrt93^Hp*om3VcEY}1Nb45B&(r8o~2L7S?n!)$8{hHxI|A;zd|W@yV^C6iqML`yLtjALMzD1* zUDa(G!5g)W6&%R`M>k>)05x?BO|9^wi^3^$-B?@c=GrwGBr{7ka zB={ubsV$$aJe#IWquykuqQ!(Yj$lqpNQ!P}&fsvUKi|5|tA{a!Yir@r^*y((1Q{m4 z&msoO#5DD5_;gHDVqDxNcAgF{$+hP9t3Oa7~xwn8KARNx(bg7K(c!wXVY zS~ncO0j#<@<2wZ%owG5JaNOU%Z#>s(sOEIo2S>QD*tdPN(5^-qbuAe57`U3*On@Sn zn20)5qHXEl9`C<8DPw~lUe}@Km$#d!c0g7ktD}RW#jLy3SVNh3-P%~aHaxYa3k)fGBhb`;;WZ5pws9CtN{eG5JiDyK zr>b$4cvN6#FEzlKf0AZ`28}H+CZFr-;bw5yFY<0~;g@HDA!Px{#B^iP#A^byQ=&YP zQ{3@zfv4YVI$1>9-KT5mg`6F&V^vw1q*{mNx+w@tcgQ;EZum@L4|q*d3^q~kgof*n z_}V(lIQH5(=ZxBe=F|ZX5xQ30*o#!1&2*9E#tgUj%q>pz#fbW(B+nRC=CK-H*LXz5 zV>*4Yx;XBG1$_z3hMJ-`>@xvO@$T(u-!ZFz>zvhZXDJYfD#GV87xh7F__O9_aciHl z)Jp#OZWD^TDTtJ?QPDxst2Q(kZD}cR*KN=8diO=(B06TDavS-xc+g?iO_^3HnuY>f zVn%SQWM|KNyZL6%e7@c-0Bcm%@G@NnghmS-#P+#PofWe#kwP8QU*J;7KXiJ)O&+xq zyQr-5{X``i4(EB+NR{srX#>8j)ecs{*bm72gkpB%oHZfpA?dM zM|sgTJKdFoIc;>OpXV z+c7TrYEmXLQgfTK2Da(EeDzxlBu%g(qn5Q%9U9~kAg4~VDhuFtP%Ml5T{Q6yK}C7L zG{W>)F}K)9Y`aauqU18G>LqqUQZ1i(f-+^&GiET{ z;-b-L`-cN?^34i?FE`z4#?s3273{E^p&PQ+?p94^vsIszS^6zNba37Tg`GT+Hfq_# zNq`iRUdU@2Z$WCx#^{x|6gw0O6dL<2+Q@;0Ob$h#6R#FB$?`gt>K~2+J*j8~^9@My zO?2%3DlccSF39205F<_lLdIs!)%yAthZ?cwboj`3wS05Van$Yx-(rx}tp6GKL;i1` z@^bauCI+4nQ_D*Xsy9IluGFWc8!=}B1kvot+A0Bt8dtJmw3Iy6^m=!eBcAu5E-1tK zOGk|8|Bj+Tb4U>vGO7-9gR|%6v>K5W<6?Ij8O5~akF=!BCtL$G*I zB=Bje;8Y%eg`Y6zL26pDii=}#1rzII9a~LcOB}cdU3YJrkO?<|DS_DNId-SUe*>jDhS%b zv1bOJ60$8I+<4#GwH(>Q2X8cCO`6qfciKYlJs_i}f`Qsa`FURS*OvB9p+VW!br=j{ z$!Ow3kT89tbM=l+j5VPIYi#qp z@3TImkg+W8(3Ww>V6BhHFJP#iQO%{Ae|RkkG2j?lzsZ3x!_TFTVKk!PRE3)qw z`<~Wi!XTHO&T4!0L z)p0{_zA(#IR*{}OSb9rJ}3>t!U=2u{Pn!N{~ud2hf)b~@9& zT6IGavtkSO_c2(eL!7>s&G9sq(|f6|ts})`+cEQ0%U=YdrEUTzLX1BsO?C3wh^wqO z_$nwiv`7rWI~SxUMZWc@;8Xia`ySj17*mk7scDb@ruolj1<09*%_6Djn@LAGlnnVl ziRWWaN~u&q=@y;>flu+l0kb=oxUX_grU=Jz#EoUdb1H+6kanRM?YR6F`b2r6I%oUQ z5e7`+=-BO60Z1IT<3%-TD=G2dxlB$fhlJikJ-lzK2iq9pwq+BGU1W$eO5}8}xYvBz zs%syQedh8~K+nq+j0-mc_!$w1{O{lNB_PwMkOIxY5VU)w4TR2u51NvC&iB@+HbBCr zRmYwz8Zx@-@N-^!UVLO*r*t3nB)ymTboi1{_d%!C4@Wtp`>4Av03oH{7vy5CqE@`I zHa5enyT_ocMqw$OE9nqQ(!<`3n5vJ&k#c;anzyy%L@J0`SMic5WVut3 zq7X1H`j5v=v$H@scVJ$Xd(}BuQCbZ6dVF&fvyZEV)l|PI)CWV?i+isg>E-(+V=z4N zcI6Hi8+4_QD}Iu?KV%AMb=gor{>ll$!)Q*O?ft?hQ;@pW;&IdtY1C{Fz11TwNOU|Q zLQv$lspcG^yKf!38er8Dbmi4&G`Th67t>&GrCOEcUQ3JYi!iw9=25%BpLsK!~1|X|TOo`sr z8?YLhp9JG2!w-*m2M&Kg+%b4n2+T(DRm*i1iq$~HX$5trRrd@PV?hC50;`~*ikMeh z=4lohm+`CA;E<0_)!X56XhAU)n3l?C8>1E@B>J7B@>E>;=#<9Io|&&H;w1>S7oMts zP1d+G9GA5JjhPLj$IgpruD9Ss;OEQG!Z24+LWs=Ic-w+X@+`&unY;HA$B>(Sy+|81 zkqOl8?xwiniELSGd8%EPo^cC*N<;uqd#!Nyvu9_nuWgu={oc{A765>^4i|rZeL?xK zZ?F1!zia^DV+c79@P9B-UtYyY^q@3p?a1MN;NVA#FL;kv8~+GmWU!GsVL zVQ#1R@~qc)+{qWPk`yOKpp=KU9^>}>J-2LGS|cdhrcqLD?aB6^hWKXpWTOI@PiuxZ zLs?v*=AhVH-^u;57X!NUcUrvqd3b1q5Kqm29HI`fP2k3?ikNfB)%># zgJB{J#Gl01vn2tT;q2ql^|S5)^8!j&*0axN31$BIOCfqw2idkqweN zbuy##WIA{sT@5TpA>1Hq7bBh2!FD@sT z7+USfu(Wz+@9tnx5&k`ZK3yY%u=yLf_ zmSQ*dJQW^LhfM|-VD)Sg{grC;*+R_t6dAqngu%56M_7)f=RczO=ImN3A9&rrtRiZw zaQ(1p*TwDXT{F^6h`DVu@p8u65J~2-zBO+uOzMWs0_A8CTLacuH1^qXDI#u1MIK>^ zw6-ryfA4R+mX-kCXZf~%&O`W1euzb7kwTaeIPsP+#-7dmmS$|NDV0 z|Ec2o&nm~gh4ITFohzdAe>4x}Y_{IN^ZH_o+N^au`EnJ#$_l&s!11M36(0S^6E1E2 zO>g~{VY{VSfBe=;KeLUDd-quCDOAW#YlXvmHuK*cA!Ane0(zP*^s%t>foQwmO;*y6 zf|DQ1BgV+6CdzIw5+`s=YYC>@lpAVK-DL7l*qGbZ9b zW>lg#whUcS)nL|t53c~eO`a@(*eARgNh*PZ9V*9?1|VXOERtsvP&+($$sphO$O3;J>EMYv9pOXIqHl^wH%)}cT8g*|$h zcCY!1^^^)zj9&6<()%n|pfN|sSfR8vcco&_XViNFwa5$Z_qgX@c!0>j*S{6w>knlW zkPT`7U5O|P6)geDUjgO#I!?t~B-UXJh~! zmS6YU>aE^R6p%iw>8yLj1Zg@(3KfLrhJMt?I5vzASaSEseb43}_phQBxc>Ff(L1uO ze=&pTxUU#1E4L2Pb*CRzI~S>NM6u5*e*o^cUD_{RPomdb>`|UwL_U%_o)kgM-vMXA zj{(;JEANb{%1AWJpV^v<@vwB6J3$E0XTo*h5~M!Gc9wA)V%)6w+UZ4T7{uGP z&Q>(|=(fdgyKoM)pIHh6kXy_wi$|_C99}O7YypQyD;YiRKd?>2^TbvZ|CEVJZCK0= ze$$4CqeZ}-$EsTC-=Z5vlK@~F8s>-*rjf%?sfNVyB}A}&MVFz$w7S>t3E3z2_-IlR z3j>7GWBIo)8lKGY3@)JZ_y?{tn1q`veatf^Am{-7uqlt2?E!#OqoSB$;d#gA!T=zn zYCpje{mNgYB;sfNDX*TlL~4D*&YcMbvUev1OyCN&QlPAJk-t7__h-Uixk)>hVrx-k z3cO*|okO7w9A}DcYbji9%sP|N)bP%xvQcxe$@f$c`km(Ume1;{{w{^#-8XFE$_XSp=>&Xo=rnY%5YNZ}#v#$)X!(s?@UiSg;%ddCzDJaNa`G0abO(jVP2_YphF`a!bhrCb6`V9pB@Zmr-^NL|r70{ER=1NDBZOdx^3|K{j zTcFpRnvfia!P;I)UheUttgvgh)n)Oe6MH6A2$=MSH4U)3#f*iNkl29f4>JaMa>Scs21U+J@YQu8(gCny|guL{kEO|98 ztI`T&G7>N%pKh?qE(f<3x7A>F)JAtT@ZB`QO*gC?B{7+t)RF`nrj%03sA zd{^oOt)q!og<@S=I@DmiPNf}!(n=B*tzh$`(2eT_ z+Y5J6BH5;9e>iDH5QZM4$IA`jXTINAE*lv?Z*lbi4CubkEjKC+Ege1j4DfjzMmUC1 zj%6M;BV;~eB(+Y83^@vvsIo_m25oKAl{r0z*fC(g(*pdrIX%6hc+$Bdh( zBN3CPeCXm^nuxZP75_as`v+uy6Bgamh z`krJfpE-BY>X&}x;>xufw=_Dd{Ek+)9=&w>^cyf}$gq*W?S_Kc513`MJNgNCy4)VG zuU{B!vR%5rL3a>{Br-*dnw)m0o}@FFEH;PB;|qi$ajLoUmdfM`9o^go=^Gdt8RsF) z)XY3LQI=NLHV{}|;=v{42~nk&Ayb2bmIMO}2cLTX2P_DPNXRItXlZoe1q@8AvB{4E zz{SItoMt{!2&59`OGHdUN+wNue&jNO%albyDO(N|wOo1f6)04sSc%fKl%=g)um|D7 zBBEmA5|UEVGJtfn$jK`xDk-a|s;O&errWpt^=TKVzaRr3-2&{_H!w6Z21B6fnSvvb zC^QBe$O4`~B#|kB9WymEx3ILbHeu3~X)_(A@1i;LNK_ElFjyR(KqQeVR9eCAXHbZr znXJM*h)hZc~KEn2c{#i}(B3MyKG&d@P1 zyNZR~H5^<#d;-F*5D^n_*>dMCMalNnE zw!_D7*PeX|uBQ(a73}9;5fU$yx4q+Ce={xNnU?iTi+QHEoBL`MNn{F@MrSZtif3B8 zGp+30tL8!~ZR}&80LEAlw*6yfJ96Mu;te3EA{t1FaJt+cFBXR<5J_Z;7FC-@XE0f8 z4wuKLWK)FL6i~L($XIx5_sm?2ZTAMkW&2{cSlQS)IJvlacx~HZO1AcPtw^?~3kV7c zi-P^ zxpFkHb(a#lPx}=Dg~1U>6dHrY;R!?%nPOsUX3+I#x3V^2(v<1)I+!(Q9*II@Jl1-} zzFVe{tT|@?asUXyTpk~2?tfx(g;J%V1`uIFna_n(+F0AQsrx^L8tc3EtWNdM|G?&>evX!VK?mCA$Ac!m3(hGLq%j(VS{kYqR4MF zOMAb;4GnX>^SAVos=FrcWJH^>f?{EI=K;#CDHB8(6!UqQmxX0@Z&Tz!Cxz~Be9!`{?+hjazd>7@CV|zYNK_R< z);0+3<^Z214{7I6EqG5VZGy9q`LuLfqDzBSm0m#j!zQb1V_)ad~lPt*sZQz zVow|{v-(u#h?6rl#kEYSWkm-2j#D4LZDpUmCNa&_XSaU}=VYVFUDJ(6;r z4aU`R2R^h#-l;#*5%e&JdwN1kCzcr7&5vIfet&(h{&5+8`uv!z^j-5A4NALL&*1^> z@8jNl`D0u>c?xgkr)2u%q{FK`hu{0~nF3?=a^vI4>IXDN7J!lAVPN5~aY*n8h(Hd8 z0b)7V6Gysbu*@BJ)3|4Wm{4ezTfiwSV3-+2z1}zuRbaV5O#LbXvO@7>iwRn6mdiTHXUe0Qkd>Q5d~e!<0>cuvIY=NSED~eWRrg`PZYO9Y=V-rL z3}(u-2TKRDRG!Vz9ooIE39e&zp1Xa;`1$_eH$|+V(C_l8YlY4~r#gS6dNNz1o4UEv zpJls#01e<>_Mr!^{@6EoFWHGvE@|JuZrgg2Y*{;gJIr}!KBG^oIMhdp=^W#hnx3q% zcUEHz`sf4odc<(tQZ6b!wV-eHgZ2CFj5&E#hzgBiCFVUds>XS`bupW6b17#V})=5j5dIW*I|CYwt8 z(I(r>NxFJJ``AAuJfJf6zz_p*(mHLkx+v@|dq8>|0V0z++O7i!;cNaTuA{v_@0=HV zP8d`k&0_x`6K*-0VNhqqE~&*cAJ^!L$yK;TGm9mb6;Q!#$nEgddvk@01QxO@$x$#fDL@VB0doElviLNST`lQCQ3;*{C6H5$+v zxn=|h1|h_o`ks=?>|lONmK!4uED{FCU+6^!fNOq15J1Qn7(9d6tO24Gm0_z!r!8tI zGJK$oog^qA6tikeA|{5iVy5U#kuhUr!ZTxp8mVC{(soTJ>BCC9tsJA9cPr#&s`Zu( z1%!;5g9~8_2v8X;d4^VaN=XoCVN?KYaFI6f2Z`&F_`FM|ZC?XpFeI>v&H|@tG z=hxA%c^!rvfiu71@YlJLYJIN9&$wm42h-0(&lk(VL}g&%1i7jgjn1sk+Q~V1!Avn0 zPLLG6-p|X9S^DE ztZ~ByMh-Vztecxr7+v$nF9{(40zd+5{`dt_0I&cO0)T+jl7X?g)sim76A;2yNRTa) zNRdP_AOS(*MUcpegs=rF{`Dh&m3+Z%0%`F!akYe7V7LWUvIpQTJmM|9iMI)4_MDB8 z#MRk#xs<>#A-!J%k+s*1l8U}Ct3jh4h}u1}XoIID+CmU5dZ#~r5t0c3f*^uO2?7L> z5=9d&m<`i=!9PU-mAr3#U*I|CC`OsF{|Eb10Qi@Wjaq5@IklvfWKOtVe;dN-=qK*`A z_2qP|!NAuZ7zevM%r2e7B@Yc9{q%Q?WNsSBW#)LJZ6xmN8&&Ouj+5|iIY?~DzFTY{3x zLP6uUwt*x>YthRnCBMt`DZ1T7_m2486YIGhFrJ#X@1(=Djizvtvq|z%b>p?%U|4F!0kLApgWk1-bdZydp)*0vc4|ZjW?KG=;B86REGG94O-TYKim`B- zZKq}cA)ECqYyVnp?DCNATMuIq`)zM;Bc!5>MJ&7Lees%Hu2c)Br=Jx?m^=g8cPTE$ zy^^S;Z$waRx2)WK)|K?u)JUnBX zq2FBmHNz|pGAal#N{16{U!RD99^MQGb(q-}vDTz-oI}U1L)v zECBASpBx#to1iJ5Jd>(0aF^fXktV4=M3XsweI2ju8|f`6NjSDOmWr?#BSt&~iVqs! z{0KCF_Fw2Q`Ao32>P_2mxpmE%=@(jK8W@v1{X~(`fqz);ZX0zp{$T z(&tIy3g@6PW}~RnxxH@%2?eH6i?6=iAPcRQxYH7yD9j5vlfdyRJ(cES${H6>P`#$s zcgEWH|ICJlpQz<|YBN54ZKF$!QwsT|6h)K}0t(A|>>CUSHH=d_h$Ahum$(T?6t)K|GK}OS^z-JzK6Nv|GGG1#{C6wK)i?qV6};G$bZiDSkAp+MqrdG4hG# zf&k9uCHl{3<88SbZuZuz=JFvV*d0y80Zlj3{%z6ZQ%LHD0NPd04FZ%jMCmg2RbUkp zeAc0qh>3VXg3{HkoeM;x<{rD51{$7V(fBYj$$BRW>6L5HCAowgR#Q;>{1ikHopIb(qL|E@$FF1Mm-qQLvKean zd1FKECi%BVQ5kQ5a5xM0y$b6fvSsT0NYxPob0I)WkTeR7t=&T>xNV_$1f(}Cg zW?D!Nu)2EN(%2qxjtXj`gr^~J=d^Lj?`#&xlof;7R;1QXT7Im=Is4pvCial7(Y;cw z5B9CObKjU5@QVQ}!EhP>&fxc+=!x3DjR8(S6-@pLrQiH9I{Rwh3zKP7Nawr9A8ehp z3FYLzs~o!-#=b4$ipfazzBB37)kh~t%_{B)T`8g(p0^K*FM~e8FMn?NGk!1rMts~z z+AwQAX?w^fe*NRE>o~S)!vz1uwJ*-+*9+Lj%8MGY!HKn^qYa|Ln>-yiWEphRY7CNd zE4t!GRKP&`XcN2Kzm z;jOICimqlp?V)0)6AqJ%SS18CHJia2GwsFAKCoktmo-w;6u( zg{pGUD(m0zvvOP#$1<(shC7Mi#~ByBieh&?*=ahLk#COz+iVlM7lIjwOc7oC!a;If z`yT1Y9_75~vrw>aD)=xSu!@5&#}(>w+4a*V^$`j8Wwk_|gRA>`>hTp=>Bzapn^!H# zf}~MA5{q2>1TvuH`$TP&D@G$}(9h`4(Guk;9vfk?V?QXIJLrHT89=BR&3^<4b4@PC z+ePo(vb6X}4WKs$4w9c|6DI{Z|i z(a)}y@(h(L0C@^v#v)CCj8F#)l|9qd(^K-%@=?;crThN=1blCr@s^1up8`p6v!?X= z0M>7z!;PtwJ5I+mI-WGlNm7C{o19)Zt8{E-j{UrJTn=j>DwvhTLYr4tR|hcug#y46wW2~lXHyLlkH7QT$H5!seRp$T%-B2Q&VB$mVKdDDU=x@SYBp+9#C2m=I$48 zGFfsJa#Xw*X1elXM88?cN+06{AKJjkJqTIgkeI# zETCwqvW)&_hSyrstLW`_=k`NY1HA41p6xK^D5^PHk(A2)MBMbFHJUn_mVkM$rvrc+ z^&W%kc_X>SMb7ircj3ad48 zD@2Xi_dxT~7)m_AoJ+@aL;U$`pw0Ibr2Zsg5S6w6_4pnR@Gcu={OtHM1ATWO`_!Q} zAgZXqT^;2x?WMW3K>hzAzP3!1bU&K1vxq~J3f-=z3^u@@H;esV1cs;6Bw340VXo<$Zl=W9WPvb| z?T2X7&!(RoDpD8Vrt`v+m2d#4ZZ!3%l|xV7n>=pZS4D(pIhfA?3|GeW>MjjGpnf-v z4z#6epHS++6bFEIY!H)y8T2#aS{LK+JoH@mG@4?PoK=ff4Ignv2U?4|XL^1YZEU*k?7-bY&{Aq6) z!z}q0Z$St`5QI*DUO@<4gh3QeTnZ@ph<~okWtN2zxOwvJV3z@!FgS`W(|yu0mEyY} z$3WFYrEL7-oY?kdnC;*Q==ygGSt*qneQ5D-F3u9Y;b zmx>n!a3s8{O89(Iwla`ZGcI8%Ql9g>*)T!M7HmYGJqSD|>qQRJ_wQ$Y!!fU4ZGP(X zsZan5nhgSxcw^*aU;F4thYF3M2^1O;Vv=ZXN`{+TZ7=tHT-+HrX=A>j?*p=PU(KhC zRg4o_h`YgGY^=d|>T_-w1Dy4TQD9V^ZX+kcB$L#CR0|Tx(+x2up$eyBifB2*=UM$^ zJp|$GHK&*Ou&=(EBC$v*%}POk0g&(sAP%NjRNH5P@>V`{PxnrV1BbfaYE-FvcYTXV z^pZ9fq?mA7A}5?Re1uSH#d;8Z)hH`ghRV*`v%f9#fIEvrISu*|0eAv&T2`auqflVJ z#R5&GAm?oHm6zQUsvxEV1u1L5plz{GQupXPw?EKhMST<}y!m2qqly+m3msz4vNo7d zV@fzI$xd53n!5U2q-k=@{H=y6u!E!{eGr9=jffJaAdesn7+_hZZnV@j%xnqUdhD<^ z;2i77NxM2qCEB;s5HlbR`=jmYJDX$+H?1wM?b+Z9DA)8im5P<8|09D;;6XtEHHk`V1{%p39HcKLDT zHpjJO2hhBLM#yo1Bx26+ME1`0(Y^Wq_2*9{*?LT`Pqo8!Wl?{ z#Cdh=exOzSPm3RR-O?+g2lL;SCxh!h6SZ(-7vi@JfV2dcsbsGm@K>O+MbB!T0EE@m z0ZaQ3j0GAv02*E%n^2YMJn09>JoEkS zll*j*4w(dV&RKtiZmX&V>IUq09`dq5ksvaz_EMvotUxO*CccJ2z5iWO(b8DX!u(b; z0+P6vo*g7?3S|f`>C2mJ>s!{xU`znFrE;SZt;yRv`~;dxXmIjZ{zo_sZ)8dP(T|^;@>7`;iw#0L`R$Y#BoetHiG8 zZp+uzDE#o5P4ncSzw2g+x>F6*57Z9?kPA>YqFRfDaDYsUx0Fg=i9*PmLV}yx!t<$g z>RQ3KV)^k~d`H?)+Q@5zb@)(s=gm4gI>DE1onX^G!9LMA(Z0Z|z~23|!*?l2+DOf5 ztDfy9!}O$Z6ZlVjC=3 ztN%w5nb=+p&yyiO%m;(u4MB*PIl*4x+;7{LaEyz zQcbfsN1!De~~h?rx`jkT{K^2DIZvs1C7t zTnIewi6+Cx&E0Q3{41{VX=fep&)X{~vgRT2^FSa00mYjY8y~kPhoIupykERqIjgaI!YMuSV>zaOf;I^x0KrshAJ`yq^i5cUaz5QZ_7FqBw^ zyl6WxA4I-f!*}|JBbgahP!aE32R`&*8o$@CyDO3uNhIP31OpBut$)0A%X;?w*tvP~ zv5IC?;iEbF4{7>{7}`zDGZ4hf(adLB>-Orre2zpw>NB77l4hTUfr zM#_KEGlu|r6~TA_S$b`C3c!T}1w1ZMP)}gl{2Qwjgg>){ctJx)&E-p>M1wG{i9-iYw48fdP71#gG%-?>e23p`Gt_x&dzf@5wRySMe31 zhLM@ToIPY{glG^1<5Eq~^U{D$^V|eDE^K`+WNSM>IJVi-)*pMQ?@vDJTJ;XC=?F=p zHMUkn*_RG}3p>eLegF^Q96-?D#^(a?IBB4VD6rVBkJmJw74DC@z(6=*2oSwbpk@QN zw7&JFjKmi!pxC}w^xIcPfOfB-9snS-fIy&L#_T>^Kf3v|gSS8RyiJ(F7<{KV-U$!G zU((_s;DpAJdbAXX3`n?nh1mq6g}Q*lW5Uz?e6I@i0g@s6el4gfM{s6C^a) z?F9BS3DAQsC;&wz0DwO)H)+M{MK7iJOhbv&3_=yn2hDFNKZw95_jZ76@L!P^rG{fj zJW-ev{MfOjYMiMW+y`ssN9X$VR^SC82$4^`5hMW$NCqOw)zwig+1|eqSqTJoB`E5> zFCdoYbKG5NfP`z3N#}~F0c^q50kC(0yabRDfKmW-ddc)9B8NF5r6ZbA8C^-mwiYmQ zlapQVXWH9uT|Y{^bs+~|ZDI^bJ8Ta6Mw_DC4f*5o8Dx?3)brRFcqowi*;yV9>ACQ8 zlh|xuZcmkz?hqC>5f+}mpVQ|#bl76mdYO;AG@G1!)HAK!JC6c#SVwC<`t&|G>ftLj z8_-1IK&LdDF6Qh;OMfEnlVDr6GCCY)nx?#_oSXTH5R;_qXRM*ATQ)h*JJP^es#>L{ z(y{M*Nm1$=ZWElT?v^wKgDdEdVOm)c>BJQYR}|?)@SrgM2Jzx&vmvUoz6Gknx(eW` zM$a{mf-NNZHEKqSv!lt2t=fwGgl;E0+#_6g72}BOS!^mES7?)eaXg8x6-5tN&Kk## zl*A>^uN4OeI9a5)J%DCRzC&4$awFY)Y*GsM;S?HSj$qGI39w*#NXsz>qdSXFeqXbG z*v|O1oG9?P&eYY8MaHU!)&gj-&$y&>$p5)lj{+h(?;%OKz@+p*=G4>j<>bqV0)x$J z+VAuxz!Fz6BUP(HkSqP-sxO!d)*8~HQ?RdEY^HNaO+BEh6qo%T~?`WRPLoM)W$EA#ts z>m!T$xaM##*jMb~|^}z9XH?Si0VE)m>V}2RV=fx7ScWh|$NpqCZ~-OCZ8a z!=f8UWA;lSeWFhE&}tdT)j>4up(7Ab_Jv|^0jg!I4i23IfWEG}PksFT0Aj}DP>63? z7L+hf3~p&jP&G^hWnoA$(xs@BR2MczKevX5bRyJrFtHa?(UHoHcHKLD;4wd|k>1_* zixC-PU?OBNC&?ihQR9MFI-o2f!b39b_`JhsK>?d~ZIL4#1M_Tt@bzK4J}40?B2k1t z8l0kI4@j6m=0?2P$eP|d&MrR_un+zKt1oi^~%b(J{ z?|~sixfoSt3ebxz!U1R37Bo95B^Oyt)S5AxLrz0gyQCynJJ&i1wJTTVYsl7x*wCu6 z>%yzhE9Gc?!mJc{rJ9aj)V{hlI66Ekqslq2j1MK82?7-vm9{9`QolyyhrU(t9M~|< znUQ5e76+p+*8wBpXFlIE*~LhFjES!q|0umAAtlLnSjRNWcH9mgL%+I7fHIMM{hG!F zbh)%5r}0eRmn~-FH#>-B7=IFGu76%fEDIcgJ|n&kFarx_f2AOCYdWo7yxRTZ$<4U953+5C-z zd>mzY_Kj>mr8&1wwdI1EvGleoC-uJ6p0h0IaPZ?5>6A>NYp<0Z_c_H*7&<1d$!kAp zYlUqia_$wS=$1a<8=i_hv& zDXha}1L%9dbyf&NQQ>>=8vWS3M-6qzj~n9_F&NNhj(wk4c2C z5`=8Ik$(r1MH$Bl>~t;7(K1h8cJ7xBc^GsqS49))jMmI=ROWISn(poarlZOE6#Cl; zAK;7njwtjlhw8DEUi9PK3Ni!7f)!D1_Cy#~f}gu_{u*H{@f)H=F<8N1k#dM#Y+@{? z5Rp`>Xl!6E2AT(KIqY+OWP&*sqO&0-U5@K;L|rIvDrXW+xo8Y!-E4^6|iAC!06%tM8MgsN@kvA$OjQF z@6iR1#}J+zGT1qz{o5D9&VPn%&4l?3^G;w!=NF~gmS~~_vB5RE$I;IXt(azqZJ9z_ zQ7WrkZURM!CNa#_3H>JUzUMg~hx@^9yy{V3=7h*i@l(MA6fg=Y7MIhAJ(++=^04b>){{Z@deMI_*R zME$@Z?$H&IU8;K=0EapVk3JU>3>Aqb4HlmVkSP-y2OEtGlpGKp%+gRz!FwZV^U63y z1|U3l`N0jy>JWO3v0ra6jo_~Y)IzT(Sf^+a*~ST5%yze8gi=3G1R`0OQWJWsNdkK* zKC>YAMAmA`#>4|x;43rMjHJ&fxP5Hjz0|n4LHGw+>(E4|V$OpQ<~+*8`SgVGMlZyd zOsQW{;M={gIFAx3SUIi&rI0X6@Sr;KT~JOpNs7hke~GKncgoSjKdgX6Ig4DKO!k3j>rGcfh z^GHY$x+YQgGDi}NPvFG1p&rIbF*=oL)gUOsN!Zto3_}Va( z0Zw==dL7KMPr|)~Y~hxKlq|_|8P+(-ay9UnyQXU^qUly?i@Mv#$>}%|!KRglZZSG% zw*5g?#59y?u}5@^5`Gh+z(Di0zj{!G{aiX-!5;3camLpbAO>y5Ua8mj&gyl+EesdD zcbPH_!c3O}$(w%Y^0WpPQFmNc0v*2P)=cxXnzgojLDGI+yWa0Hp`ED@5i`}z;%3w$ zd1oA)TV!l(s9N0FC^CNt&F0=_kPO2obDkzJ>}=M5b6)r+Q)iaZ13@DzN{J->noqqo zbg-C7cCn)@R=ANMjCtW26NtdxHdtza zCd55^Cdihr!=n&Z?MES_ETIy`KdQqLSpxMFwU)SXAyUwl26TtOQFq740=w_0ePHVz zFrq;tq(Ec0h7IkyXGNcji`LW|7_vFH0o4)WXQ3vKls($T&LM>;@aYgV_H&{XD6?RmPkfZsubelpVb9>Xr!EG9lmC$!m)_ZC8w()M$|K z!oiXJ#b1MAh|lnY)9sUO=iPKjmslS-Eo-8I@M>7l3)ELa7w_zu+x2dC12Gn?5(Gb&;8FM?Eml#+4Emiv6KS zk}8gfTbFXn1XrwtjX93iQ)S=)&FVBVX0xX$$X=cd(H2jt-$+vQ;;Ys!Q=A^2ZOYt( z1dnw43KeVVwv0@1>2X2_d>(ZZEluDm&?Y}g#~tZou8e!ljq3wFtI^PG3KlZZ6r4Fi z>9R<0=7QKp9@7m3N}%KhD!P=bP8go~yPPSp&Pm_fc08gaPXw2kN39crAuBzC!8!Ta zXO7aLcdL&r{AV6$p9o7vg&9CynMcKoEe74llh7w(BLKg!<>5`^_R4y`Oz8RM>^pg# z?c|@i<6BC3E6=Q&C~P8CReJ(Y%}3uk_w3rM&b~WW@7q+!t`U_~J8y}0-2>Lt;a0uU zAO^v`O$6}x!k5^N{XD~F;H31;$DJfLIoRIS(K|wKATiT+l23QgF$M3KMf{J7AY&~f zfP76cI;S)H3sEaN1N{9(J=|7axM(aAS0O}b!lQ-@l`6`#^WVH5cqfM6l(zU_Thei5 zcYfh`Bd3HTvS!{8wZY+p=5h*yzm`q15E$&hoFuB`4F1-b3?ri5K!+IGbs(lMbb92L zXF}U*%x22giB6#!*c?4lSs~(9wW;s6cbytBKu>4C7t&b_wZ@1x_~3CbYuPt@;OwU1 zfPF|E_FNu%u?VPq`&DVW7EJ{LgL)LEq{qT9a_)7#nAw%?;JIqzy5(g*Us z)g`fmO;2FM>xQp!suP6%sZm|Oxzc9f<+J9H#TGW&(ulZ@H43pk|3UD3En=9Y!^RJh zwCiyb74wPeSJ6OUbBb}yM5MZ|PaaP+$4LZr@12_;D+cu^?Z%saGE~HJa>x;QtQBLp z7Jm2xTOKUSTZu`70l~Kxoa@&}fgT#kPv4wcf{BmBS9|O) z=0ZE9mHa#jZ)?sr8P=yWQu>RW{AQ09Nv7)Z3(Vf16vU1rWo=3v&$&)-01z1G22mv4 zhFNV*YH4a(W*dcGZbU#Zky{Ra;Cv;C%nfC3iiWe#2~TnJXZz^5ES2D@uuLz?a$D!)?s3?15Tbka?h3n zERAzA&~siy$-w3#oiTrD=s$Lz8G*sBpVOjdVhvzi6WDvfoxu@CTh@^h3@zFj>@;0l zCDa>zSoh0AIb93V7|%24Ua(eF90P186nQ{b^e$Zx@)!Inp7wlX(}TSX@#TJ(nE`;U zfluhxMBR8&8NC53&^-VyS5&{gpKyB>$ZG|cbY2&1rJ*8jWNphm^i@Ez?{a>IqYcr; za$SFHjT2dg2^aKi!ikXQ6m?23{6TG~*(9T2dao)|!17d|7U((%B;jSX9%vz9dW9&T#1%ua_)gms3xg^L3SKdh#KLZw7$L5?2cPgExRl)-rH`o^GbEds* zQ{w18BzJP}ku9h2L9BaOeu{DRWCJU+-wol|TZ^{9l%b)&@oU=kPO*Da)62OM5w+&b z=4Hm6x9~uYUJ_bk^HK`XehR#2Hh8x!p|&@YTzKF%vglw28lOQpI)TmZgMj;fOL&|? zJe5y)Na8k~%n^{CX_lO8h<%qt?C!)&z~?QFw7L&{C^-dMZhH)yswi^7JPmRFV;ai0 z-0ZV{%8fVFc=T!YcsCuVWD4W8v3T;DB_Hu_rXrBr|5X*7Rpi#TL`O$Bn5 zsQW$P%+|C=_cLhL`0E?_yX&;p(WmqQ7xZ;szl=k?6^+R+p_2({nc)=`xk&gXW#>+^ z48N)%e$a7+H9+FyizkoI@dzo$hjPmbH2_cjolLPy9gb6=V5u!1&-Db@HGHI#-27S| zf^Yy$d{SK=PL`yf4saI+g04P9{F!bOGsSu+CS76~I~b2iGuzfum9OUvav4lstLF1$ z@v-Fcv(6lN#I^&S^5AyDPHG#=iT*sFaj4twsbA66`ZMhwP&rG=lsC(e{2*)fRe((_ zntFEw%ND8D9HWz&E~8E&1A^vlr@*@?prAAL%gjf&dLouF#h@h{lzFr|c*EERr8Ff+ zgNo86BbUmiu1Cqm!Wk;s@2LTY$=qA-@#RF0nS*I2dH^}k0T*3|SGspzHR;!|2VF;J z+jnj^oZH}Z3@ zNWxHXEj*ZUcrLk7X9jg`4xc{z4S4D{~jS$yT^r+B~-BB}(o6@?(ivNH^tY=7}$XAOk z1?Zr}p)#Tr?}$o-p1hu${QMz2IyBt0NS*>6qDFDf+Ndkryng9zeSrFF-H177d5KLV z6Es%oE$9l1E}#LoU!l^uSt(`8Cwkx0dOcx=;oRmZtIRmC9 z-gQfil?W_AVX@Z+SCDoS4`U($OK$Qjd;A)O7OG0Haar3a=<}7LlKx!v3|_Mn@@Ob; z2&A#p2gFbjiAx4Ms0Ej4&PYLL3wM4~{JUk%2QKIpARgJ?=d)RCD$*y-%gj)zlBQrL zJgeKZu0YM#ESWseQeTM%YzeWE1IAK-->|NExc<4Iq`kxo)kT!D(F6B0#qQ20%J;4H zSo6}BvzWJP+1BF1Ij(~FdK%ZfW#ZK%()nuXJ1KN^%k{jtzv%44{N`mJJzFq=IU41H zJW;49-)GTQYHhm=%=_GRVr77KB)wZ@(BWE_6sq#o6>;^`S^hc=ddjF}&s}Px;8)A3 z?&*z*-Em>pGigoM%lFnHoCY}EWS%IEgQ>DjYx60pz1AKD5S6Cn@qDs^HYkePD`J;y z<*)hDf;#mBF3K7!uapaX5%%6~+`OIxSTOFjQr=ATcWZe#P%ir&Fb2GSa6*ePfFKhB zj#5$~k`@xG&QXP&gklJQ{F@ZS0UnzM;)+TZ33BERP7WD$li@(M#oFO-Sp+5oz_lPq z^*y6s-?mc+L^2Wm#SCc}X&|*IWR`HoU*_s;Rchl@3uT>Bh5LfZ=Y}G(u=H!CVbo=9 z^`M1{x)ujjE)vJEz+4wZi@ddU^HnVzb1SzNF}WiYKjCySPbjexBF$3RlsV7Sc2fGX zlnBf^f657gyV4Ol8Q$^<;%60B*VsSk=a)rRoT#O2kkMC6)8k89xdb5&Rp-{9F4XL% z^@B^%pL!p<2u}5vt7J;^i4V`+*E>iZB_T;5OHd1Aieff}I-gr^?F`X*3qhk6pQ%L) zztIW7f};=sHplJ|tsBxBEpumG_SEaXyS71}XH+FV*c8IyjAV`E$>PbP*F2otsA@XY z>xOCxcg(d(sPI+dv%`~Fy{#^go*jKY-Z-D8CS(2${Y(( zX}ISfj>Vo?HP*VQ9*T9@fUfFD^j+Ng)XxOiEy-ZpAzMEdVrIIbAVt#BzD%A=)}Amk zQR^P(#)ysTbDkAJVNBjxZ@1lv0S@JjbxEebh&J)+IQKZ8w|;fe&g;IX-DfAHj)Ph& zx-Blm`?bz`Mx?MqZ(_8w)FIh&@lZ_9-xef0kr|Mgka_>kd!<#poq02G^|+vPBv8i#q-&Oz;lP*_{ad0uNLX$WKjN1_b97+pf?tmg)?3~ZAw~1 zcwO{Vf_E#mjl{cw}9%o#~>M z>$cxH@MRR}T|*Le4eB&8X!zZSFoobxFj0D2@J;YruprF@y8xFB@jBVHutZ=lVu7=a zTm$VR{^AuQSHG4n-0d=-Y+c>CxL=V_RtuYGmtR-8xj1DrU>0m%eHGT4*KA|h9*bO` zKX0~j)^6SnV4tJ2+ZuLd@xLI*hbFV$+(&TIVohHk_`XPsVvN`rMg* zob*K2T0g8B(zre>?$hjW)~8En=eRsMoTQ>!PiLv`MUdCkC(oRzRGUuQ&Y?{WE!FtY zUG3}eq`I!rWl~#dKWJ~=H%&)7U$?h)Eot$(wzycGY7d8a(#lAw$+1ca*FOl6j3J+Jwq75-q`B@6}z zgKX!bgn+E6=$Wf)=(0ISlyjI1`GH#~C?f;Sc!B|Vx@_F|=TEXQQ9~txc}0?AN5mIF z)H7B~mLDPR_wn*0>hh2%Og*KwyNi$2!nUdQTS$mPh_~4U-;wd}t%C;LV~})aLbVVn zktUrs^>@(l78$UE8RK|aW7+b3j@RY9`xM`TuW?2-Ob4H$5}EZr1>B8W@0W(A=H@F)2sxF9fX zBrT9hm6MFKOd(6^fKp7+o5y^fk{LIZ@-8mQV6mDjheej|fXiNOw|6=??^}qh`OyO?91@LyfD}E3t3iS;^E{_1Y{sBr4VOBC z4k2n7u1uyzp<)?5zSD3s8;^{D0TfIeS5uGnllA2)R)T{mlR`NoysXVcH3%TP&$y0L z8&8iwCJ0%&kf}|mOwp>b-CeJCbjt4v=Pt*AEmG5DGMqIF5n^EOJ2HT#n>bX!#OCOdf_@BEnQX z23ir$5X)irNwY!sCg6%kd-gYxeM8JVd`TAHd#K(4?sL&sL0 zZUG9Ue+EFYXt|Jf@-cMob`_aKl$j<}Yg_W2Q(QW94qcQce*6%sNUCbC*w?>rRY@ar zso!$L`sO@K74OJprvWx|TincZ70>-Lyd;yi0zgQ1eb#F?6NDSd6G{ZlNC}Qk_jt{r z8&qLU-cjYGw?A;=tM0M`V0(Et9#S+=Og5v0)-~sr)ZK2~!-r|X=4tH)y-`L*ZgQR`+m&49@RlReX> zY)@w@myzCj|3%A7+W7=gByF8j`{dxS?)Q}1-{l7#Z=K7hP3X-IO&1BOXXo#8SR2pW zdZVGNOv^%=A||-t>lT(5rOwPNMh4)W+k!Q0qp4rJv9C4g?>Tl})YjLCj@-q)h)mwz zC!g)oK08g=zuQ3#Yol^V3O3!43`ZR^*vI z#IR>ho?0}#i)nNTb#5Dk_ozlf_Z_MZN1@PWb8vV$^2;Ab;-+V$-S~tiXeVt^dvwr*dW~Fmk|j zB|x@LUxe+&L9vB0R4SuS_(3LiUW<}Zz0YI}GvdFGC|w*Shc~gcI&KB>(9CG4(|$30 z1qU4DQCFP0$fuxZ=uU#AWQiZCDqG)4R0D~!aB9&`@lM457*!lOOcXn%Zd6!s@AX4s zT~vo1LdawMHakuC4yCc4WQk7|87*}Ay!PPrCHBeg_gy=q<7@n8{znzzlb&jA!IP4Nb7ZPQu$(cvzX}(K#3ZG)E+k6M! z^H;ii`r=$6;qJxbcgu=@_m18O>;+fFHTII7T{bvYLzCTgUMPG_<_0zkOZkFP4=_14 z`@8(4zqr(;dbpJeq3Lj6*YZZmra1|?=LYjB`%mx3J5s6C0ErR$M% zD6YF2lV+0<5+=Jcub3~Qq%G3WR#@fN_foMiX$N+0K2MC^qdBCfAXTP-+yGoEw9tNn zUs6<7Kte=@7~Yjr`dD(#LP8~9ot1L)#x#$Hd!Job^f`B78(5Xtit^Mvt)?eDDyL1o zd)vfuJL-y&EjMm;I}0NtD|5?f5hArZ@FP?2f1wN|oK!Jg`wx)Kqe(^enY;Bw6HsOt zaBjK{ji8fUzKHw}AKAPE4^D@d0!z@pJ>IO-%R5Sdgg}`|B*)4ub4`R$!!!qY(uqMe zd-s9v8*3HCCleCpMMpm%Sn%qXQ*w3he!*12*5T@p`Eo0XUKS3@E>KIdFb;%Q?V{lh zoU{lOMN1KRI@S+NP1z1<4%ZDJmR1MrNc$|ETqHDt!wC_vZwkAo%sX0VnLP$b({=2Z zTUB>l#dP?}ek;%5$v+{S@Z7H^9$GlA;+^Ck_6}K13Ul*o*vpS{H}OH#A(LFsPj<9R zGuq`m%Z{C4CPpDMNBbr^iP1b2Q&ZYf5I#nV5TJ-8YJE1%`B6ewx8fLkdA$;pJOH^( zN&B4mh4Spny0{wO?H-S%5|`Y>2cWy5n;U=0&`+MJyXmb4`9$I4sH8(u4n!>-a&a+dkV3L+4CfT zf@C)ztwjV9A}SahmWeY?@F|v{XUi7v;A(5NboL0GJ3PLQ*U-e=8C;yi zfd~*Vum?d39@hWq29>-WG9Yub4;e&MCqngyIo*$HTRwy^+)bzyMaAM!rfP9)c^v*F zh`$VZ77xqYj;S_9qq^bZ`ibj+%^>>m(at1w0_J4Sjn?7cfA{aagCy7OHc?_voqSX&-=oc|_ zZVD$)ox!;YSTH9WSwD=H$QFfZg$H}M)hrKwHvvas4$1)JpOPfy08}9XRb>Hop}uYN z*C98&mtyJvvSP|f>s3Y^WJFFt9|8qToIt@G2JT1h{QpIm@+2t|M}O(?{1L1`$!uEZ z#Z)^Mll(4ru@ST3cv1@^vO=E*P;_LMOI?oOZ&G^c-UpN8x#|AyuVCNyIO&SzJ8JmQ zG(%UblCxvT*sN6bgZN9jBhdLI)ETyE8U%4fYOsF#AVc;<^}Z;$3%>t)&irPg$<{G& zrs)f>LwQNmKp!RCq9mEMAZYRereGg>NH)o{DT#Wwxx@Nr-vR_gcoY&gvtYuQu@dc7 zhlQzS3g-jb@V;d(q8TL!8C2KKj752vVM2Xw3IyqgnX7;u| zOIw?#lfh@~yEbm8=Hg1ZpA+TAp4b2+#6N>M5DmTujf50Ah*Tz1EnmKfb@jHT9~v>= z5;U=JI_0dMftVwsApGgz#5`j|j^12xdHt!q2KZgIeA@{7UXSC3(|VhBTa>{3p}D8{ zFge^SQ8ih3Z`dJct;5m&^X~WAw>wxR7Z2$-+hzTqZ9MONGOf>|i2oLAV(-r$k<^zD z$xpwp<=T&l68xUaKS|IuMM1)ajA}W&_ID)yE$a%ny}Uuu0CsJsvCGT1Ka;VZzUI8p z>l0Mw`?@&Ke2D){G+OA7%_tG7MCv4}CNb{zf#G_&pntZN{xuK)fXbDsX8u!8>t1^< z2aEkW3se1LG=V?$Wnid%_}^guB|s9-${iq#QGg-$H*@I25-LmoOl8W{(G$oQcq)n| z%l0V@S>)8-eQ>yr)PH@mF5Zy4(o~(V`&+E`AxfZN1r8vWvLGulJN`MAVdXciU%!e& z7fb(782zV6Jf=`8MlYI#gj zHq(H^nxbV^1Glgi2IX?DR(=e%N*n7dT%2re?WTV^?BMvE7C9i*SG}G{odZfE?%t$6 zEnU#e=lnYs@2MCuiI9Kki*3FR?x{((FW9)Bt3 ze~7!bu^#NdvG5`kuTGTwH|#1Fu%n)wLXeG>NijvUJ(OY1vF2C}%$M_3u*p(faJlN7 z_x?lLdO1G8Au!l~`W&%pqOM!|B2r$Op&Q7#OobsRFvs`-L}y(TJ#gkQga2x`n`5JL zNHoUPHJ6l*zjwJ`{#V6hEJC)*> zsWSc}-^v#)UXaz6*_yi&zrmb$PY?g~m<9vGw9?Md(sUboTmaPne=PR$b?zhWe#=y( z{K%GqqtxaGlqc~=ub@gTIb9jlkd-ji?!Nv_tG@zhG3ozKErf`_0CriPe*jmCM2X7B zfOQ@EcW~?v+GhXXx{|Hy3#?$wx^6w?*}KL!2YYsF;z2CKFD}ga*~xQel0Gn0+@~(~ z-h*%V^WmVU0RJ%|XE*!HnErNbrzD3csp|UlUgW*|;~sX$RJbRz?mOqKkAL_55!{1+ z$b{TPXtD56wcFfoLnIqs4lh>GNx(r1dW$9UT74-A&}Q2x9W$W@I=hZOND-ig)T!I@ z5X#j6EeG|Ao>vDi6^blboL+Z*CDYsnJF3F)&ks=d(N9@$2A?A^2OLFUWlfyg%UlkSecF8}?!1DrHi_VeOB zU6R!ifHhYDf&?nMZ~r!a%HM+V^gpwgc(KF zFl70@99t?@B3iy{4+3GQF}kp^GY?Zpy6*Az^#3yy2VUU4qzFR)&_7ye>?N#BWFPNe z*nWZJAVncP&iI!mDx~3!{`T6&CtNtBtza9w1`&hRbTdd&X~ANhw*EF9kWjQdJx<;c zh9ChnQrvclJB|(*4v!7aZ+5GveC+;c3|gqgE#1cxt``XC-!G&AFCHTJk2Lr3P=pan zTr+IKMg4lq@ui<~v3Vq-IFny4NWgWK#7ldSpC)$o5}H64ZJX#J5G2CSz|w9Zl2%as ziEhUqcPo)ksouBzCdQ{YWsw0{B5K3y{r(4nB#4wsS^gFO{)7&@vt)(YH)zn{{|H%O3vcl^ht?#bSJ6|6H7Bkf1JvUG2q6E%P zQvMC8%7VrFjQF|g2sw`;$%!!Y$Mv8Zr~m*MfB+=Dcs!4zMn8CdPevBV00Q(v0LT;Q zml0Lu3CJ6^MXJG*@)YN7S9BqhKDky?7r)5@bOA&D>z6H1F=_R%Lnnb$eZJ+}2AH|+r&cv8oa4^U33ys46kglG0}3uB#C4)lL~0r}(0$bWtD5F-nmGj3M5*?GmK_-zmF3Yjp_jHjov9R9>peo=^xtlPLlB$hk}ny%Gq99?w)dX(VhL%2Jhw;D&P}dfKMp< z=S~*p)&`R8xnQnSA<2?jX|Qs6kKKA0(k0wV6me*xrp3eQae?fWT51XT>Tblp1pzD; zlXZ|^+$cpIBQi;PrDeqbshZ+=faOOH8j?B=dz>z$^1 zxBVmcj1fe~U3RJSv&mSn{lFAT+12*y@(m)2cwoJ=HT?DC862_bBxNTp3wI;%*@cQs z5Tt)|KWyF~QHQY{&Co!sy_Nf6@zus1Qh6}p!Gi}69z1yP;6Wyn$z(E_OeT{(ok2l= z?Z<~Pv+7)NcW%xxFm13$6q%@K0F1#r47`ECU@#aA27|eqDaiC*N7W7Y?)MZ$CMp^L z19MLR000000001ZE0`8*J`VTxy&5l;&Qv#)=&Gs$003Z~DuRNaCO-P*JX%FMgDGFZg3gTBH z5!?{ikRd~c3>h+Hs5KP$vIMIMPLqjQB}tX)#JV2_-9ibiz%mn&RiX41=k5y0soYBK zFsV9M_2Cgdj+5j6NjXv?RWLF!t0bvX&DyBXlemPWMoqS9cC(b03vbvo!@1q2r5l+^ z9xKBq(~Rn^9_aK@q|a5vl?~OYGTKLBo;kH$t5(cx#}wLI+DU`Aw}0L}w|hL=Fh;~f zL_|bHL_|bfB*q-yPdFVNt=!<5rE_qe_r?rtii3lLgM)*EgNrz#6`Xl&+pxvnQ=lbZ zaL(!F({iNm5>nGiTIccSTKEtSe}Ov?BiVC1e?lY88m3x%OTC^eN6#Upr8=7~XociL zt|rn#XUKYFQkpB5%&l_XWF6KlTv z>wJ@6!DAlO&fI1;i0qm=D1W?D-%tAlPUZ^GJsjmHM%bvG=p#7Oy zFNq1q2?9DW77-k!Ix0A7W%O)}63tGrAh0>X?g}Rj7mn(p`snyM1aQ>JY(WxsOoY^@ z4W}wdQxf1?(zB7y$Y?IL3R>wPjfxb}r?!M?Aa0KcM4@i)28o0%#CM>KL1L-1==N!k zyIs{|F+&Fs^t9CAMK zWdD%{u4moO8oUD9Vv4Z?Mi5d>8SJSc@e7l;L`?%mBUW=wvu0lfGK?kupt{U?lQEm2 zONfqPsl&C3ke0n0>tkh8CpGAd$i7qzZ7U~)-+FK(!dQhU#W2l#aW_7U+YAIrC^+6D zKmcnZ(njeLmG2B{MRXa}Q!zWjqJzygb|sv6Tn1DZ&_}^fBY+{8(H4Ee3Pg~j>$-Vq zP6h?Oijlb*e?*2=)T)iB~X1GF-GVJoeRMHBI z35_OUy&6_RL^vK7 zNtP`*Qh7)~JHRWb%2CZ*jRPz)ARITP;DgUbaVeE64HD3osj3OktfJMO{pFZ%DGARu zmu8pHEZbhTIyO;)OuoAz#kBxVrq!5w^*wl= z0h&jk4Qz-Aj~pTru4s|SJG{U7NSY|)BjVpOfTE6F1JU6hV)_2%WZHFZo|VuwUpT90 z+ALXtmKZ~Igi8@Jy)4+e3)=>^#olb3W_^8MT)<$(yWEq}OU&Lk=e#KI^X zy#`Inir(UnnxlV@aF5zF8y8%a|7snfCV=`9{gf zp-F(+AA)bC8rzfv6TEgE?L@3yh~qLMSChJ(X-sZX6ID2v74@EgxDRiqTDN2lB;RqV zBq7!imTDx39)$!~7NmlMnivL66-}wnXPrWM0!ac+I6^rV7UMMUP%%*3C+oD)^RUcW zg75lS1WIGA36f60zK!MCj_I(g(^TC>&Kd9_JQ;d(}*A zTVT*vIMgJuY(TGo+d4H0C=$Uzws)OOT&>I^#!M7i5%TYwQ(!wH1@exOI40Y!id!98 z0z0-WeNj=$RV?9fkypB4C%GgRtMsbAa6m&UJDZ z4Ie?GsKaAhu!Mb+s;J)UOrLK~((HGw*0d?4L@o$r3yuu%6&j7PQ_?wO4C5kCrquNI zLR>IDqT*w;nl$Z+&KW(Fm<;SF#5UkIW#q|{LY!8moffvO;9?o=D|JyVV&%~5Ax0s= z(QuWnOi(A`&afU;KD~nM||p{ z0~mfZqZwEwW|!0pCKt6r;9eyI{uye?N$aSB+RNKNDNhCggTd&r4BC3M1P7S>-#$#gi-rz*wI?rP? zztc)Ln;%EV^F6-a_OWqZ6FxM_^0Y=T)O)Xb*=t^lj~ToOFZJXj2^|w&Uz1qdJ;F+}=CcNi z7B`Iip?FBsz2Oq9jvOu11%vT^GWIvG_VP)CoKE3td5BqT%qllGavon-@B2dHHj37y zxv=eRHNOt^b~lhSCs<_J zN;x!xzz1_8l!;B(s!Q8l?;u1^FK+&a?{bV{bnP!%>B#=(aR1)SnF@p3t|kb1{|^-S z@4shf!5~Kf9)*!4nxP%d-5YqqKV3%TQ+3G-GOoFFH%d6~$OsJ(t|?B%o!ZjvX!9+T zXen4je2l&k*1nRQ9NJrbpS|IIg)CLJ`6w!uwZkk4%)7BWPURHjTr9%8^3_Pb+1RR; z2W$d&JLtIAD5LcH|Awz9=I7!24DzeFHUrt)6*A~i!DtQM5+6fspzEWs8F71HWbb|_ ziO@u}shATWbeKs?1@4;!gAi!CONj>p5UZnbh%yGi(b#RYozP-D6~g=D)s(nuj&c8GGO$6IDrQTB|_azc7B8I}<00pC;>hl>y-Kr^HHFO&-#OA6Y- z3Y<_WTJZ^9n0qd8Ph%{IQZT{#m+&W6W}xih)JSdZl*`T*4T^Di_0~6>N0-M<501{@)N&mJguk$lsv4)3RjK> zqJ2X~;&dDt>tl9MF|)&S;Z#%>(5uUg&}(stUOJ?_h42b0G@V0*IPbUi7`sdWj@PAmUT-iUL0>9vMn z!6E%D0KY~81q@5;-O}>QdoRQp8;)$pFnmH0;dl^mnZCzGNXJR!_q7r@y4s0Hf{#XN z1 zIs_A}-9c14VkQkGW;8kT=1bXRiI%Xv?|kaw`msn{zB=D-6waA2X7{!UvAwDhVbbld zXb?%^L1qWO;G&um%U4mp#*prd9#!_jC%Jfcq}f~0TO^Bs`o?=wa|~}ToNxBL`{^Qlu9tNu}0#N*Pon3KIhv=DB=Oh|IjvFZIj#<#m@2XIIlpq57QHtAxr%O^# z4Id`r_ya*T9akQz7~ustoB%@Lxl2bhP3nijgf~?SS{Y$jX3>aS@T5EGj3ak1?H%NZ zao;LYZXb;4ze*PKk0;L6wq_DxSjI_Y1R!=@2xYPy~I&g#Wf>7o#|j#^_0s!$l1cQ&4loa=q%)>527RJm9HrMnN10>ZbE z#JIK~5&_KX?YHx;BM;4L&>LYxNDFr`I0lQOM8 zqcVeoCZk8jB|&Jyw3y|UF7lh<`P{*CdvCmD{^TA0~qcBR^0np8&CFZH^R z)6nhmTaz<$CfZfUBeC{umM`(bl~9C|6io$0C?@#S4zY;kt^{=p4OWcksi9Up&Xzc)A0IvQ+$VGxk+(y<6DU#twu<)KW_bJ zpD^nRCt(=gG;e{Bxz2>@BrQA94D8+@XEw;{9Z9<&1N`YTRXE}6c))%RSMztJ{<9xS1dovdSOC7#9QnYai+~y6?8%88IIc= ztt)AMlJNp<;iwJ5m;HLzKl24PlUo<4`|FWG7C2&K{N;wz_R2(0wAgn(g*q1E!64tx zDmy!~Zt}X5@c|*6VB>p|%i36hCN39O^GLZ$j(1tPkww0{*ow$_(tI5Q;e|F$0$bS} zGLzCML^dAfB>3ec$y#{RjS(W@r`9~JnyGVa#s^;)>M~SnAI`uRI;Eoi$xSqV(5rkXM{Ex|u~l~EMnqnbw_04q~#V-$_6r2$HN{zvFHUK#=2+)T#ousl@sPYMJdE2OFAttpa z#NRRdfb>{I4S#qHzH(j}d0`pUNcvNb7;I(XvFaXkfEOql41F}WNU0)5NRAef`%zvz zEFqVL2KCN`YMMc?d}ir03tk9y(Pyc#l(vgVV9lMO$VwG|41|ct=~}?AE4bwD;4kGH z%YuBqe@se6Yl}K)qT)`4(qY2qWp{m74kF4m^U6!9+Yq+&RK+ZoIW1}3ZoTWzC;S>d zxh?&KONt8eXnQ4EU%c-+dLR(b_bbDcgGx4I#Ss zqFfBchX|Ua97;KOd64rf7tacQ(6aowDX^<92`?YhJ!&}7B=r?HD^gIZ?f$>7GKY(r{1yg5JHzxf@b!8lSPTR zLO(&15KZY^6Oe&PI9$a%J#=G>&T24R80Ri&o9@u7~4vS>x;=@+|`UZVyrpW!% z`**Y_u}PmWGHn)=O3rEW9|-)%{mbjbEuDnx#!%Z1v+mZB=JO!9KH`*@<=W(cV`X28 zth>fHT4xdV>=>5%h1c6^(W+{pant^^&9kHKuHGqi86&C#D~@hp94TWMgz& z=aVfF;2IK?9ojFXu&s?Ny?caJl_PX0{xWG!F}!EL3dt_B?tdQgQVL+<2!T@4J_6Fkx4K3o)4e4s7M7MH<%}Mng&z5Rd zSar7OyUK&K8(vd&W6WnO&z*FFU!8^P2cpJp1N(AiaNUJVxE^sk?ACR$H-f`gWr+S= zzv<!$-IZCO%B*t3$zuBhmsb(%(ZgkkMUg zidz+umT(n%tWRuqZlMkJ^PRXm(=G?FS=}R!P4q zLCp5vnQCN4ppCR&aZ32WwD!q{ab_4`lVwz?ToAgy?pu{ z15Bt+Q=5NhB;hdh(w9(F+->AKThBmXeNuPV{UKv_mgct(pj2DO!PvENU*=nxG^Cui zRArQ%2J5)Z9N2JW0;R?Mx<#%Fa4%2@PzZOXbCYBc8xY2}m=z0w3nSugc#ubDg8a^N zMwKNMV5YZyxLNe{!g;QAz_K^)F%^@?aD*L|>m8<1oJ{5nv*!i270JV>c05%OgFIZk z_zOzDZr^nMMfPV(49*3CJb05PS`GUhw|J-3b}KA)Kwk26%DZk?0MGa`aEQKY5#%6y z{i+Kz=0lgrb#a(cAiABqY2#EtUz)MlHmor5(b@=7@!|Ph`F_c_uyItw9u#dyT$`$6 zcA8Iw^Gon7!=(0?@lAIFxE#bJ{Z6!@A3RGIW)pkIfXJQb40+ctQ2M~LUR=Y<(-i*Z z6im99h-KcA&hv>Z$Xzmk#p(kJTbI4o67m0ixR^uP)?L zc{S~2mPYZ0ER138CN*A@6+JaOEa%F+5kc-LWD1LGFs}WPFh$U9U;K*_rHur;Z>hHg z;J~rVh;vt^Bi)@R)Y?mHV+j5iZ`nzMovuuzDQkCkG6@bXIZ8c<+`x9%cOfTWcW&vn zeUhua1NkyyQ83NGonp+NDdnnS6I&SQQMd zA15vT&3;o-kTCL4q5%P?a?b+gWTJ=(0Y`58w8X+CaUiZBK3{%9{g)8tX+&u$l!K;! z^8BXWC$!_yy7Z3Y6_u4TJcVd|l+qNJO+_O-(@gwd6l_;s5t%`a8MUnNv0wwX2MT(H z37wrR=DM1kSYW`zsBtG23pFh*3zr~9_kT2OSek^Ja;slq^e4?1sV- zOeWYFvO-9_``BLN+sAU(eh;xS4eR}*c-tyQ!yAXUq77uzTf@R6X!@ONLd#E-7Gh1x zHjHG8SKj;Av%xBSrsMk!IfcAgy!P9_vG>{{a^cl~O?-QkE9rn6)fiqsCGts$%+WC; zZ+)z82>wQi6XQQHmLb2)wQIE$HLMsa9>=_q=%A?9bMrvpxif1#ii^iaPmrt^NK5D=^>4918Ytp<&O{wwBfddW%4&W z>Sw)oQoD*1<;P@!@{2_A@rUFal^Lf1&Yq7=rGvLEGgD7_MlxM6A|k|~fU?d3O}>2< zRWq1peTR5NiK?AA(k*Q}@8|B&xpCOjPe;k$d?E@Z#2;0ebp+-Rh49{q5U~Yx4w}F* zic`Ah8zPV3rB!o<9tg9$4b#QCQ0%u0X!I!VL%&@GB^>q$r10({4SikUV|#fZP3##e zZtS|8d98$7sBMsVKzvkld%J{u*i&PYBZUt@KbyU|z&~7j6WaVvd(3LPb~h)zjhvF) z`~SY8Y9KofGDrYtpOVYiM`a04kBq2Aw$MKM$Y2p|Hk= zHp!Co-mi`nPvy1lwwQtRjY~Z`q?^j>`NwsQe;skY!25I|pMY~{K>nj)+s}Li1-j#) zGz&QU@fA+6)7$AjetixJlsMMozrN5f_(rIb<^S6nHeL^qz=l=YDMlzv$F}$VWd|Mx zbOrr)2sSKqCw<~zhUoV^T!~Pf14zufFsPi@7(o9zLWR9qSbTh7T%k$iBwUQ*r=?wO2pg4U^qq*1s z<6*o&y%!2P#v{ji>=;ivl&6^@S#o4qk|pQxj_u{f5AtHg5&J`4TquYiauTHOnl6Ka zOk=eyztn66WEE=V6saJqGFGb!S${)T&1-YD+9~SLO$nFCGOEQ9dkIexOS}%e$;dGE zjRhyqA<+H=%4w$D8s=LOt8pV0`Mm*Sp+N;HDlidGDGd=Vp^{u9BIa5Wq|HgI9MO=< z>#;qCOeA@ds>i3$0kjwx%V%lw%Rjj*IF} z^w?3G;Z$>!Sjo_a4=XjcbC`JA&6$2HFVqV*^`cq(`Hb0YrYW(pjtyqJW#Druky(!& z2lnGR^4RCgEjcFMKHvknr7wJxQ=oGG#xUTIp}^|VLm6;s1gNaZ7Msgcjs5vn5Noi? zS!*YdfOQj0L?@Q`%$Ka5WKNM1*4vd_!H7*}G}N9&C;7C~4Z5H7vvD$Q*Co&%<)HXn zACNWQ?qLj-3vmA3*9_``?1kihidZ6mi-6Ubv4Lwz!I!LBc34kYvXPB;{q=O4*1jB@ z*Smt8ftK80Q{A$$3O7wlw%Dx^#n#P|+p7;-WlP&OYPEgKdhU$5PTPIUx?}soYT}Z$ z7@<2@mdNs*%IclT+I^Ib`y{LPIp&OZ@e+S+cSK;vf;kZ!BNpw!U`XPCg4-I+MkcQF zDXyU3H~=IleQ-ppL9PeQ={qG(t>RmAf`vJOvO=+JSSRcp4xALp5*(|XLb;%*&?bYS zQ!I=di-+aGLiiw9ek}Hb_S;p+I)w^gVOS^#izAHV23HgpPYe&AGk$pD@wrp0imVe5 z#!Id%@f2&-N$l`;PJ#CZmxK@ePAQZor+`p~P=$b3N1wtG#Lf}wjoTw3B_q|UT?c7< zfho99K)TZDO4qo$OB6`dl|f6RkXhF%YS(Eg=*A#pU{uUSZ0wo?HY&m;26623KC{51 zV&E7uj57?Ku_NER;tEkQFf=2iA}t~_=46SnWh9l!26L8#T)D=;Bb-!{)c{0y*<9sF z3%hnOh%>>ELh1x+wO~IAi6K%Gwh>qoD|(xyeobo9Adgn7N1r*jn)RDErG>tIsgwvL z?IOSAamp~V3{y&qQd0U|HBRg};=De~szw9m;4pCAdNA{^{sAuqrF(EmRif0Bz_^SBXLtOdvhKOH_V(39EQrn>iVDSyNgN@b<7<_TJ^#e5(eWz~w#rJ6F706mwh^4FwKGG?%BU&F8%>9S)?(qjlgUUfNWzwW?jxCu18Kf!$ zX)}I&=4|2XGrO>_K%QPFu177C0W$y|!H@)sP{O0pgVTtMJjwqE=NC~=XzZq4RRcES z^rV>qiQ+M}s>cwi@z0_lw}17rN}?v`@Ga+w8N}h*kX%^B+-uVv=(9}r^qga$3A{t~0C+83 zeT;Lj9p;j$1m-I|x6af7#O>&LUNiLj+H@~JLRD~#;y-EI)HjP0l0)W&w|{Y=@QX0= zHi)YqVyVgM0wW1u#w1eWzf{WFR1ywj{oLo_59*uv&d;PRqnS`#)XNT!<4K}(-bhWL zu9>dPcGJa+?Z7Qo)9`+(_*Xa}^EY*JezW3)5GjUk8}(CVC0Yc;re-$!>G`w>*I zTCz?ey`1QG%eYS`?a@CkJ*he^kDS0~_{7z`aVue;Ky(=a@u!FVV6JGk37&@GQsT{c;=$v0!dA z5bTb-sS$EhAOcaC{=7pfDh!t=d>T|$LNq#83=g@68wkd0^lkBf;wt$g_=}Zk2 z!#zc2D$A16v9I*Bb=|Q~l;y{z z+qK&}$lIwDfq$lkZAa$%r#&6bY20N~~q84n|=RbAx7aO(wi0tB=}yfpFgkoZGee zQs>z#3G{>=0?1nFkx@P6gc4%rCW7iShl?{JW2MU^v2uPpF_j^<2M#mL5RNKoZGfts z#l(pR5{GB_K|=X=n~$$ZB5m%VzZ4jQ+BSA~z!>Y3)^Eb(Iy4_q1~b%GQwy|sHlBEo zw8H!M!W1u)nK0T?AxHP^plW(@!wGMqEtwjdvXs*wcgizS7v>_eI4a1|*0G9P%+La- zgBY9p*3`kw7K7WMIEkZn7cImm%8aDV7tz^_z<2ePoDVoQ4}A%5F}F6(y$vw5?yZM- z`igUYkgGb>ea>UOPt@F#oUZ8~oV$2hZCJ9v%1Wz5i&+kC{VG;#RnRoY!A(+VTl+EO zH4@oFL@4N3D?t;$s8~>zl(j0@RD&U9dceG@+&U)rYmr|*YP3MLIMV`f+MN*xyzcc3 zgTopT^iEq>lNp{Xj1!~1UMoIDt;bu0-!-B;qg=jQO8e;c?p;`Oo%tpYyNLYfjT^?k zEaWDZ=-yZY9?)jM=5t3|d2ER?<-Ss17h;7A`5((~zPnIX0-=uZeLZW7A^NuIb3Z(xDZF+7^To3d3Y2Rhu?&BAbyjJQsc}Uk@^hu}S+R zP7y`y+1xp2Jr3*9tyHUD+;lY}HrLig9=Bv>^4C&c=Jg-HL`Gd&M7^MwpLr{q+Kg03 ziY6PcE_^eKe1BgyqkOUC@v=qG6d}s21BX82y6%us;S3Y+Y&QOwKMzi>M)WYcPr__* zvWL}qn77}}z&854n;BMRcCXpz;&62HJ6@aW4lv0(#gUprj!}P?WO;A3^mX`2aU^6hf+~a3#@q(GU@>28v^mOKYIAe4wBh1u^2J(Gnp!P$VL?DsNxifUjw=tR;ksY{%Z%S@ISk z!nIg!c8m;nPkNx>CCEpPzgGqjupXVd4P{nZqf|e-4B8MCYDBsm3nVz@-XVQY;m(q@=MDU6D$PQp1#Lj8X+CDH^QQ>ZDqllyFHz3reyCA}QcV zz=KLnQWm@7!CbLOOa>w`Oq)WoMFc7GM<|1j7?hPqkvS4X=n_&RD6}~vo7|3!+J%wb zCfOX0HeMvjk`&pZ2o_05vPq2OQc^`yjude=KJSUjm`JXZM0JcvZ!ntd4v9e`-#XDQ znvdWzy{(47_4_QZxlD*d2u}!)#yoNX5+N!MAu>ElA!>7*yGBx#6ts$mZ&TLkWK_@P zWh6n$NFejzo65?JbVZO#Sr^0eAc@{H{EvEeGfgx_M~U89Dk)D{38I|+Rb(B>F&OO=5KiDI@ts_f%AC*2<3g? z9EI|uPrf)DwE#DT2K>Q46EP5lMG+e0MT3}ch`Bh6zeG#A5Wrt2meF~$4CBUS`RBTe z-7n8ra7FHPhkdXQ_Q6o7ANO269Gey*?GC%a4v0&$^}xGA0V&FbWC zL8o}jIu%>hsoA<7kZ!l>BVeez)zISYXmU)$K*{mDDezR1W$9&4%)S8sEsp{JEv9cV z>_O?|PU!J=*X^rgVURg$d1Z`y)c&y@4&2!6_Vff2K;h(=LXZB~qGOAdBGo$sL}{P= zxy1PPK68P}m93(!tD%)|n_d|!`Zh-cPx&0E{Ly}L`F_QS*>hB9kEYyl)qmm>Azx-cAh>xC+oTLRRS~w zQ3XT;(FT+jF__osrL`DyGMxV6qqeo+(Um?u_|l2);t35&{Cqf4K>u7Ua4CS8GARDL zsx|0v7+v4Csjcl`uD;k~@!-`12&HJpk$ipz$gzMjYiOdAD7pGz_(5-A#wFI=ePrLq z{8^}nV1OqHR5HLO4?;>H=hdgQqaQWzZp~x^VaDL38@>+;6p&yFS-zmi%E#){nl4^B z>L%X4{-9H#<~;h2O`<+@;1|(=@HdZ~$6wfwG|>o&MkWo+&u1qGqDT3Z0+F&6aJp+QBG}uOO9<1itgDDqSaf?rW;en^_@=6Dd zI~9qbklwMzo_)&=1rSqqt9T*x7pkK6dyNoJ5^0cF;7lD$~!dmZV1ya$FJCLSbG!5|wv3L&8!S5W^L3>}{C;L}%J z*+TSQT2*j!^ksZ@;UdpTb%D3Z#UQ3l56 zIQ`ylp(<2QtX_X;fyoVjP^$u`>RVuhXm#wJFMtA5uf<4rC32|-f9?i-GEHTHBJ>H@C3}9`;kE?=TeR#&}PSjCg>JvBu zQ6`Z@dgM{V|LM^J+xKt)K;t8Zh9D*|ejo^+_t)Y8%FVkrpH4NML zzJc{yk}7#eGMK;jMWU~U8(TGol+nx~r^3#+OkXmmTBAPuG{tC+K*V=N0e z*_jh`3DbrS(AK4)IK=mEMk78&^<&^Fax}@akYp|g>kjA=KUZwco9U27>ngTR1|2^Fs9jpP4#Q<<7Mz{vxmd~8q@p$+M z9>zsPAoc{7n(z*D*hyT)oqH6Q?-e4n%|JV!t z_F;bzKp(^)0|lsps@@$yMs`6`jYa5Do(UpqT=@aWVyuJ4`rJ3LHwI6nYvpw~-R(X$ zuZN>7K|ZD;DW8}wp34eZp35)6DjQs}&7KUF49+p9kwvR}4Mo|O@E6KgIhD(}E0|T> zoD-*&Qh3OXRysql#Y%T@o2qCN8)c%xp4ON~(8+CPx|uo(aKLqjv1U2rL&U3R14AL2 z&EgX$$tS~%<$6}f`h)U?LTyTF+3Btbq&-sxGw;WWWYZj z4|v#Pl#NP;+^O9N1>=zmdyTyk#UxNpJ+Dw%IvUj}Z5{8-OvKip8JQ08AzyJeck`|7 zK>PW+SW9$@q|$q}EZYCj+#=xIZ!hrY#g62i9HTWftq!dU<8i_+UwKH4++p4-d+%wX z+cx|NhZNs9{}$X#_mA5Mr_YL*(!#L84T4RbKv)XNq{WyX8y|%$DRWxGl0#>$#OoLo}f&~dGm?eG) zX$fSIoeN!q*2+L?+~sP%_5u5Z>DO;}+Prg5ZGVg3V?GO*Tf^DHomgj!-GDW~5cQ8T zZ|EYC0O=X5l}Ojqwb#&-A0^nWFv<@-JF7@YFbk!9*GSc^9+i7x*~e%)n9Ikm0px(s zXc*H{oVpZ0ePYsVaKstE8{yxN{I2ZxYb{Lsjj2@Y?h_1)b-BeoVXq9w?`-|DLL%f zVS#1VQcX!8L%wk)ORTxW@hsVV#Xj{1RlCPe=>TEkYe?Oj+r#*S-F03i1b_tciv1F~ zx_b3G(Qh@2FN;3WBVNz?ix-D{F*}nsmtJB0@>?mpeC3FTfs<9F<{rMsH`2iu3#pF= zk%Rjq)9>GYrUjbLgRrBM(a4^=WB`}z=)9-?3udC(y_tWD+FhqL7ZcG)lo6N^T57fvHPlmKSXZikne67T?0+Cd)c;{*+i^ysGMcU~+ z>|tPItD9o$zNIfUCtS{-7H;k>=ru094(9rYl#4=^(A92)f~m*_y~SP0syQWARK{W} zDpD$_snIp-w%y4%4f77ToKv%0o$_{yJfy#2MFYR4W>++zl_iBt#VRl-WgPi~+DEx- z?k=?^>?Hbivt3abt_zj$24-Oi)^klG`v#r!e3L6!L$ifBE8)slz19IgyHrV$AeD?L z+oKZRrzw0QT|5u&N@jG&m|%)}W(VncMfITA zGAAaOViv^;2o>-ub+oLTVpQ=&wh&D*C6A)*;!oE6+ML`|C3Nv$uuVO9}T{KpBEzbn2ysg`I8)ifmMyq z%nvHDDh;%)hm5hXDK)EZ3V15Ev&12vo+9<-mJ28?s7__Xg3!StSHzHs0;UVrbU+m~ z)bX~?3fFmWKD?aVB;yyjUTE%n)r2|pcVNhEZ)qjCZJj|z|LmAQANcS$d{ICZFaY4Q zJMe(>xk7>Dp878rT;bJ%7U*BQ`{s{I)_AJp@u!lraiLs}YvpF#Dfi=1dAi^IkGzNs z@*+BZe3cTCNXhV8_$;QHsM)-}DiWc`h@7Mukx84@Mi)17Gdo@7kALA|MLVB>2xv-T zEQ#8izqbDW+`~W6>y#D9OqGa6%plFfYXBs%Eb;#4hUM}fLp=n9Q*}k@*_&c@7$PNI zSHV5#I46&?pUSF#sc0)>@kj!#l*%I+eoj)#7~bnH6O!Cd|h%=GrNV zuHeSwDC>2uJ3s{ILez|iVxBBA<-*`nWm$bWt^|^jk)tye+>lDAQG75>jL>GTtOa_h zcpV(uW2o7@m$BSLASV?C(K$b1L{|Cf5Z!x2rE#E`m6>1MK&P+AP`A*zMOek<8c98* z7`)k&h-lt(51k5|or-I0kbFuZl9`HV^b7F0l!Ed*f;ThkC^>hJ*8YZck_GN<#1`)L zMfx>%OQ~svGU>C-0&iW@5>88WV;lQzrk`T+$u$Hs-KB%b1xln z4JOoIRy_r*tDaNVSw}r5S{q&5$W7>|?V+-t$~}~KH9|^}Ur|v%-KbyVsqvF*1!G8B z0D40(`yKCv)UU{Xeue^wPW$)B7qeiuD^3n};8eS%~l!V%sdR}Pl< z$-S=+?ZsMiVair9;*VivC&ILuD+cFmz@1pwA9SX%$L5G57GI+tZ4ai+Toal7IR+ff zjXL~-1kNAPdDwCeN>TlU9ZwS@S;WrpJ;O*4H{xunC+v~($X&u?UZFi;^A)_j1aMpd z_UOH7{o$X4s59)};CLqtE07OZH5e0#KGX)m@@f2)rirD85-`omg>%)phz z@;iqxCrb`k+8O-s4@bz^K?}6E1p`-~pf5;b;osnYr2)+m&CsDF zXr|00&E6BZ9+06g(tK~T7IYt=0c#VYkwI*jfyd^EM$|wAj9S49&y+#GB`0jYoRh-` z%(;9^yn&a4dNWoiV`teo*wyf23-A&pK06g7>G=>b=*sLJNR{zp_nW42iZJH)Em zJJqo!9cXeaNv$uot*4SR!F+-WKP3mJ02H?OdI|{TG~6|KAA4Sl>kB6yYg>OrBl z8^Mz_W8F~G3^eU6u93c*E^T9K@qw5u!lAnV>=D`}qU+<@O$YfvIoE@&*o>WpKS#l` z1%*i^FX)xm1Mjb|9#p9FR8pZYO3()vY6v8dpzlkTW4BB2n3wp!m|Gf~+YyLospd7- zbIF;YogJrDR$C&_y&vd2_cpv6=Dv#nW^ z`5GmJ~LBWy@UmbYH}#rL}pbX3D2EE zcyQIZndDm{ZU*JLd=f^a{Zu*F33}*g8wD9C1td%oK!SBYZkvl%ilZ)SYXHoH25!` z8dscNSDK4&$vi2tb9>pQr@#IKU8b&RQbL4gQXewkstP5SBFl{^n}lZ9BdAI4S#Jy# zy+Ap(@B;X$_9x&U6HH;ppRBA2*P`v}VzMo0>O%R!9MyABHG(q!@IoO(9}&>iotA=) zcWW0YI!$@C-~M_U9|FJ>aQ22JZqWKSW!dTO_1bLXv#d z7`Q|L<>TJasC;c{w1KI}x$xroJGiC?V@S4fkI%d71$kxOr1#0kJTUH!j5I~a+VG9T&0o6>_Bvsu8bPhT`Yzoc6ij_4;9juZM*Ez! zO0AGKK}a$btHaVy0=I_kHrel#)!Z7i`{svCCF->s@DJ`3+iiA$!5SWoIuOOmQi`g> zph>uKY`4WhE3DDYibJUu=&o|Kp?P`TznJaKx$ebTL99T zG9wsfuNc<+IdYS2oosyFfdVp9GC;)aK!F(?A&6oJ3KC|ffWqxap-Dm>D8@f7kt+;j z>-2I1xjMbvL2sN+9w2}Js50Y4pe|Bc6ZJF1D+QUFXv94?4rjP4*p` zn5r7BqLZTC1ls|258P?`Hu9^-fPfYPCm14P5vGaQmS@AR; zldP=G=*&1KGB5KPR+O>DpJfj1(5a68SdRZR&atPwf>-q(r)aGi{;U0UKj2?)fByU# zeHLHV*Y{n2@0Ty6%mwof^O5vB&c_P<|46vPy_6A0lHid5e;`Bw(d_+>cc_xst}2T* zShb(qZ-9Xv@QYvj!JrcRi1_UaWkk~r)3P1c^Mf#olQjF;c0Hkt3%MWXbwBU-v$@F9 zw2Zv`g7S*Ws_L4~N~D&orwbosPM4dzho^5p{qkol4sS*vk%u?}THr?N$P2Z};pP64 zqwW~TyTO|j!*EbNzC@BqDfN7NJKqH^Xs?JUicWof|M6ebvK`k8lDzHuasElB)YVfP zXpQtyv9ZpFm?)J}mx*N#E}n(>K#*(#Dry>eO8o3s#~gRUNl9m%b&4paDfCZ94TDFl@|(1cMBdDNCLLGnANb zv0nQ5$uANOGfI+4W?5jlWa+ZxI;fbBSmjHv#04ZE0V+V1&MGZXW8whOgm}PslgWOk z1rC!%=be^eiX>X#F*$U>8JkV@2Q6eUd34b$TTC;S76eQI1I&N6n(j~B+srTyccz)f zz z<{&4Vi=1K}@;dX8*ZUhe)dJ)V79yuvguKx|$mteio{V`4=Bb#cVV;h82IiTVXJP&e z^K9IMvAA^)!Qj?CwDeo|u##_K;vQZq5kwM2w9!gT+x$C`{1EG>IPnrBUVjn_1KEMF z<}%(GppANhc(BFNZIX}C*w~xf2M-YN$UOKEDsfMTkYb6&$&DaZCg+I=#3n0$*GP

VDDqC_2eeRxv8`>~vIR3c_m|H;P_`iX$5W5>-2g4_RN6_8WtZ33i zj>i4lkSGAbVa@Nmnjko#P6%xW+4cbPYzL4j8o1a@6(&$wvVtJXDHFu({2IHf3)?RFj=no^$R$li3JfAE1=XFZ!3^PXcIgI|dXw~n z>;jf#fh8U)T$R4<03>kzlbn^6-UNB8_I-!kyVtn!oJrjnqDd4!7cu6iE^g~P0eQGw ztncJaNE2Td-TZnUs^@vfD;a8>@5Fg^{|$%XF&Qjwb$LFf!^og~;YrIkhB2-lVyIz; zC%Mq>;V%~(Ib_gtE0_u?hpDMj>fR%RTk!z_6ME|(dc}&8Fn=I=(zLLag!2+|r`D=~ zrC%cubMe;qi(PrX2a=NU%D|<|ir!N-fUwB(J%9W#)?|mP3^`^7Z(!kw?mRhbbHUXX z|5$3fStUuoOQ5q!A!x)g|8`-v%qm7Uo`;~;mdOgPk5K(S0FsD}rP25yJ+>9tV5WG+ zn~HJ_D(1JW?Tq^UgDIw(X1W<>n&mIEpM4qDRl+AaZ5eXsP7y=P;$PLX$i>w<25dHl zsmv#LxS;t%>buOOv&W3y-6j@u}0`SHW{abOjB!3v| zPveX?!9k}je$AMC-U0zw7WUEpkil{B4>iw zeB+}^zu`Vb+VWq&Q~nREAk9Xq&?Yw79$CI28Yh?vG43AD1GO zt$?qeZ1!)}gk|?%=9*`|zb&xPBL7%S^%hcRe-Z&gY9+-$wub7-vNKQmyGggjOS0{f zW4By;5qQgwDeGQ132UNt;&RXi_bSPtY13FJKg4%~e0M{jcA>v=w=;&2!OA%c?7 zw*U_CcCqgCH&s%O;XhcW=1L%-|EfwP?3Q0LAdWl*fQ6v|0^9@VLBTsxuxYLVwhl9( z5w*cCujKYN{vqZ^;**lX{1fWfsifC~E_S)A-Of3e?&qFoPkNQtJ}qED3trfwm$;l2 zu6PxrtZR_>ilK_AGP-1xF~;7)2`Aaw#jU|$!;Cc9Z1XJekCf@kHAj&W6)G(>)^pcy z*dOcct4F%#|35MTsV4QLiL{Y^GD%j-imc0#Fv5r;Gg-=73~?lsL`rG&j?rXfRMe%e z)wCNXrHL@r+Nfa~cHtPqvG~Ue9uXN01GUuCNHa|O7)HdD&5mVQw(Pm)os(2mXSvnG zxxfcRU;-Cp)^n-0#Ss>^(QYI!=aYbhBreHGOL?SSQ(1MT8$1ROAo()yEB{fhj{3jc=L9bhuJvpX zX4QT_sA!pnD{?b!vDu0M|Mcq2Ug=<`e*STZ?}3eS#qve-=1foS->8Hh8g|b`Nhci_ zcL=DD1|Ot19{~Bc7kw=NfL_eVD*zyV_!krH{nIW!l?4OP|M~%d`1IBR00Ec9EdoCa zpkJPlH^Q^mm2R@1U z*E$4GTKgUYM=ar<6k=c79-cKOsmD%J`1estWb&{#T_N_h^ zJ{l5{_~fK5tUFSYd^I&+l2(zT|6AASmbR+YHnwZVmg{Ki6ft!xO*dY#bSZa2*c`K+{W|d7YS*%349=`m2V(u>% zGO7{H$5X>InZRyOY%s6t>TUnebDw*$4+R!ob-5K*F$9q|(Nu%mmu&~L%C?iov+k6( zn8hxB^tr~M9|o4I*`?c1xh+-MTD6T;*c-`#QeCaqvGQD~(v9jIFP~doT+oCHoF$5oAq?P?gbRi*r4sz+QUMnDt6vyWn=pV3lW=cf(iJoB6IaRI_qVAjvCUf zEd9yX-mV$!LT%lN&t7e<2T>G7Pz>yLxNPw49c{+T*KW(EEZ6TbCtVN zjgOo2X((WH!i}z&tZ@MTZdLVd>uCz`Lz)phX~2s{R8ueBvVLpnlqWejleM$`w@b06 zfF#b{96PF)I4vIaGEHzsoY6$J#8mGN!Z%&6qkz2fE@ZctRmN1eU0)sZ+`nG-Vi+ic z+-pPH#r0y;sa3J>D_r?1H?=n#+vKL7oVVqtM66UuWh{=0&86`~eCGeZv88l9Onr;& z-XR*w=uD?pEKJg;EckUT?q?*HJaVQ}<($hy3ht6eW=J^E5Xywo*0^Cj`s?$H$fK%P z)on9R_~SQEBgr2 zpS!YJC#4l~GLf69yv&rgLs>gjwO4W52(t4yd$+spR@Xew<3(OmHJPs2TeD>dd_6_z zpA!5S9==Z&`lJj$rCo74m84gB8Wps*#`ZSS%IY$2xE=L(sEQ6$*6}D=Ro#(lI$CYV zB4-_~Q#Ew9=5EC8R=jT4n`C{fUweLAPoo61k}32Et|#z4MJPr_k0HAc-2<51VS5Ob z8*5cA_t)JTSy$vtC2T5nwlb$H_B99s1K{hl3)wiYOWGaJ7rB zb;;$<&$yOMYimOtZK|uyb+@ISHrCnsT02)u7h`s%&Nq>Ql7x($l$8x_&o{n_{hNe6 z50@%#0X1sbZBWO{XT2{wz%dAdK*F7Xp|)+w5(^|ksYqr`B&ao7l^3qL>Uu26A0v(r z=ol8b!~qIhhCjf__ibdHaYmB4$_>d+>Y#zg_?Jvc)YaABu>-zzI+mckFM&z^UilLC zuTs%5r@1r`77@y2H^a;;yr{7pfOH{rrP2%f_W%CX=j*ave{zyF)Fi3W*+jyd%}{fp zMB{&VL4hI5k?d}oIU$VwP}1+1c@!D2%eIARy%xT09d73*i+8Kx>2Q4tyKGP{e;oi1 z=pLUatpObnm0Oh{R5+6X7088t2BNTLoqW-yqyVr(mw7Rj}C3~N(HdJUY1~R3-8dpI??skZD2t^d}CGM(V38k!n z7N8<;Sg23ozP^KSstYtZU*qnw!X#`sk-GVSxL{CwkgSEY%v9}CrLxW=+gf~GKo4uy z7RFmGr5E6f1;!Jxfwjs;GO!A@3Do7wplj6(27J;HtRba!IW1&88drmeuOj+>Lj_7% zy-IiGuK`id<_lH%_VaJXEwzLkA5h zsTo9G13(CU95Z2D?zUs-`>1qu5UMK!C$<4`XBp70qPHc!Ii;)t3>A{pnG#+pjp!^j z0MfW)wPGy|%}kjR32DTiEs+d@(o=$PnYzX-f1#R6LRpfsk^l^pD|?UF&u5dRh5k&QnR-qE;Gbnvho(knM zF+Y_G2AG+^xF#*SPKSAh!?P?iQg}6A=|A@>98ogmoks<^+OT7-}O6QKSyA>G_bm+Dbzpg*h4~_b-DhtRL9xqdD+v9i?sS zNTd!i!lN{6XF zL^R!KsHIT_V4knM4;t4CNs2Ln>kVTyJq@orh>8$_K5ooY4wZ%G&7?FgvJg*J#*OyO z$YZh!bM7&Vm?%5XsT3U4MeaBgskT+=A{`r$ZbDU8GFa7@gJrgqveHF4U-}WxBwXa? zj$cr&#HpRZ%GglBIUS{vQHrC|Rm2GE^5jcUf^lmQbETM-N6|VpmMrO*A5s)4ux?c3 zV&QY=)*LvT)d7$QHJGl?$C5BF8*lf?*_;a2$~=)|l0ypzoy%!j9k;Lw3~cDUrlcd> z(>GnA=lQvGJ2$@NHLEuphjy8J&{#kGMzuR?Pb?LZ#{e4B!l4ace^2dfoZxGi`n#<{ zi29^i$?W8fz97Fr^E%J)A(>G+tmX)aNn;MoP1AOJz37n)tlV&6as3qKya2tl35pzb z8943X{69sv0fRjd!>%lNLFuMa&|)IlHV#prM^ep>F%~pu+!9fKdb4e6^KK=b+nP)1 zVeddvGc8aAybNNqw$kO)mW^z`6PO#Ba_WS>&r@zI6wF2@`FZku+5uGnyGAB4+BS^@ z0iWu5B%kNAw>z-T>W+~)SU1{XfT^ZyLGqJ@~-nF%&46c;z_!I3ZoQ z9|43LZ$iBG@dHHg-eLiT&5D}6i4#&J0D|KHvsM28EmQXS=`;% z6>F)4EN=*KFWvno9OV8d;LsO9%_jiF7XhsNAOMha?J{coO--}L=74av3oz&GHNWf~ zI9zoWTS<*s(DgFSdQ1-}NaLW3kAx_scsWqeX@l7fEw+!+u?(luQzF@tkb{XK9f^kk z?fC-=yXb_P40h)N9T{{MSFYVdHK-X-8y5Ef#foa>Pey+B2+sj^jCe!UTj$Re+@Rpz zBI9Ohg~iz+XHUX}5L+np20aRx!RMtx6|7@gy$o4%(^RLn?lL4h*+gF((PSaE*&Y3$ zN6c_VnUf^gh0R|Cq3PKfu>RH;O$R%F0%q^rg4zn!nMIQZ;$Ggn{Pe~zPI)~*roCyZqdT;eF;R|MU~!S2tsy+Z*Y9m-G-lKhyj{ zbOGpfDJDLCe?8oZ5uWXj+70L^Kbe>gX4ZP;`_6l3 zOl!#w*4xI%IJ4ns2KyEKH&lGEXhX{O`n*dmilh#848nwUQ=(lH+Mr%Z*7I)grmA|S z7gjCjv9J-0y#MkG;8*+AL|*Rd-r}RW3GEn})tAbBsb1B`IJrduJYd*$?G~5t#l0N+ zldycby>F?)s^Usk01VagXo@-)3Jl7^BGq+{ei`rZ7s&ngZC`(}=iHm?(^c9UZMR9ZtVn)&wnu(e=ZVz` zA3at*oY7~=oF!`5^9VV75MClg$IP}?tis)7r3PywA|qLES9`Iy8z6Q$Kf?`$Oj<8K zXiW>tg^UWrhp~yUYyI81s0Px$rCeY1aST1D*GzPVQ;tt>!AGC@@W3n|S;}~KYqIc^ zTmI->)x>z^!-`{ZaxxfzR%FXFpAZ$i^Ey>Xo)E9{Zm4B4t0z*yWLNU21UaqD)j6Zv z+0!#b#Jta5K+fm#R|tTKS|T$!?{5XbuH;b(aynH2PDN#0dAH(No%EW!8mP!ntR0;QmV3}`gxzWr9Izn%t3H36yi9QMTH zpC_2eDa}0h!_5->8kpCgQm+;HVS8{1445PsvFJsxS=MX$F)8t=ZHsqgC2^MsW!|-X{0fu@~Fq5IwXrh4-Oto_a>D-|D zqPj*1C8aDKWGjhaDGtjT^ZXsl~!cv(ag@1GN-DF6PEHG;ZuCrDXLv9}}hIy!1g zoK;0ESV4CwBbZm)2a0;W0bsH7+O9XOjInZwjho`f$LZ9I?Q zOi6sbqGIKBuu?k;Q$vFQ20=OrvRO3E@g{YNa%G(5-PVrZNpb6Tn3|2{iUQL^OwD=ST( zC#BgPo4nw?9j^F!oOvG~GyKgt;9R`m3D2!5OS;G|l>CnclM+$(&egs>C+C*sM@|(+ z%RKRmO(Ub>e4vXoulZ2z7y*n5{kY+QT-i=a7DP`GMY@V7_PLR#G*s$sQMSPn&^OiB> zonamW+b|0rid2=sMMKd#Ye2D8m(>J##K{uxmvynsRih6duuT1OluO~a1KyEPKxvrjn+yX51Qw{6c3DkeC^a>oulLt%&Xo8tnK4^W6R3 zJV-a=jl?(qI~$umFL09`AG|m-H!%JAG3Qq{cF+^bChJ;d&%*eru7(ZKjiX|iW7#gC3*_{w#wTWfLfbrf9*4r1XhI^39 zI?F!~e?ip1Z{+fgS?M>qoD<=OVyITkTdWv0sMlH&_O{qL{Ba`EILk4Gz&adjMmOkh zZfzR?v#Pclg?SEBkSVmZve2EC?HC!DFR;$k+9lY7`sh)hd0!lLQ+Vo$Z&WNx6FUS0 zUX6a(yr=~O3=&_3+8%5|hc8(;MKQM==PI){XpJ8yEmKUb?^(Lq z#TxQU#XmIKBijaCgC2N?Ko>&L>5KAJ%er$~JF~SK9fG4fn9;=Eb8^Ca|ik|Y0 zUhE~#newx4e4;Y?@JO)Xm@7BX2fny*B88Zo%SmZ2OH<_e!I~*~FY|Y$-mg>0I#yOhg;b;Bx@%;>XXmGQb@Q6H=imSqZ zrHII|34a7HB48w1ZZ96N^mhp-rp8$Fq^^M=!Xu_X?$h-3K#&Okn9o<_x-ZM)wKUqK zb@Q(yj)bEnn-TL#V&`yCC3ue@4@G1q#5zl?mGlY5nM6+voCIN{Ejb#vg!l^uRr{EN%bAIo#-c$>Es*1gx$B<59!G_(lvSd438QeGfUaV-oMq`pSlOpVg%a36IJc&^|p7+yfYVYU*!v* zF6v_*`hg3wMm=70WD^CbnM;*FJJBBM22jr1i$BXdVPIHMovufmGp}DZ{sFvacB4LO zoipxP^vUt{sZ&~1+Y`P2Y0~GlsI}EhPQKSkeDha)Dk;(Fger)F$~uy2;1)7kz^Yml zh4_L$eTIF8An(gL>u3Yez)Xvd4Ac5Mcf|vfWUjgb{-pPK{jUVJbPI!MQ z5tU$vxr?hD^E2_vE)wX|3`9c_STN=${d(CDo0S2}Bwbu<>keW6VfKhF8lWs3#NM7xs6g;4un(Z3XXdzVyX^6%jb>Y>o3 z*4>T%k(`KfkVK!2ym4;K`xUIH0;4qP=_W-$jhT6?o~VrXzbuG7@?$nT(HpTHaq$7q z!vYY<-!jelO(ahotYBHlx|nzAS_fa-Ms+<=vxOS zO@H7Ke!!n_pau_(9Yl#ZY)i>oYA<`1XBx$5IwSo2&-r$o6nwzciScTlqb}TeD#9z$VP%~agQWzZs{jw#_b z#3m4CUNP$NJ(+_hW_ARVEhqMOdDy4Xw~HD^)F5p?hv~0e?^j_2t7)_sZ^sWubZc9Z zOI<>VzQ#JM#J1-K^v^2 zORwm5^b&Jqg~cKlXidpw_%;PeM4snUs@sq8Zjys;4Do7t<^?W1=aBi;3XtE2B6jCf zW;rLOrbw~XrJ`Er4JEG4yUhuTf?M&Ly=X4&oqrS2_Ful(Zlr6O9~oL9@D7GY9x%1d z&E-TTn@bk#kURpOtpjT2Et87ij>y3}8sqerRVxlKJbMV4?cQ&;WMB3+aFx^W?CO!VDzJ~Z78z(3r=tHl~c5Pe| z@qymvDwCS613Hx?)5>onLK2I>aSn}<@Oe!2`J762!DqETqfa1mRPq&Hfug^#iAR{^ z-0mK;5{OC`j7963qW{3!LaTYbA@yQ2o=t0})}yxWsf~2o>^^g6u4_eY8A{Rv8VHWs z_cL7zJvi$k{pTUw#W({5`_mtIA;h9cbcqlW6TV1wvGL@YtP;hWCSi@}T-7d`Yt(}H zCLekWKVzal)FruAXEfe3gOS8{lb*`F`nZ)feKNG*NLo1_} zks!a2u{W-Q=X$(n3f4`5yH6(GVhX0L(_m5Ov zZ4{rEcRI&59f!Z1DprWpmYu_U19(p3!*a2!Usum*Ym-Xp$Jhhzg0Z=8rkGP|-7JZt z0V(2kN=vjwD8*ls#)e-+nd^~oqRIu5L=O3zDK||esIxRBw6wjykVLPlaMqK$vB@eG zNh3f^C6dFmvsmkV;^7XT-4`&yXf7pEW1i&;HxEftYjSSli1371l!L{Ldz&h1UJB;LF|DM_SVCO!Tsi< zd=9gG=>04ep5h<&k7ZRSTF7s<;bCZN@oZR_1A7%N*kJV@H(~1eL;I)d5wu83<|)LU z;zpZffxx!Y8equdU7c)r-Ck8AwANrGSfTyBKoTUxa*rXXuWk)>A^&ZOz;ZO1!zJ!!?K zBW>!Ghi}R}T`WhQR6%KIid8ipuo`ZhPg}Pl=zg9&Qe;qlSmO57xmH(0N<3(@%Dp|8 zhwR}AqmIzSsB}q`Z`IUTp5lfqOyx#XyhWaoHX|jiMDjRhW2TMGZ=2T=pLoKd4)$24 zPK>VAej5$r`Zf5B`&_+zPAf6X`~1`B03CddG6ipctcptNwDHEXVw3#ZYmB}!o3Dc8 z5pMEGkpn`-K*7;x8ykpGg+azl!r|>mfvW^`t*8k{9}5nA(<9Sb;n&&XK0ia<#^MX1 z)b!l!IJkU^|B%+bMiAQ0nb}<-8hdd8jE)=WhSRomb$vNW5ayDjQT#aX;v-|Uk z-OZJM@Fe`iT)U~D-RXD|2IWHZI}r%*`VA%R@YK?Bi7^TtZZfqH#R(Lf^c{nkeG@Q; zN?zXdD^G>7ml+5`_#HEz!ADD*0Tq}+6z4uZOq#VBBjIiz5%FmVsT;v!t~*v9(vc0& z6(0vdFE0p-7?+A;ep|Nf6|H(cW^1rk?IwwCJL~P}UT7lmJU!zKg%$KtTR&aA?!?0o zJU#?BISB=MFP|IRxUVY%HTde=A^7p06?E#miatVG;+95RWKDuKCU*`5f^-wW_Z*>> zIjJnzNy*hbm`-m56)&gDn?N}yZq&@m1`7Py^KFT^6&0CbcX@IZx>x0yD?BN^R)w<} z>^LM{wBUDGn%Gn}cX@Qz$<=ELuT))nK41(yvO+FCzJEl4T%&F1*$l_u?Io*uP-zjl z#HE*O7WT4#*;Rro*juRh*8q(g$)N+7DDKOjJD2(BZR+29QF8A4=tCIjtZddnaQ(ER zH~+;i=2|f59L;*4bn6fN6r8`LA1wR8EwmV=X`c7a_6b2^hJSv4ckpwM91q2|@TqKDvWA zi!a+ZN<;e!o{5bcJdM051?Uy;OfJTA7N}5u7R(xcCKiGyB*m{=pTrA`7oYx?0vlK~ zfppS%fUilQU{%~C02{CRi__6bO#>#ZQb84~{t9~A{lOl)Rtml?tGe~0&@}1|p1C|u z&GBLNcC@vTPvlJX9LZ^X+AOanOusIlkFg^k& zkAR7TKph={Z)6u?(|RHB$3tIRiVay0aGks~TyYtxys`)?UIo#WTPfg|R|HYSaz3fZ z9ZqbqolKYU2CrAuvc&=oQEIkJb_OEc)<@THV`Uoy7*wonNo))qAMR`L&^X)J(SZ`W=$tffk$cFmf>gyNrOEz`SSlek? z`}Q%bO5lHH)MD#!bNr{LU{&E88FkZAz*qaIHcvK)`+$~dI^UqaTy$~sDWYV>4d9aF zI-Kk?fIfxy-cWol5D|=NJOlM7p&uOSSFjH!X)oSxN1e2l-Imm>5&66Jt7=UIUg3-&y%t#X(aOzOvy>dJSCB>&k`Zp4hw zjz7r{l;%YrQRh}P@X_0vrP;@EHn{a>$pBz}s5sac$eLp=zB(CZT-~!s6sJ#>$gwPAP0<`Pvbj zC(HAy=+dVJNAk*fz&!;eMN|eI^G^+?{X{;6nVf^wf?8M$V;4qJj_-nX7~du8ux>9nyyVEC#%H=9hcnLl`qo@oETunMpq@?t6d8Ds`DD5}r2k^~ zfjZ4*tsjug!OAPMLZb8hd{FT1@a1!Takhob^!&AL>X4$*@o)@(1Q1}G9LCUG?3z7^ zMu@6rxbRXS0bEOJRJ3(N+a#cYAf?WB5Ub^xWeE3;Y3j`KT^$Sv;w~r7IVi3~jxPzo5ZsV?I*a3*kwFeo&h^snU z6v?!lnVS>1YWlnq-YfGzwxHh5TlWWhBfqYlvOZN_prIYmQrFh7SERq&M z)`Gh<@-9*Zw{}@QRJ7&iTZS&&1NoT%QOGHkraW)BH_%^P!5f=Nrt<0gJdCErGIYuH$^iv`zMPF4aI01C-+qS-GzhzL?N{D^bZ> z(cnoTBg^Wt0S||uxK9~tX~NhB$x5ZvkDlcTo`xS|gQDImEu=~b=hfqbNBM>x`k54v zqm<)~lol9*fIY2P35I`Nlou*Txh->qo|{=1!%Jxgmk_o3qh*uq&{*#hPEH96zK(h2 zeXbS%`eN6IP5Q0LrDzztluVM_G2{=^jSeIpCYKIcqbR_>xTW3UJ@058CK8R}gTHr! zR!z%6v=2c|ZzdB7T7&3t68DpE+`34$5bonkk&GfQPx(Mn6r>gV)vTo760-P?T3S>n z^8!UR$gH2m?`iwvTT)IlqUEJZe12bc%ZP=jBOdQNt#G`3ENpDc6 z3v8tDi~58(w%hAj^B_@Ivc>!M9(pi-$niU*e6ipJxPCkS@q2V;?;`K$4PZpFTuqGn zPR{2E=1Cq69B3LNtd^h3ZLrMm19!WDVM)+J71i#X%{+f%7$5gxnngzgq*C~b>a}A4 zO$eIQ5rQjA*(b|%O8j0ZgY$ui=5j))GkS`=AA9nF1} z{J8!N%(Ho-755 zO-^DOj7`AT4Q$}=_A9Iu0Oay)HNZR4DzHfXq2i_CnpzCd-2)eQ93v-X_Ho89DQBN+ zp-fC)wf`f;;rn%)@d4Mp{T7_j_4iJD{%^$F|DGDL`uz8JtgY-){9#n~w+{v1cMoXy z^COtBz@)P{` z#qK`W)MCKI$^ZOv@eV^xUdKHsxy~q>PvNo^mw8S57;PKy`q*Q!K(kch@4u}}&`uXI z@PWJr4KA0!R(!WYm^+mU16|#a*bUFb-QSh7Y^vq$g+KXhu{!u(in@h`aYeo+(DMgs zq<*{SB!XUv9_f%WTUDU`O^gTSEbpoAzRiPUnhmjkqjRVR@MGG_$2Q!~Pwo4N|7^fA za5!^qGIQMCV<0#!dl3yA6TbK&Cpvw8+q>#Ww|5bp5zJ2;i0zWaY#JAU2|`bQ9-fxP zOXi=9jQ=gQmdgHn@5*U&8bIR=WsKXq4+N)47SXWTI|Y?hY{o!bSJ0h@Irq#J1D+T_ z%jO9Z(=c}(r8QXHZl_ez2JOecy_WNAy}ZYpt}!bY)>o|WX9~?&yyn+kVAM`2Zt!$9 z-1#$f$8iDq!UCPOVt-nV6s^?VyzO_h-YG;I7Nn`<`{a$=4V_13Rz2a6O7ta6oof*nDKf~Yz<155&#j(iF zpZqgpfCk|bwG{&Jh3=qOm%M4v^NkCjsjw^lOple`3+@gygEh9o(@6UG`=ae1>KYq& z>qOdT8B~PT-ETJFVSjVWAwJIE!H&D-Oqz;UsNrvh zip5!O#k#?bdEYYmsby;0ZVZrP+IR#1mdyt?cKRsD?{duED*T(#To@^ac`K9!LFFd~ zIH_pc}42a`4oA1ebMy%s$A`u$`=RK*5CpPglpfq*9#VD4ThO?lj_S4?Fu?+N~*u7q~={Jyr0cIzF$>x zJ3%F_4MKdUH8b!^hvbLb6xTP}6rG2LN*I!6+YOTvz{iwY9>mOE{@%r@^!nr5L*Jy% zXN+YPSD6;yNT%If49Bi7Kf|ZZ1bIDzZnMAtJ%iw zJ3n5QEV-Q7e9?8C!!P_Y=;PFht}58F!*$Y0Yk#IBX8l(1zt;Bm;!*0+$#W28w#RT- zMU)bXmlAI~vetNAL4HOC%{NUFkYN5ZKQOC317yqiN|x(t2-+6j>3XV0Sv3XcG5^iZ z#`*0m@eZoKV4HAgB*)1vDaJ(Ve)qT!_~BeD89nr)f!`DCY1kH+3jHT~r92Qh2`B z^Slt$ds&eYNHQ6TA_pRoWT48RjUT=u!JF$q7`(z7+6f6 zB-exF^TL2Onr@^NBc0I}eV2*a=AG&J^iuczb9TmB*7KBenO}@-(jc1#MeCL9Q>&Ke zUDVq2?#dEnV;%|OFE)v}HO{?KY;Kf(7Al!P)M%INsx^;|r+0yiJX9?#M{|oCB5w!{b$9#$e2?HJx9A4!0Cc${EOv(N@<%^CLR1+o_Jw zEuNcc&UsH7x!b4q8PSXABt&LDDm>UJ)F;wvwI~j2V(Xr2D^cHZ4gotT`K??(3la(v z^Ay*tE2;r=yfw02UJ7n+EBa6q#df#F*0u@4lHI)H0pQ{f-|Y0CUpU%}1hp;L78s>6RLc|&+Vbvh0KhFz>p+*6 z0a@%F!CiZMSH=qG-OkZQaDe4~7EefCnxq7PyH|%Ovk9TO{0$>yP)#-C)lY=nJ4*|c zY^rC_LaY$n6y@wSlL^mJXqcJcswB|P<}ROXe(3=^5uRiZV};po?!DeB+x3fDOMaZP zj(w2w@fFwoeF7)`nV&QN+16jky`SktU}AiH(!90gjHy<~=!JburGm0>mEug7k4%j< zR&xeYHolBJI8acy)ZGV$Jbh{ci-a&YB&Y92L1G-)wTal9rJl92bNef{dD$Wqa(~#t+X3eks=kX`!yp;j3vQN{<|&hQC(g1&FS1odXd+5)yYZ zm8+0@P|XSU&NUj5I%}-f!7)K~xg*d^a$?k7uLwf9=bVg}#-JDUu`WvI6MTky7^L;z z3nM!pE>(C06w*>Y@@7ldCv<8ICZw}1Xz5rjH%-yu%zy| zObwT*`1#mpIV+36;droZSa5Vz8ZRg7V1*Bx4l=NNAj)hx zt-+t3I)KMNh^J-(-0#Mnmyc3(a3Cs$GXnZ$tC|-_Vl;SSB`r+qmN+nzCN_mkR^YzO z1T~FLHWLidrMmyTrJDa8zM%?^+lFwQ=G0wObF&^V*RJ#a_5A3ol1jDtRoh01$Xa*H z`$;mjZx(jnY6>>*uPv`yjQ24muSbLm-T%8!`G$VSa#H7pmC)D}?&Ue<#3*DH6OyLnMC=*(}H!f_1$UpD{K zY8DQ5Q%CieHy?L6Wm1o2%n)$^yn9^5l>`QnkhQO3w z^^YM4?lo~|-k7DQO=)^~4 z{e;{rYVll*w>PfPS)hiOy90R}0DvBE0b=52w@6B|L{u8CRr6|Eumgrm2@ zo=j`q{&V424H}d&+H^a7;7_RyDHpkhbNL4HM&Q&P+)y?LN&3bOsjL`8T@WNLgTi*J z77qnS&H&(9snwI!&fu8UtAK0a{v9q|ZNE;C=4pLD_uKmS=lOP;U8Z)Eiz@LWbfv2_ z+WBeK)0eZaWOr9CG6Tch4LNP348{Viy3{foR(@q>Ra0UePpR|oz3N%tEZmGQ^U@r^ z@sr&$=)r{r0!();9uy8aUPaOco68{0{3ICzuhnQZqbYOnRC(4StdBjVLs`JR%!~r# z9;$>!;E95&J26Td621nlRYGYM1Xfk>|BUo(sSbjn;`QBEj^uX?N@=A;P60(|bMtNjLaLD@c^cG1vN(Z_}-5tpwKNZo4LhwBZ~# z&r46gmOwV|>#izlgBxPN!Bw&&UMH+VoO+Y+9k}Ckg(Uoaz!9J0YWtkwtP*R!XS-ut zO2u0N5rwWEZOsoO{;LoZwoYi{TCZJ+OHJUj}^XQ>$I+rbfm~F zsQgfKxgpwC3d6Nu_+)1SKo580-7V8Z1O{2VqEy(&kkH2F9GstRp9(;ljyPs`A+!K4 z*NGTHf!ueuwo|*IR?=md(c@{zOb^VIs|b(~sZr)ky96!?_>=BR?5N>(oIg10neMP< z(Gq*(A-*ALN6Rc8_{6J~8QPkTdVktOjbz4JqlAeu>@d$Vr8$>GFpDh{H2OsP<=Ok& zw^t@ZV_tcIIOy*}CpBOXo-mDh2H$*WVzh;jh*{sTK5Fa$bnUO7g?TIKx7=4olXpD8 zMHoA>WFS0?#v4Y-@Wb@+z2Ydqvil&DvaXc2nreTRZTD-;Xu5?bTEeza8FRHzHQY7$ zZducL4`;qgmc8+*m9iqkOEzRk8X~}9sLAKJM@WtfBFs~?*Wc7|!SSG?I2_xoJ%4ZZ z=qSB&3}8Q|E8?_3m1yYx*9<`JqTv|h+>y(qzrvM-2Rw{(%>4uP*P7~>CngNol-D!$ zg;75JV|zRo8^^XGHxL~Su1QJr$l5mP4Eyv|B|D=Ix=^ABkwX1^d_w(6`Ej+{q!bc~ zz>_a74{+f}lmzZEJnb^szyE2<))D41(>cY}X_JM-9?eicl0>N9~{R8tl zGP}6-fQY$FwWb}oh2Y*hCX5EBl{CLcWD=-W!BBNsDi+j`vcC0r$4OZeFvz)Ji#Cw=!HMv@sPDioE9A48f?>n7uW zo_rXz^n`MlnTIUdb=a*Z(nvI}Bo~#tv>S6uSeXUfZ-MiSX4b(W6;~`G>oB851PBUJ z^FTJR-ze1}uvc0?mrLt>6J1PRdsu#7cfRxwdY?|EV~SpLX3R&Q-(drS1pI#tI~hgcfd_p)yk(}>2t0p^)@UqE%_zFO z@a^V6V*}vp$8;A*b7&8Jl{c~t!W#vEHlpp>L^2{NY0xQZ7$u0hz_4)nwT;rk_Bu%6 zCe`osl%NtXr4#0$Q#BLt%VZ}46K7@;=8~i}8f|T7hd`L>lP)oT*He#UH1Y%KBvLgF zSRFNjIIj<>ckiJe9nGZ$2tF-j6Z;W~{6VMaVN^5NJv`0|xk=8%+wxm3B_2_x0cBkqj<) z2rREKF5H(GS*ONkHmh)%Cl>-JPyz~VV{Or@i^%IjuQjn9j;i@f5`8-!J^I$zVz(Ih z-^H2A+`1Pp`7lRuH}r0=o_<-z@s9U4Fpc$`k2D#bK6T-7=S4?^JL@owq6}%eA;P+= zUD>??$-4MlrkThxF;>lF-ZJ#AEHKw*V4}G>(@v0wq!u1WzrI6@N~)6aW;=W`G5>K;gC(Pdby)rCa*)xix3>0nBH6{|o;y?5A&wcxlNlfK-WSCI zXB-f8_nF*HaFl#9(=E`Aqgg|xD>p`LQpoH}5cP`$mZ6GipC;5FZUW|4XnQF?#5^PN zElR%^;?>;7GBMu3WYaV}#C@Sy{qDAK^{0yd6qZnL!jez0ZDhxtMM(J|0q@pf%q`NO zBLema&o(!rHnSe+jBCdqP~1i%J0QCIDrR4?kJ!IQ4hvSsa`g^+8 z`?&@wysLD1*XlMjq%u_oAL=b>hjaB4*FEt+SFQ^sD!1MW)_ z_%3!>C;<~WMDkH{I}~TD!H6%;H;!nVD&dh~>2{Km@N^;1hgrD=Eer`Xx}*u${`&u{ z{OiSkx^fbmEqGliWYS@AxDTNgMR&xdq*FNI_B2maO|?g2Q%WUIEq`goW27_4u#_8T za3@WrijWmoIlFg-TRgRIfHb(nS1HNEpsQvJgI*m(wLc^Rg4S8yffnguzoqWHkx!1O z51R4dP529VmtMGM5~v}l2l#_T@0_%gyLSUn(fCYk9WT? z9#@3X6ktnqn)JC2{Rc2!41J^!lb+;t9rdDVt!uRfo;~KAN~Y-dI>9p3+E3pyn!^v! z%joo?1u@CDFC>cww?VakD_r)K^_b@5T{2+i(Q}uxR;JrGq7AkTVQjg9BD#Hg#Sg{M znJGOlrvzmvHU1|AT*AdmWMf`T(z1|_&R?cUAEo)zw>nkV9!sx^t5gJ$@pK^lD|uYo z+kRM`h@DgjJN|HqQDpoASe`vfB+wGuH?|#)9<#%^V&vlrH|>!Bupa#ul2tgrC@qEi1k<;a+Xq zw0o3$Ay4BX{wYnO4JQqVsb%n4V=h{56(9Yfl0dH;>5+@0(uuvH1MS_JLbU+HVfa_; zzv<#}!>N9pi&50UP_8uvy$d{c2!L%Y#3@`4CpgvpWJwg5y<+gM#T0M_*DksCy6VtG z`x`@%H`1-V;F5UMZ#@U%DJQ4mUKv2oOZf*x*Q+FrcjJWW!87Hm{#7$F>3Y=K848V0gt@N}cbwz6NZ0{06G3EZWKR^CIdaY9x_gi3rY2N$P+{*3vh))UbKtdO> zuPR^=88H=Z3j_t71`SGfu<9q!Y~~!$ev;U)sgA-@_W_HUHV;HxOgf`k@6-W!s8tq> z`p}yD4|nEG67-;V*doldgq-4S4V!Qop^l$A-Xpb%@ZYVleBw5Ta6&ia59V^X+}#vh z#YTL{$Ht1S6FaK=%AfQi88$#RoHW*=lDNb`u>?CNghZlZ6zbORlj{ecaX2=QhFUXE zpC&VLv3(5554*A-L`T;>pm#IyW%107o7$U<7x=kl(4^ElBX)BFetiV~$2wwp2<~!W z>GC87!{Jnn!Q65ZP-F_+pF}~U!SIKZ!4D^Ugd@RDti~lpMr(LN8H1TEjmfZ%Bij23_JBVmWU)OW$O99@OK^q5E<>)A zhZW03XPBqIl&%#GdO}_31z_uyH$SF|x5}zX)uuqgnk@1ik3UN4hLv9)QLzCaB;I(>cB&^!XGk&-Q+a!funPz;H2K?(Cp{b{L=F&TN>a6{}ZS@qNW z;mij%RFSxw`l2xK)qW372m+BxMPVkoYO9yj3kIs?>^p&nfWTy1w5DV2QfHyE<)fN~ zuT})`=Lr8{wT{>YGX=+WkVfWt!e_MKwom2v%GszQZ(Ah6HK95B)#W-aS$Z}pMTxJX zP|3_J&jEuJsH~OSU^SGN9co~<`W~g3gGhMWnnM*>8oDyn^KlDl+^&{yhBh776c#ST2lN0NFYL?pY(a+9TsR44EFLg)Ib3!2 zF?(3Zp(4tC1CT#s8Ol-JD(6RJRMmETc=RcZSp~%h5(uBcZuTAQysx!E?}&UrkTkx! z9Dz@27}(G#O=VwG&1Wu={VFUwW!=_FLe0_mFgqI-6~MwKxj;@fwK7jk5IB)SnKMo6 z-W{XPrO5~kL}sDnLR?adupwuvdiX2W%NiRMltnQ3MKO^G`xiK)car$iiFUZE&sr69 zGEvxo;_%QZIEp1H5UNL*#Xe4wI;T``GiWx+-UMfge(?I*lt|&o?is!JuQQmpRRJ&P zbJ9Hdruzt8Fbs3Z$0#f9dXQlj5prVFxTAI4%M?i`Vx&+%H0EH{mgnkmnzv0h!y>J0 z%FS;s7SkMD{zZI+-47CMvyxR*RzO^uNX!!x1YS-P0}!dLgp#FFHq^s9(xk9{n>{|a zddN&H{d>kKV9A|q7t_`WE`?=PQ zbs8p>vPA|P>P+h)-vUtfnDvbNWg@@}>i?R|L}!u)w- z+e_MHVY*coSwvOt*WatQfbH~P9h=PJ%h|#Ws~`251I6$Tw$UcFS1=Ozf_<9=(9&?| zP_}(c+IoJgBjW%Xw%1did1zFBOV#)gJ}~hVhyo3t2L8a*&&6b28OqJuqkH3NjU-j| zfd9wqs7vZaSJw4(00vt4a;?P`eP?(O_%xcPlWOPEoc5KSA)vdrNB8>ES`pYMN^d{fy}T+2|3On2+0gGvLpXtrWCA;ol6cMh1h=?^M9t_ynABKpaMSBJ-srdoNAGrVY!XGn>hWz!mF-+`M^av zRp81b=R()+(0%3RTi?M~hw<~= zg1p*~aFn8)^vQ@>&mFuEbU1zp|0Ocq$^;u{-A}4T1M@2=+D+hrugY7Dq8Z_V(gF)mCjy zAf_gj6-~UBO`K_r7SM%5l=NbOx=Qysq=7)=6OpR!P8KISOVyYou;CX2j%0ug5QquZ zk$USlPH&*jfX_dlS1^N6rUt4VyXXjNCcA32x3D_=Puq6aL>I zjr0RFuh+ZYQv>O?J zNdBB+^ZFlWU6PgWz0e?yNXtmP9h7JpDC>jvh+fcOG{vmhSwbU!m~$BfXr~&WYI35V$l?oFF8`6PS}!J08r#bbEKc4R-j~F{6@eubv++Z# z&$06LgU(X_LR3c5=@xZ0veFF8BRw4!8&)Ct_RxdI5rx=axA$fi1AKsqU&-St0?L=X z9Ex_n>q04YN=PNIMC%q^;3^tuGi*RYpFen&BN6wva!Xa1?ix!kD=8h8)-4EL%IP0F z2bT=XAUmH6ce;8Z1vjH&i`K&e9%W?sKjPk>7<)6qAX)Fu!KOu}tC!cE5Cvi^ktj3a z<{MKS@@7keh+-U~kdk{H@+IiEn1M~E9)%GI>!}f6e)dD+FQR0gcXfh1`|bRHB1G=U z>BW@##Pcfsw4)F=AioEFsTrAM`R+lg`QZVs%na;;4U$wIzNp+NGOFB|P)Mf}iq2RX z=^{Lsbes7M_(6AY(>I_)rzS_8r`Ucm|6mTj+a9|CR@!lB$1wx<%*hUqsKunM^P(47 z(%>L5*1ssM_uQsKX$sBj($LkI4?(Q>1^7AI#qZX3R&TC$A z*u?o4hK-+RyQy2XMd}uQdbJc1ibW%d@9PtSL!qcRA0PF<#ORC4|MX(1X_TQiwA+1c zNmkm}A)(t|g2ga#{)BrZY;K?!3orU7k@YqkXKn6~_@@QA16gQz;Qf0yLqqbh_!=MC z`Gsw!FjW5m3PZhHQh5SP$^)`46c3ldaxz4oCygyAI(X&5Vl2B464pA6-W5VLX!{==VHl2Fm5nXxl(1)6lfq82e6r&&sD6BAwjyh`; zP()`O(P#j#8b+D9H1#wv_D*_Q;_O*qWiCCNJ9G6u0I(P37FYcV`(iCj3NZkiQld@Q zChX{vp`S^gUu+p?sOqf{_4p&}xFQT7?-uOi!!isWLfpd;00}|=4>7YBu=S1Yj)8{P z(X77TN9{0C@fMF_S@QXOdhG4EgksjpYRI6m*xKP1qNjlS7X3(Yb*xNaj% zV&~=f0-JU1S|9P20jRJ1vUU5KK0xnBqV(=LQS+TnVQIOL*PcQM@84`o{vcF zp~Y+1W`W};R;H-|UpC}8)xU3H!6`AY<6FxVxXULXlRv~!EP$@13FCOHSD}YLW8=RS zs+b@EFo-1z?s*_?1QZsOoB**FLmA_EF1e-pFB{KVHSzC9zAJcK`Z5R-!LF>QjueYDl66;202L>KN}g^uKSS}Y6ZHQ z4kcs;1rx*y?jQC;s!uZv~ITF7p_Pp#NI0U?>4x=7HSKDM;z~ zBJ$vX0NuFa*p_U7^`}63;-;1}L~-pe*Ra>%8q+1y4kHe1Y{^GNK?{c%oJI-ChHn{E zL5L9|hIr#8lPwgVAqXv;^{>>7zk~1GxU>bO0D8%s|CfytM-~{6Sd+&*B%o#U^BkpP z+sc&TP(vmdrxa4pmn`3u*WWy1`)oi)Yu`&I_U-+Cs}juqwz8}FhJQcRMSz&NIQ#|P z%TgJ1BF+&WUBmFiJ$wb7mip@4Ey|Kz9B%z9Tw6;@xf@(|C(`=wd6B~{ic1Tm1|u$G z8+vg`Y1HhOXMb*b=#zcR{wu+>merEN%mt8ekklb_OAvp^;}3Bp0WS1Z;N_figfvlM7F7vz~yK|N9tRO6g78vzF$Q|hD5)_C_qh_w$ z_VhwXt7CeBf_Ou4oS;i!`=^6DoP#vkHW7RV{FVU4omOwm=C~bSPhGnH<_3Lg)QIZW z;EMRC<Gwg$D)%><{JE{}m`?Dpg84@Zl7R8Xirz zvZDyUC~0e{tqoYRQrpA3RacRs)ziA=H`$Bgk6o?aLDX-R_0Z*BDcvS}_Et3Br{QXi z+P8bx(=u&Pq%K%lewUMa#FeZIp&i8TuKi)-lkd#Tt%x=$W zV`(@=0C;7h^vcu(947$k*rIi0S*;&eFP4Ft zP%sQ3%TafhtAV{wDZ+T9MOX`PNM8Ft(Vux@B9r-VVr)HdFsx+&P*m1Jw^7Qn_oIP! zIIJ}Qu<4dMqvJm}UdI=PMd!l(LXYt3c4dqQV<}U?3J>=>?-o80oE|=2>B?*W+H|lZ z&^P+?{43^RwI+Nq&Tq+q5?&1y0M$;|?Kol;sH`pO!LC3T3MiM?14$tH7YS2-#|vT+ z0E5=;>FL}QIlX|5q0o@`2QpS6I1<>!l7A`8X~xbWgC|18X%llU>77}lzLKPCrEOPs-&-M(0kJ8-=y%`BXttk4bN>H>-<1 z9WFX^Jb^PL#&z?>*>UK;_2zXt0o|>XSsw`2+nGnL7bZ#na9ToY>`aiQHQZ3HOM}Fp;(6mHk9?uab{dFFo6_0=Xhk46hpir zD{;8=J4HIg9BB`w{seq?4NN}io9A8LgsXW}cWJFgsiG z&a-3KrKlKOoQa4mfL@#c2;WvB61!Sm)f%FM8yu4o`i33y4qUKakANO|)7gO7xFy7r zt1yycrG$Gjhyzx$Mv#ew{P(H3KjAu;dFBDtg08$53)ISy#wVBmWEJ^3K@27Bn*|MACX8m?EV-2P?_Old>?B^<`;#M@g?6Wj zo#Q{>j7cnf!7jXV&+^d`pUHzIl_0kuio(!O36IijwWhBG)#E~&jJ!EoI@o)(D=;p1 z)B^vxv}EGRB{L+=__cT|P0+@J8bZO_JUL7O8RyaL8gdzM*h*)9Ki;Fsm7=JW`nq>n zM&$tRLrKmuA4JW!`Qp0^aKpm&v42{|QfS1z)lT~B%LhO8E1dFcjp(!@I3_bF$Y6dy zX_-^;_F@=$I)cR0!K`$!vtY{D^${v98^kiy8+*TTo=6%%LGaFOOLgm>og*&ANnlrG zHg_^yk~lK|fd&nO_?C1Y<~MHdt*8%ZwiNg@aGa+-Ty*G;Ode}2b!?Lv3}XQ?3Li_P zcaPRNQAD7JYHdW@XRR_yOPhcFI4m}Q1%|3ewp*~}LP|l9%?v8*PdG_*c*&7>bcb#av8(r~(`c>dTyZ;+(Me##Ru#;u)Aw>y*`Z}aAf%`OTiy^|J2nH zP}iO_I)#G0aLGrRCUk#`s}nba5sfL9#o6BqP^y;;shEzvTO-NUGceLF=6zIr3yt0W zfBcVMnxZ4l*bsZe$A=agZoXV%))>m+m}pD-HTbT$bgfvXLAGJ_L5m#(W_niktqeQD z{4(L@0<|Mtz9@`Mcusv&^Vf~X?`roiAHC=N#AWqPKH_S9_M##m;Uz~`?CZc0;3rH> zN{Y~DkMHrSrnz~>tl!acAv~{Xm+Ei4U zc+j1}za>AZC!UY>DZ=5NFMVZR1qZn*x^^~sA`<`N5m(qua`Qud<_u1%62e;^b@}m_07JfwSIq(J zSLMs-e+2J|4ayb!PgWK{Zy*A~H}b5t|6?Y4&r!vaHy|MF`SAC>BAAvpcDLy1YA;KJs`C*^#IH@Aq91F+u4CG#>~9+ zyyChexsvHWcdB}w0sY|4FXxE0Z@M1Mzv9Z0dd!$54}wE-M@$NuZxpkI2(&U_!OK)6 zply>CNY@nYd7xnR_b0`VG*^l*2yHA8vO1>jd;KeOV9<6WF))da-+lwj2bbMSXO2D(SkC z0y9?DvupE7G=~Aeu@=Apg+~h!g@ph}B$4Kvp@ICT8JT&#Lqn)%Wm1I#KgfxI6`P=9L#KQLiFmmHHyL?)>if*hyI&l@hp=)kXNN zAb*%FvS!vM6*uGH+vO3*Y;Ajx%^T3D6EUTAP%Ug5zJ%_N$G zek3TQH1TxgIJp)(4fpHvjE%1Aw$4kt?m(nKjO0}#_3k;C#49YsC;3+_ay$3qW8Rg6 zqb}T!%@VOljB<}0QMa!dcNzGKyK&7_J7`02H69bu;qBUP%S!^KD<)-S%O(L*M5L%V z$S?}RP79&)b2s%fGGFMkm`;gLi!e?#%qVtTv^i(nL?AaDq0y!xUqrC{D}1ahEhfMZ zUTR%XM5)4u_!)itB`s^pH;9$~gbM4#Z zLC6k+;jVQ8cn$x}*XFM^%GMy2^r}U$76)OSE%ZAG>t9UTO&&<2E~B-@$@I1ALacwA zfnC*`S{3VSO4b$s-_~?9EizL+RzBU1^_5WT>k`xwU;CO84yg~Wy-EQ9YVj|+A5=zF z%5`);WQTEyL|DxJU^^!q!`)#=-YKkTu(u78=P)Rm3`T^-Vm+*N1}6DuImu&dTPX#i zeyWd$EBXJBz7Wf8m;8g2!Gl3eAw#bT0&dadj}=a%lV)Ol4nzA1cxGp7eQ|9jwoTjY=-zR zwm5(MOyHumwYhZ8EUbiSeYbHnKUhHWU6Zu)4X`E9@yECU(IJ-~Zq^e!>q2TodH8n2%a?stQ$)mm|bP{_q zWNu{Xag}~7Q5wfu6#6NBrpn$nb}k^PgiG>7bgP4l#3^uT#)pDJ(ur!^)`)V}(h|6W z(KzSlls3$uMa&t8`e~FY!X5$^nr!Lx?4_bJX^6wFIc>tf?WdT1WQDqOH1up&BfukY zt)R5cq)5@iNBHwzm-mO=EY9?mWS{V_(6a^tf?

u$*tyC^g_aG0lclR5x!5h8}T9#@=)gt-Tiz1WIgTcb!+_UkBy zwzxa53!gp1NMPzZ3Xf4#psyc9OWIu8+0<|PZl>J1b@-Qs;|UM zXnGhOp%)P5`j4qVS-{ETvU4oMajG8Y*aLfP(dSsD&o7=sP=bsMG3S`X%6^YC&sAE1 zya4$2E|FB^!Mh(l3IBcF+}J zMh=~zJp>gZxq_qC0qC>1aRWBf@&9Kg%hz&%dqV95hzO(L}0OF^q$!a+~*eDyH{Me14nmU zk6*k&$5|KU=eVOh=-$br+0D)&{x0ruUKx31R;r{$s7Hx?Qw3pgdQh?apZc}dl;_KZ zsXYI1aB4$&PeD;$SMWfUplQo`_crP*X?WdMWQVtGee5ChYsFVHxi8bD)6193I^qeo zWC!7TQgCzl-q#@Zn*A^>%0w9lqLUMWVXDtRH5uMLtZq*AbaV(H+BrEB9qq}^&Ne(4 zC1o*}`+y;hszuj&VbUHeKqLK9dOSJq6X=DCpb-cW;aEo-E-WzRYPPiDo`OcMGf$R7 zf0dc`_(X_?!4y!u9gem+qn1BJtE_0i>-Si@brnGA(CG{Dw z@>Hl-@}XVt*hKRKj7j*HnVypIpi_Mh?`z>a5U=wUoc!SraaY)izmR0Q>)LRlRowqt zzaO58!4Mdx`rMX@)!yH-$J8=C2k*o_qOan9!@jBwm_(;y-3K)?j|QkXSSefw#_wdA z_wR>KbJHWmCtQ1$Z=Ug_aMc{R{bjSFD=LocHUzc=9bIoq<=uMKZ`-#n-sPu5-^NYJ z!@l;oJ{HxiX)^N?_Aw|h7=dA`&&4KCsr1u_%Yp%D=$6Tr>DdpXQJM&7XX4+hJHs|3 z0o@73+-bn_u9YcP6J_*e&DtXIQr<0A&X?6}@08VYbdlYNc1-Cz+n#*DIZ}bewKQFg z*)~&NhVbz;;=?~Kh~vl+7!8a%*#T#@=o)-p&)L5J!ZW_G0zb5X0Q+oIP1bbzBFVZE z;rS)UqBlP05>Amg+rx~n59%nzD~No0iX4k#G~8g`nH+($UPwBl@zw$uJfMJ-x}xmDGJAM2Yxj- zx;xkth<1)n0rvJpXD4fpYjE;3ju(`BkoX;&mS)9Y9RD>Q#oE3TT4I)i#;)cuFk$hf zAx`URuyxowYYqpw-3e+Z*My}nvF;4UPRGP#PjP7q=^BN+VcbvXaTN-X{sS>2SgZit z&(9uOv7!Iq^Mm4X*jC{6JCxDZ{=UlTZhv*U$`u1}_|w~f^)_*IFP~dY`$y!2ZRj^8 z5UIYL`P+-Q*b6s2J)@&NpXHI!9-baHfAZH60=RRXi6w%eHs9@p={X*GA3ou+<%tLx z{Z9$V+~k3?^Z(%Ghw=DA_i?~E*oB=kQaR^;JdR1Ce-9U;>u3Szu^wu4RV^tcM)-Nq zgJ7vW;zCGBXkKVg4SMgkNMrFpgAo!_F2b~CqcaI;5+6DZxE58YVDB)cy42pI4KoXN z2v82!|EGI@g-f`>WmlC*hUzjRcc>~L6qNYrXuXv zUpPZ#p@ElM642sL{76g`y=rk4r<-I0s!cecU^-U5B0bE*gJiBxPi(m9{KXNuxml17 z->^W|_`5}@^x5u`x#=EhrU$y4dl;|c&a6Qp&2P{kamxj}F>3>oj4pr`PKsYg@c>_1 zGEEm%!gB=1zP?AYPMuf9bq zqQ}E$w$0Z|6ZTHf|Ao0c^cK!WOGMMYoa;aJ6Z|_)oHZThm1ws4X-AFn;rl$r%koSC5dK-ctaOOKPoN-VGoAVzh+6FzS$uK z1uYVH$^`_$9A2>%B8;Y^o24e5D7lQmfx9-Yi2(^!wYQ=-=ZQC%gcjfbWxN6tGQ(Pl zDQ9{~bYk@Kj5T(yS1Y3*ln_Eln zPd3-zk!#U?YZD>6o(>xmvF-2f25{olfq8fG^5S0ZM-` z`2{BlX}frwg>n_-pC&9n+`c=4DDsB05h0wkFpYJs$?hAeOijTBUe8=zpLs34aZ|EV z^l}HySR3@hj1|;%JAn^lkzXF=zPOJ^jdYZ#fkwf36iNfsW1>L~vQiK~x@YFTMIbqZ zh{uPJpVOm~@ot97Y=FwWN5-&jD)T6l^L@h=wRj6WkPb_~4@f<)f{XZaaxTkH4fJ>PkCNBY=1?GIDg^d@@wf6mpJoN@wn-oU8=>oP@j zFL7c_qrZpWJ2EhpquB#mxFk#mfpa}kYC+(7klg9~zDT)!TcUeHJ(`lzTnJ04N3#>! z5;6Ao=F{vu65UhlB7*rXg)l*V96O;SG0py4Eo@JESw&TPl%yxUqKto)oanjt`G?AW zQLhTLAp%3C?DV4z>aD)0>OxF@MRoBKh?4WpxN z1u^BLzdcfJRNeX(=BTR?_l~Wp{(w2?b_ZqL2o1;%0$|{iI95*6W`?NG^i`?d}$-?;I8dN{1e|t0`YA^_1gr}+xT+%2d2CW|0^+Pw46Rw1m{X=d2f0Ry;Sf0yMnHQd=tLK zTp>QQER*|LDzgBe_Ny$z{q)SqvBv5PQex*=2h+Y`a9-bHEuAa47Nq`-4P!R9*i9f zE*5_Xh`E`T8neYViz$PZt(8}Vxj{?sJ(lcpU%hCr7PSr|FYDNSn?yiJWkQmUbTwP_ zf&JX@Y^m5^e9Vs=BZ=&ftg95x*t>RN$jvF&p&t7M(0{^ZgUjzKx!!UMjk*L;h7@`Z2|yzc#DHYGdbnET8+ zYo~so)?Z>r@e3Q8>)1k1!q-AsrM3PT%E`u1DWosRWR*jA+zM7|l9p|nfC zd#&p^MINfdymSb(eRK6c+|Xe})G>CEe9Jtz_0U zjdWWRu--k`qQcMnIM)C108$(GT|mr6auT^V{d01_fuv;13CLk*qw?~RVPOaigi%pK z5mXs92s!kCO!6)vdQT2aDhqa8zc#ay_EE3iBy#S}+dE@7f5;53DR2*7ux2JaLvwp< zkIVDx-riL44JGQ8$G2#}A(OFrw*EUh?=(b`M!YQ-0GzO#_ctYPlsu(08G{B~Co%5a zP!a=9R9}r0%)(V%`e3Lc+YP&4Rr3C(I43*9p^|rO68oDkk}%~BMOy1OZwZI)vAxkp zz;<=O0nQ+KrQt;Nm(&-w(t>uoLo3cOq6SbE!wIDm=#OmUZUIY!k>;Y>Plpt*))BJSZy2_18pyt6eyasiH{hlY7e-@{#24p^Gm-uIXtRhItv0iPQvWn<}7mI-OypKQqCEFqQ@$Jv0Npaj4z>ye)ecYUaCZ3Uk8s*tKDO}G^b{toqI!>`|s-h>nW zjI}n1xM<*A&`-%8NmTG$!*^XK^BFpQB=iKv;P)IidK&bRB%H7+4b~XaeJLFgdh~br zSwaQ3X|45WtJ(zLt^+LP2mjAoF~cN4{e5CuTMp^z#mr1t4eW+E@h%#cE+<@=3MT%* zVr_!>R(Cdg>%YS|T7wr|^j$oVHw0lZFG0vE{&llJCJbsP}XFpNYKq; zgk71W=6>>K9lG*YBnv^m!7h*Zy^Gp&!lPTCUV&ayz6 z>2Df2j$!)b5C8ScDMfp5Oz|c-oc;-?a@ZA?vLHM5o(znhNiq)1#}_0E@OSsYte{zU zfe4zN4T6@_=;CFltTAK=P?@`}Vb&&HTOGXSL`9Y<&C+YN6g-il@SC)$2KOZPlrI``mFDFX)Lf^js0RI}ogdgm~07O8$zh&)bb^XuL zDtpK4gLL){!#{7L=p^409}IYbDb+&9aN(OiKqFZ=McAUlGwS*lv@i~SrnE_~mj`d# zhVokIq%k=a78AYk*qnp+NSzq`Icz7U@O0!OkCEet_EjR+MKnv7m{FaWm`M%ui5p)y zpZKWbrndPV1Z=*4!iW-qXTWTFlopXdBQ}EHFWlMgRL)cwI{K%)KO!(yI0z6q$zI5- z9Q@&i5i0nA_KlerTs(LWmqW-74tA0G*lTfB`;drW1R^4kKp-&el!S}(nMz1BVTBK# zfySc7R*A}BMX_`4vm+^7(nr6_DZ0 zGul(Qk33Vm#$$U{t?y`MYO{2@Kfh{VfA}qX@&@DdtA9=FhisOYN9pgga_^Jj=0eUR zF6dqfkzSh9>T{B59$413+|ZQ!V~mFQu#UUS3S8(xHG$`Zy{Ty38+_)U)qY<~Rps`Y zq}MM0@s;Zb_C`pXms6A{p=ZIdX}9iE{0^HT%fhp?n#>b}CZ$;Ux| zsE4)blk{RbwiPS)Jl_6P@|5(AyJW*>)QkZ|G!H@KWLp%jEtDTVA7+n{(f?-y8|8X79g)FvB* zBLzIcj-t-Gg72lVP4H%=<@ssTX)oS$89SH67$*=2$Kl{7h_=g&N=Qtl!k+&PKJK%! zQXaxoGgVO$@iz%SkVB%nyh=)Th*ZH+c^7Jhj{uKG1ab3Fj=HCSDAJN*%~7)!)MgMh z_#BrMg`>rSdOKP*j>G7Y*4X*5c0@AD*TyzzX+-!7lmF#u6LX((K940oR`ATbl+7P`V@rwu)k!ORLxUW!H+bh!K zv$$tq_9;RJrMTxZ&^ZiZlGviSH_-4ts)V(qfwy|(lb5$bd0f5~LpQSQe{nc8)&Qbk z<}hJauocX{owiy~U0%?U;lZgqFNlj=2w}llF)5#54F;jS%0KNrw6C*dA0u zo}eOPTM+8bkq3h~t&~;(H>IIID);TFto?~7$ICXGqnA;bRL$cMw=Q+A$*0(`TC;HT z>XbPvxP~s}0&>g+E5$+GX!bZB35Zae&6NfL8m#cW05^qMF5$XsTewz-Ae&SqhN*JM z8@Y2auBEUq0&$oL5>O)q%nX2-?opWVDh{ieSU!q@hERo8AP%}A0dYlu+n-h3u=3+; zm>6nSIj%vY1$7s#9>+lyP!Ulw2>_9WK}?vrAbnBeGg==~VH&$|rRm4<`Qn_*;}sTk zj#K9Q7h}{Y!j2fOEb~LhSCrFonH6RwvZ8A;e^3>pF0YcR9wPl~X^ji}At42E+5plr z!#xFT%sHgz4)R0y18YOuAwu(peQ_7|VVN~NKcMAMByN)rcXGMOKg8vZWjb!q=K)Mz9T zb})=A_$KqKDpX4Na!2Ju40ln@NW=`g&PnvjCsHV?XsK?!hZxdhg8W3J18YJqoU}JW z9{tFsMNhE~r#6Nd{_HMor^Srz;rw2!WsPA+)R7e>lZk`HBQ2sOZU{=*G_C%Pl(2Ci{j6Q# z|9kRD8#ZCKMD^I^&KheGhlnI96~QvID9*Tm!mzGL$$RF?7a438?QDxj?(lJSeTjKr zd>vUdVAs5`=NDb9kR^?e?wnhpJTiCFar$`$Lid5l*64!oq*RHJW|S7{6LODEroVLH z-!r%gnlY_{W$(Boa`Iv^OgtQ!!jc{v_sy`&Feb*@X*P2qf2epx6gtTBV>L|X^{UkH z>F}ZPa#77l#PnU*PZ&}dOdEu>jALU?@&E$Tb4Bw*UNi3n<7!Bdo9SF`E-GKTZP=P8 z<^Xb|koIbc7xmjh{nFI#{g87rn(XrGBM#m<=dQ8`85e@XyiiudhH(a%u}m&jI8oBW15_yfxO~ z03zhVGkdTzHWeEd4g7>mMk-}J#WoC$+LasE65W3fGJJ&0+9RdrNb@iXwM2R|bZ6-* z{!|#{oew^O^unJIG76E&cu9fmE`yeiMSid6PgTA3v^zf$CsA?{v{$x}uH+|(=dXZ_ zWFZTZ$wXS-m_jWj(|wtHHkN0;lo@?X{T*RT{!M3qpxTn9UE**E^{)Zj-m_o7pZAf! zkC9Uug$ud=QQ-f)^IZiNCf?5TTrqz|R2v-G?c|*Dq%C|79D2CI#6$0y{f_d=^0rR4 z#vCsC=i01_&gpSHF7+C(!UK~zITG>5uyKFZTBNC{vbQ5LsrgUJbBL^1I~tWAEPA$A zLG_87%yO?xLnE z0|u4S{WnzoI3Mom9l;q_AnMkN&R$-FP{WsE$3#}vS=Vo!DlP4P`vOg~EB9U23Tg3D zU@zGfze;QF8{9`arr5^no4?iomLK}F>pJ=4YW{3X_Uek$Pj}CQ9#2p6&NDB(+*bvk zeEwYUn|0^U|M#ym*5&W~xVm=RaYTLRXaC-R{qpGb|NZ{0@cPQP1IF8bop+zNU;Wo# z+P8lWo@L#(S=c(M|9;s^W&iYXHPnBLezu`y*Z=?j^Okt|UHy-s#ebc@K5hU1&wmpD zRnG)I&cu4ETI{Fx(>(mBU%6TzQTx^Z{|++r>%Ra9pjo^~UHrD^{{p}Rn*UP)Y>^O; z>0RyY%YiXc=&3|~)FdLB#S2=Z6}3}DqIJGyYun^9C%h5!nnIHs!EO5YhxE2ES?_~9 z7$>w})Fw+Gx_YT)ws~P@1e5gci@`L@J`?KWtud&gLH`Q2`pCaTvO5PY`(iM)OZrop zNJKOyBMa?~qyhX$+=n3a$*6u5g(0v-01IccQ zwfW?hi6PLx%J&K3wdE~vD_+~fV=N6q!)sawB` zF{{q}KFC?LfZAi=d!+>(h{ve>E9>EAo&ty{k*r~eTnzU=az=eU)aPF3yD}C5&c-&3^9^uMeS-538$vc zEVgLZC$BcQNWszsY1Uv6@*Opih|71L6GQK$^yKMkOW;7_^#E3qTzGZ2gA}mL<8U`)1 zci&C8#>m8Cfj;v0#1n%rv827iJT`c0+KAfN+-(yYG1l;`g$Uaq+!Ga-?>rw4PEJ^K zuTAjy#4@$itO`^3_=H4)WR26V=5y2UQ7?pvZ!N9(kVr6S#ix{*J8~@z^FX#~0Fu>* zu3l=HaWBll$GN&O`$G}WlTvQVjX@Nb>q%`MVkb#r9#yVMAez)GBoXebl3+SAY+h}f zispouvwf7pv$I#ErGKZRVv4~Nti_NNjf#`>=|k5*S}ccdXCp{n>SU|NX1}j;GtiDv z(u_ydADMl2r0}d;QUwbM`JqU6Akyq8dPVOUr~+V2lW-hWsdbp7cxd>POvRNudetT` zVQ>_t&0Wf5@2^9M(@TmzF-6D`B;s-2j$WCqR+UpU-Bns=L3XB+m?fHQPvR=%a36@l zy9a4d#0YQOu;dP4`5es^&lNr0F*bsv4r1NI*2>(IoBov%?3FNgnAu1x9fEClZ$w21 z=$&q}QZH~N?_GrcG_FN#$11AZRBd=yo~RqoTq!+`-dY&M2oHMfii+|<>YoO0!nm_P z<7DYxxz32eSdg+Kbp{dFBK&b%b2MfvrPxcW^2S3#-Uot5ErJ-82uD?F5==*?P9C;s zS5Yq$T|#VP*)A{$`HmV_@*_$s-0;~`iD$!ErLa^JSM1Czky`3=ZS1MBu$0FKzTiZ4 zvYjhu3|e>jBE1z1gy#-N$k?)19H_k7#G21mM`(r@)h_Ayps@ab2@#$<0RWN3sXsSj zjg5ZUQSYR2ieRn~J;Y=b%82%*b<&hAgOHKO0)5o3oMtl_OtGZBBK9gJ(?-L9L3i}YJfuvzMC&RbmBZ1e z#KtNN4YkDBlJRs|HFXS<--j52ABsR=ha9$yLj}9lkhH0*0&Z&TS?+9|kNGv%1~SBc&13{agcxeD=@{VK6#!vu#~8_CWwv{a!pGdV5F<<-9URQGHC*Q! zL*70&p~sUKy=PNZ_+YtV9P3}Xxl-&lA18PASnbXU8&pv2@0I9LPs0*Sew%@DXBHSr zp!c&H+_;5HYJ&Xww}XfNZZ#OrB5$f#a1KwK(jSb@N~7(f;;88Fzc zi-&UvVz_apI0)x0Zck?yV3WTR)V8*}CE%ow=ig1alLu#apUKlpI70>35%T#2;aDet zL;i;7u%6DMNP4K-yf~6ZPrgHB>Iro!>C^cHO)-ZeB9c%cVY9o>_0vnJhe(*xZpnB$`$+Q%06LDBVHu)e zj{^|+nn;nNPq*Gx6%~|nqZg&9xFppMPp%F$BT-A#fks-%p?Y>VpX|G)5ZUEnX=R3+ zoHHRrX|$>}*(?USUxL<(ktj4aPXKc+F-92F;=t5_+S+b9XR_(j`OnY(=_TZ~8%N;^ zE3MGYj%pPAkE9H=U zqd*Q}b5@dP=6zd6O=tJEu~k89R!gwUKAL~#PLbgxT{|DZOe#kT;Te5~v{j)dh9S6% zQ=0AjpFvg%KSU)9^^wrUuG7vt6pkIj>DTe#OgHociZPX%RzYX$E{dXZ#vrUlZ;?zp z5*Y~xOIUV-HM)c|I{5l z0XS8GBwlM zam#*p4$p1H5}yf(^68M&(K;4=RwBj9LaRU{ViE5M^Lx6)nvCZY7;TN)GA%H_pptST znp(DOESwNwTnXenVt~}Z&&L`A1Gj!nUZsZSQ?4JzmBkV*RZkEfuw=8bQvVFZjHK-( zGk)HxX4Qsevk@eeG*(s`Cdvw#w%4?!njkz41BPLo^vDF2taA>XV{c|Q9ptX9(W+~k zeN`5@*)+Q>tb*MMg}h{u!bqkc=YwWbx24EF7Y%A*Yj=_wJ=?(aAvdb~(Cpxm(f$z; zvO}RtgZuxV+sG?1)G>a4 zTUZk#RYi7siVu?nKyXF^6mZ?)rn^l7qX_+Jsapav&}scHEo+i2_8xOo$rAZj`vEjT zk5`tkGEngJ*SxM>ajh`7Qb6Be33f}>GdTC4I}3?*JyjjDW0&%MXXX_EynXahED4S#4U%ZU^RdS zCTb>Ae6wYuLDWJM(b-Xqt^m73S7e^;g@6?wyxBY;3cCDDC}(JZ>RT!zKUh&qb6LNm zx?3np(^xumlT5^1mm#^_AiDWe&ij19p;mD_l;wr=<^l~6U||6>an%AL$~Z{98O)00 zYiE=khcZ0ZM}zFx)X2kin!3e;^p|i@h&*P6X2{KDBR~r75EtbtlgTE;u$H(I5D__} z21VfReOH@kr5N}aPSG@yparLju5bt~hXccxvTSup;dB9$#-wWI07`O63-DPgd=w>6 z_^~(W!N(Ej5%$Y{0(XgOX*V9a8L~tX-5#raq-2*k8n4h_I-9ptmFUydcJ6Q%* zNHa&%EGw8=18|9p7QjJiaOov65T6 zrDmmx%nUL@G*YMCX{!_`0Xd?`Z{ZLfCTp0}6Fqm!XlzO-)RySVT9kDanCRD7dO(|T zrs{ajHojKe#Gi#BEq_u7mAGpFw6+DnlI4B$!-PRxB)7ZW4uH{_GYcqapSgzaI=Teh zY8O#xi>!l*uI&)sMZbpp_ONA(&LzU2kzT=3KW%dWh1FY16V+1j=p5bDrqr?7NwVdA z%V-7$S@ZQSsk4L`wF7&+U#%%kTVz){=*~i-u_r@OAveO=yRzGhtJyj%Ggx$#X~y(b zz0a;{6=clqB)!pIF81&&vzpP+ubW~8BGL9MgR6|}N{?0YB{K`h;u*bFQ#&8rJ*c9Q zi3M_beXdYUOiFa=KBk0Wa7SfYN&7r*AK+-s?rdu~zvh45q03|&1gCs3u{RO}$bIu% z>}FKCiv_tfa_1>70WP)J*`%$3!FN)8%+*$r7c+NsP5m3U1drKDC!5=bVA&S-4{o5K zQP!Tj0KcKIof7T;SaW3fhE!|}l?q?}cV$hq$vGu}D+%!x3&#G-_aa&zvrDHDp^k4d zOUtk4cmrXhK?1~KXb*7;vn_A|9GuEJ2co>h3W_61so5Oe_zS+&mOkFkWBOiA1FreJ z!RtfaLA7L{?;|t@LWXj{3(F#-*MBtIs$c|XnR%5uPMjz5#)p!Z4OJrUDMrvR%1syV zf*F@Ps(Y8)E=dralu0AVE#^wc1*=?eRyDTx#6=Mq-*qx`C(LG~3%8v^ZXSC6k&d{7 z-&6H}XrK2Oi>EC({6Pb)i{7?ENLXlQ03a%SG9_|_pxQi!nPp!#sf#6jzCT+5XG4hJ zNBN#}Ow+IkxI!PYD9vLcZtI8o&_%Cpj2Yq?eR@sim2UB@|1xqgL&3!!yPWsy$*%!4 zF;xNPWF$k>+}aokfz@;RV>_fk zacXMhfIHNbkm$G0|E}lVdJx)O0o|) zho_?0&pDh3(pqqxxB%RlfNnd`w@E<|r5HutY|T8vsB=q4jQ|n4<6jO+oJ)v6)l&w1PB4AjDBd zyoQV$!(-MyI^>!T1bp8Cy&`^;Wun8&sIXypaR&H>Y~3f&;oS(F3$K|}Na^nzM<*l_ zmAe@11p|OW9daHEcpiRTHg!bT=U=I-x%;#g!e*&|9>x>`#eU_v-6MBmB!e`xf79w) z95+-xkvh$SdWQHaUe-de%sJ}edR(_uk?u4=8Dum?St~VNX3aj#J_Vd|`!;(k4RozY zR?DTLRAe!}MtUP<<*u*Xl3B?eYiDzl%G3t=xRv~F;Pqq)KoSY*B@W7YO?X;NLLKMT z+54hQK*bhsJtPRY!8n}vCpE5^_f-z%2)UNOFobxwud4z&(xDC=3r?;tC}GTU8-4T~ zJ2f+u1-#qzJz$bRX%sogyU=&5Dr)HOEZK>LpqEaGz(JXjQXw&7d=4QwmcBW-F1@R$FKiI;C04eBQilI?D-CD~YpiAshG zTxRJ$?ef#mPEeBNvcfU%a8@x(G2ZY7=$C|C&)%9VN{M@GKM${@2qs#)s92ptMYSg{ zy>sCQ_gW1gR(+D|sul=h(LdRpgt=#RnR%c^2C;B(kIQ!lIo z4^Di8lEBO3gHKi8NChL5#%qA!b=lk98^^1Qo$NX!H`yy;_7UtOm+YEaf}&uHjn|4y z@LB_5S&XBWsT1uiykJ7L^WZxM%MnMI5Z&?zhEPXd_jtLrxy9=?- z#$cCw^QW83^gUu^MtU5h!gN6pgI2$;0JYTuO_v@M5ARW;)3dmY3gqr_BTEiRN#@nY zPdyw!W~E;j&08}$)vHHHVl8*seKxXvu2Ps7Nopt0D>pf6U#`38CZH4r8wA9>4hZ8I zA#JctV~I1?4Je9Tx@_wZaGT(HKy>xoF@;d>rb^O`P0H&^<)*1I zU?n}&Wh{ai*f4aBwx2!+d}G5>tH7k*Qr((*m72&#q5lmmaSt{F=TEwqR+@FcjI?cv zw7yt20PCKf&kYeE@lmfCWU6~%Xt+5>L)~e;l7yM&IxCJ$A=cjfR)CDu3I_t*pqa=1 zEoln)^~$6K%Z-QK_daL97UZn*!Xii}ZRd8gAfUc0JRScM+ z1Z66g4k59HYdcsyGbRKBXwB(2XNwT3PHYTbQp)CQk+KDJ9ZG_jy-i|_FP`5;7Gs~e zGD~}WN+EDPa=>^W7uQj3N$|?v!E;M0gi$yk!#IJra&H+6@#gtmWML}YazNe}XM_BK z6YFimm1;H$OJy|=T1jZP!b!PXnCC47Vx4cW^vV5kA`kzITgAz+D?4RiqkoFYQ5`l$p{uP%t5Saig7d zFz@c53%D8O4y#URn$qpXs(=bW6?Yk6(wuMPQ1!tK!{V}m0=4(o+}v`*8b?tW6I{IP z<(64NVmT%>??OFse~tHP?A+@RcFgdwHm4T1nwaA(k~Iz94%FXO=i*D}s^4u-t*0S- zdE517lK0O<2GmR9?D6Ac$5FOxfVhk88cz z@BaCxcF6x8Ke6|b%)fOiX0&f_;?URMx}JwLkW&&d!@zrlgmTab_iCp2%&qqu!E{0; zWv>rfE>!pzLf%_E^9;h1#0E#NBisyD$YKYOArqy1+KB0H^$hUzHiOg5%2yS*n#R+7 z1@As#X&Ikntp+J~2+!m9OfQ_n6W=cnmFIK+4 zBU~1__3r2M<7q?_#%HRdYPnOSuY1lR71PLEC?1X>j!$VY<{CBWED zt8znOkxO=!*z58rL1;yy+ud6aF*GcH_Bk=*T&;TzGEr}9=%Dp?EqSPjc;~?=hOCYqtq8ZnUEzr*~ZC5nmefPMA!Sc){jmMh)xrx8e>vvv%i*4b$Sc|$ay}M8HL~xSKIK8<V@HLPUG2YJLK%J`0OKW|kjn)oysAI*x|p4k_GBp~g2~4p+UH(Xz$! zGg4^$QBziQS)5A@0tfslhL;VxrK%dFFflc8IoY+oUbk!iZdqJ6*fdB;~M<05cQT$R)(>`04 zPv){h|7XXQ4nJ1U8x3w^^7N={R0-W1v?Dw0rlW8k2qyFwJsdTN!!mzC>oP)MTQKl!s@GI6Te!?OPn+X4O_d;;ht)s>NaH zR1vnLCFa&G^$+j>9CgHtP1_V3UIk#o@ERc{Ujzv7J8Sl%Pmx8_~lrVD)VA1 zVnjqmE<@yyB#p6EtpF}gcdrEkvcp_>>AC$5!bpz>emKCZ&PAVB202D8^Ijp?Z@akh z#JETogw2eb`3A{r|xi6Lfj+En>z4 zgNo#ViBKHOpMAgnuXfHDJvPg!R)ApOZ8y0J6VM}`KT!Y)gL-*)-4QR&_EY3)FBF77 z51A0D;ayUhQr@;fzjWftx|df+|L({K%+$0W!R#^Y(iS0AKr|Q@YYmu+j@)wXjl|x= z=fI6pI=rfwI11mu7s!FruhF9sBWn~;>g=W;VOuoDyzR3>V)je-;QVnd z58XmMvO39(w^$HRnJpPXdZE9L81W(s5z^d4mI_!oX)k~Zefel8aK#D~zWffGP?9c| zZ{NH26IQyeVxy>5zzP~QzkB1Nz1}m|by8h&IDLpK&vvM8?HSIzzh2IFe5e}`G0u&b zQZ*Dc^+yd+kFcQ5iw%#FLv<05@H~9wy;DkBT9f9LNpixXRNxE1d&w!np!6faoDY)X7acj2Mz!q|7d$ z_huGXQyuo{OFWaME1&RV5EP_Hq2El9A!aIesrmm*PiDL&F?pPYxSLve%J3i8h&e-D zE1MwrNtSx+fQ>$7^nJkL8N zyI&z#e5z8S4FZzt1DEvp56}CNYcsU4J;F~FSA>Y#4ME>nDxJ!Rhyt}4rlma z8RmS?o6@P51(UzcGma!9G9H?O4Iv6Xr|@`^!hiMR-I^q4!uX(wIaSjNDw?-2L>I-I z$*ic9N=kgQ|1KeqMKA<%d7**Aw77c)S`CWy6I$5>B+fu(#VB14$eWdJi~uK~lQk+z z9g_MdFi_$bz}KKVYy`kRI`P1# zdk+PK3yxO053Vsp{ld4?Y-B}o2uW}jm;+=xssOK!y`cp^p}fVNQQRS=f={5NDZP!j zNOxK82pOQcF2(&~D_gyZdT0bnkB70E>^$%^!N$KL zZk7U%wm3VJ#j&sGMR~M{gy0(IjPQ&05aA~pAc=v<>+SE5E|BDHeVUy6;`Q-+cDq>d zrP5;$gvj*WVecNhJ*L~_w2)c}2n`T?oofV5fTv0+A?iDthon5dfv9b?GPP>hV{2TT zb3q7E^m8tKtZ&N8CUM(<+1aI=v7DN)l#ltBmvJ8=(eIJfLC}#^5@X-*SxPOi~jFs6P$ zi!YJI(Vq%3!!!ec_pA@Bq*!6jePL$}>=06POZ?pzGyxTmD-Yxv?E^P%HWSq+DK z`QyS8D2s&%4-mp+3*dbMIeroN_R=g1s3&v}@gVQH z8vW~naBYo*vpoTcRP;Xo;kYsTDVK+&mKu6z7D|}%dJY=%me1a+k{fD<1h7r>6#yTv zAR5|L4ZNqw@Q`8Hpn;7qOrO3KzraPxnx=eY7fZ)rsMQM%WR3cfC?*vN(xcq0w0WP# ztDg|g{e1d-d%2zu4i)5MFEwuCk9NSa44LkPzJLPA((kHyy+9BH*ORDZg~{np%AIC)5`JVvBL*IJ{v&N`id71vx1AfQ6sfvm5mhnRi-luB0XEt`JnBQaY{$Hp9eC3+0uO9(@9U^WrvT{Dw(6 zAp_`K65L0a;>1v3O7Q5f7O~j_D$tCoE=@!BLJ>NQ7GIvPm-D2k z)wMe^oN!oblZZ;cD>}vA{j1bc zKoioym)4O8zybpY;6aRSG0tmhp}y^G#@ z(;8~lQ3V9IZm!u!KPt=_fQ`C}cV3XAxCi5WR)@VxYa)DLBrYn@AM(VIM^-b)ozVPQ z#ohWMaXq{q^IlL|nL| zZS6~JQ)q}=nZFU?R$KxZcb*SHvB`5tLh3BFE{l?!D4p9^`{F40B-s|wNk7L^3}*#E z_DCs8&(TnH4hL^cE~6IJTxZ<38Q@HJT^ZzJMxCk=p;d14Q5!oSqBw+~)7nC$+pj|GKYG=S|JhDnKQFG@M05YK_lPO7?W;eh#w5oTY7 zBJ1|K{YZcW;vf&1yD6tC9V|GA$TV*>LZmnB#+@obf`~CzM3|jj_DpETs7X|K>bnV; zB+JlAp-E@@A#xHW^AgCgI5!(jT&N7-CqxpV1;0kQ!bd8R0I`O}da$1F&vw6pDBFyr z_3iAm%-B|Wu|DDh&AUDO!}HLdUUH=LYGw)huy}_;LQ6G#!g>Bf6A&&EQ;O{@tURNh zDoGtl9UU5Dd4zvE2U|paNiV(_i>Z2kO*dlFBKOWbQc;u;;fds#JfEV-o>p)62)5*M zVjv-V!o?i1z0gX`cLgV3H>Jn%pH1-$j^)nK-Rs>`58cl^--!vISXvOfJ3Tu`Q{p3* z470Ch{A3^+AnnHZ!{ShVP=LTU@0IXn0Ff(C=0Lj0+0{S3&ty6=zAAgLo1KL*lQ8`j z!mM}djkXis9RSdOV%WkYHM|6|~7>Q%rHP^ln`OnJ0u+JnJ66gR9Ilbe=1NpV z#eVVkxIi%qXV|z5c%z(?dtf@L{?X|SP3+U#;DMs4aikTq-NR~X^(D@Xiy8AG0W?zn zVp28XgBmx~VAw>$39U*QZN{Nv-8;H^!2tquexi=uKiR|)Hj9AR@G)uU+yL~MzW3)% z}A6<)RtIOr$lG~F%(>08;X(8sQS#Oel!B>dz6E)SX z8&IkiSC+m>KI+?cZptn6K80RCeAD2#vylPn%u(h~^SKa)@7VXEl(2_)LfLvQJL`<+ODBsQmJq>P{h zhz=g>wcFUb?}7Frf|H&BeQ7Vt`HY36#JaUz$jBPS-q&*L@Lafn0+)%H?ROb*j+^j0 zxuk2Z?-%Mtc|j;W4bbJL|0M|L{_yX5rlOlu4TQrDH+u zQJt|(!~8P!Bs)(DD5ea)d|Q#2`*ar{$gmPeutrv51UplOdh!u4067W?P;pgoKV=l9Mpiahc!X3aYcRyA_fg3cULydECS76IXpS=M@N? zU+5~C>2*8N$;O>$ccRmjhn2a2@|rt>aZZk0vD!j+A87_QxjzorB5BHCihSmCta^E2 z953_TIau?fNecsK5naACFnUb>eSydBBv0K--dg=6 zEI^V~0is}ORI;;0+XD2ft}qJtRtLB#Oi-yYHPCRU;w_gz*@n#1`i8{@<(Tou=e(qX zrZ3XZ@h?FdEW+w;FYY3{c8`2K>m;~MI>)BzemlyjSuW_Za#N%`;5=aU)R?A8r@;Fb zREYLnzAibmy?S)`P9gC=3U$|fPl;4QSuwoXCDcR8;T`xG#`!EdYBn9@!^Vi2JB0NZS8jRB)6)#mr0P_vt=ygOe1Iqf9+OO{e!> z;@#^FoMD28N;cifYv8L)0PQHloVgY=Mi+7XVQei=>fc%tKe$4(|8P-LAG5XksHYxb zI`&6-L(#nVm<7pLvAO}7AQ~f#7L+n#spSbBv*98i!#ireIB~;xk+Ef-^v%1FP(~;) z%$|^wI&pKFBJ*ItM)s@pi-&`YwwbvO7yGthT7mpXNbs>sHCk?=V}VEx>O#<*$b5#u^6t6l)p6kIYQQSoV>-X*h2b@Kv0tyI=UcAo7mF7X> z!Y-__aJEIoo%G@yo>PK4`{`_dMsj$39V5h<#aX&{fiP{}h77fzKVR={RA1}8Hgb|_ z9xuCxp7Pzv_TwRd_~IKk$Y1kC*&DXWPwx|gcu)8#wjo^s!Pf3vX&R8Aq)iaQ;}Ckd z%DZi&WZ6*2O%?Y#ZsP?l=l5b7(=38n)G$PHSJaPGr-(nmQm*uE7H^-cQo9Q~UwzT4-=yBEy+H+>u7 z$k`i(1X&WACMJi9ft?QI^vyPQdy$r8o_b$n0EN2bU7onj*G~I5p($9KzD~W47h|V~ zoY4GG*k|_+b}O^c=`$`lVk}R8{I@ZFCSR;uvLo>hh!h}_=RWxeEhF`=Lo|aJoY?OM zVyK9z2cO~}LUnA;z2I-Zc&7t1RA|N_r|_TWLYgRO8s>I7#24fAOX9RI^DYO~_BDIm zszD&bvX8!>z)~ktbT`ZD6rm($Xt!O|>tO~lNqwLG5uGx7TjUSbsO${~AjJs5T^4!c zLR8@L^KM#@qC*de^on~a7`i|)|p>7R7_iZ`O^v-p!ICo2>X?c+Wt+ilS5 zl93tkY3J#e$j1x80<#N+19W-JRz9@7Cx>qJ&@H0mct7fBpuSiDIp#Lkcwy0BJxN3? zRyVZr&=ub2G?r-~S-8#l5~pJtHj)w5WA ziF)*tSRf#p^>AB<8ZOt%pK_#!9KWa>hiN$a?j;}->f{JVntHUK9u>Bo!~szpI}!P@ zWK=x|Dw4jSRSwmH+i~Gnv0>nY3WZGB?kxZ8Mu?oxIW&GFrX|3a0va_ts&#hvd9-Y@vodR9 z5^Cmif<~GvJ^cBPZRqcpLsA z%5Hj37xKRmMfPPs>xjuS0%&LG8^2+B_^CFhWx4=-6>r*q{8SDpZE*mR?i169gH{9h zBH6bMSU_;sQ&36L6p&7Ri7h2xR0HBT0o{j!1AqfaZS{QXY4beJ*(2x8xSwe-+(a_o z0yhJ!SUt^ICsLGh`J2_z72V)=^0-%oYgv`8rnVoz+D~v-$~{tv+k%Gw%?jJpLm%5Ed8ky;U^K8rAMiwbmfnKQ_^jsIk6y=wkRo35d1=h&!9!X0x_+v~XrlSbLY@)};5~@xk@!r8n zI-(fJL{4xx=2`o$^ z)olG*FPqAm`Iu`Ng-XYTX;zAzBbB{$z0V2Z;o3Moen7IfiBNBwq>W(xx34&)|g{3ucO|Kwe5BCY$C0$&BV+%`W8trxL zyGH8`UG78&m$Na2!=cti`rH{MvJ5`h95Jv%${9!-Zrcd|UJb85S8biAwSd;xDYDK< zt>#vWK`f+c!{a<#u7_iIF^=#d3L?;_*dir&Xb1Z-KyXWsW9YMW&EXct75_k~PaKV=qR7)2$PLu|X5*ahLCfGUA! zXy^4rAx&MIJ9BVJwo_0zMWJ13Y@BtKxY0!mv2 zV0GfU4&no3T{O7q7~9`yLrak~@1H)l>U#aKbA`?kR@P!cvklu|e@+Q`S2&xj?1`vfxgN8M?{jpg*UG3nsm+_ z=dOA4>gUc(!FUn?)8nk;s8(Xb;Sv3_r-~hKc2U7MQr{;^v8hvuj$eW9>Ym75s=waO z$ZR-+1rRI&%XFce=|Bz}4L(}rSz3>L;(JatS9c@NFP>KOvq7j0G4ES)`U;a(1EROl zN^EiRfO^Cj$8RuU)ipDu|5#X|HOUNZmi~xTJa!_pO_HhJetC|p1%7Jv!z+VD`($up6 z@_rDi;@S*^=gqM?Kgn$<4mBnyryzQr=jqq`Plca~?59WPZl78YQ66}qrMH4flD}52 zxO7r?gThV))C}T!ZhytMg`%7PiwB3K`UX^_lTm9Ik~8Jl zn$?CwaFn`E8Y*MSLyD4u*v@AQ8irJL-sP?`zxW0AFj(Cl*HtSJj*-2uWq%-KcaMqc zstq}Z;*oKz4kkLLBqC#-P$_q%7|(gzpY5Wpt2}i^J^6l^c1M&?MPq7lmQqtnbj(;@ z{NuZ4b``9BbDTdR=iQv`p<1~YuYauEzzUVY>(r`ySckhubaOEYZx8FReYm6R(nVG@ zpaT(Q@d9HeBdE&oXn3;FlXstLW2IKtQp#?(d3t<3iHVH58!~{M4y9+u8p4FmQlX@5 zaR_T^_<{`9v`YAst@7sa9BzLMbB(>mh81IdmS8c^a@1{H8)_f6m6igCzqFaGk;G5uNfs;nw?d|#^avWG)r&E zC_iYltn%7h@yq1#`YGp>W#eg8t7a9X)wTL1;dRyHyY-xZqAJ!W#64DM3hI@K#bI|k zZ*#~%Dyi;k450b!9Mm+@U0ct=)jG+S*=MJ{gY%UeWREiibTQ@LF29+s-1_|TdJyOB zvgzmt)f?}qcP@6rh1Li-;!u*G{ZjX*in6&TR2ZSay@&i2a+P$sJi5wnV&wM> zpdt=$L+ahnLLxy+k{#!Cv7A7H8Nnqi5}~stJExP9u0veLhV6_{z-+B|yj%=NnxlMA5;X96tg z2^A|~xObQG$Vrv=b`;Up`{V*Mb3}W|PjI1NaD$>O0KPsTYzRzCN;fE~_4K$D@OhT- z4eBJ{BDHDrv@C(5rl2`{=1;q0RwerCl)BP|yZCo4#N!50Ag2)sgkTATQUKQ=EMSym zoxSG3HGu1)Kw&}L2vOHYK{y={F{NPJF++=#On^KTH3jv#n*unFSD4HTTpPG9Dil&!i}AQND&#ak#Ngm+#DhMP zHA$~i>4v*Kppe3X#|@!@oDKvry^uQ<07z3^=>Y>UV?>$S>>qQ$UsEd2S0m~UPI2ync0%?s-IgM7pexhPA`1}p- zSx+;%`PL^x(NI(*_|k`65hcYFy78-p@a8o6(raWq-x)1c6M`+ES+~e#Ntm#ZZ?zCU z;B-lM%GBM=LN&l^~BoUdR-ZsRaM18~+5DDn4^; z>nOXnao`BmzllRMcbDNtZ@I$SrP#7tqG+XErVY1|+fnRzpQ0Vr9PU=2EDA7eaX~P- zC$H3epM;s-?CUf+@m_-B*>wr~;D4?gg2|;`d@bYf(xNK%hQuB-W58%-7!;d&?=r?m zSg*|;1M{upO~#F<=*4Y-9pAZb`fJU@7^2AEkdKOaRS==&u5Szn)KmBcLh5~QzuL9x z{ajnS9J1FqfYxxpB7Y-7{M966L5uv2UC+=kr4L-Vf`mzIb!|*G-qDNv4S<@8#f)J1 zU?5B)e{F;@+%vP(RatYYY z2)8(Y`Z8E3G(ZNSNt|*ZzX&bko{TX!u3%8p|Ccn%P;obfmXJii*^K1AC|@bm`2 zb=FlM$a1ZQ^O~_`Y*jgj_(F9-MH~mvn>{!C^W4@odEiF#M3{GBI>IHSQpqI+2ocV<-{0)THU z1x8vVl|WeQD&9bMjR=|5b-D}(xfn2?E&}K75Sa_*&~cQfc(Mq3?i2wiBbNUk{cWtCKnGw$IzVDYBDQI_AuW+!#bLxEkI%2s26ItU(5*;jbp5|9BVS zo`wvn#=7~3-eXRwVGef~5jX!YT#TOx%sbYe7qXiB3rdpe>2tM&6Oe^Ld&Vd#o$<7u zyNFYV?Y>B|o|^$F-DH$1f0tDr1bwVoUL!?o{D|vN;)dxnuh1l@r&^ulg{3_(b))Ht|h6qLr?UiIZER87AANgl=Rlg`!_=hoA&tWrBq73tCL(or-J=U@gS zB91{=5P+5JUeJn?Bl+EHwZWp#=dk1G>Yl$KAqc+Oo)^=KYBIZBh(k=0k zHfD)Z{V--~I|@yXQ7#H%BPO{8KRp_K_ZU2S=m)$IN1|>n_bICWKo;srO_2^c>|cYK{QZ4;bq!nm z;}>JS)&B4I-@k3vsr_Xb<<{!M*vqUl3{!DBAWU470Y?Yx1_JGtw*#P+*cvK{QnL(9 zL|uY?{JT|S{`3D|pQ|GM`Te)=-@SPD=;4F=^?R+YS6Q6Q!Go!d{z}X-JC#7mJJ()G zBPVH1OqWPs>lqu;-*$&*aWwxEYkqAGuTh+!WBhO~YJV&!p}ebDmb5ai5KzQGS;-~# zpY<$r`2OX0-+X-k?8(g|-2ZsHoU|;&C6glrxLdiquM-2mi11^z?I$6uJ{#W^=WTF& zcx43|pN=0u((1Kq20ieaE*K*a%~TqSg@Sq7eI_-C(0~=hw{Lk9b=uhmh24#aEr>77 zyQzV~Ff$KtY6J`{g!y8QkXx8tYr&^0tZ?g49=T`_;oKHLN0dcyG+9aax8OqM1f;F^ zezZ)EL6&zH&0H@c6}2uPBZO2+VTJ`?iG;xEN5hTJ3Q~?%>f_-C*C(e{*Jzsdp*XVa zG03cW#vYdW4wt*Bv57MHSsIN>W3NGLcMaEmyuLg=Ovl5ZQiH}~qW8&O1S%?LnMh@5 z+4Ud@yy`+ibJSstyHeot=0RZJ<1?a_& z=oqdDC@%LoW<|XiIwyxv_NG?^F%Nvs!cwGbWex-8KPaFCBez_)9D?#2zNi@Z5dK-i zG-U}ADDVD6xPY~4NcJzrWakPL%Qm(lK=9NWB;4D_tW6TMO*_B|GflBz%{E$@t_=bT zd2~R+;3bNl;MKD`Yr%~yS=$OSjKE1D-Viap;JXD`@FCKw@Ovi& z@MS_Cwn&VpCyvbHu#9n46IS;q?efkKuE31vq5uu35Vj(mzXz5$Ncgaz^E{csB;EbL z_uLn|Ynvq;_OTUNnWz~E8uYtSLvf281_BdX4Ty=WoQoaC6hD7yeDr1V1`WP`-$~7P z=1kR2@#H^j-!_qe#_6$Jgy9}F^+U~d_ zfEViF1pq(YuM@{`RH^F<{`pNfNKxz|thLw#0cvwmQsgoi^#_&C+A=jB9GZO)eLd-u zX4I8~sub9QntWZ#^x3d$Q_agfUe4nYM5XwMh{t654CXxbp^6c2F{HIjbL^B7yCb*5e-ib34q#3#fq#@78FWz zm+|Ni_kMs0K#*;6G4q4cr3zY_45*Suq7B*43`QWH;30se*1G8m9Z*!+DufYXCYp`0 zhvo=aOGVT`4m}@yz!1jhzsKpofhABT3Bh}icpKWM>4ska(&Gvz=Gx2B2=TU;*>>#b zV@->uSD2c^Y1{eIy#G!tDjeG$7k%s2P$41qy^QaDrrGZL0;UYK+F^9;_j`W;m!IvG zFqxQm%8+Ul6QAlhiNa7_EMUI^ReRJnxmw6XI=kX_%^5;)5QNmdtmGx?6HP?}-N~zJ z&iWu}bl^@IwXBV5zZlEKj_<*FT|lkN)V?lh?V3l6=A)M$>}e>_asLbv3Y(gy-p@XU z`c#m#x%6^*b;Y7NM>mSZ?+=Y$5=)0Y>*$v#ApI)fibET@mqon>@lsy`^BIr>r8&2n zGjD){(9{{%<<`OL?!SgvQSd^HxsONzOhl$9Vmp|E)Zuz7*va&Y-92|`^tyGi=8N#q z!y1-WfnLz%is6;x&}FB06LfvHdOm<)GMTT|w!WCi^_}8JZ1&jY|tj%>NT9ehsjFH-ck>afb?Z^8VO*!#UXh zvwcGux;#1HFA&pZAxdsJ1BbAU3!JBEa2jaPkHpMBp73j-%U3^%L5iH2QqfbTA^kcsNR9oQr$1k5hynplfBWRuvY?Z2rXr3$h zaigkG&W-B6Yz5yyk#>_={FV+`Xf%+sq{K6`!jopar-t@$Gjokecyis|h2BUe{;U7~%HKYzW5<1jHhpxBeh`*~>7anl7fJ(n5bPt_r7 zs`IP|ZqG3{|4%IZn(fGc=Vfhiqk^E#3U+4T2`<|J;r{2#<>ZbWuRR#Rnlu}*ChMqH zGJ2BYwqdXE{qZ@#F~55YcQIdtpwfY%kY_I_!}HJ2?Mu8cH-KU^>ZyLP#fwi88O7dvPN)P zq5GDzfL(1H^Ms_TBKLAl{5By!hx}9(L6l?nYwTQ#jFDa_=<+Du0uwvsn=8_9(z-1#-#Whcwa?G@j#o0zsF&fG6*%5&m)a^gUOST{xd|^WhlmS2B5}-qeh`52 zml73Vs3Z;9D6ZI9#EuL9DB;(>=<|tdng$+FyWcix3yYoV%{R(7Dn>rxF!IDPjPf3% zg)0&Ro!N=NFb|Q+_OvPC;_<9I?)C4VrxoyIdBej13@N(;E*U^O+xB~Q(33kv9vBE> zyyYHWe&KctU=)R7z3^`4aAF(+4*rzZ-e-5SX7KPjCVe%l^~akS@u08qjjPY$o@dT< zwX2}~qB?5vI*<(uqx{YftSHP86AVvi{FOBx;G8KkH~AQVXnEqsPb*(M#3X2sdl$}dKTnu|ZcE$LcxYMa`PeSTMA_M%DMM+;OhLTnW!tX+t_)oj2`{%o>NWRI+qVeFkARb(eR zw4XRvz~Q|WLUcDDNgH({u@-=%0Ac-mTSAPb(p8j-T7LT`wrSRnE2Y$$$MA36HQYoc(^0cD>j&qLbj-w9|CfiiWYqMgMJLfoRIw>4ZPWc| zhH)y6ty!0sx$2piS zxK$6=p@_CTa4v`UGb)Q1+@99P)_@N2i^%?B|5MJDQ>A+!0Vhkd=FTC_(lp-RAW_^u z*|017@iNJV)btjJnI1S~V32zm;35tde3a*V>4$d`z!r{{g!hJuXYzkfphnG1`KS?4 zwt3zUKFSb1<|HRWZ+~a89L1FS=xW$4ZspbM3PGDvr=k0BdZ4rOogL10x{pIYY;B(q zIOXv^>5p`kCnEaoB_l0`5!@i}{_?xEOXMGPatq9qJQfUsq)yxPScorH@y97%oE8wA zB*{ZTra$J=tO}PYb*S{OBIZof&w^+8k3;@if@LO$2(YncGrpi|Py3G|P(vRa$^zN( zyTM66RpJ)Nxld{^En_hnZc``C|0DSv!z!M?E$8GulZ++?DcTDKzfd+`~Jiz~xCfVur7k&L* zOaOlUf7}#LOiU6Q3`l?MNoj3-B|nY>GGV&!lJ%B))?Z!|ZwN4!AEBl=)|i?c=jHth zCtd(}^jBw3Uojyy@mO^~GQ2ikpS3>I|8Y1Xq2HtH5qqW?W+PGjyru`@KW-P7R?S+I zmc#N(>KaKw{hCG>x51HsD%@!C@)37|QTK+t702%UvIe@YNRKH`5945m5u{xV=REgt zQyWjRO(!+m8;WDIQF>X{rGsMZJi7ba-?yy>{$Y3RDES&QrF+X8??aFG3!QyL{>)r? zxOMcu4MKw&yVIq7UPD*o|JSgaSO4Z<-;q5L#v4*))i%k!+o^W%U7M(3UBo~d4{Im5~gS?t!rV4TB;F0SFAg7k;B83zGK(8em$#M zG9510KiChC8+q?AYdMIKe+Bm0>qpLypDdqgQh$G)MnA8nd7Yo~Ih7F8_Y{RwahnM+7_c_*^*!52?z)_w$=Z&U!ANKF+VwyNkAccH3x zN93H6{Xbcs#(Nm>4+JzGpL5b3*|YI_&<+)Ln-oDHnY%^C%5Z_M$?av%+WksLqb(sOKEntIi9wp^Yp%< zqUgas`;ADQy*1f?1b_1 zFRSA!^ks3J>YJv}F-_)!gr#ZriaUWo%TIb@iJni0mkf8@>3eC3Qqe`Q-3DXt6H}Uv z%%L^+_)Ua8YaJ2KH8w0@8-4+vjx;+Bz9dl99ZirQ+V%z;z!K52h~ z?{{t7C-$3k>ApGZq)n_)BwlobrM3Gu^td%qYC1*os2hKyht%GPxT4$E*ZF|H*3szyx7ipe$f+ll*s}x!c7Eto zMYeeSsM%35iU8E&w&?`x9hdZ>7W4P80n0Ovt)1pH{cW57(-wl=RNg+#x z&lBYI*GSW*rxDfQzb(tcG3CR+mr&`Z<<=EPQ%=tM7u%~RLuvJ7V~fZVLhn}Qx6SM! zbIWW+6uyjVwWWGUPclo=8}|z(kst^Nhyy%ojCkj?;{pl|NYgdV?j$=RwhbP*Bm&^Y zE2wMQ;|1x;dDEGKfB^jerRo^`(2dg%`3BX$3l5z&W!&d*ooCAIzGE&@+gH&KkM1ig zFW6UhC1+o~@IZXvBw@g>;>rxK@;26qPVlg10{cS#5bPh8MrRFoYiDWSTH%4E`>#oQ ze~n4}m)Us0wL;Gp9XZV(@iOFqnkyp&n-3D#j zh3zz~eQ^^7`&tjc{=d(IlQi5eYV-}2Rs!y4txy1u;&wS^`ZC?DP0IssO_#nl3}RDn z%B8)~8Se$yXtB~M*0aigTVr3uCNJYxI9}%Jzmr?r#A-hmG#lM5)9(}~-fpni{dPxY zBm3TNZMQr6?EKe>+^iOEpc+pzzs9(3t1TbCmd-kfO%7hUB{i(nU4zx!=GR(}R;t$u z?R?Ar#qUpw%OzRJ2iD`Wc4{>>Su2yF8{Bxosv~ClZ?xg~J4Md@OagFa z&6I7XwK_Jn<3RvOvB$9uXkZH<0wtsqCtU!~MFF4?fIWK%05Gz^LLozzN|g$Wm6q4_ zskgisusKgEY#Gq-Fx|lq3VA)+EgBGN=>REp3e?UV!K|nNoWtc+e8q1F@LP(kH?2gT z=IW|~7(lUA&7)-NeM5!XlbBQ~y`I&pbd`!J1~I+TQ&Pdza8l(&Spm7q@H+&$4rcP3Max;jN+#@mw2_T zZunq?o1KHU3*<}w@DCd8Vu2dT}cc1BxJpX&Uyf6PIM4Zh*(Y}av2TOQ%Ktr-9 zQc}6$#inq6E|{RUr0?Hf^xKh$14~{O6KkdDfyt}W)WQ$s=4`lj6Tk;r`5bH3y+=Hk zC;y`(J>O`dk_-+;98Cr`C>A8qR;7EHn#1RU{@d*jzz&cfxg0Dxb^Xysrc5Y{MN`_3 zm&$mBO%;?=kQr;M>v=({4b8*aTqM)epsL^#jT)TO6f(lMszCL!(1%X4BSau)d2qQJ zclyWAyh)c*JFLOHr=CesxKo=|lY*w4wrPDfPmM6|q&^0j63(b~w1?x%*bAN1F#UTX z*MuXO6wK%F0gwNasd60j8}9$Qab`g9P;}84EDlc~KSPL!Nl3}W={*HNN=GrAkSn^2 zRjJFc?~6v;>N-71(M)U11D`m91Mk?{Mw3%RG8b3(9z1&T?8R&A*g5p>!)Ih$-~R9) zflAA9!N_&RVsp4WzCb7vOQbp>Gq<2kX+?*ce~qo3y@R8Zvx_TTHqX8A(kt!+2acRL zyT>IH{-|8tuYp@M51Qd#qlY|rdgQSuo_dz47B9TaOvGz%y!FoeHfZC`hc7=L`1|OS z&jJL-3)bVSAm0$%q*sVgVZud-6eU`W??~DE(dII-eu}F}yab7oBumLbsx;{`YL+R> zFWGYB%9HQ60)>kFQLIF1UzL@qT!qU1-WK1h_P57s68kxcUr^MkN7aC)5nU5TQm3?N z?Y6ciFtN1j(21SQ6&&5Tdhqn(>(g%_dB&h2!<{igP%R;mQDS4pvrLfqXVMg@X)|Wc znYUok{Of_F7HLjrFu50H$>#9j$&2@*VUW6qNZ+6sPRJEXRT_17?KN7Ro}_4oX!+btm^5YDj9GI%G;g5?7A;w} zV%3^;8#Zm(wqw_xeFqLZ=BVS2?KHNLJ^KzEI&$m;1cpFc<{pkfqR<#D4o@JGS{~Eq zEv1n6HTYm+S`bJ7VQyh*Wew07g;H2-4wuIl6v-BeB~qEZSfNs-)@XHl6)IJ!_P1L~ z)u=^AQI}CYss=QT=$bGzYtgE$M$AmX(ypTxo!Gi?bmJD*gQpk2W_|h%7&P>@5h<)d zOsezG!~4;1FHM%pe#uQ&YjvXLowJbd%_2JmU<`#Qiee}Z#Y6SX%cBY)Z`E_MGWeG& zne*zo6(t|8W-g{bnnG%FEN5=^vc}R!O^(l$n@e5=-Q3N~o4a-k^7gJDAE4WFydbZ0 z8O+?H#FjmdOvTAj(NN86b2$WS&lTug2?ODT+O72J%>r|cKq?&(cA6-eK6rpcgA%cI?WU#^f4H91P}d=J9krO(EG zMyJ-dIb<-B(@&uhMjBL6`N$(Y>Tb7$&_Wg9a2ewK1qRk zRj=4-XPkA;c^6y^poT#V#W1F)zYUlyCI>30)1XOLia1SZ%?EUPxma=HB^V%4 zl4Ju7GFS>VstkjcN8+B95i*T5%4l$O)Np*M#3}j4J-HN9x&EK`_x@LCs%fU1p-8cr zQKd|cWl{x?SyZeK@HHI`qWue*t;C$DtU1|Uu*veww;=Ku=yA(F2Ucj2#e4gGs9k%V zbzUry${0+o&ZRi}4jejay<;aJFa!$g0l!IyU=YNfx4U+Ya0C*C#$ekYSK~6C&|e~n zOrg?DOwG(Y*upYyE9CV{T{f0BVq+`akQ8KMe#yKZuQ{R98j^nRMUa zG%OUfp7E4|HFafx01Kz*-L4S89?r!Z(kXSZKuFWgbWSUsFBu$zK1EyJ@Q;||4%NcI zm0b==Pu;!_&@6F2wT}T)W%EW2P*3jj?9BT-c_S=5ok`xQ=2$$PgBr2xAtM+PMgDzBnBj9`#9OL160GzCMhqwY=-VWz+D9 zEp0mJL*g_r_3~$kF4F;&7UGT#uM-5W%Bq&U73*#$fUKZgqQzT&&brBqQi95ax=xBJ z^Nl`l<_l&Xu6lh{ZNWoDE6O7|s&!ZMt$lF5b*1zXYx7VxDKgQjbKzi~o}z)9cX@>O>!|j>=tN~kr=dz%9qoEnzJX(L#0)9;LD?$0 zpxB9&p!i<2m+dMTT#X)6S3yfTkt!8bI_yfeyeRG3u~6A_GxrGsn1=#E=10f6 zyAeQ`8y8(22JK70x|~6(HeAJ7?s7}o?Yt42L?v~Yh%2ChGId$sSl0dR{HT@_TM_bz z;B%t+t+*TNaeLVkXAT{Y54^uUc^+nNAH$rA(<#JOGkj+Cg!FbFszc&^NPf-V*Com| zX!UKlQrp{o7HShZn~RpI=ri+tJhE24p4vuxY?fUxuC~?ivCUUqblTGl`mTV>(-|#- zNMdcbfB8}Sq20aoM}qdm^J6$OcQtwzXUp$S;|47caodl7RBd}t-Yq{ayBbBpnlrA=Lk zEl~uMn7~Fw$6U2v6fXWsI~2COA1bKphBHWv(2qvG(TWg=Lgp7}zFCE97f&j;_JVA9 zyPPj=))ZKlko86)DWQ(f&7%4S&b#gcjlo_$&JKg=GUHCt$t>lq-r(3S@VLUn?tXwn z#pLt-A#CzVuGU+|4XjuQ&jAQWXi&==T)GvnpJF>-22J37_B%J6t5aVSqh#A>xuky$ z`)wQ)Y<0W*VV$a8N+RA=a;*0Ti@oU`HDZv`-BvXn^)Z*#oyG{lhJq^INwDnnjg9;6 zZl>52w^2%c`7MGE1!7DD$Uy0s!kP%Gfq2~cK-?-U>Q-+UY>`04MaRTuGT0#D@_35) z=!C>;sULCWJ`e^mhEI~umJ`8bGwHHzBR_Q1burDJWT@ZdXzokGw^W*o3^9;k*bG~w zsS9g&)SAslh;(XoJ3Rry?~i+pU4EQ|nMC(xK=!mn+CJESTT(|$n!ofiG(`&P&GJnuUguN=Tn?G zEMY66CF2yXNuNE=UA)L%VYVHD?dJR^32##Pw|upI{J1J!_Avd7etEjFDpBIFx=Dxe zA?mqt^PWxV+OE94x#2cx{H3QHxbT#HGl2jCA*38n85+8c@i9>>tYgC>fx-TTUPJ)c z=d*$ULdHN7I*9cI;B8SE%o7IFGC?t%JG5Xs2nd9{uUbMvbPUD4Pi~uHSSAQB=q8D# zlrY?F*-Es7KKnG!%87sT&WDUkq^gTxAP_R9Hz5$Z01i|JT%p5Ma!LaZhZbyy0D+MA zRZB>Sj-j~s$!${%@1yHDr%S*@F`Qv5$u48|=SHSQ7@L@ynM)M#m{Vvmldcs=FW;iLc^l>sM6 zMz7ARbHsJsuI!DoW{Tki$)K41bw*Yu1rUM}I*MKOA2NB@g}=S0EE;qzB)-EZ$fkU| z%_YvR{CpjL)TcfCT(A8F}x2NjuDZM?7M2+dvT2Ioj^qZwuM1sl6|6ji|oqnlmP+TQmY$Z}9)pZxB^h~8s zsTzD2-X;Ust+~%TljVW6^nc`9j6zD*cWdVn2{JC>8J#r5l>ztY^!5Y`f*>+*85lvz zATkJoQNC8A+;ub7;eEt|_j=rWb9%Oaklfl!Zb0q}$lU<)j^dos-&$XBz0va&+&~uJ zJteE?Pl!+8*+2qHA4ynYI1&W+EFhU3?2h|CkstbMAop2MXkWQe&4-SR_~_B9ph~oM<3Wk(87RiAk7`6G4cP zLl-!LfBVA|73I*r=P`$JI;tcoWEtP0aA zCW{WiJMx3!DF&T>8-&4tyEKS{Fc=kIexZ-Q{J*@a=Wor!Pbwz-Z4d{ml0&xGvz>>p z?X$TvugE^+@7B|p$2Rk5hw)N9{`5*06CGZE5ilvP=EH9_W~_Jle*a$csk_eSxkF@L zJTNFd`OwD>aSeMsFk>~zc0z<;x{Wswe5jEoADt;fK>|98;RKUqJ28Ne_0-E|`B`l; z%SKoq0$d-qr$;-ZD3;hwc4-m(x)v8Vd_Kd+n5yR)3^Wzc`>qVdp?n~O9jJxAvf3AT zs1DVk+RsaiFq_HmOS1`^{c-bq;jV~@EZ4>?>RVdW@3qJG_?%B0dgdZV-P%Y6hG_)b zmg>OiZ*y&#la^X8T-XRs?e=&6Z*l#}k0{#2<$tTYZ+Hw`3;*z8wms=ij*ojMr3sc> z{hjXk{CIuT9A7_n^v8z8zwH~8&$>@Hii8D0( zz58ArK=wMYEh^T|UiB*&18K{Bf0S(;UH|V7vzbb;~)P9du}_!mAkZg5o@At$*aUE zeC@g`9ym&_w$4q>soLZx;FVC{P&`#mMCSHFcmJ|tj;PbCO8IhgmqpJ${#iGf3tM)?(cuO*j6{= z;hQ^Q52HiZ*6Hs1=Oa>kt9sqV&(jZ0JQ;9cvSODWTgx`VYSrc6YbQBxF*~j}%XX@T z%lqEqjx^1Q&R-m_cy4*aGi&e64brv#^AA52n3WqZn(LZfSj#s*IAhy?4TW1BVamT` z9FJdE^G{FoqgUC&`@g?hE;_f+e^s7+wL$gUQxym5FST|bJRQ7UtbDg~I*)z*$-pn~ zx6FU4f7Hn?{)V>f6#neH6C-nv6@1L7-;h!3GE@5U^)K7)BbHqF+LCy7#wm8I*QRS$ zZjpEA{A-vKacTQu)?G8X+Ogd`T`jTJr6P!<=adyX>@EoJ;J)k_+pk zBfIm3RxEJ6|JL`a)J%@3Z^x(1RbHJE{KbQRQtZBj63xBU8L>Hi%cLQxsF7`!11NqQ z8-U4$iIMlqf`#>r(t_JtRrG5&0TaGziEBhjN@7W>RdP`(kYX@0Ff`XSG}1M+3^6pd zGB&U>Fx56Nv@$SQ{^BV!iiX_$l+3hB+#0TJjRj?`@T!oAlAy$Lg@U5|w9K4Tg_6pG zRE5lfl4J&kiaC!z@o*G|X=t4CKYhmYX%GXmGPhnbx3IFX_hb=fVFi~4lfx;@%9}$J qPT#n4;>ejJGDp}?H+U@Y(qnifE?Dx($#g2v3INS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lxRtf@J#ddWzYh$IT%G?WUP)qwZeFo6#1NP{E~&-IMVSR9nfZANAafIw@=Hr>m6Sjh!2!gbC7EdmoAQdG z-U511A0(r1sAr&$ON8HhHpzaZAxfDE&W3`#A|&nX2t%g)fu25bY0Ai{kR z4G8t2d6^}4Mo=wi!sxmp5b_9XkOk2-_!niS0s|7_E~p*IVo2&izOxF*tVqp?aLLR~ z%_|1^#mLCSMjxvTx=!c(ocyBTg2d!hJ42`zBq4OwV0$8Q+Jhtm)oG&-ifyFWha@eq zC@^i=aoOm@)2SVo@b#P1fO%x2r;B5VhG=Y{wKub)z`twOf-3wiEVCQJ47*%cEm-u3 z`AfJ$b_qEjv52ta!EOx8J(jdf^b0)vw=-AMaxEbQ#5!VZtN^#8cmfBm(Bh;GUc zov91Nxn9hho4agfgq?s&Q;yo&g_!{_QYNk6v5_%fg{l3@#ubxOer8wg?D?D^@V5AK zhT*Evh$sIFBzk{W$MEw$EGrfL8pBt$v?l2;F;B^!S^a>kpyGRxs_z2LRI zNU3p^Izy=i+wW&$Zr`NlT{JB5^JDOjj-F#Kwg1!8V9kBp1;2dvx$C_@9(;Mvvdlc* z%P)g(RaO7*>*@DloBB3)MI*zWBkwwo#t5beR`1?r^XdDALqT3aJ)X;39!IE5ak_WK e^V!Tr54cr#$gKI`?cfJ0csyPGT-G@yGywpJx!s-s literal 0 HcmV?d00001 diff --git a/assets/favicon-32x32.png b/assets/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6462562e0ef81ec1de24ce42793b0c696bd47b GIT binary patch literal 2281 zcmZ`)3pkW%8~$b-V@Pt2j3KqeFwWDM9L6ceVVuUP3}!UzFw+0kO001Cn zXNx0%QjWKU1;O|0Xwwx?@CTdY%>ke)Q}j=g0Cp5UUOV=aT_|3!2VP13;t> z0L=OW06G@{Wa)*!xL`m>GMQ*c!Q%l9P!|RSAd&zds6oI7fG7aGXrKn1fE@U$6Cg*n zFi-$Ur2_n07;jMW7989>&Zgw!K(-@tpkL8)9KLNGL<2d}b#zedq1$>zfGy4QHY6>4 zjR64APO2M`NyIy#18HH}q##-VS(_EcLjwSYg$C6yGLr;ng@uMkpjoDf4Fnq0d1fR6 zz5!u|m?DUHXSgMeL53S@>uBpBup)3c9K#5rpb0qZEjoBIMVw|b>1ZS}IyzcAT2GtC z2uA9fn3y1SP)HO?3q)u|#Dp_REUoYe)y*J($H9>!0vS{~lS&JR^Wu^MXpu})1cI07 z>)Nc7Nu_LO3Xj-o3v3X{^B{G#b&&r=BeSUgLgRThX&ZfQro-@pp}h#?2wG?)uPm${ z3bT>n|BT!9Z4$Qe?%`A>_HW8A^KKS#+rOP=r*SvIi9scUA9ABE-L0~A+IHZ1-JzYS zEOICjM-3x~NAP+Qah9iA;F2Fbha z9k;(ZS{qhywy+`?DuLtu*$!v!W-C_V?&IL*Ddo4^#h3ECl!V1M3uX`( zYN$hY{zY!!oK3}XwfvGx3j3uS(=I)#;!ohP^)Fc8-Lo#=ntyJER?shZE!Cf$Gd4CL z6>}pGrISQ{_u{6>$k~@L0hiy@P2Y~{O%1P&hJ@A9jfXFLYWWGZkl5W?GJ{W5_?&D; za%r^GFR`K$!tjM|Qs}@Eq_E(piw?<=`eM#s&Ir`k_kGOM>%`wx{rG-;MJz{QV#K{@ z(&vGOw8#TuAA)_c3JbCFRFJZ|H{IRPH24^Tt zSW7#AJ8Qt2d)aLM-$UU>uhP<D~nrE=kW9UDCB0; zQIkE`-!FU2pM0|ERNd`&S+D)c#Ud+{Z!^qPQesXi$qBW3Q@WikPkGq4Why90nFlQ( zw7zW=q}d3mXDXV{wy(Ol`J^X*gy9^r(Uv1B`c*ITrLAB`4Uf&o)FFNv?z>0vk8f(&<2AWo=O3Zs=q>X6%`au&cPpGdR`>~Gj-=a%XeKl zBx!PI=6ZToo5`6QlYhp!^^UEyC*IzRW_KP(L0^`;K5w8yOmK=Cn)>QPO}=briIR5J zu9ZXigy;jZ{JD>rdopg;zeY#FUIk0UnJ$H+2gI_XmCZVdUkGX zxOPul3ltN*2%lcIe`6xrp)ND??NAE~YGZu*$q+*fQ`M4iS%tbB&fTZl=SzDyTa<<= z$d`P)D#*Ryzm~f9-sf8?b#G+#hSidEJH~P8OB8OYvb)eAt8&V6u$?vxzuoGl?BQPC zE{p8Ev`CC8`^8&s(CWmyrK!GG&u|X0YlcHno>jwZZ$tZP;!}-t&vxIr534BtaOS8{ zd}>m;T}Pp7|IywA4WZJIkt)&A?88;>Bl!#q?|m0BWJn|sg#8o{))I|B8nQB!4?i2= zT>sfWD)PyP9&C~1v*M1%F2|yC?x{t?zTe}a_ICvk>!q&_%%bKO8!~O3j3^lgTaTJt zf#z^6684FY|HtBV20zz7(JuJ+nU^Gc$CR#Ttk^l3>gC1K5RrV69eYkjvl_dGyLNqF zQvL@svE7!ryKT;v|4v8XUoHz#kG!SD&8%vc z`Lz70xi0#l8G8yJr-obgPfQm)IqihRls1{Qv=OEYMDKW2clZml*IkmU)Wi+-_2Es` zNhh);l`ix9-TM#(d#G%D1d7oZcfER;GHf>%>|R-7GFD!e#Z9Bnx8ma}N(2WdCZ2O9 zmjW7C91jIEb0GuIi(Nt9cr^>j8e*xWRH1PqGrtncwV`q2DoaYAvVX|DHXfi>?@NI6 zOOF#cno%<6er`P2`{m7*PkE{{XAc**zQ2srmi|FLElxAoTK13D6vVHLs5l$w)x_Z{ f*v$!}hIPSvk9tUzl3xmWKX5xMN8AGo|D?YF+ZTAw literal 0 HcmV?d00001 diff --git a/assets/favicon.png b/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..5667b8f39a35e54b84e33f63cdab41c732ba0c0a GIT binary patch literal 15204 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

=FAN4&;Xw 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.innerHeight*n||0 + + Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + Zola + 2023-08-14T00:00:00+00:00 + https://thogiti.github.io/atom.xml + + Mastering Rank One Constraint System R1CS with Circom Examples + 2023-08-14T00:00:00+00:00 + 2023-08-14T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/mastering-rank-one-constraint-system-r1cs-with-circom-examples/ + <p><strong>In Draft Mode</strong></p> +<h1 id="overview"><a href="https://thogiti.github.io/mastering-rank-one-constraint-system-r1cs-with-circom-examples/#overview">Overview</a></h1> +<p>Rank-1 Constraint Systems, or R1CS, are a critical component in cryptographic protocols, especially those related to zero-knowledge proofs such as zk-SNARKS. They are a system of equations used to represent computations, and are particularly useful in scenarios where we want to prove that a certain computation was done correctly, without revealing any other information about the inputs or the computation itself.</p> +<p>In the context of zk-SNARKS, an arithmetic circuit is converted into a R1CS. Each constraint in the R1CS corresponds to one logic gate in the circuit. The &quot;rank-1&quot; refers to the rank of the matrix produced in this conversion process.</p> +<p>In the <a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#process-flow-of-a-zero-knowledge-proof">previous</a> blog post, we saw a process flow of creating a Zero Knowledge Proof system. Here is the high level view of this flow:</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230313/zkp-process-flow-diagram-2023-04-13-150046.png" alt="Zero Knowledge Proof Process Flow" /></p> +<p>Constraint systems are collections of arithmetic constraints over a set of variables. They play an essential role in computational problems, particularly in the realm of cryptographic protocols and zero-knowledge proofs. In a constraint system, there are two types of variables: high-level variables (the secret inputs) and low-level variables (the internal inputs and outputs of the multiplication gates).</p> +<h2 id="understanding-the-role-of-r1cs-in-zero-knowledge-protocols">[Understanding the Role of R1CS in Zero-Knowledge Protocols]</h2> +<p>Zero-Knowledge (ZK) protocols, which are commonly used in cryptography, require provers to demonstrate that they know a solution to a computational problem. This problem is often expressed as a Rank-1 Constraint System (R1CS). </p> +<p>An R1CS is essentially a collection of non-linear arithmetic constraints over a set of variables, also referred to as signals. The security of an R1CS primarily relies on its non-linear components, as these are the parts of the system that are challenging for an attacker to solve. </p> +<p>In contrast, the linear (additive) constraints, despite being part of the system, do not significantly contribute to its security. This is because these constraints are relatively straightforward to solve, making them less effective as a defense against potential attacks.</p> +<h2 id="definition-and-explanation-of-r1cs">[Definition and Explanation of R1CS]</h2> +<p>A Rank-1 Constraint System (R1CS) is a specific type of constraint system. It consists of two sets of constraints: multiplicative constraints and linear constraints. Each multiplicative constraint takes the form <code>a_L * a_R = a_O</code>, while each linear constraint takes the form<code> W_L * a_L + W_R * a_R + W_O * a_O = W_V * (v + c)</code>. Here, <code>a_L</code>, <code>a_R</code>, and <code>a_O</code> represent the left input, right input, and output of each gate in the circuit. <code>W_L</code>, <code>W_R</code>, <code>W_O</code>, and <code>W_V</code> are weights applied to their respective inputs and outputs.</p> +<h2 id="relation-to-circuits-of-logical-gates">[Relation to Circuits of Logical Gates]</h2> +<p>In the context of zk-SNARKs, an arithmetic circuit is converted into an R1CS. Each constraint corresponds to one logic gate in the circuit. This conversion is crucial because zk-SNARKs require computational problems to be expressed as a set of quadratic constraints, which are closely related to circuits of logical gates.</p> +<h2 id="constructing-r1cs-for-zero-knowledge-proofs">[Constructing R1CS for Zero Knowledge Proofs]</h2> +<p>We'll delve into numerous examples illustrating how to construct Rank-1 Constraint Systems (R1CS) for given polynomial equations or statements, particularly when creating Zero Knowledge Proofs. </p> +<p>We'll utilize <code>Circom</code> and <code>snarkjs</code>, two powerful tools that facilitate the representation and handling of non-linear and linear constraints. These will help us understand how circuits are compiled and how a witness is created.</p> +<p>Please note, to follow along with this tutorial, you need to have <code>snarkjs</code> and <code>Circom</code> installed. You can install them using Node.js as follows:</p> +<pre data-lang="bash" style="background-color:#fefbec;color:#6e6b5e;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#d73737;">npm</span><span> install snarkjs +</span></code></pre> +<p>For Circom installation, follow the official documentation at <a href="https://docs.circom.io/getting-started/installation/#installing-dependencies">docs.circom.io</a>.</p> +<h1 id="circom-r1cs-examples">[Circom R1CS Examples]</h1> +<p>Before we can create an r1cs, our polynomials and constraints need to be of the form</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/r1cs-eq1.jpg" alt="r1cs-form" /></p> +<p>Also, Circom expects the constraints to be of the form $Aw * Bw - Cw = 0$, where $A$ is the left hand side of matrix, $B$ is the right hand side of matrix and $C$ is the output matrix forms. The variable $w$ is witness vector. Here the witness $w$ will be of the form $[1, out, x, y, ...]$</p> +<p>The matrices $A$, $B$, and $C$ have the same number of columns as the witness venctor $w$, and each column represents the same variable the index is using.</p> +<p>We will see and verify this form by Circom when we compiled the Circom circuits and see the info on the constraints.</p> +<h2 id="example-1">[Example 1]</h2> +<p><strong>Circuit</strong> $out = x*y$</p> +<p>Since our equation is already in the form of quadratic constraint, $out = x * y$ or $A*B-C=0$, where $x$ is the left hand side matrix $A$, $y$ is the right hand side matrix $B$ and $out$ is the results matrix.</p> +<p>The witness $w$ will be $[1, out, x, y]$.</p> +<p>Remember that the matrices $A$, $B$, and $C$ will share the same columns as the witness vector $w$.</p> +<p>$A$ is [0, 0, 1, 0], because only $x$ is present, and no other variables in the polynomial. +$B$ is [0, 0, 0, 1] because the variables in the right hand side are just $y$. +$C$ is [0, 1, 0, 0] because we only have the $out$ variable.</p> +<p>Now, we can verify that $Aw * Bw - Cw = 0$.</p> +<p>You can verify the above calculations of the matrices by running the below sagemath code.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># define the matrices +</span><span>C = </span><span style="color:#d73737;">matrix</span><span>(</span><span style="color:#d73737;">ZZ</span><span>, [[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span>A = </span><span style="color:#d73737;">matrix</span><span>(</span><span style="color:#d73737;">ZZ</span><span>, [[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span>B = </span><span style="color:#d73737;">matrix</span><span>(</span><span style="color:#d73737;">ZZ</span><span>, [[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>]]) +</span><span> +</span><span>x = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>y = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>out = x * y +</span><span> +</span><span style="color:#999580;"># witness vector +</span><span>witness = </span><span style="color:#d73737;">vector</span><span>([</span><span style="color:#b65611;">1</span><span>, out, x, y]) +</span><span> +</span><span style="color:#999580;"># Calculate the results +</span><span>A_witness = A * witness +</span><span>B_witness = B * witness +</span><span>C_witness = C * witness +</span><span>AB_witness = </span><span style="color:#d73737;">vector</span><span>([A_witness.</span><span style="color:#d73737;">dot_product</span><span>(B_witness)]) +</span><span> +</span><span style="color:#999580;"># Print the results +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">A * witness = </span><span>{A_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">B * witness = </span><span>{B_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">C * witness = </span><span>{C_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">(A * witness) * (B * witness) = </span><span>{AB_witness}&quot;) +</span><span> +</span><span style="color:#999580;"># Check the equality +</span><span>result = C_witness == AB_witness +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">result: </span><span>&quot;,result) +</span><span> +</span><span style="color:#999580;"># Check that the equality is true +</span><span style="color:#b854d4;">assert </span><span>result, &quot;</span><span style="color:#60ac39;">result contains an inequality</span><span>&quot; +</span><span> +</span></code></pre> +<p>The output will look like below:</p> +<pre style="background-color:#fefbec;color:#6e6b5e;"><code><span>A * witness = (15189) +</span><span>B * witness = (90533) +</span><span>C * witness = (1375105737) +</span><span>(A * witness) * (B * witness) = (1375105737) +</span><span>result: True +</span><span> +</span></code></pre> +<p>The Circom circuit template for this will look like below:</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>pragma circom 2.1.4; +</span><span> +</span><span>template Multiply2() { +</span><span> signal input x; +</span><span> signal input y; +</span><span> signal output out; +</span><span> +</span><span> out &lt;== x * y; +</span><span> } +</span><span> +</span><span>component main = Multiply2(); +</span><span> +</span><span>/* INPUT = { +</span><span> &quot;X&quot;: &quot;5&quot;, +</span><span> &quot;y&quot;: &quot;77&quot; +</span><span>} */ +</span></code></pre> +<p>Let's compile this file with Circom compiler and create r1cs file. Run the below commands at the terminal.</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>circom multiply2.circom --r1cs --sym +</span><span>snarkjs r1cs print multiply2.r1cs +</span></code></pre> +<p>Here is the output from the above commands:</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/multiply2-r1cs-output.png" alt="multiply2-r1cs" /></p> +<p>We should be expecting $x<em>y-out=0$ because Circom shows the constraints as $A</em>B-C=0$. </p> +<ul> +<li>Why do we this very big number <code>21888242871839275222246405745257275088548364400416034343698204186575808495616</code>?</li> +<li>What is this number?</li> +</ul> +<p>In Circom, math is done modulo <code>21888242871839275222246405745257275088548364400416034343698204186575808495617</code>. The above number <code>21888242871839275222246405745257275088548364400416034343698204186575808495616</code> is equivalent to <code>-1</code> in Circom. </p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">21888242871839275222246405745257275088548364400416034343698204186575808495617 +</span><span> +</span><span style="color:#999580;"># 1 - 2 = -1 +</span><span>(</span><span style="color:#b65611;">1 </span><span>- </span><span style="color:#b65611;">2</span><span>) % p +</span></code></pre> +<p>The output is as below:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b65611;">21888242871839275222246405745257275088548364400416034343698204186575808495616 +</span></code></pre> +<p>So, the <code>snarkjs</code> command output is equivalent to $out - x*y =0$.</p> +<p>Our matrices are:</p> +<p>$A = [0, 0, -1, 0]$, $B = [0, 0, 0, 1]$, $C = [0, -1, 0, 0]$</p> +<p>Let’s recompile our circuit with a wasm solver:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>circom multiply2.circom --r1cs --wasm --sym +</span><span> +</span><span>cd multiply2_js +</span></code></pre> +<p>We create the <code>input.json</code> file:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>echo &#39;{&quot;x&quot;: &quot;11&quot;, &quot;y&quot;: &quot;9&quot;}&#39; &gt; input.json +</span></code></pre> +<p>Now, compute the witness:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>node generate_witness.js multiply2.wasm input.json witness.wtns +</span><span> +</span><span>snarkjs wtns export json witness.wtns witness.json +</span><span> +</span><span>cat witness.json +</span></code></pre> +<p>We can check that circom is using the same column layout for witness $w$ we have been using: $[1, out, x, y]$, as $x$ was set to <code>11</code> and $y$ to <code>9</code> in our <code>input.json</code>.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/multiply2-r1cs-wasm-witness-output.png" alt="multiply2-r1cs-wasm-witness" /></p> +<p>We can manually check our matrices if they satisfy the constraint $Aw*Bw = Cw$.</p> +<p>$w = [1, 99, 11, 9]$, $A = [0, 0, -1, 0]$, $B = [0, 0, 0, 1]$, $C = [0, -1, 0, 0]$</p> +<p>$Aw = -11$, $Bw = 9$, $Cw = -99$, $Aw*Bw = -99$.</p> +<h2 id="example-2">[Example 2]</h2> +<p><strong>Circuit</strong> $out = {x * y * u * v}$</p> +<p>Remember that in R1CS, you can only have at most one multiplication in the constraint. The above equation has three multiplications. We use intermediate variables to <em>flatten</em> the polynomial like below.</p> +<p>$$u1 = x * y$$ +$$u2 = u * v$$ +$$out = u1 * u2$$</p> +<p>The witness vector will be $[1, out, x, y, u, v, u1, u2]$. This makes our matrices $A$, $B$, and $C$ will have eight columns, the same columns as $w$. </p> +<p>We have three constraints, hene we will have three rows in the matrices $A$, $B$, and $C$. Each row representing the corresponding constraint as written above.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/r1cs-ex2.jpg" alt="r1cs-ex2" /></p> +<p><strong>Constructing Matrix A from left hand terms</strong></p> +<p>The witness vector is $[1, out, x, y, u, v, u1, u2]$.</p> +<p>The matrix A will be of the form:</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A_{3,8} = +</span><span>\begin{pmatrix} +</span><span>a_{1,1} &amp; a_{1,2} &amp; a_{1,3} &amp; a_{1,4} &amp; a_{1,5} &amp; a_{1,6} &amp; a_{1,7} &amp; a_{1,8} \\ +</span><span> +</span><span>a_{2,1} &amp; a_{2,2} &amp; a_{2,3} &amp; a_{2,4} &amp; a_{2,5} &amp; a_{2,6} &amp; a_{2,7} &amp; a_{2,8} \\ +</span><span> +</span><span>a_{3,1} &amp; a_{3,2} &amp; a_{3,3} &amp; a_{3,4} &amp; a_{3,5} &amp; a_{3,6} &amp; a_{3,7} &amp; a_{3,8} +</span><span>\end{pmatrix} +</span></code></pre> +<p>Now, let's fill the matrix $A$ for the first row (first constraint). </p> +<p>$$u1 = x * y$$</p> +<p>Since, there is only $x$ in the left hand terms. the first row of A will $[0, 0, 1, 0, 0, 0, 0, 0]$.</p> +<p>Hence, after the first constraint, we get</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A_{3,8} = +</span><span>\begin{pmatrix} +</span><span>0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> +</span><span>a_{2,1} &amp; a_{2,2} &amp; a_{2,3} &amp; a_{2,4} &amp; a_{2,5} &amp; a_{2,6} &amp; a_{2,7} &amp; a_{2,8} \\ +</span><span> +</span><span>a_{3,1} &amp; a_{3,2} &amp; a_{3,3} &amp; a_{3,4} &amp; a_{3,5} &amp; a_{3,6} &amp; a_{3,7} &amp; a_{3,8} +</span><span>\end{pmatrix} +</span></code></pre> +<p>Now, let's fill the matrix $A$ for the second row (second constraint). </p> +<p>$$u2 = u * v$$</p> +<p>Since there is $u$ in the left hand side term, we get the second row of A to be $[0, 0, 0, 0, 1, 0, 0, 0]$.</p> +<p>Hence, after the second constraint, we get</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A_{3,8} = +</span><span>\begin{pmatrix} +</span><span>0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> +</span><span>0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> +</span><span>a_{3,1} &amp; a_{3,2} &amp; a_{3,3} &amp; a_{3,4} &amp; a_{3,5} &amp; a_{3,6} &amp; a_{3,7} &amp; a_{3,8} +</span><span>\end{pmatrix} +</span></code></pre> +<p>Now, let's fill the matrix $A$ for the third row (third constraint). </p> +<p>$$out = u1 * u2$$</p> +<p>Since there is $u1$ in the left hand side term, we get the third row of A to be $[0, 0, 0, 0, 0, 0, 1, 0]$.</p> +<p>Hence, after the third constraint, we get the final form of matrix $A$.</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A = +</span><span>\begin{array}{c} +</span><span>\begin{matrix} +</span><span>1&amp;out &amp; x &amp; y &amp; u &amp; v &amp; u1 &amp; u2 +</span><span>\end{matrix}\\ +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 +</span><span>\end{bmatrix} +</span><span>\color{red}\begin{matrix}R_1\\R_2\\R_3\end{matrix}\hspace{-1em}\\ +</span><span>\end{array} +</span></code></pre> +<p>Here is the final matrix A in the tabular form:</p> +<table><thead><tr><th></th><th>1</th><th>out</th><th>x</th><th>y</th><th>u</th><th>v</th><th>u1</th><th>u2</th></tr></thead><tbody> +<tr><td>R1</td><td>0</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr> +<tr><td>R2</td><td>0</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0</td></tr> +<tr><td>R3</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td></tr> +</tbody></table> +<h2 id="method-2">[Method 2]</h2> +<p>Alternatively, we can express the left hand side terms in the three constraints as a linear combination of the witness vector. </p> +<p>$$u1 = x * y$$ +$$u2 = u * v$$ +$$out = u1 * u2$$</p> +<p>Here we can expand the left hand side terms using the witness vector $w$ and form the matrix $A$ as below.</p> +<p>$$u1 = (0.1 + 0.out + 1.x + 0.y + 0.u + 0.v + 0.u1 + 0.u2) * y$$ +$$u2 = (0.1 + 0.out + 0.x + 0.y + 1.u + 0.v + 0.u1 + 0.u2) * v$$ +$$out = (0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 1.u1 + 0.u2) * u2$$</p> +<p>Hence, the matrix $A$ can be written as </p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 +</span><span>\end{bmatrix} +</span></code></pre> +<p><strong>Constructing Matrix B from right hand terms</strong></p> +<p>We can follow the above steps but now we reduce the rhight hand side terms.</p> +<p>$$u1 = x * (0.1 + 0.out + 0.x + 1.y + 0.u + 0.v + 0.u1 + 0.u2)$$ +$$u2 = u * (0.1 + 0.out + 0.x + 0.y + 0.u + 1.v + 0.u1 + 0.u2)$$ +$$out = u1 * (0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 1.u2)$$</p> +<p>Hence, the matrix $B$ will as follows:</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>B = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 +</span><span>\end{bmatrix} +</span></code></pre> +<p><strong>Constructing Matrix C from output terms</strong></p> +<p>We can follow the above steps but now we reduce the output terms.</p> +<p>$$(0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 1.u1 + 0.u2) = x * y$$ +$$(0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 1.u2) = u * v$$ +$$(0.1 + 1.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 0.u2) = u1 * u2$$</p> +<p>Hence, the matrix $B$ will as follows:</p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>C = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 +</span><span>\end{bmatrix} +</span></code></pre> +<p>We can verify the above using the below sagemath code:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span> +</span><span style="color:#999580;"># define the matrices +</span><span>A = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span> +</span><span>B = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>]]) +</span><span> +</span><span>C = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span> +</span><span>x = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>y = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>z = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>u = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span> +</span><span style="color:#999580;"># reductions +</span><span>out = x * y * z * u +</span><span>v1 = x * y +</span><span>v2 = z * u +</span><span> +</span><span> +</span><span style="color:#999580;"># witness vector +</span><span>witness = </span><span style="color:#d73737;">vector</span><span>([</span><span style="color:#b65611;">1</span><span>, out, x, y, z, u, v1, v2]) +</span><span> +</span><span> +</span><span style="color:#999580;"># Calculate the results +</span><span>A_witness = A*witness +</span><span>B_witness = B*witness +</span><span>C_witness = C*witness +</span><span>AB_witness = A_witness.</span><span style="color:#d73737;">pairwise_product</span><span>(B_witness) +</span><span> +</span><span style="color:#999580;"># Print the results +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">A * witness = </span><span>{A_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">B * witness = </span><span>{B_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">C * witness = </span><span>{C_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">(A * witness) * (B * witness) = </span><span>{AB_witness}&quot;) +</span><span> +</span><span style="color:#999580;"># Check the equality +</span><span>result = C_witness == AB_witness +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">result: </span><span>&quot;,result) +</span><span> +</span><span style="color:#999580;"># Check that the equality is true +</span><span style="color:#b854d4;">assert </span><span>result, &quot;</span><span style="color:#60ac39;">result contains an inequality</span><span>&quot; +</span><span> +</span></code></pre> +<p>The output will look like below:</p> +<pre style="background-color:#fefbec;color:#6e6b5e;"><code><span>A * witness = (85530, 65887, 6198615690) +</span><span>B * witness = (72473, 49454, 3258375698) +</span><span>C * witness = (6198615690, 3258375698, 20197418725537501620) +</span><span>(A * witness) * (B * witness) = (6198615690, 3258375698, 20197418725537501620) +</span><span>result: True +</span></code></pre> +<p>Here is the Circom Circuit for this example:</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>pragma circom 2.1.4; +</span><span> +</span><span>template Multiply4() { +</span><span> signal input x; +</span><span> signal input y; +</span><span> signal input u; +</span><span> signal input v; +</span><span> +</span><span> signal u1; +</span><span> signal u2; +</span><span> +</span><span> signal out; +</span><span> +</span><span> u1 &lt;== x * y; +</span><span> u2 &lt;== u * v; +</span><span> out &lt;== u1 * u2; +</span><span>} +</span><span> +</span><span>component main = Multiply4(); +</span><span> +</span><span>/* INPUT = { +</span><span> &quot;X&quot;: &quot;5&quot;, +</span><span> &quot;y&quot;: &quot;10&quot;, +</span><span> &quot;u&quot;: &quot;3&quot;, +</span><span> &quot;v&quot;: &quot;4&quot;, +</span><span>} */ +</span><span> +</span></code></pre> +<p>Let's compile this and generate a witness.</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>circom multiply4.circom --r1cs --wasm --sym +</span><span> +</span><span>snarkjs r1cs print multiply4.r1cs +</span><span> +</span><span>cd multiply4_js +</span><span> +</span><span>echo &#39;{&quot;x&quot;: &quot;5&quot;, &quot;y&quot;: &quot;10&quot;, &quot;u&quot;: &quot;3&quot;, &quot;v&quot;: &quot;4&quot;}&#39; &gt; input.json +</span><span> +</span><span>node generate_witness.js multiply4.wasm input.json witness.wtns +</span><span> +</span><span>snarkjs wtns export json witness.wtns witness.json +</span><span> +</span><span>cat witness.json +</span><span> +</span></code></pre> +<p>We get the following output.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/multiply4-r1cs-wasm-witness-output.png" alt="multiply4-r1cs-wasm-witness-output" /></p> +<h2 id="example-3">[Example 3]</h2> +<p><strong>Circuit</strong> $out = x*y + 2$</p> +<p>We can repeat the above reduction process and get the matrices. We write the matrices for $out-2=x*y$. We have one constraint and witness vector will be $w = [1, out, x, y]$.</p> +<p>$A = [0, 0, 1, 0]$, $B = [0, 0, 0, 1], $C = [-2, 1, 0, 0]</p> +<h2 id="example-4">[Example 4]</h2> +<p><strong>Circuit</strong> $out = 2x^2 + y$</p> +<p>We write the matrices for $out-y=2x^2$. We have one constraint and witness vector will be $w = [1, out, x, y]$. </p> +<p>$A = [0, 0, 2, 0]$, $B = [0, 0, 1, 0], $C = [0, 1, 0, -1]</p> +<h2 id="example-5">[Example 5]</h2> +<p><strong>Circuit</strong> $out = 3x^2y + 5xy - x - 2y + 3$</p> +<p>We can reduce the equations to below:</p> +<p>$$u1 = 3<em>x</em>x$$ +$$u2 = u1*y$$ +$$x+2y-3-u2+out = 5xy$$</p> +<p>We have three constraints. Our witness vector will be $w = [1, out, x, y, u1, u2]$.</p> +<p>Hence, the our matrices $A$, $B$, and $C$ can be written as </p> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>A = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 3 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 5 &amp; 0 &amp; 0 &amp; 0 +</span><span>\end{bmatrix} +</span></code></pre> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>B = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 1 &amp; 1 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 +</span><span>\end{bmatrix} +</span></code></pre> +<pre data-lang="math" style="background-color:#fefbec;color:#6e6b5e;" class="language-math "><code class="language-math" data-lang="math"><span>C = +</span><span>\begin{bmatrix} +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\ +</span><span> 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 \\ +</span><span> -3 &amp; 1 &amp; 1 &amp; 2 &amp; 0 &amp; -1 +</span><span>\end{bmatrix} +</span></code></pre> +<p>We can check these matrices with below sagemath code:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span> +</span><span style="color:#999580;"># define the matrices +</span><span> +</span><span>A = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">3</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span> +</span><span>B = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">5</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>]]) +</span><span> +</span><span>C = </span><span style="color:#d73737;">matrix</span><span>([[</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">0</span><span>], +</span><span> [</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">0</span><span>,</span><span style="color:#b65611;">1</span><span>], +</span><span> [-</span><span style="color:#b65611;">3</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">2</span><span>,</span><span style="color:#b65611;">0</span><span>,-</span><span style="color:#b65611;">1</span><span>]]) +</span><span> +</span><span>x = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span>y = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>,</span><span style="color:#b65611;">100000</span><span>) +</span><span> +</span><span> +</span><span style="color:#999580;"># reductions +</span><span>out = </span><span style="color:#b65611;">3 </span><span>* x * x * y + </span><span style="color:#b65611;">5 </span><span>* x * y - x- </span><span style="color:#b65611;">2</span><span>*y + </span><span style="color:#b65611;">3 +</span><span style="color:#999580;"># the intermediate variables +</span><span>u1 = </span><span style="color:#b65611;">3</span><span>*x*x +</span><span>u2 = u1 * y +</span><span> +</span><span> +</span><span style="color:#999580;"># witness vector +</span><span>witness = </span><span style="color:#d73737;">vector</span><span>([</span><span style="color:#b65611;">1</span><span>, out, x, y, u1, u2]) +</span><span> +</span><span> +</span><span style="color:#999580;"># Calculate the results +</span><span>A_witness = A*witness +</span><span>B_witness = B*witness +</span><span>C_witness = C*witness +</span><span>AB_witness = A_witness.</span><span style="color:#d73737;">pairwise_product</span><span>(B_witness) +</span><span> +</span><span style="color:#999580;"># Print the results +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">A * witness = </span><span>{A_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">B * witness = </span><span>{B_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">C * witness = </span><span>{C_witness}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">(A * witness) * (B * witness) = </span><span>{AB_witness}&quot;) +</span><span> +</span><span style="color:#999580;"># Check the equality +</span><span>result = C_witness == AB_witness +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">result: </span><span>&quot;,result) +</span><span> +</span><span style="color:#999580;"># Check that the equality is true +</span><span style="color:#b854d4;">assert </span><span>result, &quot;</span><span style="color:#60ac39;">result contains an inequality</span><span>&quot; +</span></code></pre> +<p>We will see the output:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>A * witness = (133875, 5974171875, 44625) +</span><span>B * witness = (44625, 61540, 307700) +</span><span>C * witness = (5974171875, 367650537187500, 13731112500) +</span><span>(A * witness) * (B * witness) = (5974171875, 367650537187500, 13731112500) +</span><span>result: True +</span></code></pre> +<p>Let's compile this and generate a witness.</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>circom Example5.circom --r1cs --wasm --sym +</span><span> +</span><span>snarkjs r1cs print Example5.r1cs +</span><span> +</span><span>cd Example5_js +</span><span> +</span><span>echo &#39;{&quot;x&quot;: &quot;5&quot;, &quot;y&quot;: &quot;10&quot;}&#39; &gt; input.json +</span><span> +</span><span>node generate_witness.js Example5.wasm input.json witness.wtns +</span><span> +</span><span>snarkjs wtns export json witness.wtns witness.json +</span><span> +</span><span>cat witness.json +</span><span> +</span></code></pre> +<p>We get the following output.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230814/Example5-r1cs-wasm-witness-output.png" alt="multiply4-r1cs-wasm-witness-output" /></p> + + + + Paper Review - Zero Knowledge Proofs for Decision Tree Predictions and Accuracy + 2023-07-24T00:00:00+00:00 + 2023-07-24T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/ + <h1 id="in-draft-mode"><strong>IN DRAFT MODE</strong></h1> +<h1 id="summary"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#summary">Summary</a></h1> +<p>Machine learning has become increasingly prominent and is widely used in various applications in practice. Despite its great success, the integrity of machine learning predictions and accuracy is a rising concern. The reproducibility of machine learning models that are claimed to achieve high accuracy remains challenging, and the correctness and consistency of machine learning predictions in real products lack any security guarantees. In this paper, the authors initiate the study of zero knowledge machine learning (ZKML) and propose protocols for zero knowledge decision tree predictions and accuracy tests.</p> +<ul> +<li>This paper presents a novel way of proving that a decision tree can make a correct prediction on a given data point without revealing anything about the decision tree itself. This is called a zero knowledge decision tree prediction protocol.</li> +<li>The protocol has two phases: a setup phase and a proving phase. In the setup phase, the decision tree is encoded in a way that takes linear time in the size of the tree. In the proving phase, the prediction is computed in a way that only depends on the length of the prediction path and the number of features of the data point.</li> +<li>The protocol uses several advanced techniques from the field of zero knowledge proofs for computations in the RAM model, but adapts them in non-black-box ways to suit the decision tree setting.</li> +<li>The protocol converts the decision tree prediction to a small circuit of size $O(d + h)$, where $d$ is the number of features and $h$ is the height of the tree.</li> +<li>The paper also extends the protocol to prove the accuracy of a decision tree on a testing dataset, which is called a zero knowledge decision tree accuracy protocol.</li> +<li>The accuracy protocol has two optimizations that reduce the number of hashes in the zero knowledge proof backend to be exactly equal to the number of nodes in the decision tree. This number does not depend on the size of the testing dataset and can be much smaller than $2^h$ if the tree is unbalanced.</li> +<li>The paper implements and evaluates both protocols on several real-world datasets. The results show that for a large decision tree with <code>23</code> levels and <code>1,029</code> nodes, it takes only <code>250</code> seconds to generate a proof for its accuracy on a testing dataset with <code>5,000</code> data points and <code>54</code> features. The proof size is <code>287KB</code>, and it takes <code>15.6</code> seconds to verify it.</li> +</ul> +<h1 id="citation-of-the-paper"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#citation-of-the-paper">Citation of the Paper</a></h1> +<p>Jiaheng Zhang, Zhiyong Fang, Yupeng Zhang, and Dawn Song. 2020. Zero Knowledge Proofs for Decision Tree Predictions and Accuracy. In Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security (CCS '20). Association for Computing Machinery, New York, NY, USA, 2039–2053. https://doi.org/10.1145/3372297.3417278</p> +<h1 id="zero-knowledge-proofs"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#zero-knowledge-proofs">Zero Knowledge Proofs</a></h1> +<p>The paper proposes the use of zero knowledge proofs (ZKP) to ensure the integrity of machine learning predictions and accuracy without leaking any information about the model itself. A zero knowledge proof allows a prover to produce a short proof that can convince any verifier that the result of a public function on the public input and secret input of the prover is correct. The secret input is usually referred to as the witness or auxiliary input. Zero knowledge proofs guarantee that the verifier rejects with overwhelming probability if the prover cheats on computing the result, while the proof reveals no extra information about the secret beyond the result.</p> +<ul> +<li>A zero-knowledge argument of knowledge for an $NP$ relation $R$ using a tuple of algorithms $(G, P, V)$ with the following properties.</li> +<li>The first property of this argument system is <strong>completeness</strong>, which means that for every public parameter $pp$ generated by $G(1^λ)$, if $(x; w) ∈ R$ and $π ← P(x, w, pp)$, then the probability that Verifier $V$ accepts the proof $(x, π, pp)$ as valid is $1$.</li> +<li>The second property is <strong>knowledge soundness</strong>, which ensures that any computationally-bounded prover $P^∗$ cannot convince $V$ of a false statement $(x; w) ∉ R$ without possessing a witness $w$. This property is guaranteed by the existence of a $PPT$ (probabilistic polynomial time) extractor $E$ that can extract $w$ from the executing process and randomness of $P^∗$ with negligible probability.</li> +<li>The third property is <strong>zero knowledge</strong>, which means that there exists a $PPT$ simulator $S$ that can simulate the view of any verifier $V^∗$ without knowing the witness $w$ or any information about $(x; w)$. This property ensures that the proof does not reveal any information about the witness or the statement beyond what is already known.</li> +<li>Finally, the definition introduces the concept of a <strong>succinct</strong> argument system, which limits the total communication between $P$ and $V$ (proof size) to be polynomial in the security parameter $λ$, the size of the input $x$, and the logarithm of the witness size $|w|$. This property ensures that the proof can be efficiently verified and transmitted without revealing any additional information.</li> +</ul> +<h1 id="zero-knowledge-decision-tree"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#zero-knowledge-decision-tree">Zero Knowledge Decision Tree</a></h1> +<p>The model introduces a knowledgeable prover equipped with a pre-trained decision tree. The prover takes the initiative by committing to the decision tree upfront. Subsequently, the verifier raises queries about the predictions of data samples. To validate its accuracy, the prover generates a convincing proof alongside the results.</p> +<p>But first, let's introduce some concepts and definitions: $F$, a finite field; $T$, a binary decision tree with a height $h$ and $N$ nodes $(N ≤ 2^h −1)$; and $D$, the test dataset containing data points with $d$ features, where each data point, $a ∈ F^d$. Moreover, we have $[M]$, representing the set of all target classifications. The decision tree algorithm, denoted as $T : F^d → [M]$, is responsible for mapping data points to their corresponding classifications. When a data point $a ∈ D$ is fed into the decision tree, $T(a) ∈ [M]$ is the classification prediction.</p> +<p>Embracing transparency, the scheme assumes that both parties are aware of the height (or an upper bound) of the decision tree. Furthermore, they denote $comT$ as the commitment of the decision tree, $y_a$ as the class returned by the decision tree for data point $a$, and $π$ as the proof ingeniously crafted by the prover. Finally, ${0, 1}$ represents the verifier's output, indicating whether to accept or reject the classification and proof.</p> +<p>The zero-knowledge decision tree scheme (zkDT) consists of the four algorithms, $G$, $Commit$, $P$, and $V$:</p> +<ol> +<li> +<p>The $pp ← zkDT.G(1^λ)$ algorithm: With the security parameter given, generate the public parameter $pp$. </p> +</li> +<li> +<p>The $comT ← zkDT.Commit(T , pp, r)$ algorithm: This step involves the prover committing to the decision tree $T$ using a random point $r$. </p> +</li> +<li> +<p>The $(y_a, π ) ← zkDT.P(T , a, pp)$ algorithm: When given a data point $a$, the decision tree algorithm is executed, producing $y_a = T(a)$ and an accompanying proof $π$.</p> +</li> +<li> +<p>The ${0, 1} ← zkDT.V(comT , h, a, y_a, π , pp)$ algorithm: At this stage, the Verifier validates the prediction of $a$, the classification $y_a$, and the proof $π$ provided by the prover.</p> +</li> +</ol> +<h2 id="intuition-of-the-construction-of-zkdt"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#intuition-of-the-construction-of-zkdt">Intuition of the construction of zkDT</a></h2> +<p>Here is a sequence diagram describing the specific construction of zkDT.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230724/zkDT-sequence-diagram.png" alt="Intuition of the construction of zkDT" /></p> +<ul> +<li>The general idea of the construction of zkDT involves the prover $P$ sending the commitment of a decision tree $T$, $comT$, to the verifier $V$.</li> +<li>After receiving the data sample $a$ from the verifier, the prover computes $y_a$ and the corresponding witness $w$ for proving $y_a = T(a)$, then sends $y_a$ to the verifier.</li> +<li>This relationship $R = ((ya, a, comT); w)$ is treated as a $NP$ relationship as described above in the <a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#zero-knowledge-proofs">ZKP</a>.</li> +<li>The verifier and the prover then invoke the backend zero-knowledge proofs protocol to verify the relationship $R$ without leaking any information of $T$ except for $y_a$.</li> +<li>This approach ensures that the privacy of the decision tree is preserved while still allowing for accurate predictions to be made and verified.</li> +</ul> +<h2 id="authenticated-decision-tree"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#authenticated-decision-tree">Authenticated Decision Tree</a></h2> +<p>The paper introduces the concept of an Authenticated Decision Tree (ADT), which is a decision tree that has been authenticated by a commitment scheme. The ADT is used in the proposed protocols for zero knowledge decision tree predictions and accuracy tests. The ADT is constructed by hashing the root of the decision tree concatenated with a random point, which is used as the commitment.</p> +<ul> +<li>A naive approach to committing to a decision tree is to compute the hash of the entire tree, but this would result in high overhead when proving predictions.</li> +<li>Another approach is to use a Merkle hash tree on all the nodes in the decision tree, but this would still introduce overhead in the zero knowledge proof backend.</li> +</ul> +<h2 id="construction-of-adt"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#construction-of-adt">Construction of ADT</a></h2> +<p>The paper describes the construction of the ADT, which involves hashing the root of the decision tree concatenated with a random point to produce the commitment. The paper notes that the commitment must be randomized in order to prove the zero knowledge property of the scheme later.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230724/Committing-algorithm-of-ADT-scheme-zkDT.png" alt="Construction of ADT" /></p> +<ul> +<li>Each node in ADT contains three pieces of information: the attribute $(v.att)$, the threshold $(v.thr)$, and pointers to the left and right children $(lc, rc)$.</li> +<li>The construction of ADT is illustrated in the above figure, which shows how the hash of an intermediate node is computed using the hashes of its children and its own attribute and threshold values.</li> +<li>The inclusion of the attribute and threshold values in the hash computation ensures that the integrity of the decision tree is maintained, and any tampering with the tree structure or values will be detected during verification.</li> +<li>The verification algorithm for ADT is similar to that of the Merkle hash tree, where the proof includes the prediction path from the root to the leaf node that outputs the prediction result, as well as the hashes of the siblings of the nodes along the prediction path.</li> +<li>With the proof, the verifier can recompute the root hash and compare it with the commitment to ensure the validity of the prediction.</li> +<li>The advantage of using ADT over Merkle hash tree is that the verification of ADT only requires $O(h)$ hashes, where $h$ is the height of the decision tree, whereas Merkle hash tree requires $O(h log N)$ hashes, where $N$ is the number of nodes in the tree.</li> +<li>The construction of zkDT uses ADT to efficiently turn decision tree predictions and accuracy into statements of zero knowledge proofs, which allows the owner of a decision tree model to convince others of its accuracy without revealing any information about the model itself.</li> +</ul> +<p>With the construction of ADT, we can update our methodology of the algorithms used in the ADT for zero knowledge proofs of decision tree predictions and accuracy.</p> +<ul> +<li>In order to prove the zero knowledge property of the scheme, the commitment has to be randomized. This means that a random point $r$ is added to the root of the decision tree and the hash of the root concatenated with r is used as the final commitment. This is shown in the above figure.</li> +<li>This ADT described in the paper does not have to support dynamic insertions and deletions for the purpose of the application, which simplifies the construction significantly.</li> +<li>The first algorithm, $pp ← ADT.G(1^λ)$, samples a collision-resistant hash function from the family of hash functions.</li> +<li>The second algorithm, $comADT ← ADT.Commit(T, pp, r)$, computes hashes from leaf nodes to the root of $T$ with the random point $r$ as shown in the above figure.</li> +<li>The third algorithm, $πADT ← ADT.P(T, Path, pp)$, given a path in $T$, contains all siblings of the nodes along the path Path and the randomness $r$ in the above figure.</li> +<li>The fourth algorithm, ${0, 1} ← ADT.V(comADT, Path, πADT, pp)$, given Path and $πADT$, recomputes hashes along Path with $πADT$ as the same progress in the above figure and compares the root hash with $comADT$. It outputs $1$ if they are the same, otherwise, $0$.</li> +<li>These algorithms are used to efficiently turn decision tree predictions and accuracy into statements of zero knowledge proofs.</li> +</ul> +<h1 id="proving-the-validity-of-the-prediction"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#proving-the-validity-of-the-prediction">Proving the Validity of the Prediction</a></h1> +<h2 id="the-protocol-for-proving-the-correctness-of-the-prediction-in-a-decision-tree-involves-using-a-zero-knowledge-proof-on-top-of-the-validation-process-to-keep-the-prediction-path-and-sibling-hashes-confidential-zero-knowledge-this-protocol-ensures-that-the-verifier-only-receives-a-binary-output-1-or-0-indicating-whether-all-the-checks-are-satisfied-or-not-making-it-both-sound-and-zero-knowledge">The protocol for proving the correctness of the prediction in a decision tree involves using a zero knowledge proof on top of the validation process to keep the prediction path and sibling hashes confidential (zero knowledge). This protocol ensures that the verifier only receives a binary output $(1 or 0)$ indicating whether all the checks are satisfied or not, making it both sound and zero knowledge.</h2> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230724/Zero-knowledge-decision-tree-prediction.png" alt="Zero knowledge decision tree prediction" /></p> +<p>The below steps explain the design of an efficient zero knowledge proof protocol proposed in the paper for validating decision tree predictions.</p> +<ul> +<li>The protocol reduces the validity of the prediction using a committed decision tree to an arithmetic circuit.</li> +<li>The public input of the circuit includes the data sample $a$, the commitment of the decision tree $comT$, and the prediction result $y_a$.</li> +<li>The secret witness from the prover includes the prediction path <strong>$a$</strong> and the randomness $r$ used in the commitment of ADT.</li> +<li>To improve efficiency, the prover inputs the siblings of nodes on the prediction path and the permutation $\hat{a}$ of the data sample $a$ ordered by $v.att$ of the nodes on the prediction path as part of the witness.</li> +<li>The purpose of the extended witness is to check the permutation between the data sample and the ordered sample and to validate the prediction path in the committed decision tree.</li> +<li>The whole circuit consists of three parts: validating the prediction algorithm of the decision tree, checking the permutation between the data sample $a$ and the ordered sample $\hat{a}$, and checking the validity of the prediction path in the committed decision tree.</li> +<li>The output of the circuit is either $1$ or $0$, denoting whether all the conditions are satisfied or some check fails.</li> +</ul> +<h2 id="decision-tree-prediction"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#decision-tree-prediction">Decision Tree Prediction</a></h2> +<p>The above figure 2 describes the zero knowledge decision tree prediction.</p> +<ul> +<li>The validation process is efficiently implemented using an arithmetic circuit with the help of auxiliary input $\hat{a}$.</li> +<li>The representation of a and $\hat{a}$ is slightly modified to be index-value pairs, where $a = (1, a[1]), . . . , (d, a[d])$ and $a = (i_1, a[i_1]), . . . , (i_d , a[i_d])$.</li> +<li>The circuit checks for every internal node $v_j$ on the prediction path $(j = 1, . . . , h−1)$ that (1) $v_j.att = i_j$, and (2) if $a[i_j ] &lt; v$j.thr$, $v_j+1 = v_j.left$, otherwise $v_j+1 = v_j.right$.</li> +<li>The equality tests and comparisons are computed using standard techniques in the literature of circuit-based zero knowledge proof with the help of auxiliary input.</li> +<li>Finally, the circuit checks if ya = vh .class. The circuit outputs 1 if all the checks pass, and outputs 0 otherwise.</li> +<li>The total number of gates in this part is O(d + h), which is asymptotically the same as the plain decision tree prediction in Algorithm 1.</li> +<li>If h &lt; d, which is usually true in practice, the circuit only checks the indices of the first h − 1 pairs in ̄a. The rest of the indices are arbitrary, as long as ̄a is a permutation of a.</li> +<li>The prover and the verifier can either agree on the length of the prediction path and construct a separate circuit for every data sample, or use the height of the tree as an upper-bound to construct the same circuit for all data samples.</li> +<li>Both options are supported by the scheme, and the asymptotic complexity is the same. However, the former is more efficient but leaks the length of the prediction paths.</li> +</ul> +<h2 id="permuitation-test"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#permuitation-test">Permuitation Test</a></h2> +<h2 id="path-validation"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#path-validation">Path Validation</a></h2> +<h2 id="zero-knowledge-decision-tree-prediction-protocol"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#zero-knowledge-decision-tree-prediction-protocol">Zero Knowledge Decision Tree Prediction Protocol</a></h2> +<h1 id="zero-knowledge-decision-tree-accuracy"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#zero-knowledge-decision-tree-accuracy">Zero Knowledge Decision Tree Accuracy</a></h1> +<h1 id="validating-decision-tree-accuracy"><a href="https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/#validating-decision-tree-accuracy">Validating Decision Tree Accuracy</a></h1> +<p>The paper proposes a protocol for validating decision tree accuracy using a zero knowledge proof. The protocol involves the prover generating a proof that the decision tree</p> + + + + Unlocking the Power of ElGamal Encryption: Implementing and Enhancing Security with SageMath + 2023-06-23T00:00:00+00:00 + 2023-06-23T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/ + <ul> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#introduction">Introduction</a></li> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#elgamal-encryption">ElGamal Encryption</a></li> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#enhancing-security-of-elgamal-encryption">Enhancing Security of ElGamal Encryption</a></li> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#finding-a-safe-generator">Finding a Safe Generator</a></li> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#practical-applications-of-elgamal-encryption">Practical Applications of ElGamal Encryption</a></li> +<li><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#conclusion">Conclusion</a></li> +</ul> +<h1 id="introduction"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#introduction">Introduction</a></h1> +<p>ElGamal encryption is a widely-used public key encryption algorithm that provides confidentiality and security in communication systems. It was proposed by Taher ElGamal in 1985 and is based on the Diffie-Hellman key exchange protocol. In this guide, I will walk through the key components of the ElGamal encryption scheme, including key generation, encryption, and decryption. I will also demonstrate how to implement the algorithm using the SageMath software and enhance the security of the system by using a 256-bit random prime number.</p> +<h1 id="elgamal-encryption"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#elgamal-encryption">ElGamal Encryption</a></h1> +<p>Key Components The ElGamal encryption scheme consists of three main components:</p> +<ul> +<li>Key Generation: The process of generating a pair of public and private keys for the encryption and decryption process.</li> +<li>Encryption: The process of transforming plaintext into ciphertext using the public key.</li> +<li>Decryption: The process of recovering the plaintext from the ciphertext using the private key.</li> +</ul> +<p>In ElGamal encryption, the public key is used for encrypting the message, while the private key is used for decrypting it. The security of the ElGamal encryption scheme is based on the difficulty of solving the discrete logarithm problem.</p> +<p>Let's consider an example of the ElGamal encryption process:</p> +<ul> +<li>Alice and Bob agree on a large prime number $p$ and a primitive root $g modulo p$.</li> +<li>Bob chooses a random private key $x$ and computes his public key $Y = g^x mod p$.</li> +<li>Alice wants to send a message $M$ to Bob. She chooses a random integer $k$ and computes the ciphertext $(a, b) = (g^k mod p, M * Y^k mod p)$.</li> +<li>Bob receives the ciphertext and decrypts it using his private key: $M = b * a^{-x}\ mod\ p$.</li> +</ul> +<p><strong>Flow of the ElGamal encryption</strong></p> +<p>Here is the complete flow diagram of ElGamal encryption.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230623/Flow-ElGamal-encryption.png" alt="ElGamal encryption Flow" /></p> +<pre data-lang="mermaid" style="background-color:#fefbec;color:#6e6b5e;" class="language-mermaid "><code class="language-mermaid" data-lang="mermaid"><span>sequenceDiagram +</span><span> +</span><span>Alice-&gt;&gt;Bob: Generate key pair (public key, private key) +</span><span>Note right of Alice: (g^a mod p, a) +</span><span>Note right of Bob: (g^b mod p, b) +</span><span>Alice-&gt;&gt;Bob: Send public key (g^a mod p) +</span><span>Bob-&gt;&gt;Alice: Encrypt message with Alice&#39;s public key +</span><span>Note right of Bob: Encrypted message: (g^b mod p, M * (g^a)^b mod p) +</span><span>Alice-&gt;&gt;Alice: Decrypt message with private key +</span><span>Note right of Alice: Decrypted message: M = (g^a)^(-b) * (M * (g^a)^b mod p) mod p +</span></code></pre> +<p>Implementing ElGamal Encryption with SageMath SageMath is an open-source mathematics software that provides a powerful environment for implementing various cryptographic algorithms, including ElGamal encryption. To get started with SageMath, you can install it on your local machine or use the online version available at sagemath.org.</p> +<p>Once you have SageMath installed and running, you can implement the ElGamal encryption process as follows:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span> </span><span style="color:#b854d4;">from </span><span>sage.all </span><span style="color:#b854d4;">import </span><span style="color:#b65611;">* +</span><span> +</span><span> </span><span style="color:#999580;"># Key Generation +</span><span> p = </span><span style="color:#b65611;">23 </span><span style="color:#999580;"># Prime number +</span><span> g = </span><span style="color:#b65611;">5 </span><span style="color:#999580;"># Generator +</span><span> x = </span><span style="color:#b65611;">6 </span><span style="color:#999580;"># Bob&#39;s private key +</span><span> Y = </span><span style="color:#d73737;">power_mod</span><span>(g, x, p) </span><span style="color:#999580;"># Bob&#39;s public key +</span><span> +</span><span> </span><span style="color:#999580;"># Encryption (Alice) +</span><span> M = </span><span style="color:#b65611;">12 </span><span style="color:#999580;"># Message +</span><span> k = </span><span style="color:#b65611;">3 </span><span style="color:#999580;"># Random value +</span><span> a = </span><span style="color:#d73737;">power_mod</span><span>(g, k, p) +</span><span> b = (</span><span style="color:#d73737;">power_mod</span><span>(Y, k, p) * M) % p +</span><span> +</span><span> </span><span style="color:#999580;"># Decryption (Bob) +</span><span> M_decrypted = (b * </span><span style="color:#d73737;">power_mod</span><span>(a, -x, p)) % p +</span><span> +</span><span> </span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Original message:</span><span>&quot;, M) +</span><span> </span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Encrypted message:</span><span>&quot;, (a, b)) +</span><span> </span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Decrypted message:</span><span>&quot;, M_decrypted) +</span></code></pre> +<p>This example demonstrates the basic ElGamal encryption process with a fixed prime number $p$. The output shows the original message, the encrypted message, and the decrypted message.</p> +<h1 id="enhancing-security-of-elgamal-encryption"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#enhancing-security-of-elgamal-encryption">Enhancing Security of ElGamal Encryption</a></h1> +<p>Choosing a 256-bit Random Prime Using large prime numbers in the ElGamal encryption process is crucial for ensuring the security of the system. Larger prime numbers make it more difficult for an attacker to solve the discrete logarithm problem, which is the basis of the ElGamal encryption scheme's security.</p> +<p>To generate a 256-bit random prime number in SageMath, you can use the <code>random_prime()</code> function:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span> p = </span><span style="color:#d73737;">random_prime</span><span>(</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256</span><span>, </span><span style="color:#d73737;">lbound</span><span>=</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">255</span><span>, </span><span style="color:#d73737;">proof</span><span>=</span><span style="color:#b65611;">False</span><span>) </span><span style="color:#999580;"># 256-bit prime number +</span></code></pre> +<p>By updating the previous SageMath code with this new prime number generation method, you can enhance the security of the ElGamal encryption process.</p> +<h1 id="finding-a-safe-generator"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#finding-a-safe-generator">Finding a Safe Generator</a></h1> +<p>In the ElGamal encryption scheme, selecting a safe generator $g$ is crucial for the security of the system. A safe generator is a number that generates a cyclic subgroup of the multiplicative group $modulo p$, where $p$ is a large prime number. </p> +<p>To find a safe generator $g$, follow these steps:</p> +<ol> +<li>First, select a large prime number $p$ and compute $(p-1)/2$, which should also be prime. This new prime number is denoted as $q$.</li> +<li>Now, choose a random number $g$ from the set ${2, 3, ... , p-2}$.</li> +<li>Calculate $(g^q) mod p$. If the result is not equal to 1, then g is a safe generator.</li> +</ol> +<p>Here's an example of how to find a safe generator using SageMath:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Find a safe generator $g$ for a given prime $p$ +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">find_safe_generator</span><span>(</span><span style="color:#d73737;">p</span><span>): +</span><span> q = (p - </span><span style="color:#b65611;">1</span><span>) // </span><span style="color:#b65611;">2 +</span><span> g = </span><span style="color:#b65611;">2 +</span><span> </span><span style="color:#b854d4;">while </span><span style="color:#b65611;">True</span><span>: +</span><span> </span><span style="color:#b854d4;">if </span><span style="color:#d73737;">power_mod</span><span>(g, q, p) != </span><span style="color:#b65611;">1</span><span>: +</span><span> </span><span style="color:#b854d4;">return </span><span>g +</span><span> g += </span><span style="color:#b65611;">1 +</span><span> +</span><span style="color:#999580;"># Example: Finding a safe generator for a 256-bit prime number +</span><span>p = </span><span style="color:#d73737;">random_prime</span><span>(</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256</span><span>, </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">255</span><span>) +</span><span>g = </span><span style="color:#d73737;">find_safe_generator</span><span>(p) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Safe generator (g):</span><span>&quot;, g) +</span></code></pre> +<p>By following this method, you can ensure that the chosen generator $g$ is safe and suitable for use in the ElGamal encryption scheme.</p> +<h1 id="practical-applications-of-elgamal-encryption"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#practical-applications-of-elgamal-encryption">Practical Applications of ElGamal Encryption</a></h1> +<p>ElGamal encryption has numerous practical applications, including:</p> +<ul> +<li>Secure communication: ElGamal encryption can be used to ensure confidentiality in communication systems, such as email and instant messaging.</li> +<li>Digital signatures: ElGamal encryption can be adapted for use in digital signature schemes, providing integrity and non-repudiation for electronic documents and transactions.</li> +<li>Key exchange: ElGamal can be used as a key exchange protocol, allowing two parties to establish a shared secret key over an insecure channel.</li> +<li>Secure voting systems: ElGamal encryption can be employed in secure electronic voting systems to maintain voter privacy and ensure that votes are accurately counted.</li> +</ul> +<p>Despite its benefits, ElGamal encryption has some limitations that should be considered when choosing a cryptographic solution:</p> +<ul> +<li>Computational complexity: ElGamal encryption and decryption require modular exponentiation operations, which can be computationally expensive, especially for large prime numbers.</li> +<li>Message expansion: The ciphertext in ElGamal encryption consists of two elements, resulting in a message expansion factor of two compared to the original plaintext size.</li> +<li>Lack of built-in authentication: ElGamal encryption does not provide built-in message authentication or integrity checking, which may require additional mechanisms to ensure data integrity.</li> +</ul> +<h1 id="conclusion"><a href="https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/#conclusion">Conclusion</a></h1> +<p>In this article, I have provided an in-depth explanation of ElGamal encryption and its key components, including key generation, encryption, and decryption. I have also demonstrated how to implement the ElGamal encryption algorithm using SageMath and enhance the security of the system by using a 256-bit random prime number.</p> +<p>ElGamal encryption is an essential tool in the field of cryptography, with numerous practical applications in secure communication, digital signatures, key exchange, and secure voting systems. However, it is crucial to consider its limitations and choose the most suitable encryption scheme for your specific needs.</p> +<p>I encourage you to experiment with ElGamal encryption using SageMath and explore its potential in various applications. By understanding the fundamentals of ElGamal encryption and its implementation, you can build more secure and robust cryptographic systems.</p> +<p>You can find the full code in the github repo <a href="https://github.com/thogiti/ElGamal-Encryption/">github.com/thogiti</a>.</p> +<p><strong>References</strong></p> +<ol> +<li>ElGamal, T. (1985). A public key cryptosystem and a signature scheme based on discrete logarithms. IEEE Transactions on Information Theory, 31(4), 469-472.</li> +<li>Diffie, W., &amp; Hellman, M. E. (1976). New directions in cryptography. IEEE Transactions on Information Theory, 22(6), 644-654.</li> +</ol> + + + + Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit + 2023-06-14T00:00:00+00:00 + 2023-06-14T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/ + <h1 id="rate-limiting-nullifier-rln-review">Rate Limiting Nullifier (RLN) Review</h1> +<p>I recently had the pleasure of conducting my first security audit of a Zero Knowledge Proofs (ZKP) protocol. The protocol in question was the Rate Limiting Nullifier (RLN) Zero Knowledge Proofs Protocol, with its circuits written in Circom. My main focus during this review was on the Circom Circuits of the Zero Knowledge Proofs gadgets. And let me tell you, it was quite the adventure! I mean, who knew math could be so exciting?</p> +<p>During my review of the RLN Zero Knowledge Proofs Protocol, I learned a great deal about the intricacies of the RLN specifications, the verifications, and how to identify underconstraint systems. My mathematical background proved to be invaluable in helping me understand these complex concepts. It’s like they always say, “mathematics is the language of the universe”! But seriously, who comes up with this stuff? Additionally, I gained a deeper understanding of ZKP primitives attack vectors and other potential vulnerabilities in the system. It’s like being a detective, but for ZKP systems! And let me tell you, it’s not as easy as it looks. </p> +<p><strong>Review Resources:</strong></p> +<ul> +<li>The code repository at <a href="https://github.com/Rate-Limiting-Nullifier/circom-rln">github.com/Rate-Limiting-Nullifier</a></li> +<li>The RLN V1 specification document at <a href="https://rfc.vac.dev/spec/32">rfc.vac.dev</a></li> +<li>The RLN V2 specification document at <a href="https://rfc.vac.dev/spec/58">rfc.vac.dev</a></li> +</ul> +<p><strong>Auditors:</strong></p> +<ul> +<li><a href="https://github.com/thogiti/">0xnagu</a></li> +</ul> +<h2 id="table-of-contents">Table of Contents <!-- omit in toc --></h2> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#executive-summary">Executive Summary</a></p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#scope">Scope</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#explanation-of-findings">Explanation of Findings</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#critical-findings">Critical Findings</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#high-findings">High Findings</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#medium-findings">Medium Findings</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#low-findings">Low Findings</a> </p> +<p><a href="https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/#final-remarks">Final Remarks</a> </p> +<h2 id="executive-summary">Executive Summary</h2> +<ul> +<li>There are no critical or high impact bugs in the code.</li> +<li>There were some low impact bugs mainly under constrained input variables between the Circom circuits and their corresponding Solidity contracts. </li> +</ul> +<p><strong>Rate Limiting Nullifier</strong></p> +<p>Rate limiting nullifier (RLN) is a construct based on zero-knowledge proofs (sometimes called ZKP gadget) that provides an anonymous rate-limited signaling/messaging framework suitable for decentralized (and centralized) environments using Secret Shamir Sharing (SSS) scheme.</p> +<p><strong>Motivation</strong> +Some applications of rate limiting nullifier in anonymous decentralized networks include:</p> +<ol> +<li>Decentralized voting applications: RLN helps prevent voting outcomes from being manipulated by spam or sybil attacks, ensuring the integrity of the voting process. </li> +<li>Anonymous group chat applications: By preventing users from spamming or polluting group chats, RLN enhances the user experience in these applications.</li> +<li>Direct anonymous attestation: RLN can be used in combination with Direct Anonymous Attestation (DAA) to implement service rate-limiting in a scenario where messages between users and the service are sent anonymously while preserving message unlinkability</li> +<li>Blockchain-based social networks: RLN can be applied to decentralized social media networks to prevent spam, sybil attacks, and other types of abuse targeting APIs and applications, thus enhancing the overall security and reliability of these networks.</li> +<li>Rate limiting in web applications: RLN can be integrated with Web Application Firewalls (WAF) to protect against denial-of-service attacks, brute-force login attempts, and API traffic surges, providing a more secure and reliable web application experience. </li> +</ol> +<p><strong>RLN V2</strong> +The RLN V2 protocol is a more general construct, that allows to set various limits for an epoch (it’s 1 message per epoch in RLN-V1) while remaining almost as simple as it predecessor. Moreover, it allows to set different rate-limits for different RLN app users based on some public data, e.g. stake.</p> +<p>The RLN Circom circuits were reviewed over 13 days. The code review was performed between May 31 and June 12, 2023. The RLN repository was under active development during the review, but the review was limited to the latest commit, <a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/tree/37073131b9c5910228ad6bdf0fc50080e507166a">37073131b9</a> at the start of the review. </p> +<p>The official documentation for the RLN circuits was located at <a href="https://rate-limiting-nullifier.github.io/rln-docs/">rate-limiting-nullifier.github.io</a>.</p> +<p><strong>Flow</strong></p> +<p>Here is the complete flow diagram of RLN protocol for the Circom circuits.</p> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230614/RLN-Flow-Diagram.png" alt="RLN Protocol Flow" /></p> +<pre data-lang="mermaid" style="background-color:#fefbec;color:#6e6b5e;" class="language-mermaid "><code class="language-mermaid" data-lang="mermaid"><span> +</span><span> graph TD +</span><span> ext_null&gt;External Nullifier] --&gt; h1(hash) +</span><span> secret{{Secret Trapdoor &amp; nullifier}} --&gt; h0(hash) --&gt; a_0 +</span><span> a_0{{Secret hashed a_0}} --&gt; h1 +</span><span> msg_id&gt;Message_ID `k`] --&gt; h1 +</span><span> msg_id --&gt; limit_check(Message Limit Check) +</span><span> msg_limit&gt;Message Limit] --&gt; limit_check +</span><span> h1 --&gt; a_1 --&gt; h2(hash) --&gt; int_null([Internal Nullifier]) +</span><span> a_1 --&gt; times +</span><span> m&gt;Message] --&gt; h3(hash) --&gt; times(*) --&gt; plus(+) +</span><span> a_0 --&gt; plus --&gt; sss([Shamir&#39;s Share y_share]) +</span><span> a_0 --&gt; h4(hash) --&gt; id_com([id_commitment]) +</span><span> h4 --&gt; merkle(MerkleProof) +</span><span> +</span></code></pre> +<h2 id="scope">Scope</h2> +<p>The scope of the review consisted of the following circuits at the specific commit:</p> +<ul> +<li><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/37073131b9c5910228ad6bdf0fc50080e507166a/circuits/rln.circom">rln.circom</a></li> +<li><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/37073131b9c5910228ad6bdf0fc50080e507166a/circuits/utils.circom">utils.circom</a></li> +<li><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/37073131b9c5910228ad6bdf0fc50080e507166a/circuits/withdraw.circom">withdraw.circom</a></li> +</ul> +<p>After the findings were presented to the RLN team, fixes were made and included in several PRs.</p> +<p>This review is a code review to identify potential vulnerabilities in the code. The reviewers did not investigate security practices or operational security and assumed that privileged accounts could be trusted. The reviewers did not evaluate the security of the code relative to a standard or specification. The review may not have identified all potential attack vectors or areas of vulnerability.</p> +<p>yAcademy and the auditors make no warranties regarding the security of the code and do not warrant that the code is free from defects. yAcademy and the auditors do not represent nor imply to third parties that the code has been audited nor that the code is free from defects. By deploying or using the code, RLN and users of the contracts agree to use the code at their own risk.</p> +<h2 id="code-evaluation-matrix">Code Evaluation Matrix</h2> +<table><thead><tr><th>Category</th><th>Mark</th><th>Description</th></tr></thead><tbody> +<tr><td>Access Control</td><td>Not applicable</td><td>The code does not explicitly implement access control mechanisms. It does not have specific checks or restrictions on who can access or modify the data.</td></tr> +<tr><td>Mathematics</td><td>Good</td><td>The code includes mathematical operations such as addition, multiplication, and hashing using the Poseidon function. It also includes range checks and bit manipulation operations.</td></tr> +<tr><td>Complexity</td><td>Good</td><td>The complexity of the code is relatively low. It consists of basic mathematical operations and includes a Merkle tree inclusion proof and range checks.</td></tr> +<tr><td>Libraries</td><td>Average</td><td>The code includes the Circomlib library, specifically the Poseidon circuit, which is used for hashing.</td></tr> +<tr><td>Decentralization</td><td>Not applicable</td><td>The code does not explicitly address decentralization. It does not include mechanisms for distributed consensus or interaction with a decentralized network.</td></tr> +<tr><td>Code stability</td><td>Good</td><td>The code appears to be well-structured and follows the Circom syntax. It does not contain any obvious errors or issues that would affect its stability.</td></tr> +<tr><td>Documentation</td><td>Low</td><td>The code does not include extensive documentation. There are some comments explaining the purpose of certain components, but more detailed documentation would be beneficial.</td></tr> +<tr><td>Monitoring</td><td>Average</td><td>The code does not include specific monitoring mechanisms. It does not have built-in logging or tracking of events or performance metrics.</td></tr> +<tr><td>Testing and verification</td><td>Average</td><td>The code includes some basic range checks and a Merkle tree inclusion proof, which are important for ensuring the correctness of the code. However, it does not include comprehensive testing or verification procedures.</td></tr> +</tbody></table> +<h2 id="explanation-of-findings">Explanation of Findings</h2> +<p>Findings are broken down into sections by their respective impact:</p> +<ul> +<li>Critical, High, Medium, Low impact +<ul> +<li>These are findings that range from attacks that may cause loss of funds, impact control/ownership of the contracts, or cause any unintended consequences/actions that are outside the scope of the requirements</li> +</ul> +</li> +<li>Gas savings +<ul> +<li>Findings that can improve the gas efficiency of the contracts</li> +</ul> +</li> +<li>Informational +<ul> +<li>Findings including recommendations and best practices</li> +</ul> +</li> +</ul> +<hr /> +<h2 id="critical-findings">Critical Findings</h2> +<h3 id="1-critical-identitysecret-gets-revealed-for-certain-inputs-x-hash-of-the-message">1. Critical - <code>identitySecret</code> gets revealed for certain inputs <code>x</code> (hash of the message)</h3> +<p>The <code>identitySecret</code> gets revealed when the input signal <code>x</code>, the hash of the message, is <code>0</code> modulo prime <code>p</code> of the scalar field used. When the <code>x</code> is <code>0</code> or <code>21888242871839275222246405745257275088548364400416034343698204186575808495617</code> (in Ethereum) or the prime <code>p</code>, the order of the scalar field $Fp$ arithmetic circuits, the product <code>a1 * x</code> becomes zero thus revealing the <code>identitySecret</code>. </p> +<ul> +<li>This prime <code>p</code> is the order of the scalar field of the $BN254$ curve.</li> +<li>Circom 2.0.6 introduces two new prime numbers to work with +<ul> +<li>The order of the scalar field of the $BLS12-381$. +<ul> +<li><code>52435875175126190479447740508185965837690552500527637822603658699938581184513</code></li> +</ul> +</li> +<li>The goldilocks prime <code>18446744069414584321</code>, originally used in $Plonky2$.</li> +</ul> +</li> +</ul> +<p><strong>Recommended Solution</strong></p> +<p>Constraint on the input signal <code>x</code> and also on the product <code>a1 * x</code> to be non-zero modulo prime <code>p</code>.</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>isZero(x).out === 0 +</span><span>isZero(a1*x).out === 0 +</span><span> +</span></code></pre> +<h2 id="high-findings">High Findings</h2> +<p>None.</p> +<h2 id="medium-findings">Medium Findings</h2> +<p>None.</p> +<h2 id="low-findings">Low Findings</h2> +<h3 id="1-low-incosistency-between-rln-contract-and-rln-circuit-on-the-number-of-bits-for-usermessagelimit">1. Low - Incosistency between RLN contract and RLN circuit on the number of bits for userMessageLimit</h3> +<p>In RLN.sol, the messageLimit can take upto 2<strong>256 - 1 values whereas messageId &amp; userMessageLimit values in circuits is restricted to 2</strong>16 - 1 .</p> +<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/37073131b9c5910228ad6bdf0fc50080e507166a/circuits/rln.circom">rln.circom</a></p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>template RLN(DEPTH, LIMIT_BIT_SIZE) { +</span><span>... +</span><span> // messageId range check +</span><span> RangeCheck(LIMIT_BIT_SIZE)(messageId, userMessageLimit); +</span><span>... +</span><span>} +</span><span>component main { public [x, externalNullifier] } = RLN(20, 16); +</span></code></pre> +<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-contracts/blob/main/src/RLN.sol">rln.sol</a></p> +<pre data-lang="solidity" style="background-color:#fefbec;color:#6e6b5e;" class="language-solidity "><code class="language-solidity" data-lang="solidity"><span>uint256 messageLimit = amount / MINIMAL_DEPOSIT; +</span></code></pre> +<p><strong>Recommended Solution</strong></p> +<p>Update the relevant code at <a href="https://github.com/Rate-Limiting-Nullifier/rln-contracts/blob/main/src/RLN.sol">rln.sol</a> with something like below:</p> +<pre data-lang="solidity" style="background-color:#fefbec;color:#6e6b5e;" class="language-solidity "><code class="language-solidity" data-lang="solidity"><span>function register(uint256 identityCommitment, uint256 amount) external { +</span><span> ... +</span><span> uint256 messageLimit = amount / MINIMAL_DEPOSIT; +</span><span> require( messageLimit &lt;= type(uint16).max , &quot;Max length of your message limit is 65535&quot;); +</span><span> ... +</span><span> } +</span></code></pre> +<h3 id="2-low-unused-address-input-signal-in-the-withdraw-circuit">2. Low - Unused <code>address</code> input signal in the Withdraw circuit</h3> +<p>The input signal <code>address</code> was declared but not used in the output calculation. </p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span> signal input address; +</span></code></pre> +<p><strong>Recommended Solution</strong> +Assign a local computation for the unused input signal <code>address</code>. For example:</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span> signal addressDoubled &lt;== address + address; +</span></code></pre> +<h3 id="3-low-missing-rangechecks-for-the-data-inputs">3. Low - Missing rangechecks for the data inputs</h3> +<p>The Circom circuits are missing explicit rangechecks for several input parameters suchh as <code>DEPTH</code>, <code>address</code>, <code>LIMIT_BIT_SIZE</code>, etc. </p> +<p><strong>Recommended Solution</strong> +Perform explcit range checks and constrain the data input parameters to improve the soundness of the ZKP system.</p> +<h2 id="informational-findings">Informational Findings</h2> +<p>The Circom circuits are further tested for <code>Weak Verification</code> soundness property using <a href="https://github.com/franklynwang/EcneProject">Ecne tool</a> from 0xParc. This tests if, given the input variables in a QAP (R1CS constraints), the output variables have uniquely determined values. An underconstrained circuit admits valid proofs for multiple different outputs, given the same input. In the worst case, an attacker can generate a valid proof for an underconstrained circuit for any output--meaning that an attacker would be able to convince a verifier who (incorrectly) believes the circuit to be properly-constrained that the attacker knows the pre-image of arbitrary outputs.</p> +<h3 id="ecne-findings">Ecne Findings</h3> +<p>The Circom cuits were compiled to non-optimized R1CS constraints system and then they were tested for <code>Weak Verification</code> to check for any bad constraints or underconstraints. All the circuits passed the Ecne tests without any bad or underconstraints. This verifies that R1CS equations of the given circuits uniquely determine outputs given inputs (i.e. that the constraints are sound).</p> +<h3 id="error-handling">Error Handling</h3> +<p>Consider adding below error handling to check for specific conditions and throw an error or return an error code when those conditions are not met. This helps provide meaningful error messages or handle exceptional cases in a controlled manner.</p> +<p><strong><code>rln.circom</code></strong></p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>// Add error handling for Merkle tree inclusion proof +</span><span>root &lt;== MerkleTreeInclusionProof(DEPTH)(rateCommitment, identityPathIndex, pathElements); +</span><span>assert(root !== 0, &quot;Invalid Merkle tree inclusion proof&quot;); // Throw an error if the Merkle tree inclusion proof is invalid +</span><span> +</span></code></pre> +<p><strong><code>withdraw.circom</code></strong></p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span>// Add error handling for address length check +</span><span>assert(address.length == EXPECTED_ADDRESS_LENGTH, &quot;Invalid address length&quot;); // Throw an error if the address length is not as expected +</span><span> +</span></code></pre> +<p><strong><code>utils.circom</code></strong></p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span> +</span><span>// Add error handling for length check +</span><span>assert(leaf.length == EXPECTED_LEAF_LENGTH, &quot;Invalid leaf length&quot;); // Throw an error if the leaf length is not as expected +</span></code></pre> +<h3 id="poseidon-and-some-additional-remarks"><code>POSEIDON</code> and Some Additional Remarks</h3> +<ul> +<li>The RLN circuit assumes that the underlying hash function (<code>Poseidon</code>) is: +<ul> +<li>Collision-resistant</li> +<li>Resistant to differential, algebraic, and interpolation attacks</li> +<li>Behaves as a random oracle</li> +</ul> +</li> +<li>The Merkle tree used for membership proof is assumed to be secure against second-preimage attacks.</li> +<li>The security of the circuit depends on the security of the cryptographic primitives used for range checks and SSS share calculations.</li> +<li>The security of the circuit also depends on the secrecy of the <code>identitySecret</code> signal, which is assumed to be kept secret by the user.</li> +<li>Social engineering attacks are still a valid way to break the system.</li> +<li>An attacker can obtain the <code>identitySecret</code> signal of a user by using methods such as social engineering, phishing attacks, or exploiting vulnerabilities in the user's system.</li> +<li>Once the attacker has obtained the <code>identitySecret</code> signal, they can calculate the <code>identityCommitment</code>, <code>rateCommitment</code>, <code>a1</code>, and <code>y</code> signals for that user, and use them to break the security of the RLN circuit.</li> +</ul> +<h2 id="final-remarks">Final remarks</h2> +<p>Overall, the code demonstrates good implementation of mathematical operations and basic functionality. However, it could benefit from more extensive documentation and additional testing and verification procedures.</p> + + + + Unveiling the Weighted Set Cover Problem: Optimizing Resource Allocation + 2023-05-25T00:00:00+00:00 + 2023-05-25T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/ + <ul> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#introduction">Introduction</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#problem-explanation">Problem Explanation</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#problem-definition-weighted-set-cover">Problem Definition Weighted Set Cover</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#solution-greedy-algorithm">Solution Greedy Algorithm</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#implementation-in-sagemath">Implementation in SageMath</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#example-scenario">Example Scenario</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#applications-in-blockchain-technology-and-machine-learning">Applications in Blockchain Technology and Machine Learning</a> +<ul> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#blockchain-transaction-fee-optimization">Blockchain Transaction Fee Optimization</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#machine-learning-feature-selection">Machine Learning Feature Selection</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#relating-to-karp-reduction">Relating to Karp Reduction</a></li> +<li><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#conclusion">Conclusion</a></li> +</ul> +<h1 id="introduction"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#introduction">Introduction</a></h1> +<p>Welcome, fellow adventurers, to a captivating journey through the realms of the weighted set cover problem (WSC)! Imagine yourself as a wise ruler of a vast kingdom, yearning to promote tourism and showcase the wonders of your realm. But with a limited budget, how do you ensure that every precious gem in your kingdom receives the attention it deserves? Fear not! The weighted set cover problem comes to your rescue, providing a strategy to maximize coverage while minimizing cost. Let's embark on this quest together!</p> +<h1 id="problem-explanation"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#problem-explanation">Problem Explanation</a></h1> +<p>In this kingdom, attractions are like gleaming gems scattered across the land, and subsets represent different regions or provinces. The goal is to select a set of travel packages (subsets) that cover all the attractions (items) while keeping the total cost (weight) within your budget. Mathematically, we define the weighted set cover problem using set notation and equations. Let $U$ be the set of items, $S$ be the collection of subsets, $w(i)$ be the weight associated with item i, and $B$ be the budget. Our objective is to find a minimum-weight set cover such that the total weight is minimized $(∑w(i)$ for $i$ in $C$) and within the budget $(∑w(i)$ for $i$ in $C ≤ B$).</p> +<p>Now, let's understand this step by step:</p> +<h1 id="problem-definition-weighted-set-cover"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#problem-definition-weighted-set-cover">Problem Definition Weighted Set Cover</a></h1> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230525/setcover.jpg" alt="Weighted Set Cover Example" /></p> +<p>Given:</p> +<ul> +<li>A universe $U$ of $n$ items (attractions in our analogy).</li> +<li>A collection $S$ of m subsets (regions/provinces).</li> +<li>A weight $w(i)$ associated with each item $i$, indicating its cost.</li> +<li>A budget $B$.</li> +</ul> +<p>Find:</p> +<ul> +<li>A minimum-weight set cover, which is a collection of subsets that covers all the items in $U$, such that the total weight of the selected subsets is less than or equal to the budget $B$.</li> +</ul> +<p>Mathematically, we can represent the problem as follows:</p> +<p>Let $U = {1, 2, 3, ..., n}$ be the set of items. +Let $S = {S₁, S₂, ..., Sₘ}$ be the collection of subsets. +Let $w(i)$ be the weight associated with item $i$. +Let $B$ be the budget.</p> +<p>The objective is to find a set $C$ of subsets such that:</p> +<ul> +<li>$C$ covers all items in $U$.</li> +<li>The total weight of the subsets in $C$ is minimized: $∑w(i)$ for i in $C$ is minimized.</li> +<li>The total weight of the subsets in $C$ is less than or equal to the budget $B: ∑w(i)$ for $i$ in $C ≤ B$.</li> +</ul> +<p>To solve this problem, we can use various algorithms, and one popular approach is the greedy algorithm. The idea behind the greedy algorithm is to iteratively select the subset that covers the maximum number of uncovered items while keeping the total weight within the budget. We can repeat this process until all items are covered.</p> +<h1 id="solution-greedy-algorithm"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#solution-greedy-algorithm">Solution Greedy Algorithm</a></h1> +<p>Imagine you're accompanied by a knowledgeable tour guide who knows the ins and outs of each region. The guide suggests using the greedy algorithm, a tried-and-true strategy. At each step, the algorithm selects the subset that covers the maximum number of uncovered items, ensuring the greatest coverage for your budget. This iterative process continues until all items are covered. Picture a sequence diagram where the tour guide carefully evaluates subsets and intelligently selects the most promising ones.</p> +<h1 id="implementation-in-sagemath"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#implementation-in-sagemath">Implementation in SageMath</a></h1> +<p>Enter SageMath, your trusty advisor equipped with mathematical prowess! SageMath is a powerful mathematical software that enables us to implement the weighted set cover algorithm with ease. Let's dive into the code and unravel its secrets.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Import the required modules +</span><span style="color:#b854d4;">from </span><span>sage.all </span><span style="color:#b854d4;">import </span><span style="color:#b65611;">* +</span><span> +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">weighted_set_cover</span><span>(</span><span style="color:#d73737;">U</span><span>, </span><span style="color:#d73737;">S</span><span>, </span><span style="color:#d73737;">w</span><span>, </span><span style="color:#d73737;">B</span><span>): +</span><span> C = [] </span><span style="color:#999580;"># Selected subsets +</span><span> uncovered = </span><span style="color:#d73737;">set</span><span>(U) </span><span style="color:#999580;"># Initially, all items are uncovered +</span><span> +</span><span> </span><span style="color:#b854d4;">while </span><span>uncovered: +</span><span> best_subset = </span><span style="color:#b65611;">None +</span><span> max_covered = </span><span style="color:#b65611;">0 +</span><span> +</span><span> </span><span style="color:#b854d4;">for </span><span>subset </span><span style="color:#b854d4;">in </span><span>S: +</span><span> covered = uncovered.</span><span style="color:#d73737;">intersection</span><span>(subset) +</span><span> </span><span style="color:#b854d4;">if </span><span style="color:#1fad83;">len</span><span>(covered) &gt; max_covered: +</span><span> best_subset = subset +</span><span> max_covered = </span><span style="color:#1fad83;">len</span><span>(covered) +</span><span> +</span><span> C.</span><span style="color:#d73737;">append</span><span>(best_subset) +</span><span> uncovered -= best_subset +</span><span> +</span><span> total_weight = </span><span style="color:#1fad83;">sum</span><span>(w[i] </span><span style="color:#b854d4;">for </span><span>subset </span><span style="color:#b854d4;">in </span><span>C </span><span style="color:#b854d4;">for </span><span>i </span><span style="color:#b854d4;">in </span><span>subset) +</span><span> </span><span style="color:#b854d4;">return </span><span>C, total_weight +</span></code></pre> +<p>In this code snippet, we start by importing the necessary modules from SageMath. The <code>weighted_set_cover</code> function takes four parameters: <code>U</code> (the set of items), <code>S</code> (the collection of subsets), <code>w</code> (the dictionary representing the weights of items), and <code>B</code> (the budget).</p> +<p>Inside the function, we initialize an empty list <code>C</code> to store the selected subsets. We also create a set <code>uncovered</code> containing all the items initially, as none of them are covered.</p> +<p>Next, we enter a loop that continues until all items are covered. Within this loop, we search for the best subset that covers the maximum number of uncovered items. To accomplish this, we iterate through each subset and find the intersection with the uncovered items. If the number of covered items is greater than the previous maximum, we update the <code>best_subset</code> and <code>max_covered</code> variables accordingly.</p> +<p>After selecting the best subset, we add it to our list of selected subsets <code>C</code> and remove the covered items from the <code>uncovered</code> set.</p> +<p>Finally, we calculate the total weight of the selected subsets by summing the weights of the items within each subset in <code>C</code>.</p> +<h1 id="example-scenario"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#example-scenario">Example Scenario</a></h1> +<p>Let's consider a whimsical example to bring this problem to life. In your kingdom, you have five enchanting items (1, 2, 3, 4, 5) and four distinct regions or provinces: {1, 2}, {2, 3, 4}, {1, 3, 5}, and {4, 5}. Each item carries a unique weight: item 1 has a weight of 3, item 2 has a weight of 5, item 3 has a weight of 2, item 4 has a weight of 4, and item 5 has a weight of 1. Your budget for promoting these treasures is set at 10.</p> +<p>Let's invoke our trusty SageMath code to find the optimal solution:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>U = {</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">4</span><span>, </span><span style="color:#b65611;">5</span><span>} </span><span style="color:#999580;"># Set of items +</span><span>S = [{</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">2</span><span>}, {</span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">4</span><span>}, {</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">5</span><span>}, {</span><span style="color:#b65611;">4</span><span>, </span><span style="color:#b65611;">5</span><span>}] </span><span style="color:#999580;"># Collection of subsets +</span><span>w = {</span><span style="color:#b65611;">1</span><span>: </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">2</span><span>: </span><span style="color:#b65611;">5</span><span>, </span><span style="color:#b65611;">3</span><span>: </span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">4</span><span>: </span><span style="color:#b65611;">4</span><span>, </span><span style="color:#b65611;">5</span><span>: </span><span style="color:#b65611;">1</span><span>} </span><span style="color:#999580;"># Weight associated with each item +</span><span>B = </span><span style="color:#b65611;">10 </span><span style="color:#999580;"># Budget +</span><span> +</span><span>selected_subsets, total_weight = </span><span style="color:#d73737;">weighted_set_cover</span><span>(U, S, w, B) +</span><span> +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Selected Subsets:</span><span>&quot;) +</span><span style="color:#b854d4;">for </span><span>subset </span><span style="color:#b854d4;">in </span><span>selected_subsets: +</span><span> </span><span style="color:#1fad83;">print</span><span>(subset) +</span><span> +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Total Weight:</span><span>&quot;, total_weight) +</span></code></pre> +<p>Executing this code will display the result of our royal decree: the selected subsets and their total weight. The output will provide valuable insights into which regions or provinces you should include in your travel packages to maximize coverage while keeping costs under control.</p> +<h1 id="applications-in-blockchain-technology-and-machine-learning"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#applications-in-blockchain-technology-and-machine-learning">Applications in Blockchain Technology and Machine Learning</a></h1> +<p>The weighted set cover problem finds its applications in various technological domains, where efficient resource allocation and optimization are crucial. Let's explore two intriguing examples in the blockchain and machine learning fields.</p> +<h2 id="blockchain-transaction-fee-optimization"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#blockchain-transaction-fee-optimization">Blockchain Transaction Fee Optimization</a></h2> +<p>In the realm of blockchain technology, the weighted set cover problem can be employed to optimize transaction fee calculations. In blockchain networks like Bitcoin or Ethereum, users must pay transaction fees to incentivize miners or validators to include their transactions in the next block.</p> +<p>Consider a scenario where a user wants to perform multiple transactions while minimizing the total transaction fee paid. Each transaction corresponds to an item, and the available subsets represent different sets of transactions that can be included in a block. The weights associated with the items can represent the transaction fees.</p> +<p>By solving the weighted set cover problem, blockchain systems can identify the optimal set of transactions to include in a block, maximizing the number of transactions while minimizing the total fee paid by the user.</p> +<h2 id="machine-learning-feature-selection"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#machine-learning-feature-selection">Machine Learning Feature Selection</a></h2> +<p>Feature selection plays a vital role in machine learning, where the goal is to identify the most relevant features or attributes that contribute to accurate predictions or classifications. The weighted set cover problem can be utilized to solve feature selection challenges efficiently. In Machine Learning, there are different kinds of techniques to identify the best predictors to explain the data.</p> +<p>Imagine a dataset with a large number of features, each representing a potential attribute. By treating the features as items and subsets as different combinations of feature subsets, the weighted set cover problem can help identify the minimal set of features that provide optimal predictive power.</p> +<p>Solving the weighted set cover problem in the context of machine learning allows for efficient feature selection, reducing computational complexity, and improving model performance and interpretability.</p> +<p>These are just two glimpses into the vast applications of the weighted set cover problem in the technological landscape. Whether in blockchain, machine learning, or other domains, this problem provides valuable insights and optimization strategies for resource allocation, decision-making, and problem-solving. As technology advances, the weighted set cover problem continues to contribute to innovative solutions and efficient resource utilization.</p> +<h1 id="relating-to-karp-reduction"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#relating-to-karp-reduction">Relating to Karp Reduction</a></h1> +<p>The weighted set cover problem has an intriguing connection to Karp reduction, a fundamental concept in computational complexity theory. We can formally express this relationship using mathematical notation. </p> +<p>In computational complexity theory, Karp reduction is denoted by the symbol $\leq_{\text{Karp}}$, indicating that one problem can be reduced to another. In our case, we can demonstrate that the weighted set cover problem is Karp reducible to the Set Cover problem.</p> +<p>Let's define the two problems mathematically:</p> +<ol> +<li> +<p>Weighted Set Cover Problem (WSC):</p> +<ul> +<li>Given a universe of items $U$, a collection of subsets $S$, weights $w(i)$ for each item $i \in U$, and a budget $B$,</li> +<li>The objective is to find a minimum-weight set cover $C$ such that $\sum_{i \in C} w(i) \leq B$.</li> +</ul> +</li> +<li> +<p>Set Cover Problem (SC):</p> +<ul> +<li>Given a universe of items $U$ and a collection of subsets $S$,</li> +<li>The objective is to find the smallest collection of subsets $C$ such that $\bigcup_{X \in C} X = U$.</li> +</ul> +</li> +</ol> +<p>To establish the Karp reduction from the WSC problem to the SC problem, we construct an instance of the SC problem using the same universe $U$ and subsets $S$ as in the WSC problem. Additionally, we assign unit weights to all items in the SC problem.</p> +<p>Formally, we can express the Karp reduction as follows:</p> +<p>$WSC \leq_{\text{Karp}} SC$</p> +<p>This reduction shows that the WSC problem can be transformed into the SC problem, indicating that the WSC problem is at least as hard as the SC problem. Since the SC problem is known to be NP-complete, this implies that the WSC problem is also NP-complete.</p> +<p>Understanding this mathematical relationship between the WSC problem and Karp reduction provides valuable insights into the computational complexity of the problem and establishes connections with other NP-complete problems. It allows us to leverage existing algorithms and problem-solving techniques developed for the SC problem when tackling the WSC problem.</p> +<h1 id="conclusion"><a href="https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/#conclusion">Conclusion</a></h1> +<p>Congratulations! You have successfully embarked on a journey through the fascinating world of the weighted set cover problem. We began our adventure by imagining ourselves as rulers, seeking to promote tourism in our kingdom. We learned about the problem's formulation using mathematical notation and equations, and we employed the greedy algorithm as our trusted tour guide to select subsets that covered the maximum number of attractions while staying within our budget.</p> +<p>With the help of SageMath, we implemented the weighted set cover algorithm, carefully considering the code's structure and functionality. We then applied our implementation to an example scenario, where we discovered the optimal subsets and their total weight.</p> +<p>The weighted set cover problem holds great importance in various real-world applications, such as optimization, resource allocation, and data analysis. It provides a valuable framework for decision-making and problem-solving.</p> +<p>As you venture forth, remember to explore further, experiment with different scenarios, and adapt the code to your specific needs. May your kingdom thrive with flourishing tourism and abundant gem-filled travel packages!</p> +<p>Happy covering, noble ruler!</p> +<p>You can find the complete sagemath code at the github repo <a href="https://github.com/thogiti/Weighted-set-cover-problem">github.com/thogiti</a>.</p> +<p><strong>Additional References</strong></p> +<ol> +<li><a href="https://optimization.cbe.cornell.edu/index.php?title=Set_covering_problem">optimization.cbe.cornell.edu</a></li> +<li><a href="http://www.cs.cornell.edu/courses/cs6820/2022fa/Handouts/LP2.pdf">cs.cornell.edu</a></li> +<li><a href="https://en.wikipedia.org/wiki/Set_cover_problem">en.wikipedia.org</a></li> +<li><a href="https://en.wikipedia.org/wiki/Polynomial-time_reduction">en.wikipedia.org</a></li> +<li><a href="https://courses.engr.illinois.edu/cs473/sp2011/lectures/21_notes.pdf">courses.engr.illinois.edu</a></li> +</ol> + + + + Understanding Caulk Protocol: A Beginner's Guide to Sublinear Time Lookup Arguments (In Draft Mode) + 2023-05-20T00:00:00+00:00 + 2023-05-20T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/ + <h1 id="note-this-article-is-in-draft-mode-and-i-didn-t-finish-writing-the-sections-of-the-caulk-protocol-proof-read-test-the-code-for-correctness-and-adding-references-please-check-it-again-in-1-2-weeks-before-i-publish-it"><strong>Note: This article is in draft mode and I didn't finish writing the sections of the Caulk protocol, proof read, test the code for correctness and adding references. Please check it again in 1-2 weeks before I publish it.</strong></h1> +<h1 id="introduction">Introduction</h1> +<p>In this blog we will review Caulk protocol for computing efficient lookup arguments in sublinear time.</p> +<p>The Caulk protocol offers a significant improvement over existing cryptographic solutions for vector commitment schemes, providing a more efficient and secure approach to position-hiding linkability. Its potential impact on future cryptographic systems and applications is immense, paving the way for more scalable and practical solutions in privacy-preserving applications, verifiable computation schemes, and lookup tables.</p> +<p>Full citation of the paper: +@misc{cryptoeprint:2022/621, +author = {Arantxa Zapico and Vitalik Buterin and Dmitry Khovratovich and Mary Maller and Anca Nitulescu and Mark Simkin}, +title = {Caulk: Lookup Arguments in Sublinear Time}, +howpublished = {Cryptology ePrint Archive, Paper 2022/621}, +year = {2022}, +note = {\url{https://eprint.iacr.org/2022/621}}, +url = {https://eprint.iacr.org/2022/621} +}</p> +<h2 id="what-is-the-caulk-protocol-and-why-it-matters">What is the Caulk protocol and why it matters</h2> +<p>The Caulk protocol is a groundbreaking cryptographic solution that addresses the challenges of vector commitment schemes in a more efficient and secure manner. It is designed to provide position-hiding linkability for vector commitment schemes, allowing users to prove in zero-knowledge that one or multiple values belong to a committed vector. This innovative approach has significant implications for privacy-preserving applications, verifiable computation schemes, and lookup tables.</p> +<p>Vector commitment schemes play a crucial role in cryptography, as they enable the creation of compact data structures that can store large numbers of elements while allowing users to prove that specific elements have been committed to. The Caulk protocol enhances these schemes by offering sublinear time lookup arguments, drastically reducing the computational overhead and making them more practical for real-world applications.</p> +<h2 id="the-role-of-vector-commitment-schemes-in-cryptography">The role of vector commitment schemes in cryptography</h2> +<p>Vector commitment schemes are fundamental cryptographic primitives that underpin numerous constructions and protocols. They allow users to commit to a potentially large set of elements in a compact manner and later prove that a specific element is part of the committed set. These proofs should be succinct, unforgeable, and ideally, zero-knowledge, meaning that they do not reveal any information about the committed element.</p> +<p>Some common applications of vector commitment schemes include privacy-preserving cryptocurrencies, membership proofs, ring signatures, and anonymous credentials. In these scenarios, it is essential to provide efficient and secure solutions that can scale with the growing demands of modern cryptographic systems.</p> +<h2 id="challenges-with-existing-cryptographic-solutions">Challenges with existing cryptographic solutions</h2> +<p>Existing cryptographic solutions for vector commitment schemes often rely on heavy cryptography machinery, which can result in significant computational overheads and limit their scalability and adoption. For example, the first version of the Zcash cryptocurrency used a SHA-2-based Merkle tree and the Groth16 SNARK to prove coin ownership, resulting in a prover time of 40 seconds, which was barely usable in practice.</p> +<p>The Caulk protocol addresses these challenges by offering a more efficient and secure alternative to existing solutions. By leveraging the KZG polynomial commitment scheme and introducing position-hiding linkability, the Caulk protocol can drastically reduce the prover time and proof size, making it more practical for real-world applications.</p> +<p>Here's a simple example of Rust code to demonstrate the creation of a commitment using the Caulk protocol:</p> +<p>First, add the following dependencies to your Cargo.toml file:</p> +<pre data-lang="toml" style="background-color:#fefbec;color:#6e6b5e;" class="language-toml "><code class="language-toml" data-lang="toml"><span>[dependencies] +</span><span style="color:#d73737;">arkworks-gadgets </span><span>= &quot;</span><span style="color:#60ac39;">0.3.0</span><span>&quot; +</span><span style="color:#d73737;">arkworks-utils </span><span>= &quot;</span><span style="color:#60ac39;">0.3.0</span><span>&quot; +</span><span style="color:#d73737;">caulk </span><span>= { </span><span style="color:#d73737;">git </span><span>= &quot;</span><span style="color:#60ac39;">https://github.com/caulk-crypto/caulk</span><span>&quot; } +</span></code></pre> +<p>Then, use the following Rust code to create a commitment using the Caulk protocol:</p> +<pre data-lang="rust" style="background-color:#fefbec;color:#6e6b5e;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b854d4;">use </span><span>ark_bls12_381::Bls12_381; +</span><span style="color:#b854d4;">use </span><span>ark_ff::UniformRand; +</span><span style="color:#b854d4;">use </span><span>ark_std::rand::rngs::OsRng; +</span><span style="color:#b854d4;">use </span><span>caulk::commitment::{CaulkCommitment, Commitment}; +</span><span style="color:#b854d4;">use </span><span>caulk::srs::</span><span style="color:#b65611;">SRS</span><span>; +</span><span> +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">main</span><span>() { +</span><span> </span><span style="color:#b854d4;">let</span><span> vector = vec![</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">4</span><span>, </span><span style="color:#b65611;">5</span><span>]; +</span><span> </span><span style="color:#b854d4;">let</span><span> rng = &amp;</span><span style="color:#b854d4;">mut</span><span> OsRng; +</span><span> </span><span style="color:#b854d4;">let</span><span> srs = </span><span style="color:#b65611;">SRS</span><span>::&lt;Bls12_381&gt;::dummy(</span><span style="color:#b65611;">32</span><span>); +</span><span> +</span><span> </span><span style="color:#b854d4;">let</span><span> caulk_commitment = CaulkCommitment::&lt;Bls12_381&gt;::new(&amp;srs, &amp;vector); +</span><span> </span><span style="color:#b854d4;">let </span><span>(commitment, randomness) = caulk_commitment.</span><span style="color:#1fad83;">commit</span><span>(rng); +</span><span> println!(&quot;</span><span style="color:#60ac39;">Commitment: </span><span style="color:#b65611;">{:?}</span><span>&quot;, commitment); +</span><span>} +</span></code></pre> + + + + Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples + 2023-05-09T00:00:00+00:00 + 2023-05-09T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/ + <ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#introduction-demystifying-elliptic-curves-and-their-applications">Introduction Demystifying Elliptic Curves and Their Applications</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#the-power-of-elliptic-curve-cryptography-ecc">The Power of Elliptic Curve Cryptography (ECC)</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#unlocking-the-potential-of-ecc-with-sagemath">Unlocking the Potential of ECC with SageMath</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#understanding-the-fundamentals-of-elliptic-curves">Understanding the Fundamentals of Elliptic Curves</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#definition-of-an-elliptic-curve">Definition of an Elliptic Curve</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#points-on-an-elliptic-curve">Points on an Elliptic Curve</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#visualizing-points-on-an-elliptic-curve">Visualizing Points on an Elliptic Curve</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#exploring-the-structure-of-elliptic-curve-groups">Exploring the Structure of Elliptic Curve Groups</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#elliptic-curve-arithmetic">Elliptic Curve Arithmetic</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#performing-point-addition-on-elliptic-curves">Performing Point Addition on Elliptic Curves</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#mastering-point-doubling-techniques">Mastering Point Doubling Techniques</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#efficient-scalar-multiplication-algorithms">Efficient Scalar Multiplication Algorithms</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#computing-the-inverse-of-a-point">Computing the Inverse of a Point</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#verifying-associativity-and-commutativity-in-elliptic-curve-arithmetic">Verifying Associativity and Commutativity in Elliptic Curve Arithmetic</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#visualizing-elliptic-curve-arithmetic-operations">Visualizing Elliptic Curve Arithmetic Operations</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#working-with-elliptic-curves-in-sagemath">Working with Elliptic Curves in SageMath</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#defining-and-visualizing-elliptic-curves-with-sagemath">Defining and Visualizing Elliptic Curves with SageMath</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#uncovering-points-on-elliptic-curves">Uncovering Points on Elliptic Curves</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#manipulating-elliptic-curve-groups-in-sagemath">Manipulating Elliptic Curve Groups in SageMath</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#point-addition">Point Addition</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#point-doubling">Point Doubling</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#scalar-multiplication">Scalar Multiplication</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#multiscalar-multiplication">Multiscalar Multiplication</a></li> +</ul> +</li> +</ul> +</li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#applications-of-elliptic-curve-arithmetic">Applications of Elliptic Curve Arithmetic</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#securing-communications-with-elliptic-curve-cryptography-ecc">Securing Communications with Elliptic Curve Cryptography ECC</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#ensuring-data-integrity-with-digital-signatures-ecdsa">Ensuring Data Integrity with Digital Signatures ECDSA</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#establishing-secure-connections-with-key-exchange-ecdh">Establishing Secure Connections with Key Exchange ECDH</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#ethereum-blockchain-applications">Ethereum Blockchain Applications</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#zero-knowledge-voting-using-plonk">Zero Knowledge Voting using Plonk</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#reflecting-on-the-power-of-elliptic-curve-arithmetic">Reflecting on the Power of Elliptic Curve Arithmetic</a> +<ul> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#expanding-your-knowledge-with-advanced-ecc-topics">Expanding Your Knowledge with Advanced ECC Topics</a></li> +<li><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#exploring-further-resources-and-learning-materials">Exploring Further Resources and Learning Materials</a></li> +</ul> +</li> +</ul> +<h1 id="introduction-demystifying-elliptic-curves-and-their-applications"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#introduction-demystifying-elliptic-curves-and-their-applications">Introduction Demystifying Elliptic Curves and Their Applications</a></h1> +<p>Elliptic curves are a fascinating area of mathematics that have found numerous applications in modern cryptography, particularly in the field of Elliptic Curve Cryptography (ECC). ECC has gained popularity due to its ability to provide the same level of security as traditional cryptographic methods, such as RSA, but with smaller key sizes. This results in faster computations and reduced storage requirements, making ECC an attractive choice for securing communications in resource-constrained environments.</p> +<p>In this blog post, we aim to provide a comprehensive introduction to elliptic curve arithmetic and its applications in cryptography. We will explore the basics of elliptic curves, delve into the arithmetic operations performed on them, and demonstrate how to work with elliptic curves using the powerful SageMath software. By the end of this post, you will have a solid understanding of the fundamentals of elliptic curve arithmetic and be well-equipped to explore more advanced topics in ECC.</p> +<h2 id="the-power-of-elliptic-curve-cryptography-ecc"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#the-power-of-elliptic-curve-cryptography-ecc">The Power of Elliptic Curve Cryptography (ECC)</a></h2> +<p>ECC is a public-key cryptosystem that relies on the algebraic structure of elliptic curves over finite fields. It offers several advantages over traditional cryptosystems, such as:</p> +<ol> +<li> +<p><strong>Smaller key sizes</strong>: ECC provides the same level of security as RSA with significantly smaller key sizes. For example, a 256-bit ECC key is considered to be as secure as a 3072-bit RSA key.</p> +</li> +<li> +<p><strong>Faster computations</strong>: Due to the smaller key sizes, ECC operations are generally faster than their RSA counterparts, making ECC more suitable for resource-constrained devices.</p> +</li> +<li> +<p><strong>Improved security</strong>: ECC is believed to be more resistant to certain types of attacks, such as quantum computing attacks, compared to traditional cryptosystems. This makes ECC a forward-looking choice for securing communications in the face of evolving threats.</p> +</li> +</ol> +<h2 id="unlocking-the-potential-of-ecc-with-sagemath"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#unlocking-the-potential-of-ecc-with-sagemath">Unlocking the Potential of ECC with SageMath</a></h2> +<p>SageMath <a href="https://www.sagemath.org/">sagemath.org</a> is an open-source mathematics software system that provides a powerful environment for working with various mathematical structures, including elliptic curves. It offers a rich set of tools and libraries for performing arithmetic operations on elliptic curves, making it an ideal platform for learning and experimenting with ECC.</p> +<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/Elliptic_curve_simple.svg/2560px-Elliptic_curve_simple.svg.png" alt="Elliptic Curve Example" /></p> +<p>Throughout this blog post, we will cover the following topics:</p> +<ul> +<li>Basics of elliptic curves: definition, points, and example plots</li> +<li>Elliptic curve arithmetic: point addition, doubling, scalar multiplication, and inverse of a point</li> +<li>Working with elliptic curves in SageMath: defining, plotting, and finding points on curves</li> +<li>Implementing elliptic curve arithmetic in SageMath: code examples for point addition, doubling, scalar multiplication, and inverse of a point</li> +<li>Applications of elliptic curve arithmetic: securing communications (ECC), digital signatures (ECDSA), and key exchange (ECDH), blockchain protocols, zero knowledge proofs (ZKP), zero knowledge machine learning</li> +</ul> +<p>By the end of this post, you will have a solid foundation in elliptic curve arithmetic and be well-prepared to explore more advanced topics in ECC and its applications in cryptography.</p> +<h1 id="understanding-the-fundamentals-of-elliptic-curves"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#understanding-the-fundamentals-of-elliptic-curves">Understanding the Fundamentals of Elliptic Curves</a></h1> +<p>Elliptic curves are algebraic structures that play a crucial role in modern cryptography. To understand the basics of elliptic curves, let's start with their definition.</p> +<h2 id="definition-of-an-elliptic-curve"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#definition-of-an-elliptic-curve">Definition of an Elliptic Curve</a></h2> +<p>An elliptic curve is defined by an equation of the form:</p> +<p>$$y^2 = x^3 + ax + b$$</p> +<p>where $a$ and $b$ are constants, and the curve must satisfy the condition $4a^3 + 27b^2 \neq 0$ to ensure that it has no singularities (i.e., no self-intersections or cusps). In the context of cryptography, we often work with elliptic curves over finite fields, which means that the coordinates $(x, y)$ and the constants $a$ and $b$ are elements of a finite field.</p> +<h2 id="points-on-an-elliptic-curve"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#points-on-an-elliptic-curve">Points on an Elliptic Curve</a></h2> +<p>A point $(x, y)$ on an elliptic curve satisfies the curve's equation. In addition to the points that lie on the curve, there is an additional &quot;point at infinity&quot; denoted by $\mathcal{O}$, which serves as the identity element for the elliptic curve group (more on this later).</p> +<h2 id="visualizing-points-on-an-elliptic-curve"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#visualizing-points-on-an-elliptic-curve">Visualizing Points on an Elliptic Curve</a></h2> +<p>To visualize an elliptic curve, we can plot the points that satisfy the curve's equation. Let's use SageMath to plot an example of an elliptic curve over the real numbers.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>a, b = -</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">1 +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>([a, b]) +</span><span style="color:#d73737;">plot</span><span>(E, </span><span style="color:#d73737;">xmin</span><span>=-</span><span style="color:#b65611;">3</span><span>, </span><span style="color:#d73737;">xmax</span><span>=</span><span style="color:#b65611;">3</span><span>, </span><span style="color:#d73737;">ymin</span><span>=-</span><span style="color:#b65611;">3</span><span>, </span><span style="color:#d73737;">ymax</span><span>=</span><span style="color:#b65611;">3</span><span>) +</span></code></pre> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230509/sagemath-elliptic-curve-example.png" alt="Elliptic Curve Plot" /></p> +<p><em>An example of an elliptic curve plot generated using SageMath.</em></p> +<h2 id="exploring-the-structure-of-elliptic-curve-groups"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#exploring-the-structure-of-elliptic-curve-groups">Exploring the Structure of Elliptic Curve Groups</a></h2> +<p>Elliptic curves have an inherent group structure, which is the foundation for elliptic curve arithmetic. The group operation is defined as the addition of points on the curve. The point at infinity, $\mathcal{O}$, serves as the identity element, meaning that for any point $P$ on the curve, $P + \mathcal{O} = P$.</p> +<p>The group operation has the following properties:</p> +<ol> +<li><strong>Closure</strong>: The sum of any two points on the curve is also a point on the curve.</li> +<li><strong>Associativity</strong>: For any points $P$, $Q$, and $R$ on the curve, $(P + Q) + R = P + (Q + R)$.</li> +<li><strong>Identity</strong>: There exists an identity element $\mathcal{O}$ such that for any point $P$ on the curve, $P + \mathcal{O} = P$.</li> +<li><strong>Inverse</strong>: For any point $P$ on the curve, there exists an inverse point $-P$ such that $P + (-P) = \mathcal{O}$.</li> +</ol> +<p>The group structure of elliptic curves is what enables us to perform arithmetic operations on points, which is the basis for elliptic curve cryptography.</p> +<p>In the next sections, we will delve deeper into elliptic curve arithmetic and demonstrate how to work with elliptic curves using SageMath. By understanding the fundamentals of elliptic curves and their group structure, you will be well-prepared to explore more advanced topics in elliptic curve cryptography and its applications.</p> +<h1 id="elliptic-curve-arithmetic"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#elliptic-curve-arithmetic">Elliptic Curve Arithmetic</a></h1> +<p>Elliptic curve arithmetic is the foundation for elliptic curve cryptography. In this section, we will cover the following topics:</p> +<ul> +<li>Performing point addition on elliptic curves</li> +<li>Mastering point doubling techniques</li> +<li>Efficient scalar multiplication algorithms</li> +<li>Computing the inverse of a point</li> +<li>Verifying associativity and commutativity in elliptic curve arithmetic</li> +</ul> +<h2 id="performing-point-addition-on-elliptic-curves"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#performing-point-addition-on-elliptic-curves">Performing Point Addition on Elliptic Curves</a></h2> +<p>Point addition is the primary operation in elliptic curve arithmetic. Given two points $P$ and $Q$ on an elliptic curve, their sum $R = P + Q$ is computed as follows:</p> +<ol> +<li>Find the line $L$ that passes through $P$ and $Q$.</li> +<li>Find the third point of intersection $R'$ between $L$ and the elliptic curve.</li> +<li>Reflect $R'$ across the x-axis to obtain $R$.</li> +</ol> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230509/point-addition-in-ECC.png" alt="Point addition on Elliptic Curve " /></p> +<p><em>A geometrical visualization of a point addition on elliptic curve.</em></p> +<p>In SageMath, point addition can be performed using the <code>+</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>Q = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = P + Q +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;"> P+Q = </span><span>&quot;, R) +</span></code></pre> +<h2 id="mastering-point-doubling-techniques"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#mastering-point-doubling-techniques">Mastering Point Doubling Techniques</a></h2> +<p>Point doubling is a special case of point addition where $P = Q$. In this case, the line $L$ is the tangent to the curve at point $P$. The process for computing $R = 2P$ is similar to point addition:</p> +<ol> +<li>Find the tangent line $L$ at point $P$.</li> +<li>Find the second point of intersection $R'$ between $L$ and the elliptic curve.</li> +<li>Reflect $R'$ across the x-axis to obtain $R$.</li> +</ol> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230509/point-doubling-in-ECC.png" alt="Point doubling on Elliptic Curve " /></p> +<p><em>A geometrical visualization of a point addition on elliptic curve.</em></p> +<p>In SageMath, point doubling can be performed using the <code>*</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = </span><span style="color:#b65611;">2 </span><span>* P +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;"> 2*P = </span><span>&quot;, R) +</span></code></pre> +<h2 id="efficient-scalar-multiplication-algorithms"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#efficient-scalar-multiplication-algorithms">Efficient Scalar Multiplication Algorithms</a></h2> +<p>Scalar multiplication is the operation of adding a point $P$ to itself $k$ times, denoted as $[k]P$. Efficient algorithms for scalar multiplication, such as the double-and-add algorithm, can significantly improve the performance of elliptic curve cryptography.</p> +<p>In SageMath, scalar multiplication can be performed using the <code>*</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>k = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>R = k * P +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;"> k*P = </span><span>&quot;, R) +</span></code></pre> +<h2 id="computing-the-inverse-of-a-point"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#computing-the-inverse-of-a-point">Computing the Inverse of a Point</a></h2> +<p>The inverse of a point $P = (x, y)$ on an elliptic curve is the point $-P = (x, -y)$. The inverse is used in elliptic curve arithmetic to compute the difference between two points.</p> +<p>In SageMath, the inverse of a point can be computed using the <code>neg</code> method:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>P_inv = -P +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;"> P_inv = </span><span>&quot;, P_inv) +</span></code></pre> +<h2 id="verifying-associativity-and-commutativity-in-elliptic-curve-arithmetic"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#verifying-associativity-and-commutativity-in-elliptic-curve-arithmetic">Verifying Associativity and Commutativity in Elliptic Curve Arithmetic</a></h2> +<p>Associativity and commutativity are essential properties of elliptic curve arithmetic. To verify these properties, we can perform arithmetic operations on random points and check if the results satisfy the properties.</p> +<p>In SageMath, we can verify associativity and commutativity as follows:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>Q = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span> +</span><span style="color:#999580;"># Verify associativity: (P + Q) + R == P + (Q + R) +</span><span style="color:#1fad83;">print </span><span>((P + Q) + R == P + (Q + R)) +</span><span> +</span><span style="color:#999580;"># Verify commutativity: P + Q == Q + P +</span><span style="color:#1fad83;">print </span><span>(P + Q == Q + P) +</span></code></pre> +<p>By understanding the fundamentals of elliptic curve arithmetic and mastering the techniques for point addition, point doubling, scalar multiplication, and computing the inverse of a point, you will be well-prepared to explore more advanced topics in elliptic curve cryptography and its applications.</p> +<h2 id="visualizing-elliptic-curve-arithmetic-operations"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#visualizing-elliptic-curve-arithmetic-operations">Visualizing Elliptic Curve Arithmetic Operations</a></h2> +<p>To better understand the arithmetic operations on elliptic curves, we can visualize the process of point addition, point doubling, and scalar multiplication using graphs.</p> +<p>In SageMath, we can plot the elliptic curve and the points involved in the arithmetic operations:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">13 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span> +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">plot_points_on_curve</span><span>(</span><span style="color:#d73737;">E</span><span>, </span><span style="color:#d73737;">points</span><span>, </span><span style="color:#d73737;">labels</span><span>, </span><span style="color:#d73737;">colors</span><span>): +</span><span> curve_plot = </span><span style="color:#d73737;">plot</span><span>(E, </span><span style="color:#d73737;">xmin</span><span>=-</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">xmax</span><span>=</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">ymin</span><span>=-</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">ymax</span><span>=</span><span style="color:#b65611;">5</span><span>) +</span><span> real_points = [(</span><span style="color:#d73737;">float</span><span>(pt[</span><span style="color:#b65611;">0</span><span>]), </span><span style="color:#d73737;">float</span><span>(pt[</span><span style="color:#b65611;">1</span><span>])) </span><span style="color:#b854d4;">for </span><span>pt </span><span style="color:#b854d4;">in </span><span>points] +</span><span> point_plots = [</span><span style="color:#d73737;">point2d</span><span>(pt, </span><span style="color:#d73737;">color</span><span>=colors[i], </span><span style="color:#d73737;">size</span><span>=</span><span style="color:#b65611;">30</span><span>, </span><span style="color:#d73737;">zorder</span><span>=</span><span style="color:#b65611;">5</span><span>) + </span><span style="color:#d73737;">text</span><span>(labels[i], pt, </span><span style="color:#d73737;">fontsize</span><span>=</span><span style="color:#b65611;">10</span><span>, </span><span style="color:#d73737;">color</span><span>=colors[i], </span><span style="color:#d73737;">horizontal_alignment</span><span>=&#39;</span><span style="color:#60ac39;">left</span><span>&#39;, </span><span style="color:#d73737;">vertical_alignment</span><span>=&#39;</span><span style="color:#60ac39;">bottom</span><span>&#39;) </span><span style="color:#b854d4;">for </span><span>i, pt </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">enumerate</span><span>(real_points)] +</span><span> </span><span style="color:#b854d4;">return </span><span>curve_plot + </span><span style="color:#1fad83;">sum</span><span>(point_plots) +</span><span> +</span><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>Q = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = P + Q +</span><span> +</span><span style="color:#d73737;">plot_points_on_curve</span><span>(E, [P.</span><span style="color:#d73737;">xy</span><span>(), Q.</span><span style="color:#d73737;">xy</span><span>(), R.</span><span style="color:#d73737;">xy</span><span>()], [&#39;</span><span style="color:#60ac39;">P</span><span>&#39;, &#39;</span><span style="color:#60ac39;">Q</span><span>&#39;, &#39;</span><span style="color:#60ac39;">R</span><span>&#39;], [&#39;</span><span style="color:#60ac39;">red</span><span>&#39;, &#39;</span><span style="color:#60ac39;">blue</span><span>&#39;, &#39;</span><span style="color:#60ac39;">green</span><span>&#39;]) +</span></code></pre> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230509/point-addition-ecc-visualiation.png" alt="Elliptic Curve Arithmetic Visualization" /></p> +<p><em>An example of an elliptic curve plot with points P, Q, and R generated using SageMath.</em></p> +<p>By visualizing the arithmetic operations on elliptic curves, we can gain a deeper understanding of the underlying mathematical concepts and their applications in cryptography.</p> +<p>We have covered the fundamentals of elliptic curve arithmetic, including point addition, point doubling, scalar multiplication, computing the inverse of a point, and verifying associativity and commutativity. We have also demonstrated how to perform these operations using SageMath and visualize the results to improve understanding.</p> +<p>By mastering these concepts and techniques, you will be well-equipped to explore more advanced topics in elliptic curve cryptography, such as key exchange, digital signatures, and secure communication protocols.</p> +<h1 id="working-with-elliptic-curves-in-sagemath"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#working-with-elliptic-curves-in-sagemath">Working with Elliptic Curves in SageMath</a></h1> +<p>SageMath is a powerful open-source mathematics software system that provides extensive support for working with elliptic curves. In this section, we will cover the following topics:</p> +<ul> +<li>Defining and visualizing elliptic curves with SageMath</li> +<li>Uncovering points on elliptic curves</li> +<li>Manipulating elliptic curve groups in SageMath</li> +</ul> +<h2 id="defining-and-visualizing-elliptic-curves-with-sagemath"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#defining-and-visualizing-elliptic-curves-with-sagemath">Defining and Visualizing Elliptic Curves with SageMath</a></h2> +<p>To define an elliptic curve in SageMath, we can use the <code>EllipticCurve</code> function, which takes a list of coefficients <code>[a, b]</code> for the curve equation $y^2 = x^3 + ax + b$:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>a, b = -</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">1 +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>([a, b]) +</span></code></pre> +<p>To visualize the elliptic curve, we can use the <code>plot</code> function:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#d73737;">plot</span><span>(E, </span><span style="color:#d73737;">xmin</span><span>=-</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">xmax</span><span>=</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">ymin</span><span>=-</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#d73737;">ymax</span><span>=</span><span style="color:#b65611;">5</span><span>) +</span></code></pre> +<p><img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230509/sagemath-elliptic-curve-example.png" alt="Elliptic Curve Plot" /></p> +<p><em>An example of an elliptic curve plot generated using SageMath.</em></p> +<h2 id="uncovering-points-on-elliptic-curves"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#uncovering-points-on-elliptic-curves">Uncovering Points on Elliptic Curves</a></h2> +<p>To find points on an elliptic curve, we can use the <code>points</code> method, which returns a list of points on the curve over a finite field:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">13 +</span><span>F = </span><span style="color:#d73737;">IntegerModRing</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F, [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>points = E.</span><span style="color:#d73737;">points</span><span>() +</span><span style="color:#1fad83;">print</span><span>(points) +</span></code></pre> +<p>Output:</p> +<pre style="background-color:#fefbec;color:#6e6b5e;"><code><span>[(0 : 1 : 0), (7 : 5 : 1), (7 : 8 : 1), (8 : 5 : 1), (8 : 8 : 1), (11 : 5 : 1), (11 : 8 : 1)] +</span></code></pre> +<h2 id="manipulating-elliptic-curve-groups-in-sagemath"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#manipulating-elliptic-curve-groups-in-sagemath">Manipulating Elliptic Curve Groups in SageMath</a></h2> +<p>Elliptic curves have an inherent group structure, which allows us to perform arithmetic operations on points. SageMath provides various methods to manipulate elliptic curve groups, such as point addition, point doubling, and scalar multiplication.</p> +<h3 id="point-addition"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#point-addition">Point Addition</a></h3> +<p>To add two points on an elliptic curve, we can use the <code>+</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>Q = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = P + Q +</span></code></pre> +<h3 id="point-doubling"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#point-doubling">Point Doubling</a></h3> +<p>To double a point on an elliptic curve, we can use the <code>*</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>P = E.</span><span style="color:#d73737;">random_element</span><span>() +</span><span>R = </span><span style="color:#b65611;">2 </span><span>* P +</span></code></pre> +<h3 id="scalar-multiplication"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#scalar-multiplication">Scalar Multiplication</a></h3> +<p>To perform scalar multiplication on a point, we can use the <code>*</code> operator:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>P = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span>k = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>R = k * P +</span></code></pre> +<h3 id="multiscalar-multiplication"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#multiscalar-multiplication">Multiscalar Multiplication</a></h3> +<p>Multiscalar multiplication is an operation that computes a linear combination of points on an elliptic curve with given scalar coefficients. Given points $P_1, P_2, \dots, P_n$ on an elliptic curve and scalars $k_1, k_2, \dots, k_n$, the multiscalar multiplication computes the result $R = k_1P_1 + k_2P_2 + \dots + k_nP_n$. Efficient algorithms for multiscalar multiplication, such as the Pippenger's algorithm or the interleaved window method, can significantly improve the performance of elliptic curve cryptography.</p> +<p>In SageMath, we can perform multiscalar multiplication using a loop and the <code>+</code> and <code>*</code> operators:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>points = [E.</span><span style="color:#d73737;">random_element</span><span>() </span><span style="color:#b854d4;">for </span><span style="color:#d73737;">_ </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">range</span><span>(</span><span style="color:#b65611;">5</span><span>)] +</span><span>scalars = [</span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) </span><span style="color:#b854d4;">for </span><span style="color:#d73737;">_ </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">range</span><span>(</span><span style="color:#b65611;">5</span><span>)] +</span><span> +</span><span>R = </span><span style="color:#d73737;">E</span><span>(</span><span style="color:#b65611;">0</span><span>) </span><span style="color:#999580;"># Initialize R as the identity element of the elliptic curve group +</span><span style="color:#b854d4;">for </span><span>i </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">range</span><span>(</span><span style="color:#1fad83;">len</span><span>(points)): +</span><span> R += scalars[i] * points[i] +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;"> Multiscalar Multipliciation: </span><span>&quot;, R) +</span></code></pre> +<p>Alternatively, we can use the <code>sum</code> function and a list comprehension to achieve the same result:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>R = </span><span style="color:#1fad83;">sum</span><span>(scalars[i] * points[i] </span><span style="color:#b854d4;">for </span><span>i </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">range</span><span>(</span><span style="color:#1fad83;">len</span><span>(points))) +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;"> Multiscalar Multipliciation: </span><span>&quot;, R) +</span></code></pre> +<p>By understanding multiscalar multiplication and its efficient algorithms, you can further optimize elliptic curve operations and enhance the performance of cryptographic protocols based on elliptic curves.</p> +<p>There are several efficient algorithms for computing multi-scalar multiplication (MSM) in Elliptic Curve Cryptography. Five popular algorithms are:</p> +<ol> +<li> +<p>Double-and-add algorithm: This is the most basic algorithm for scalar multiplication, similar to the square-and-multiply algorithm for modular exponentiation. It computes kP by iterating through the bits of k, doubling the current point at each step, and adding P if the corresponding bit in k is 1 <a href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication">en.wikipedia.org</a>.</p> +</li> +<li> +<p>Montgomery Ladder: This algorithm computes scalar multiplication using a ladder-like structure, which is efficient and resistant to side-channel attacks. It operates on x-coordinates only, making it well-suited for curves in Montgomery form <a href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication">en.wikipedia.org</a>.</p> +</li> +<li> +<p>wNAF (Windowed Non-Adjacent Form) method: This algorithm computes scalar multiplication using a windowed non-adjacent form, which is a signed binary representation of the scalar. It allows for faster calculations by reducing the number of point additions required <a href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication">en.wikipedia.org</a>.</p> +</li> +<li> +<p>Straus' algorithm (also known as Shamir's trick): This algorithm computes multi-scalar multiplication (kP + lQ) more efficiently than performing two separate scalar multiplications. It combines the double-and-add algorithm with interleaving, allowing simultaneous computation of kP and lQ <a href="https://eprint.iacr.org/2003/257.pdf">eprint.iacr.org</a>.</p> +</li> +<li> +<p>Pippenger's algorithm: This algorithm is a generalization of Straus' algorithm for computing multi-scalar multiplication with more than two points. It divides the scalars into smaller groups and computes the scalar multiplication for each group separately before combining the results <a href="https://cr.yp.to/papers/pippenger.pdf">cr.yp.to</a>.</p> +</li> +</ol> +<p>We have explored how to work with elliptic curves in SageMath, including defining and visualizing elliptic curves, uncovering points on elliptic curves, and manipulating elliptic curve groups. By understanding these concepts and techniques, you will be well-equipped to explore more advanced topics in elliptic curve cryptography and its applications.</p> +<p>SageMath provides a powerful and user-friendly environment for working with elliptic curves, making it an invaluable tool for researchers, students, and practitioners in the field of cryptography. By mastering the use of SageMath for elliptic curve operations, you will be able to efficiently implement and analyze cryptographic algorithms based on elliptic curves, paving the way for secure and efficient communication in the digital world.</p> +<h1 id="applications-of-elliptic-curve-arithmetic"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#applications-of-elliptic-curve-arithmetic">Applications of Elliptic Curve Arithmetic</a></h1> +<p>Elliptic curve arithmetic plays a crucial role in various cryptographic applications, including securing communications, ensuring data integrity, establishing secure connections, and enabling privacy-preserving protocols. In this section, we will discuss the following applications of elliptic curve arithmetic:</p> +<ul> +<li>Elliptic Curve Cryptography (ECC)</li> +<li>Digital Signatures (ECDSA)</li> +<li>Key Exchange (ECDH)</li> +<li>Ethereum Blockchain Applications</li> +<li>Zero Knowledge Voting using Plonk</li> +</ul> +<h2 id="securing-communications-with-elliptic-curve-cryptography-ecc"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#securing-communications-with-elliptic-curve-cryptography-ecc">Securing Communications with Elliptic Curve Cryptography ECC</a></h2> +<p>Elliptic Curve Cryptography (ECC) is a public-key cryptosystem that relies on the algebraic structure of elliptic curves over finite fields. ECC provides the same level of security as traditional cryptosystems like RSA, but with smaller key sizes, making it more efficient and suitable for resource-constrained environments.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Generate an elliptic curve and a base point +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">9 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">8 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">7 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">6 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">4 </span><span>- </span><span style="color:#b65611;">1</span><span>), [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>G = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for Alice +</span><span>a = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>A = a * G +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for Bob +</span><span>b = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>B = b * G +</span><span> +</span><span style="color:#999580;"># Alice and Bob compute the shared secret +</span><span>shared_secret_A = a * B +</span><span>shared_secret_B = b * A +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;">shared_secret_A == shared_secret_B? </span><span>&quot;, shared_secret_A == shared_secret_B) +</span><span> +</span></code></pre> +<h2 id="ensuring-data-integrity-with-digital-signatures-ecdsa"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#ensuring-data-integrity-with-digital-signatures-ecdsa">Ensuring Data Integrity with Digital Signatures ECDSA</a></h2> +<p>The Elliptic Curve Digital Signature Algorithm (ECDSA) is a widely-used digital signature scheme that provides data integrity and authentication. ECDSA signatures are smaller and faster to compute than RSA signatures, making them suitable for various applications.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b854d4;">from </span><span>hashlib </span><span style="color:#b854d4;">import </span><span>sha256 +</span><span> +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">9 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">8 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">7 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">6 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">4 </span><span>- </span><span style="color:#b65611;">1</span><span>), [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>G = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for the signer +</span><span>d = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>Q = d * G +</span><span> +</span><span style="color:#999580;"># Sign a message +</span><span>message = </span><span style="color:#b854d4;">b</span><span>&quot;</span><span style="color:#60ac39;">Hello, world!</span><span>&quot; +</span><span>hash_value = int.</span><span style="color:#d73737;">from_bytes</span><span>(</span><span style="color:#d73737;">sha256</span><span>(message).</span><span style="color:#d73737;">digest</span><span>(), &#39;</span><span style="color:#60ac39;">big</span><span>&#39;) +</span><span>k = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>R = k * G +</span><span>r = </span><span style="color:#d73737;">Integer</span><span>(R[</span><span style="color:#b65611;">0</span><span>]) % E.</span><span style="color:#d73737;">order</span><span>() </span><span style="color:#999580;"># Convert R[0] to an integer before performing modulo +</span><span>s = ((hash_value + d * r) * </span><span style="color:#d73737;">inverse_mod</span><span>(k, E.</span><span style="color:#d73737;">order</span><span>())) % E.</span><span style="color:#d73737;">order</span><span>() +</span><span> +</span><span style="color:#999580;"># Verify the signature +</span><span>w = </span><span style="color:#d73737;">inverse_mod</span><span>(s, E.</span><span style="color:#d73737;">order</span><span>()) +</span><span>u1 = (hash_value * w) % E.</span><span style="color:#d73737;">order</span><span>() +</span><span>u2 = (r * w) % E.</span><span style="color:#d73737;">order</span><span>() +</span><span>X = u1 * G + u2 * Q +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the signatures same? </span><span>&quot;, r % E.</span><span style="color:#d73737;">order</span><span>() == </span><span style="color:#d73737;">Integer</span><span>(X[</span><span style="color:#b65611;">0</span><span>]) % E.</span><span style="color:#d73737;">order</span><span>()) </span><span style="color:#999580;"># Convert X[0] to an integer before performing modulo +</span><span> +</span></code></pre> +<h2 id="establishing-secure-connections-with-key-exchange-ecdh"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#establishing-secure-connections-with-key-exchange-ecdh">Establishing Secure Connections with Key Exchange ECDH</a></h2> +<p>The Elliptic Curve Diffie-Hellman (ECDH) key exchange protocol enables two parties to establish a shared secret over an insecure channel. ECDH provides the same level of security as traditional Diffie-Hellman, but with smaller key sizes and faster computations.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Define the Elliptic Curve +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">9 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">8 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">7 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">6 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">4 </span><span>- </span><span style="color:#b65611;">1</span><span>), [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>G = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for Alice +</span><span>a = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>A = a * G +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for Bob +</span><span>b = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>B = b * G +</span><span> +</span><span style="color:#999580;"># Alice and Bob compute the shared secret +</span><span>shared_secret_A = a * B +</span><span>shared_secret_B = b * A +</span><span style="color:#1fad83;">print </span><span>(&quot;</span><span style="color:#60ac39;"> shared_secret_A == shared_secret_B? </span><span>&quot;, shared_secret_A == shared_secret_B) +</span><span> +</span></code></pre> +<h2 id="ethereum-blockchain-applications"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#ethereum-blockchain-applications">Ethereum Blockchain Applications</a></h2> +<p>Elliptic curve arithmetic is widely used in Ethereum blockchain applications, such as smart contracts and zero-knowledge proofs. Ethereum uses the secp256k1 elliptic curve for its cryptographic operations, including generating addresses and signing transactions.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b854d4;">from </span><span>hashlib </span><span style="color:#b854d4;">import </span><span>sha256 +</span><span> +</span><span style="color:#999580;"># Define the secp256k1 elliptic curve +</span><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(</span><span style="color:#d73737;">GF</span><span>(p), [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>G = E.</span><span style="color:#d73737;">lift_x</span><span>(</span><span style="color:#b65611;">55066263022277343669578718895168534326250603453777594175500187360389116729240</span><span>) +</span><span> +</span><span style="color:#999580;"># Generate a private-public key pair for an Ethereum user +</span><span>private_key = </span><span style="color:#d73737;">randint</span><span>(</span><span style="color:#b65611;">1</span><span>, E.</span><span style="color:#d73737;">order</span><span>() - </span><span style="color:#b65611;">1</span><span>) +</span><span>public_key = private_key * G +</span><span> +</span><span style="color:#999580;"># Ethereum address generation (simplified) +</span><span>address = </span><span style="color:#d73737;">sha256</span><span>(</span><span style="color:#d73737;">str</span><span>(public_key).</span><span style="color:#d73737;">encode</span><span>()).</span><span style="color:#d73737;">hexdigest</span><span>()[-</span><span style="color:#b65611;">40</span><span>:] +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Ethereum address:</span><span>&quot;, &quot;</span><span style="color:#60ac39;">0x</span><span>&quot;+address) +</span><span> +</span></code></pre> +<h2 id="zero-knowledge-voting-using-plonk"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#zero-knowledge-voting-using-plonk">Zero Knowledge Voting using Plonk</a></h2> +<p>Plonk is a highly efficient zero-knowledge proof system that leverages elliptic curve arithmetic to enable privacy-preserving protocols, such as zero-knowledge voting. Plonk uses the Kate-Zaverucha-Goldberg (KZG) polynomial commitment scheme, which is based on elliptic curves.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Define an elliptic curve and a base point for Plonk +</span><span>p = </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">256 </span><span>- </span><span style="color:#b65611;">2</span><span>^</span><span style="color:#b65611;">32 </span><span>- </span><span style="color:#b65611;">977 +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(</span><span style="color:#d73737;">GF</span><span>(p), [</span><span style="color:#b65611;">0</span><span>, </span><span style="color:#b65611;">7</span><span>]) +</span><span>G = E.</span><span style="color:#d73737;">lift_x</span><span>(</span><span style="color:#b65611;">55066263022277343669578718895168534326250603453777594175500187360389116729240</span><span>) +</span><span> +</span><span style="color:#999580;"># Generate a KZG commitment to a polynomial +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">kzg_commit</span><span>(</span><span style="color:#d73737;">poly_coeffs</span><span>, </span><span style="color:#d73737;">G</span><span>): +</span><span> </span><span style="color:#b854d4;">return </span><span style="color:#1fad83;">sum</span><span>(coeff * (G * i) </span><span style="color:#b854d4;">for </span><span>i, coeff </span><span style="color:#b854d4;">in </span><span style="color:#1fad83;">enumerate</span><span>(poly_coeffs)) +</span><span> +</span><span style="color:#999580;"># Example polynomial and its commitment +</span><span>poly_coeffs = [</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">4</span><span>] +</span><span>C = </span><span style="color:#d73737;">kzg_commit</span><span>(poly_coeffs, G) +</span><span style="color:#1fad83;">print</span><span>(C) +</span><span> +</span></code></pre> +<p>In a zero-knowledge voting system using Plonk, voters can prove that their votes are valid without revealing their actual choices. This ensures both privacy and integrity in the voting process.</p> +<p>In conclusion, elliptic curve arithmetic is a fundamental building block for various cryptographic applications, including securing communications, ensuring data integrity, establishing secure connections, and enabling privacy-preserving protocols. By understanding and implementing these applications using SageMath, you can harness the power of elliptic curve cryptography to develop secure and efficient solutions for real-world problems.</p> +<h1 id="reflecting-on-the-power-of-elliptic-curve-arithmetic"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#reflecting-on-the-power-of-elliptic-curve-arithmetic">Reflecting on the Power of Elliptic Curve Arithmetic</a></h1> +<p>Elliptic curve arithmetic has proven to be a powerful tool in modern cryptography, providing efficient and secure solutions for various applications. Its smaller key sizes and faster computations make it an attractive choice for resource-constrained environments and privacy-preserving protocols.</p> +<h2 id="expanding-your-knowledge-with-advanced-ecc-topics"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#expanding-your-knowledge-with-advanced-ecc-topics">Expanding Your Knowledge with Advanced ECC Topics</a></h2> +<p>To further enhance your understanding of elliptic curve cryptography, consider exploring advanced topics such as:</p> +<ul> +<li>Pairing-based cryptography: Utilizing bilinear pairings on elliptic curves to enable novel cryptographic primitives, such as Identity-Based Encryption (IBE) and Attribute-Based Encryption (ABE).</li> +<li>Lattice-based cryptography: Investigating the connections between elliptic curve cryptography and lattice-based cryptography, which is believed to be resistant to quantum attacks.</li> +<li>Isogeny-based cryptography: Studying isogenies between elliptic curves, which can be used to construct post-quantum cryptographic schemes.</li> +</ul> +<h2 id="exploring-further-resources-and-learning-materials"><a href="https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/#exploring-further-resources-and-learning-materials">Exploring Further Resources and Learning Materials</a></h2> +<p>To dive deeper into elliptic curve arithmetic and its applications, consider the following resources:</p> +<ul> +<li>Books: +<ul> +<li>&quot;A Course in Elliptic Curves&quot; by J.S. Milne</li> +<li>&quot;Elliptic Curves: Number Theory and Cryptography&quot; by Lawrence C. Washington</li> +</ul> +</li> +<li>Online courses: +<ul> +<li><a href="https://www.coursera.org/course/crypto">Stanford University's Cryptography course</a> on Coursera</li> +<li><a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-fall-2005/">MIT's Mathematics for Computer Science course</a> on OpenCourseWare</li> +</ul> +</li> +<li>Research papers: +<ul> +<li><a href="https://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/">Elliptic Curve Cryptography: A Gentle Introduction</a></li> +<li><a href="https://eprint.iacr.org/2018/825.pdf">A Survey of Elliptic Curve Cryptography</a></li> +</ul> +</li> +</ul> +<p>By expanding your knowledge in elliptic curve arithmetic and exploring advanced topics, you can stay at the forefront of cryptography and contribute to the development of secure and efficient solutions for real-world problems.</p> +<p>You can find the complete sagemath code at the github repo <a href="https://github.com/thogiti/Elliptic-curve-arithmetic-sage">github.com/thogiti</a>.</p> + + + + Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability + 2023-05-08T00:00:00+00:00 + 2023-05-08T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/ + <p>Danksharding is an innovative approach to scale Ethereum's blockchain, aiming to achieve over 100,000 transactions per second by enabling rollups to add cheaper data to blocks <a href="https://ethereum.org/en/roadmap/danksharding/">ethereum.org</a>. As Ethereum moves towards Proto-Danksharding and eventually full Danksharding <a href="https://ethereum.org/en/roadmap/">ethereum.org</a>, data extraction and interpolation become crucial aspects of the block-building process. </p> +<p>In this blog post, we will explore the potential of using product codes, a powerful algebraic coding theory tool, for efficient data extraction and interpolation in the context of Danksharding. We will also provide a hands-on example using SageMath to demonstrate the practical applications of product codes in this process.</p> +<ul> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#what-is-danksharding">What is Danksharding</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#implications-for-danksharding">Implications for Danksharding</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#product-codes-in-data-extraction-and-interpolation">Product Codes in Data Extraction and Interpolation</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#generalized-reed-solomon-codes">Generalized Reed-Solomon Codes</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#data-extraction-and-data-interpolation-in-danksharding">Data Extraction and Data Interpolation in Danksharding</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#example-of-error-correction-codes-in-danksharding">Example of Error Correction Codes in Danksharding</a></li> +<li><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#conclusion">Conclusion</a></li> +</ul> +<h1 id="what-is-danksharding"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#what-is-danksharding">What is Danksharding</a></h1> +<p>Danksharding is a technique used in Ethereum to improve the efficiency and scalability of data storage and retrieval. The core idea behind danksharding is to distribute data across multiple shards, which allows for faster and more efficient access to specific pieces of data. One of the critical aspects of danksharding is ensuring the integrity and reliability of the data stored within the shards. This is where error-correction codes, specifically Generalized Reed-Solomon Codes (GRS), come into play.</p> +<h1 id="implications-for-danksharding"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#implications-for-danksharding">Implications for Danksharding</a></h1> +<p>As Ethereum moves towards Proto-Danksharding and full Danksharding, the importance of efficient data extraction and interpolation in the block-building process cannot be overstated <a href="https://www.coindesk.com/layer2/2022/06/08/scaling-ethereum-beyond-the-merge-danksharding/">coindesk.com</a>. The use of product codes, as demonstrated in our SageMath example, offers a promising approach for addressing these challenges by harnessing their algebraic properties.</p> +<p>In particular, the error-correcting capabilities of product codes can help ensure the integrity of data in the Ethereum ecosystem, allowing full nodes to present fraud proofs and maintain transparency <a href="https://www.alchemy.com/overviews/danksharding">alchemy.com</a>. Moreover, the structured redundancy provided by product codes can facilitate data availability sampling, a critical requirement for the development of lightweight clients and the proper functioning of Danksharding <a href="https://ethereum.org/en/roadmap/danksharding/">ethereum.org</a>.</p> +<h1 id="product-codes-in-data-extraction-and-interpolation"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#product-codes-in-data-extraction-and-interpolation">Product Codes in Data Extraction and Interpolation</a></h1> +<p>The algebraic properties of product codes, such as linearity, error-correcting capabilities, and structured redundancy, can be harnessed for efficient data extraction and interpolation in the block-building process of Danksharding. These properties enable the development of techniques that extract relevant information from data sets and interpolate missing values, which are essential for ensuring data availability and integrity in the Ethereum ecosystem <a href="https://www.alchemy.com/overviews/danksharding">alchemy.com</a>.</p> +<h1 id="generalized-reed-solomon-codes"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#generalized-reed-solomon-codes">Generalized Reed-Solomon Codes</a></h1> +<p>Generalized Reed-Solomon Codes, GRS, codes are an extension of Reed-Solomon codes <a href="https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction">wikipedia.org</a>, which are widely used in error-correcting codes. They are particularly useful for data extraction and data interpolation stages in danksharding, as they are capable of correcting errors and filling in missing values in the data blobs <a href="https://users.math.msu.edu/users/halljo/classes/codenotes/GRS.pdf">math.msu.edu</a>.</p> +<h1 id="data-extraction-and-data-interpolation-in-danksharding"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#data-extraction-and-data-interpolation-in-danksharding">Data Extraction and Data Interpolation in Danksharding</a></h1> +<p>Data extraction is the process of retrieving specific pieces of data from the shards, while data interpolation is the process of filling in missing values in the data blobs. GRS codes can be used to ensure the integrity of the data during these processes by encoding the data before storage and decoding it upon retrieval.</p> +<p>To illustrate the potential of product codes and GRS codes in the context of Danksharding, let's consider an example using SageMath <a href="https://www.sagemath.org/">SageMath.org</a>, an open-source mathematics software system. The code is intended for use in data extraction, data interpolation stages of danksharding in Ethereum, and error corrections of data blobs <a href="https://arxiv.org/abs/1310.2473">arxiv.org</a>.</p> +<h1 id="example-of-error-correction-codes-in-danksharding"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#example-of-error-correction-codes-in-danksharding">Example of Error Correction Codes in Danksharding</a></h1> +<p>Algebraic properties of product codes that are useful in coefficient extraction and missing data analysis include linearity, error-correcting capabilities, and structured redundancy. These properties enable efficient techniques for extracting information from data sets and interpolating missing values. In this example, we will use SageMath to demonstrate how these properties can be applied to extract coefficients and estimate missing data.</p> +<ol> +<li>Creating the Generalized Reed-Solomon Code:</li> +</ol> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>C = codes.</span><span style="color:#d73737;">GeneralizedReedSolomonCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">59</span><span>).</span><span style="color:#d73737;">list</span><span>()[</span><span style="color:#b65611;">1</span><span>:</span><span style="color:#b65611;">41</span><span>], </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">59</span><span>).</span><span style="color:#d73737;">list</span><span>()[</span><span style="color:#b65611;">1</span><span>:</span><span style="color:#b65611;">41</span><span>]) +</span><span> +</span></code></pre> +<ul> +<li><code>GF(59)</code> creates a Galois Field of order <code>59</code></li> +<li><code>.list()[1:41]</code> generates a list of elements from the Galois Field, excluding the first element <code>(0)</code>.</li> +<li><code>codes.GeneralizedReedSolomonCode()</code> creates a GRS code over the specified Galois Field with the given parameters.</li> +</ul> +<ol start="2"> +<li>Creating a random message vector and encoding it using the GRS code:</li> +</ol> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>msg = </span><span style="color:#d73737;">random_vector</span><span>(C.</span><span style="color:#d73737;">base_field</span><span>(), C.</span><span style="color:#d73737;">dimension</span><span>()) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Original message:</span><span>&quot;, msg) +</span><span>c = C.</span><span style="color:#d73737;">encode</span><span>(msg) +</span><span> +</span></code></pre> +<ol start="3"> +<li>Simulating the transmission of the encoded message with a static error rate of 3:</li> +</ol> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>err = </span><span style="color:#b65611;">3 +</span><span>Chan = channels.</span><span style="color:#d73737;">StaticErrorRateChannel</span><span>(C.</span><span style="color:#d73737;">ambient_space</span><span>(), err) +</span><span>Chan +</span><span>r = Chan.</span><span style="color:#d73737;">transmit</span><span>(c) +</span><span> +</span></code></pre> +<ol start="4"> +<li>Decoding the received message to the code and checking if it's equal to the original encoded message:</li> +</ol> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>c_dec = C.</span><span style="color:#d73737;">decode_to_code</span><span>(r) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the decoded received message to the code and the original encoded message equal?</span><span>&quot;,c_dec == c) +</span><span> +</span></code></pre> +<ol start="5"> +<li>Decoding the received message to the original message and checking if it's equal to the original message:</li> +</ol> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>m_unenc2 = C.</span><span style="color:#d73737;">decode_to_message</span><span>(r) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Decoded received message</span><span>&quot;, m_unenc2) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the decoded received message to the message and the original message equal?</span><span>&quot;,m_unenc2 == msg) +</span><span> +</span></code></pre> +<p>Now, here is the complete code and the link to the github repo <a href="https://github.com/thogiti/GeneralizedReedSolomonCodesforDankshardingEthereum">github.com</a>:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Create a Generalized Reed-Solomon Code over GF(59) with parameters +</span><span>C = codes.</span><span style="color:#d73737;">GeneralizedReedSolomonCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">59</span><span>).</span><span style="color:#d73737;">list</span><span>()[</span><span style="color:#b65611;">1</span><span>:</span><span style="color:#b65611;">41</span><span>], </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">59</span><span>).</span><span style="color:#d73737;">list</span><span>()[</span><span style="color:#b65611;">1</span><span>:</span><span style="color:#b65611;">41</span><span>]) +</span><span> +</span><span style="color:#999580;"># Create a random message vector and encode it using the GRS code +</span><span>msg = </span><span style="color:#d73737;">random_vector</span><span>(C.</span><span style="color:#d73737;">base_field</span><span>(), C.</span><span style="color:#d73737;">dimension</span><span>()) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Original message:</span><span>&quot;, msg) +</span><span>c = C.</span><span style="color:#d73737;">encode</span><span>(msg) +</span><span> +</span><span style="color:#999580;"># Simulate the transmission of the encoded message with a static error rate of 3 +</span><span>err = </span><span style="color:#b65611;">3 +</span><span>Chan = channels.</span><span style="color:#d73737;">StaticErrorRateChannel</span><span>(C.</span><span style="color:#d73737;">ambient_space</span><span>(), err) +</span><span>Chan +</span><span>r = Chan.</span><span style="color:#d73737;">transmit</span><span>(c) +</span><span> +</span><span style="color:#999580;"># Decode the received message to the code and check if it&#39;s equal to the original encoded message +</span><span>c_dec = C.</span><span style="color:#d73737;">decode_to_code</span><span>(r) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the decoded received message to the code and the original encoded message equal?</span><span>&quot;,c_dec == c) +</span><span> +</span><span style="color:#999580;"># Decode the received message to the original message and check if it&#39;s equal to the original message +</span><span>m_unenc2 = C.</span><span style="color:#d73737;">decode_to_message</span><span>(r) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Decoded received message</span><span>&quot;, m_unenc2) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the decoded received message to the message and the original message equal?</span><span>&quot;,m_unenc2 == msg) +</span><span> +</span><span> +</span></code></pre> +<p>In this example, we demonstrated the encoding, transmission, and decoding process of data using Generalized Reed-Solomon Codes for error correction which can be used to extract coefficients and estimate missing values or perform error correction in a dataset. By leveraging the algebraic properties of product codes, we can design efficient algorithms for extracting relevant information and interpolating missing values, which are crucial aspects of the block-building process in Danksharding.</p> +<h1 id="conclusion"><a href="https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/#conclusion">Conclusion</a></h1> +<p>In summary, product codes offer a powerful and efficient approach for data extraction and interpolation in the context of Danksharding, helping Ethereum achieve its scalability goals. By leveraging the algebraic properties of product codes and utilizing tools like SageMath, we can develop efficient algorithms to address the challenges associated with the block-building process in Danksharding. As Ethereum continues to evolve, the integration of product codes in the block-building process will be instrumental in realizing the full potential of Danksharding and achieving a truly scalable blockchain.</p> + + + + Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide + 2023-05-07T00:00:00+00:00 + 2023-05-07T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/ + <p>This article would provide an in-depth understanding of how product codes from algebraic coding theory can be applied to Danksharding to improve Ethereum's scalability. It would cover the fundamentals of product codes, their application in Danksharding, and the potential benefits for Ethereum's network.</p> +<ul> +<li><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#product-codes-and-their-relation-to-danksharding-in-ethereum">Product Codes and Their Relation to Danksharding in Ethereum</a></li> +<li><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#product-codes-in-coding-theory">Product Codes in Coding Theory</a></li> +<li><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#application-of-product-codes-in-danksharding">Application of Product Codes in Danksharding</a></li> +<li><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#sagemath-example-implementing-product-codes">SageMath Example: Implementing Product Codes</a></li> +</ul> +<h1 id="product-codes-and-their-relation-to-danksharding-in-ethereum"><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#product-codes-and-their-relation-to-danksharding-in-ethereum">Product Codes and Their Relation to Danksharding in Ethereum</a></h1> +<p>Product codes, a concept from algebraic coding theory <a href="https://en.wikipedia.org/wiki/Coding_theory">en.wikipedia.org</a>, can be utilized to enhance the robustness and fault tolerance of data storage and retrieval in Danksharding <a href="https://ethereum.org/en/roadmap/danksharding/">ethereum.org</a>, a scalability solution for Ethereum. In this article, we will explore the relationship between product codes and Danksharding, and demonstrate how product codes can be applied to this context using SageMath, an open-source mathematics software system.</p> +<h1 id="product-codes-in-coding-theory"><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#product-codes-in-coding-theory">Product Codes in Coding Theory</a></h1> +<p>Product codes are block codes that are formed by taking the Cartesian product of two or more simpler block codes <a href="https://en.wikipedia.org/wiki/Coding_theory">en.wikipedia.org</a> such as Hamming codes or Reed-Solomon codes. The resulting code has improved error-correcting capabilities compared to the individual component codes. They are used to increase the number of errors that can be corrected during data transmission. In the context of Danksharding, product codes could be used to add redundancy to data blobs, allowing for better error detection and correction in case of data corruption or loss.</p> +<h1 id="application-of-product-codes-in-danksharding"><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#application-of-product-codes-in-danksharding">Application of Product Codes in Danksharding</a></h1> +<p>Consider the data organization process in Danksharding, where data is organized into large blobs that are verifiable and available without interpreting them. By using product codes, it may be possible to add redundancy to the data blobs, enhancing error detection and correction.</p> +<p>Moreover, product codes could also play a role in the coefficient extraction and data interpolation processes of Danksharding. By leveraging the algebraic properties of product codes, it may be possible to design more efficient algorithms for extracting relevant information from the data and estimating missing values in data sets.</p> +<h1 id="sagemath-example-implementing-product-codes"><a href="https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/#sagemath-example-implementing-product-codes">SageMath Example: Implementing Product Codes</a></h1> +<p>To demonstrate the application of product codes in Danksharding, let's create a simple example using SageMath. First, we need to install SageMath and import the required libraries:</p> +<p>First, let’s create two Hamming codes over the binary field GF(2). We’ll use codeword lengths of 3 and 7 respectively:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>C1 = codes.</span><span style="color:#d73737;">HammingCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>), </span><span style="color:#b65611;">2</span><span>) +</span><span>C2 = codes.</span><span style="color:#d73737;">HammingCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>), </span><span style="color:#b65611;">3</span><span>) +</span><span> +</span></code></pre> +<p>Next, we’ll combine these two Hamming codes to form a product code:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>C_product = C1.</span><span style="color:#d73737;">product_code</span><span>(C2) +</span><span> +</span></code></pre> +<p>Now let’s generate a random data vector of appropriate length and encode it using our product code:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>data_blob = </span><span style="color:#d73737;">random_vector</span><span>(C_product.</span><span style="color:#d73737;">base_field</span><span>(), C_product.</span><span style="color:#d73737;">dimension</span><span>()) +</span><span> +</span><span>encoded_blob = C_product.</span><span style="color:#d73737;">encode</span><span>(data_blob) +</span><span> +</span></code></pre> +<p>We’ll set the error rate for our communication channel to 3:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>err = </span><span style="color:#b65611;">3 +</span><span> +</span></code></pre> +<p>Now we can create a communication channel with a static error rate and transmit our encoded data through it. This will introduce errors in the transmitted data:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>Chan = channels.</span><span style="color:#d73737;">StaticErrorRateChannel</span><span>(C_product.</span><span style="color:#d73737;">ambient_space</span><span>(), err) +</span><span>corrupted_blob = Chan.</span><span style="color:#d73737;">transmit</span><span>(encoded_blob) +</span><span> +</span></code></pre> +<p>Finally, we can decode the received data using our product code’s decoding algorithm and unencode it to recover the original message:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>decoded_blob = C_product.</span><span style="color:#d73737;">decode_to_code</span><span>(corrupted_blob) +</span><span> +</span><span>decoded_blob_msg = C_product.</span><span style="color:#d73737;">unencode</span><span>(decoded_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the messages same? </span><span>&quot;, decoded_blob_msg == data_blob) +</span><span> +</span></code></pre> +<p>Now, here is the complete code and the link to the github repo <a href="https://github.com/thogiti/ProductCodesDanksharding/blob/main/ProductCodesDanksharding.sage">github.com</a>:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># Create two Hamming codes over the binary field GF(2), with codeword lengths 2^2-1=3 and 2^3-1=7 respectively +</span><span>C1 = codes.</span><span style="color:#d73737;">HammingCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>), </span><span style="color:#b65611;">2</span><span>) +</span><span>C2 = codes.</span><span style="color:#d73737;">HammingCode</span><span>(</span><span style="color:#d73737;">GF</span><span>(</span><span style="color:#b65611;">2</span><span>), </span><span style="color:#b65611;">3</span><span>) +</span><span> +</span><span style="color:#999580;"># Combine the two Hamming codes to form a product code +</span><span>C_product = C1.</span><span style="color:#d73737;">product_code</span><span>(C2) +</span><span> +</span><span style="color:#999580;"># Generate a random data vector of appropriate length +</span><span>data_blob = </span><span style="color:#d73737;">random_vector</span><span>(C_product.</span><span style="color:#d73737;">base_field</span><span>(), C_product.</span><span style="color:#d73737;">dimension</span><span>()) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">data_blob: </span><span>&quot;,data_blob) +</span><span> +</span><span style="color:#999580;"># Encode the data using the product code +</span><span>encoded_blob = C_product.</span><span style="color:#d73737;">encode</span><span>(data_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">encoded_blob: </span><span>&quot;,encoded_blob) +</span><span> +</span><span style="color:#999580;"># Set the error rate for the communication channel +</span><span>err = </span><span style="color:#b65611;">3 +</span><span> +</span><span style="color:#999580;"># Create a communication channel with a static error rate +</span><span>Chan = channels.</span><span style="color:#d73737;">StaticErrorRateChannel</span><span>(C_product.</span><span style="color:#d73737;">ambient_space</span><span>(), err) +</span><span> +</span><span style="color:#999580;"># Transmit the encoded data through the channel, introducing errors +</span><span>corrupted_blob = Chan.</span><span style="color:#d73737;">transmit</span><span>(encoded_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">corrupted_blob: </span><span>&quot;, corrupted_blob) +</span><span> +</span><span style="color:#999580;"># Decode the received data using the product code&#39;s decoding algorithm +</span><span>decoded_blob = C_product.</span><span style="color:#d73737;">decode_to_code</span><span>(corrupted_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">decoded_blob: </span><span>&quot;,decoded_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the codes same? </span><span>&quot;, data_blob == decoded_blob) +</span><span> +</span><span style="color:#999580;"># Unencode the decoded codeword to recover the original message +</span><span>decoded_blob_msg = C_product.</span><span style="color:#d73737;">unencode</span><span>(decoded_blob) +</span><span style="color:#1fad83;">print</span><span>(&quot;</span><span style="color:#60ac39;">Are the messages same? </span><span>&quot;, decoded_blob_msg == data_blob) +</span><span> +</span></code></pre> +<p>This SageMath example demonstrates how product codes can be applied to the context of Danksharding, enhancing the robustness and fault tolerance of data storage and retrieval processes.</p> +<p>In conclusion, product codes from algebraic coding theory have the potential to improve the error detection and correction capabilities of Danksharding in Ethereum. Further research and development are required to fully understand the benefits and implementation challenges of applying product codes to this context. Nonetheless, this theoretical possibility holds promise for enhancing Ethereum's scalability solutions.</p> + + + + Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve + 2023-04-30T00:00:00+00:00 + 2023-04-30T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/ + <p>In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications <a href="https://hackmd.io/@jpw/bn254">hackmd.io/@jpw</a>. We will exploit the fact that $(p−1)/2$ is odd to compute the Frobenius automorphism efficiently.</p> +<h1 id="what-is-frobenius-automorphism"><a href="https://thogiti.github.io/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/#what-is-frobenius-automorphism">What is Frobenius Automorphism?</a></h1> +<p>The Frobenius automorphism is an endomorphism that maps a point $(x,y)$ on an elliptic curve defined over a prime field $F_p$ to $(x^p,y^p)$. It is an important property of elliptic curves over finite fields and has various applications in cryptography <a href="https://math.stackexchange.com/questions/4377341/explanation-of-frobenius-endomorphism-on-elliptic-curves">math.stackexchange.com</a>.</p> +<h1 id="efficient-computation-using-exponentiation-by-squaring"><a href="https://thogiti.github.io/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/#efficient-computation-using-exponentiation-by-squaring">Efficient Computation Using Exponentiation by Squaring</a></h1> +<p>To compute the Frobenius automorphism efficiently, we will use the exponentiation by squaring technique. This method allows us to compute $x^p$ and $y^p$ more efficiently by exploiting the fact that $(p−1)/2$ is odd.</p> +<p>Let's walk through the implementation step by step:</p> +<h2 id="step-1-define-the-prime-p-and-the-curve-constant-b">Step 1: Define the prime $p$ and the curve constant $b$</h2> +<p>We first define the prime $p$ and the curve constant $b$, which are the parameters for the BN254 elliptic curve.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>p = </span><span style="color:#b65611;">16798108731015832284940804142231733909889187121439069848933715426072753864723 +</span><span>b = </span><span style="color:#b65611;">3 +</span></code></pre> +<h2 id="step-2-construct-the-elliptic-curve-e-over-f-p">Step 2: Construct the elliptic curve $E$ over $F_p$</h2> +<p>Next, we construct the elliptic curve $E$ over the finite field $F_p$.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>F_p = </span><span style="color:#d73737;">GF</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F_p, [</span><span style="color:#b65611;">0</span><span>, b]) +</span></code></pre> +<h2 id="step-3-frobenius-automorphism-using-exponentiation-by-squaring-technique">Step 3: Frobenius automorphism using exponentiation by squaring technique</h2> +<p>We define the Frobenius automorphism by using the property of the prime field and the exponentiation by squaring technique. The <code>exponentiation_by_squaring</code> function computes the result of $x^n % mod$ efficiently.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b854d4;">def </span><span style="color:#6684e1;">exponentiation_by_squaring</span><span>(</span><span style="color:#d73737;">x</span><span>, </span><span style="color:#d73737;">n</span><span>, </span><span style="color:#d73737;">mod</span><span>): +</span><span> result = </span><span style="color:#b65611;">1 +</span><span> </span><span style="color:#b854d4;">while </span><span>n &gt; </span><span style="color:#b65611;">0</span><span>: +</span><span> </span><span style="color:#b854d4;">if </span><span>n % </span><span style="color:#b65611;">2 </span><span>== </span><span style="color:#b65611;">1</span><span>: +</span><span> result = (result * x) % mod +</span><span> x = (x * x) % mod +</span><span> n //= </span><span style="color:#b65611;">2 +</span><span> </span><span style="color:#b854d4;">return </span><span>result +</span><span> +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">frobenius_on_curve_efficient</span><span>(</span><span style="color:#d73737;">P</span><span>): +</span><span> x, y = P.</span><span style="color:#d73737;">xy</span><span>() +</span><span> x_frob = </span><span style="color:#d73737;">exponentiation_by_squaring</span><span>(x, p, p) +</span><span> y_frob = </span><span style="color:#d73737;">exponentiation_by_squaring</span><span>(y, p, p) +</span><span> </span><span style="color:#b854d4;">return </span><span>E.</span><span style="color:#d73737;">point</span><span>([x_frob, y_frob]) +</span></code></pre> +<h2 id="step-4-apply-the-frobenius-automorphism-to-a-point-on-the-curve">Step 4: Apply the Frobenius automorphism to a point on the curve</h2> +<p>Finally, we apply the Frobenius automorphism to a random point $P$ on the elliptic curve.</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span>P = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span>frob_P_efficient = </span><span style="color:#d73737;">frobenius_on_curve_efficient</span><span>(P) +</span><span> +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">Point P: </span><span>{P}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">Frobenius(P) (efficient): </span><span>{frob_P_efficient}&quot;) +</span></code></pre> +<p>Here is the complete code <a href="https://github.com/thogiti/ECC-BN254-Frobenius/blob/main/ECC-BN254-Frobenius.sage">github.com/thogiti</a> for the efficient computation of Frobenius Automorphism on BN254 elliptic curve:</p> +<pre data-lang="python" style="background-color:#fefbec;color:#6e6b5e;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#999580;"># BN254 curve is a pairing-friendly curve defined over a prime field $F_p$, where $p$ is a 254-bit prime. +</span><span style="color:#999580;"># The curve equation is $y^2=x^3+b$, where $b$ is a curve constant. +</span><span> +</span><span style="color:#999580;"># Define the prime $p$ and the curve constant $b$ +</span><span>p = </span><span style="color:#b65611;">16798108731015832284940804142231733909889187121439069848933715426072753864723 +</span><span>b = </span><span style="color:#b65611;">3 +</span><span> +</span><span style="color:#999580;"># Construct the elliptic curve $E$ over $F_p$ +</span><span>F_p = </span><span style="color:#d73737;">GF</span><span>(p) +</span><span>E = </span><span style="color:#d73737;">EllipticCurve</span><span>(F_p, [</span><span style="color:#b65611;">0</span><span>, b]) +</span><span> +</span><span style="color:#999580;"># Define the Frobenius automorphism for the elliptic curve using the property of the prime field and the exponentiation by squaring technique +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">exponentiation_by_squaring</span><span>(</span><span style="color:#d73737;">x</span><span>, </span><span style="color:#d73737;">n</span><span>, </span><span style="color:#d73737;">mod</span><span>): +</span><span> result = </span><span style="color:#b65611;">1 +</span><span> </span><span style="color:#b854d4;">while </span><span>n &gt; </span><span style="color:#b65611;">0</span><span>: +</span><span> </span><span style="color:#b854d4;">if </span><span>n % </span><span style="color:#b65611;">2 </span><span>== </span><span style="color:#b65611;">1</span><span>: +</span><span> result = (result * x) % mod +</span><span> x = (x * x) % mod +</span><span> n //= </span><span style="color:#b65611;">2 +</span><span> </span><span style="color:#b854d4;">return </span><span>result +</span><span> +</span><span style="color:#b854d4;">def </span><span style="color:#6684e1;">frobenius_on_curve_efficient</span><span>(</span><span style="color:#d73737;">P</span><span>): +</span><span> x, y = P.</span><span style="color:#d73737;">xy</span><span>() +</span><span> x_frob = </span><span style="color:#d73737;">exponentiation_by_squaring</span><span>(x, p, p) +</span><span> y_frob = </span><span style="color:#d73737;">exponentiation_by_squaring</span><span>(y, p, p) +</span><span> </span><span style="color:#b854d4;">return </span><span>E.</span><span style="color:#d73737;">point</span><span>([x_frob, y_frob]) +</span><span> +</span><span style="color:#999580;"># Apply the Frobenius automorphism to a point on the curve +</span><span>P = E.</span><span style="color:#d73737;">random_point</span><span>() +</span><span>frob_P_efficient = </span><span style="color:#d73737;">frobenius_on_curve_efficient</span><span>(P) +</span><span> +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">Point P: </span><span>{P}&quot;) +</span><span style="color:#1fad83;">print</span><span>(</span><span style="color:#b854d4;">f</span><span>&quot;</span><span style="color:#60ac39;">Frobenius(P) (efficient): </span><span>{frob_P_efficient}&quot;) +</span><span> +</span></code></pre> +<p>Here is the link to the github repo which implements the efficient computation of Frobenius Automorphism on BN254 Elliptic Curve, the complete code, explanations and instructions <a href="https://github.com/thogiti/ECC-BN254-Frobenius">github.com/thogiti</a>.</p> + + + + Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors + 2023-04-12T00:00:00+00:00 + 2023-04-12T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/ + <h1 id="overview">Overview</h1> +<p>We will implement dot product of two vectors of size <code>N</code> using Zero Knowledge Proofs (ZKP) in Circom, Halo2, . According to <a href="https://k12.libretexts.org/Bookshelves/Mathematics/Precalculus/07%3A_Vectors/7.04%3A_Dot_Product_and_Angle_Between_Two_Vectors">k12.libretexts.org</a>, the dot product of two vectors <code>A</code> and <code>B</code> of size <code>N</code> is given by:</p> +<pre style="background-color:#fefbec;color:#6e6b5e;"><code><span>A.B = a1*b1 + a2*b2 + ... + aN*bN +</span></code></pre> +<ul> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#overview">Overview</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#process-flow-of-a-zero-knowledge-proof">Process Flow of a Zero Knowledge Proof</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-circuit-for-dotproduct-of-two-vectors">Circom Circuit for Dotproduct of Two Vectors</a> +<ul> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-setup-and-installation">Circom Setup and Installation</a> +<ul> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-install-dependencies">Circom Install dependencies</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#install-circom">Install Circom</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#install-snarkjs">Install Snarkjs</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-circom-circuit-for-the-dotproduct-of-two-vectors">Implementing Circom Circuit for the Dotproduct of Two Vectors</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#halo2-circuit-for-dotproduct-of-two-vectors">Halo2 Circuit for Dotproduct of Two Vectors</a> +<ul> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#halo2-setup-and-installation">Halo2 Setup and Installation</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-halo2-circuit-for-the-dotproduct-of-two-vectors">Implementing Halo2 Circuit for the Dotproduct of Two Vectors</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#what-is-a-trusted-setup-and-why-is-it-necessary-in-a-real-world-application">What is a trusted setup and why is it necessary in a real-world application?</a></li> +</ul> +</li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#noir-circuit-for-dotproduct-of-two-vectors">Noir Circuit for Dotproduct of Two Vectors</a> +<ul> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#installing-noir">Installing Noir</a></li> +<li><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-noir-circuit-for-the-dotproduct-of-two-vectors">Implementing Noir Circuit for the Dotproduct of Two Vectors</a></li> +</ul> +</li> +</ul> +<h1 id="process-flow-of-a-zero-knowledge-proof"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#process-flow-of-a-zero-knowledge-proof">Process Flow of a Zero Knowledge Proof</a></h1> +<p>The below diagram describes a typical process flow in creating a Zero Knowledge Proof system. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230313/zkp-process-flow-diagram-2023-04-13-150046.png" alt="Zero Knowledge Proof Process Flow" /></p> +<p>To create zero-knowledge proofs and circuits using different libraries like Circom, Noir, and Halo2, follow these steps:</p> +<ol> +<li>Define the problem: Identify the problem you want to prove using zero-knowledge proofs. For instance, prove that you are a member of top 100 Uniswap liquidity provider without revealing any additional information or that you identified a critical bug in a smart contract without revealing any additional information.</li> +<li>Choose the appropriate ZKP library: Select the library that suits your needs, such as Circom, Noir, or Halo2 or others. Each library has its own set of features and trade-offs: +<ul> +<li>Circom: A domain-specific language (DSL) designed for creating circuits in a simple and intuitive way. It's useful for creating zk-SNARK circuits. For more details on Circom, visit the <a href="https://docs.circom.io/">official documentation</a>.</li> +<li>Noir: A high-level, general-purpose language for creating zero-knowledge proofs. It's easy to understand and has a growing ecosystem. For more details on Noir, visit the <a href="https://noir-lang.org/">official documentation</a>.</li> +<li>Halo2: A library for constructing zk-SNARKs without a trusted setup, providing a more secure and efficient alternative to some other libraries. For more details on Halo2, visit the <a href="https://zcash.github.io/halo2/index.html">official documentation</a>.</li> +</ul> +</li> +<li>Create the circuit: Design the circuit that represents the problem using the chosen library. This involves defining the inputs, outputs, and constraints that must be satisfied for the proof to be valid.</li> +<li>Generate the proof: Using the library's tools, generate the zero-knowledge proof that demonstrates the statement is true without revealing any additional information.</li> +<li>Verify the proof: Implement the verification process to ensure that the proof is valid and the statement is true, without learning any additional information.</li> +</ol> +<h1 id="circom-circuit-for-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-circuit-for-dotproduct-of-two-vectors">Circom Circuit for Dotproduct of Two Vectors</a></h1> +<p>In this example we will investigate how to write a Circom circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof withoit revealing any additional information.</p> +<h2 id="circom-setup-and-installation"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-setup-and-installation">Circom Setup and Installation</a></h2> +<p>The complete and latest documentation for installing the Circom ecosystem can be found <a href="https://docs.circom.io/getting-started/installation/">here</a>. The older versions of Circom can be also installed from the <a href="https://github.com/iden3/circom_old">old circom repository</a>.</p> +<h3 id="circom-install-dependencies"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#circom-install-dependencies">Circom Install dependencies</a></h3> +<p>The Circom compiler is written in Rust. To have Rust available in your system, you can install <code>rustup</code>. If you’re using Linux or macOS, open a terminal and enter the following command:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>curl --proto &#39;=https&#39; --tlsv1.2 https://sh.rustup.rs -sSf | sh +</span></code></pre> +<p>You also need the latest version of <code>Node.js</code> (or <code>yarn</code>). You can install them from <a href="https://nodejs.org/en/download">here</a>.</p> +<h3 id="install-circom"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#install-circom">Install Circom</a></h3> +<p>First, clone the circom repository: </p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>git clone https://github.com/iden3/circom.git +</span></code></pre> +<p>Enter the circom directory and use the cargo build to compile:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>cargo build --release +</span></code></pre> +<p>The installation takes around 3 minutes to be completed. When the command successfully finishes, it generates the circom binary in the directory <code>target/release</code>. You can install this binary as follows:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>cargo install --path circom +</span></code></pre> +<p>The previous command will install the circom binary in the directory <code>$HOME/.cargo/bin</code>. </p> +<h3 id="install-snarkjs"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#install-snarkjs">Install Snarkjs</a></h3> +<p>You can install <code>snarkjs</code> with the following command:</p> +<pre data-lang="shell" style="background-color:#fefbec;color:#6e6b5e;" class="language-shell "><code class="language-shell" data-lang="shell"><span>npm install -g snarkjs +</span></code></pre> +<h2 id="implementing-circom-circuit-for-the-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-circom-circuit-for-the-dotproduct-of-two-vectors">Implementing Circom Circuit for the Dotproduct of Two Vectors</a></h2> +<p>To implement the dotproduct of two vectors in Circom, we can follow the steps below:</p> +<ol> +<li>Define the two vectors <code>A</code> and <code>B</code> of size <code>N</code>.</li> +<li>Define a variable to store the dot product.</li> +<li>Calculate the dot product by multiplying the corresponding components of <code>A</code> and <code>B</code> and adding them together.</li> +<li>Output the dot product.</li> +</ol> +<p>Here's what the code would look like in Circom:</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span> +</span><span>template DotProduct(N: number) { +</span><span> signal A[N]; +</span><span> signal B[N]; +</span><span> signal result; +</span><span> +</span><span> component multiply[N]; +</span><span> component add[N-1]; +</span><span> +</span><span> for (i = 0; i &lt; N; i++) { +</span><span> multiply[i] A[i] * B[i] -&gt; add[i]; +</span><span> } +</span><span> +</span><span> for (i = 0; i &lt; N-1; i++) { +</span><span> add[i] + add[i+1] -&gt; add[i+1]; +</span><span> } +</span><span> +</span><span> add[N-2] -&gt; result; +</span><span>} +</span><span> +</span></code></pre> +<p>In the above code, we define two input signals <code>A</code> and <code>B</code> of size <code>N</code>, which represent the two vectors. We also define an output signal <code>result</code>, which will store the dot product.</p> +<p>We then define two components, <code>multiply</code> and <code>add</code>. The <code>multiply</code> component multiplies the corresponding components of <code>A</code> and <code>B</code>, while the <code>add</code> component adds them together. We use a loop to connect the outputs of the <code>multiply</code> components to the inputs of the <code>add</code> components. We also use a loop to connect the outputs of the <code>add</code> components to each other, until we reach the final output signal <code>result</code>.</p> +<p>To use this template, we can simply instantiate it and provide values for the <code>A</code> and <code>B</code> signals:</p> +<pre data-lang="circom" style="background-color:#fefbec;color:#6e6b5e;" class="language-circom "><code class="language-circom" data-lang="circom"><span> +</span><span>template Main() { +</span><span> signal A[4] = [3, -5, 4, 2]; +</span><span> signal B[4] = [2, 6, 5, 1]; +</span><span> signal result; +</span><span> +</span><span> DotProduct(4)() +</span><span> .A(A) +</span><span> .B(B) +</span><span> .result(result); +</span><span> +</span><span> print(result); +</span><span>} +</span><span> +</span></code></pre> +<p>In the above code, we define the two input signals <code>A</code> and <code>B</code> of size <code>4</code>, and an output signal <code>result</code>. We then instantiate the <code>DotProduct</code> template with a size of <code>4</code>, and connect its <code>A</code> and <code>B</code> signals to the corresponding input signals. We also connect its <code>result</code> signal to our output signal. Finally, we print the <code>result</code> signal.</p> +<h1 id="halo2-circuit-for-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#halo2-circuit-for-dotproduct-of-two-vectors">Halo2 Circuit for Dotproduct of Two Vectors</a></h1> +<p>In this example we will investigate how to write a Halo2 circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof without revealing any additional information.</p> +<h2 id="halo2-setup-and-installation"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#halo2-setup-and-installation">Halo2 Setup and Installation</a></h2> +<p>Halo2 requires the latest Rust. You can find more about developing using Halo2 at the official <a href="https://zcash.github.io/halo2/index.html">halo2 documentation</a>.</p> +<h2 id="implementing-halo2-circuit-for-the-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-halo2-circuit-for-the-dotproduct-of-two-vectors">Implementing Halo2 Circuit for the Dotproduct of Two Vectors</a></h2> +<p>To implement the dotproduct of two vectors in Halo2, we first need to define our circuit in Halo2. Here is the code for this:</p> +<pre data-lang="rust" style="background-color:#fefbec;color:#6e6b5e;" class="language-rust "><code class="language-rust" data-lang="rust"><span> +</span><span style="color:#b854d4;">use </span><span>halo2::{ +</span><span> circuit::{Layouter, SimpleFloorPlanner}, +</span><span> plonk::{Circuit, ConstraintSystem, Error}, +</span><span> poly::Rotation, +</span><span>}; +</span><span> +</span><span style="color:#999580;">// Define the circuit struct +</span><span>#[</span><span style="color:#d73737;">derive</span><span>(Debug)] +</span><span style="color:#b854d4;">struct </span><span>DotProduct&lt;</span><span style="color:#b854d4;">&#39;a</span><span>&gt; { +</span><span> </span><span style="color:#d73737;">a</span><span>: &amp;</span><span style="color:#b854d4;">&#39;a</span><span> [</span><span style="color:#b854d4;">u64</span><span>], +</span><span> </span><span style="color:#d73737;">b</span><span>: &amp;</span><span style="color:#b854d4;">&#39;a</span><span> [</span><span style="color:#b854d4;">u64</span><span>], +</span><span> </span><span style="color:#d73737;">result</span><span>: &amp;</span><span style="color:#b854d4;">&#39;a mut</span><span> [</span><span style="color:#b854d4;">u64</span><span>], +</span><span>} +</span><span> +</span><span style="color:#999580;">// Implement the Circuit trait for our circuit +</span><span style="color:#b854d4;">impl</span><span>&lt;</span><span style="color:#b854d4;">&#39;a</span><span>&gt; Circuit&lt;SimpleFloorPlanner&gt; </span><span style="color:#b854d4;">for </span><span>DotProduct&lt;</span><span style="color:#b854d4;">&#39;a</span><span>&gt; { +</span><span> </span><span style="color:#b854d4;">type </span><span>Config = (); +</span><span> </span><span style="color:#b854d4;">type </span><span>FloorPlanner = SimpleFloorPlanner; +</span><span> +</span><span> </span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">without_witnesses</span><span>(&amp;</span><span style="color:#d73737;">self</span><span>) -&gt; </span><span style="color:#b854d4;">Self </span><span>{ +</span><span> DotProduct { +</span><span> a: </span><span style="color:#d73737;">self</span><span>.a, +</span><span> b: </span><span style="color:#d73737;">self</span><span>.b, +</span><span> result: &amp;</span><span style="color:#b854d4;">mut </span><span>[</span><span style="color:#b65611;">0</span><span>; N], +</span><span> } +</span><span> } +</span><span> +</span><span> </span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">configure</span><span>( +</span><span> </span><span style="color:#d73737;">_config</span><span>: </span><span style="color:#b854d4;">Self::</span><span>Config, +</span><span> </span><span style="color:#d73737;">meta</span><span>: &amp;</span><span style="color:#b854d4;">mut </span><span>ConstraintSystem&lt;SimpleFloorPlanner&gt;, +</span><span> ) -&gt; Result&lt;(), Error&gt; { +</span><span> </span><span style="color:#999580;">// Define the input signals A and B +</span><span> </span><span style="color:#b854d4;">let</span><span> a = meta.</span><span style="color:#1fad83;">advice_column</span><span>(); +</span><span> </span><span style="color:#b854d4;">let</span><span> b = meta.</span><span style="color:#1fad83;">advice_column</span><span>(); +</span><span> +</span><span> </span><span style="color:#999580;">// Define the intermediate signals for multiplication +</span><span> </span><span style="color:#b854d4;">let</span><span> mul = (</span><span style="color:#b65611;">0</span><span>..N) +</span><span> .</span><span style="color:#1fad83;">map</span><span>(|_| meta.</span><span style="color:#1fad83;">advice_column</span><span>()) +</span><span> .collect::&lt;Vec&lt;_&gt;&gt;(); +</span><span> +</span><span> </span><span style="color:#999580;">// Define the intermediate signals for addition +</span><span> </span><span style="color:#b854d4;">let</span><span> add = (</span><span style="color:#b65611;">0</span><span>..N - </span><span style="color:#b65611;">1</span><span>) +</span><span> .</span><span style="color:#1fad83;">map</span><span>(|_| meta.</span><span style="color:#1fad83;">advice_column</span><span>()) +</span><span> .collect::&lt;Vec&lt;_&gt;&gt;(); +</span><span> +</span><span> </span><span style="color:#999580;">// Define the output signal result +</span><span> </span><span style="color:#b854d4;">let</span><span> result = meta.</span><span style="color:#1fad83;">advice_column</span><span>(); +</span><span> +</span><span> </span><span style="color:#999580;">// Constrain the input signals to the values provided +</span><span> </span><span style="color:#b854d4;">for </span><span>(i, &amp;value) in </span><span style="color:#d73737;">self</span><span>.a.</span><span style="color:#1fad83;">iter</span><span>().</span><span style="color:#1fad83;">enumerate</span><span>() { +</span><span> meta.</span><span style="color:#1fad83;">enable_constant</span><span>(a[i], value.</span><span style="color:#1fad83;">into</span><span>())?; +</span><span> } +</span><span> </span><span style="color:#b854d4;">for </span><span>(i, &amp;value) in </span><span style="color:#d73737;">self</span><span>.b.</span><span style="color:#1fad83;">iter</span><span>().</span><span style="color:#1fad83;">enumerate</span><span>() { +</span><span> meta.</span><span style="color:#1fad83;">enable_constant</span><span>(b[i], value.</span><span style="color:#1fad83;">into</span><span>())?; +</span><span> } +</span><span> +</span><span> </span><span style="color:#999580;">// Constrain the multiplication signals to the product +</span><span> </span><span style="color:#999580;">// of the corresponding components of A and B +</span><span> </span><span style="color:#b854d4;">for</span><span> i in </span><span style="color:#b65611;">0</span><span>..N { +</span><span> meta.</span><span style="color:#1fad83;">multiply</span><span>( +</span><span> Rotation::prev(), +</span><span> &amp;[a[i], b[i]], +</span><span> mul[i], +</span><span> )?; +</span><span> } +</span><span> +</span><span> </span><span style="color:#999580;">// Constrain the addition signals to the sum of the +</span><span> </span><span style="color:#999580;">// corresponding multiplication signals +</span><span> </span><span style="color:#b854d4;">for</span><span> i in </span><span style="color:#b65611;">0</span><span>..N - </span><span style="color:#b65611;">1 </span><span>{ +</span><span> meta.</span><span style="color:#1fad83;">add</span><span>( +</span><span> Rotation::cur(), +</span><span> &amp;[mul[i], mul[i + </span><span style="color:#b65611;">1</span><span>]], +</span><span> add[i], +</span><span> )?; +</span><span> } +</span><span> +</span><span> </span><span style="color:#999580;">// Constrain the output signal to the last addition signal +</span><span> meta.</span><span style="color:#1fad83;">copy</span><span>( +</span><span> Rotation::cur(), +</span><span> add[N - </span><span style="color:#b65611;">2</span><span>], +</span><span> result, +</span><span> )?; +</span><span> +</span><span> </span><span style="color:#999580;">// Constrain the output signal to the value provided +</span><span> </span><span style="color:#b854d4;">for </span><span>(i, &amp;value) in </span><span style="color:#d73737;">self</span><span>.result.</span><span style="color:#1fad83;">iter</span><span>().</span><span style="color:#1fad83;">enumerate</span><span>() { +</span><span> meta.</span><span style="color:#1fad83;">constrain_equal</span><span>(result, value.</span><span style="color:#1fad83;">into</span><span>())?; +</span><span> } +</span><span> +</span><span> Ok(()) +</span><span> } +</span><span>} +</span><span> +</span></code></pre> +<p>In this code, we define our circuit struct <code>DotProduct</code>, which contains the input signals <code>a</code> and <code>b</code>, and an output signal <code>result</code>. We also implement the <code>Circuit</code> trait for our circuit, which defines how the circuit should be constructed and constrained.</p> +<p>We define the input signals <code>a</code> and <code>b</code> using <code>meta.advice_column()</code>, which creates a new advice column in the circuit. We also define the intermediate signals <code>mul</code> and <code>add</code>, which will be used to perform the multiplication and addition operations. Finally, we define the output signal <code>result</code>.</p> +<p>We constrain the input signals to the values provided using <code>meta.enable_constant()</code>, which constrains the advice column to a constant value. We then constrain the multiplication signals using <code>meta.multiply()</code>, which constrains the product of the corresponding components of <code>a</code> and <code>b</code> to the corresponding multiplication signal. We then constrain the addition signals using <code>meta.add()</code>, which constrains the sum of the corresponding multiplication signals to the corresponding addition signal. Finally, we constrain the output signal to the last addition signal using <code>meta.copy()</code>, and constrain it to the value provided using <code>meta.constrain_equal()</code>.</p> +<p>To use this circuit, we can instantiate it with the values for <code>a</code> and <code>b</code>, and an empty vector for <code>result</code>. We can then create a proof using <code>Prover::prove()</code>, and verify the proof using <code>Verifier::verify()</code>. Here's an example:</p> +<pre data-lang="rust" style="background-color:#fefbec;color:#6e6b5e;" class="language-rust "><code class="language-rust" data-lang="rust"><span> +</span><span style="color:#b854d4;">use </span><span>halo2::{ +</span><span> dev::MockProver, +</span><span> plonk::{Circuit, ConstraintSystem, Verifier}, +</span><span>}; +</span><span> +</span><span style="color:#999580;">// Define the size of our vectors +</span><span style="color:#b854d4;">const</span><span> N: </span><span style="color:#b854d4;">usize </span><span>= </span><span style="color:#b65611;">4</span><span>; +</span><span> +</span><span style="color:#999580;">// Define our main function +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">main</span><span>() { +</span><span> </span><span style="color:#999580;">// Define the input signals A and B +</span><span> </span><span style="color:#b854d4;">let</span><span> a = [</span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">5</span><span>, </span><span style="color:#b65611;">4</span><span>, </span><span style="color:#b65611;">2</span><span>]; +</span><span> </span><span style="color:#b854d4;">let</span><span> b = [</span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">6</span><span>, </span><span style="color:#b65611;">5</span><span>, </span><span style="color:#b65611;">1</span><span>]; +</span><span> +</span><span> </span><span style="color:#999580;">// Define the output signal result +</span><span> </span><span style="color:#b854d4;">let mut</span><span> result = [</span><span style="color:#b65611;">0</span><span>; N]; +</span><span> +</span><span> </span><span style="color:#999580;">// Instantiate the circuit +</span><span> </span><span style="color:#b854d4;">let</span><span> circuit = DotProduct { +</span><span> a: &amp;a, +</span><span> b: &amp;b, +</span><span> result: &amp;</span><span style="color:#b854d4;">mut</span><span> result, +</span><span> }; +</span><span> +</span><span> </span><span style="color:#999580;">// Create a proof +</span><span> </span><span style="color:#b854d4;">let</span><span> prover = MockProver::run(N, &amp;circuit, vec![]).</span><span style="color:#1fad83;">unwrap</span><span>(); +</span><span> </span><span style="color:#b854d4;">let</span><span> proof = prover.proof; +</span><span> +</span><span> </span><span style="color:#999580;">// Verify the proof +</span><span> </span><span style="color:#b854d4;">let</span><span> verifier = Verifier::new(N, &amp;circuit, &amp;proof).</span><span style="color:#1fad83;">unwrap</span><span>(); +</span><span> assert!(verifier.</span><span style="color:#1fad83;">verify</span><span>().</span><span style="color:#1fad83;">is_ok</span><span>()); +</span><span> +</span><span> </span><span style="color:#999580;">// Print the result +</span><span> println!(&quot;</span><span style="color:#b65611;">{:?}</span><span>&quot;, result); +</span><span>} +</span><span> +</span></code></pre> +<p>In this code, we define the input signals <code>a</code> and <code>b</code> and the output signal <code>result</code>. We then instantiate the <code>DotProduct</code> circuit with these values. We create a proof using <code>MockProver::run()</code>, which simulates the circuit execution and generates a proof. We then verify the proof using <code>Verifier::new()</code> and <code>verify()</code>. Finally, we print the <code>result</code>.</p> +<p>Note that in this example, we use <code>MockProver</code> to generate a proof and verify it. In a real-world application, we would use a trusted setup to generate the proving and verifying keys, and use those keys to generate and verify proofs. We would also need to ensure that the inputs and outputs of the circuit are properly encrypted and decrypted to prevent information leakage. However, these details are beyond the scope of this example.</p> +<h2 id="what-is-a-trusted-setup-and-why-is-it-necessary-in-a-real-world-application"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#what-is-a-trusted-setup-and-why-is-it-necessary-in-a-real-world-application">What is a trusted setup and why is it necessary in a real-world application?</a></h2> +<p>A trusted setup is a process used in some zero-knowledge proof systems, including Halo2, to generate the proving and verifying keys that are used to generate and verify proofs. The trusted setup involves a group of trusted individuals or entities who collectively generate and destroy a secret value that is used to generate the keys. The secret value is destroyed after the keys are generated, so that no one can learn it and use it to generate fake proofs.</p> +<p>The trusted setup is necessary in a real-world application because it ensures that the proving and verifying keys are generated in a way that is secure and unbiased. Without a trusted setup, an attacker could potentially generate their own keys and use them to generate fake proofs that are accepted by the system. The trusted setup ensures that the keys are generated in a way that is independent of the attacker, and that the attacker cannot learn the secret value used to generate the keys.</p> +<p>In Halo2, the trusted setup involves generating a random permutation of the circuit's columns, and using this permutation to generate the keys. The permutation is generated using a multiparty computation protocol, where each participant contributes a random value that is combined to generate the final permutation. The permutation ensures that the circuit's columns are mixed together in a way that prevents an attacker from learning anything about the circuit by observing the keys.</p> +<p>Once the trusted setup is complete, the proving and verifying keys are distributed to the users of the system, who can use them to generate and verify proofs. The users do not need to trust each other or the system, because the keys were generated in a way that is secure and unbiased. However, the users must ensure that the inputs and outputs of the circuit are properly encrypted and decrypted, to prevent information leakage.</p> +<p>In summary, a trusted setup is a process used to generate the proving and verifying keys for a zero-knowledge proof system, and is necessary in a real-world application to ensure that the keys are generated in a way that is secure and unbiased.</p> +<h1 id="noir-circuit-for-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#noir-circuit-for-dotproduct-of-two-vectors">Noir Circuit for Dotproduct of Two Vectors</a></h1> +<p>In this example we will investigate how to write a Noir circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof without revealing any additional information.</p> +<p>For more details about Noir programming language, visit the <a href="https://github.com/noir-lang/noir">official documentation</a>.</p> +<h2 id="installing-noir"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#installing-noir">Installing Noir</a></h2> +<p>Noir is a Rust based language. You can visit the official documentation for <a href="https://noir-lang.org/getting_started/nargo/nargo_installation/">installation instructions</a>.</p> +<h2 id="implementing-noir-circuit-for-the-dotproduct-of-two-vectors"><a href="https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/#implementing-noir-circuit-for-the-dotproduct-of-two-vectors">Implementing Noir Circuit for the Dotproduct of Two Vectors</a></h2> +<p>To implement the dotproduct of two vectors in Noir, we first need to define our circuit in Noir. Here is the code for this:</p> +<pre data-lang="rust" style="background-color:#fefbec;color:#6e6b5e;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#999580;">// Noir does not have a built-in dot product function, so we create one +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">dot_product</span><span>(</span><span style="color:#d73737;">vect_A</span><span>: [field], </span><span style="color:#d73737;">vect_B</span><span>: [field]) -&gt; field { +</span><span> </span><span style="color:#b854d4;">let mut</span><span> result: field = </span><span style="color:#b65611;">0</span><span>; +</span><span> </span><span style="color:#b854d4;">let</span><span> N = vect_A.</span><span style="color:#1fad83;">len</span><span>(); +</span><span> +</span><span> </span><span style="color:#b854d4;">for</span><span> i in </span><span style="color:#b65611;">0</span><span>..N { +</span><span> result += vect_A[i] * vect_B[i]; +</span><span> } +</span><span> +</span><span> </span><span style="color:#b854d4;">return</span><span> result; +</span><span>} +</span><span> +</span><span style="color:#999580;">// Example usage +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">main</span><span>() { +</span><span> </span><span style="color:#b854d4;">let</span><span> vect_A: [field] = [</span><span style="color:#b65611;">1</span><span>, </span><span style="color:#b65611;">2</span><span>, </span><span style="color:#b65611;">3</span><span>, </span><span style="color:#b65611;">4</span><span>]; +</span><span> </span><span style="color:#b854d4;">let</span><span> vect_B: [field] = [</span><span style="color:#b65611;">5</span><span>, </span><span style="color:#b65611;">6</span><span>, </span><span style="color:#b65611;">7</span><span>, </span><span style="color:#b65611;">8</span><span>]; +</span><span> +</span><span> </span><span style="color:#b854d4;">let</span><span> result: field = </span><span style="color:#1fad83;">dot_product</span><span>(vect_A, vect_B); +</span><span> +</span><span> </span><span style="color:#999580;">// The result should be 70 (1*5 + 2*6 + 3*7 + 4*8) +</span><span> assert_eq!(result, </span><span style="color:#b65611;">70</span><span>); +</span><span>} +</span><span> +</span></code></pre> +<ol> +<li>The <code>dot_product</code> function is defined with two input parameters, <code>vect_A</code> and <code>vect_B</code>, both of which are arrays of fields (a field is a type in Noir representing a finite field element). The function returns a field.</li> +<li>Inside the <code>dot_product</code> function, a mutable variable result is initialized with a value of <code>0</code>, and the length of <code>vect_A</code> is stored in the variable <code>N</code>.</li> +<li>A for loop iterates through the indices of both input arrays, from <code>0</code> to <code>N-1</code>. In each iteration, the corresponding elements of the two arrays are multiplied and added to the <code>result</code>.</li> +<li>The <code>result</code> is returned as the output of the <code>dot_product</code> function.</li> +<li>The main function demonstrates how to use the <code>dot_product</code> function. Two arrays, <code>vect_A</code> and <code>vect_B</code>, are defined, and their dot product is calculated using the <code>dot_product</code> function.</li> +<li>Finally, an assertion checks that the <code>result</code> is equal to <code>70</code>, which is the expected dot product value <code>(15 + 26 + 37 + 48)</code>.</li> +</ol> +<p>The following steps will build the ZKP program and creates proofs and verifies the proof without any additional information.</p> +<ul> +<li>Build: <code>nargo check</code> </li> +<li>Prove: Enter the inputs in <code>Prover.toml</code> and run <code>nargo prove p -v</code>. Or, <code>nargo prove --show-output p</code> to show println logs. </li> +<li>Verify: <code>nargo verify p</code></li> +</ul> + + + + Paper Review - Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning + 2023-03-04T00:00:00+00:00 + 2023-03-04T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/ + <h1 id="overview"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#overview">Overview</a></h1> +<p>The paper aimed to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM) using machine learning methods. The study found that machine learning models demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification. The authors suggest that these modern machine learning methods may enhance identification of high-risk HCM subpopulations.</p> +<h1 id="citation-of-the-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#citation-of-the-paper">Citation of the Paper</a></h1> +<p>Stephanie M. Kochav, Yoshihiko Raita, Michael A. Fifer, Hiroo Takayama, Jonathan Ginns, Mathew S. Maurer, Muredach P. Reilly, Kohei Hasegawa, Yuichi J. Shimada, Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning, International Journal of Cardiology, Volume 327, 2021, Pages 117-124, ISSN 0167-5273, https://doi.org/10.1016/j.ijcard.2020.11.003.</p> +<h1 id="faqs"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#faqs">FAQs</a></h1> +<h2 id="explain-abstract-of-this-paper-in-simple-terms"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#explain-abstract-of-this-paper-in-simple-terms">Explain Abstract of this paper in simple terms</a></h2> +<p>This paper is about using machine learning to predict adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study found that machine learning models were better at predicting these events than traditional methods. The authors suggest that these new methods could help identify high-risk patients with HCM.</p> +<h2 id="explain-abstract-of-this-paper-in-2-lines"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#explain-abstract-of-this-paper-in-2-lines">Explain Abstract of this paper in 2 lines</a></h2> +<p>This paper aimed to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM) using machine learning methods. The study found that machine learning models demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification.</p> +<h2 id="explain-abstract-of-this-paper-like-i-am-five-years-old"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#explain-abstract-of-this-paper-like-i-am-five-years-old">Explain Abstract of this paper like I am five years old</a></h2> +<p>This paper is about using a computer to help doctors predict if someone with a heart problem called hypertrophic cardiomyopathy (HCM) might get very sick or die. The computer was better at predicting this than the doctors were.</p> +<h2 id="what-are-the-contributions-of-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#what-are-the-contributions-of-this-paper">What are the contributions of this paper</a></h2> +<p>The contributions of this paper are:</p> +<ol> +<li>Using machine learning methods to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM).</li> +<li>Demonstrating that machine learning models were better at predicting adverse cardiac events compared to traditional methods.</li> +<li>Suggesting that these new methods could help identify high-risk patients with HCM.</li> +</ol> +<h2 id="explain-the-practical-implications-of-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#explain-the-practical-implications-of-this-paper">Explain the practical implications of this paper</a></h2> +<p>The practical implications of this paper are significant for patients with hypertrophic cardiomyopathy (HCM) and their healthcare providers. The paper proposes the use of machine learning methods to improve the prediction of adverse cardiac events in patients with HCM. The development of accurate risk stratification methods can help identify high-risk patients who may benefit from more intensive monitoring or treatment. This can lead to better patient outcomes and improved quality of life. The machine learning models developed in this paper outperformed conventional risk stratification methods, demonstrating their potential to enhance the identification of high-risk HCM subpopulations. The use of machine learning methods in clinical practice can also help healthcare providers make more informed decisions about patient care and resource allocation. Overall, this paper highlights the potential of machine learning methods to improve risk stratification and patient outcomes in HCM.</p> +<h2 id="summarize-introduction-of-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#summarize-introduction-of-this-paper">Summarize introduction of this paper</a></h2> +<p>The introduction of this paper provides an overview of hypertrophic cardiomyopathy (HCM), which is a heart condition characterized by thickening of the heart muscle. HCM is a common cause of sudden cardiac death in young people and athletes. The paper highlights that current methods for predicting adverse cardiac events in patients with HCM are not very accurate, and there is a need for better risk stratification methods. The authors propose using machine learning methods to improve the prediction of adverse cardiac events in patients with HCM. The paper aims to develop and evaluate machine learning models that can identify high-risk patients with HCM and improve patient outcomes. The authors suggest that these new methods could enhance the identification of high-risk HCM subpopulations and improve patient care.</p> +<h2 id="methods-used-in-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#methods-used-in-this-paper">Methods used in this paper</a></h2> +<p>In this paper, the authors used a prospective cohort study design to evaluate the use of machine learning methods for predicting adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study included 183 adults with HCM who were followed up for a median of 2.2 years. The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death.</p> +<p>The authors used a logistic regression model as the reference model, which included known predictors of adverse cardiac events in HCM. They also used random forest classification to identify 20 predictive characteristics based on a priori knowledge and machine learning methods. Four machine learning models were developed using different algorithms, including elastic net regression, support vector machines, random forest, and gradient boosting.</p> +<p>The performance of the machine learning models was evaluated using measures such as sensitivity, specificity, and the area under the receiver-operating-characteristic curve (AUC-ROC). The results showed that all four machine learning models outperformed the reference model in predicting adverse cardiac events in patients with HCM. The elastic net regression model had the highest AUC-ROC of 0.93, compared to 0.79 for the reference model. The authors concluded that machine learning methods have the potential to enhance risk stratification and improve patient outcomes in HCM.</p> +<h3 id="study-population"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#study-population">Study Population</a></h3> +<p>The study population in this paper consisted of 183 adults with hypertrophic cardiomyopathy (HCM). The study design was a prospective cohort study, which followed up the patients for a median of 2.2 years to evaluate the use of machine learning methods for predicting adverse cardiac events in patients with HCM.</p> +<h3 id="data-extraction-and-analysis"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#data-extraction-and-analysis">Data Extraction and Analysis</a></h3> +<p>The data extraction in this paper involved collecting clinical and demographic data from the study participants, including age, sex, family history, medical history, and echocardiographic measurements. The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death.</p> +<p>The analysis in this paper involved the use of machine learning methods to develop predictive models for adverse cardiac events in patients with HCM. The authors used a logistic regression model as the reference model and developed four machine learning models using different algorithms, including elastic net regression, support vector machines, random forest, and gradient boosting. The performance of the models was evaluated using measures such as sensitivity, specificity, and the area under the receiver-operating-characteristic curve (AUC-ROC).</p> +<p>The baseline clinical characteristics can be found in the Table 1. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Baseline_clinical_characteristics.jpeg" alt="clinical characteristics" /></p> +<h2 id="results-of-the-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#results-of-the-paper">Results of the paper</a></h2> +<p>The results of the paper showed that all four machine learning models outperformed the reference model in predicting adverse cardiac events in patients with HCM. The elastic net regression model had the highest AUC-ROC of 0.93, compared to 0.79 for the reference model. The sensitivity and specificity of the elastic net regression model were 88% and 84%, respectively. The majority of the outcome events (85%) were heart transplants. The authors concluded that machine learning methods have the potential to enhance risk stratification and improve patient outcomes in HCM.</p> +<p>The predictive performance analysis can be found in the Table 3. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Predictive_performance_of_ML_models.jpeg" alt="predictive performance analysis" /></p> +<h2 id="conclusions-from-the-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#conclusions-from-the-paper">Conclusions from the paper</a></h2> +<p>The paper concluded that machine learning methods have the potential to improve risk stratification and predict adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study found that the machine learning models outperformed the conventional logistic regression model in predicting adverse cardiac events. The elastic net regression model had the highest predictive accuracy, with an AUC-ROC of 0.93, sensitivity of 88%, and specificity of 84%. The authors suggest that these modern machine learning methods may enhance identification of high-risk HCM subpopulations and improve patient outcomes.</p> +<p>The confusion matrix can be found the Table 4. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Confusion_matrix.jpeg" alt="confusion matrix" /></p> +<h2 id="limitations-of-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#limitations-of-this-paper">Limitations of this paper</a></h2> +<p>There are several limitations to this paper, including:</p> +<ol> +<li> +<p>The sample size of the study was relatively small, which may limit the generalizability of the findings to larger populations.</p> +</li> +<li> +<p>The study was conducted at a single center, which may limit the generalizability of the findings to other settings.</p> +</li> +<li> +<p>The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death, which may not capture all adverse cardiac events that are relevant to patients with HCM.</p> +</li> +<li> +<p>The study did not include genetic testing, which is an important factor in the diagnosis and management of HCM.</p> +</li> +<li> +<p>The study did not include data on the use of implantable cardioverter-defibrillators (ICDs), which are commonly used in the management of HCM.</p> +</li> +<li> +<p>The study did not include data on the use of medications, such as beta-blockers and calcium channel blockers, which are commonly used in the management of HCM.</p> +</li> +<li> +<p>The study did not include data on the presence of comorbidities, such as hypertension and diabetes, which may affect the risk of adverse cardiac events in patients with HCM.</p> +</li> +</ol> +<p>Overall, while the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM, further research is needed to validate these findings in larger, more diverse populations and to address the limitations of the study.</p> +<h2 id="future-works-suggested-in-this-paper"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#future-works-suggested-in-this-paper">Future works suggested in this paper</a></h2> +<p>The paper suggests several future directions for research, including:</p> +<ol> +<li> +<p>Validation of the machine learning models in larger, more diverse populations to assess their generalizability.</p> +</li> +<li> +<p>Incorporation of genetic testing data into the machine learning models to improve risk stratification.</p> +</li> +<li> +<p>Inclusion of data on the use of medications and implantable cardioverter-defibrillators (ICDs) in the machine learning models to improve risk stratification.</p> +</li> +<li> +<p>Development of machine learning models that can predict specific adverse cardiac events, such as sudden death or heart failure, rather than a composite outcome.</p> +</li> +<li> +<p>Exploration of the use of machine learning models in combination with other risk stratification tools, such as cardiac magnetic resonance imaging (MRI) and exercise stress testing.</p> +</li> +<li> +<p>Investigation of the potential of machine learning models to guide treatment decisions, such as the use of ICDs or the timing of surgical interventions.</p> +</li> +</ol> +<p>Overall, the paper suggests that machine learning methods have the potential to improve risk stratification and patient outcomes in HCM, and that further research is needed to fully realize this potential.</p> +<h1 id="advanced-questions"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#advanced-questions">Advanced Questions</a></h1> +<h2 id="how-did-the-design-of-the-research-study-impact-the-results-and-conclusions-drawn-from-the-data"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-did-the-design-of-the-research-study-impact-the-results-and-conclusions-drawn-from-the-data">How did the design of the research study impact the results and conclusions drawn from the data?</a></h2> +<p>The design of the research study impacted the results and conclusions drawn from the data in several ways. The use of a prospective cohort design allowed for the collection of detailed clinical and demographic data, which was essential for the development of the machine learning models. However, the small sample size and single-center design of the study may limit the generalizability of the findings to other populations and settings. Additionally, the use of a composite outcome may not capture all relevant adverse cardiac events, which may limit the clinical utility of the machine learning models. Despite these limitations, the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM and suggests several future directions for research.</p> +<h2 id="what-specific-design-elements-were-used-to-ensure-the-validity-and-reliability-of-the-study-findings"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#what-specific-design-elements-were-used-to-ensure-the-validity-and-reliability-of-the-study-findings">What specific design elements were used to ensure the validity and reliability of the study findings?</a></h2> +<p>The paper did not provide specific information on the design elements used to ensure the validity and reliability of the study's findings. However, the use of a prospective cohort design and the application of modern machine learning methods are generally considered to be rigorous approaches to data collection and analysis. Additionally, the paper reported statistical measures of model performance, such as sensitivity, specificity, and area under the receiver-operating-characteristic curve, which provide information on the accuracy of the machine learning models. Overall, while the paper did not provide detailed information on the design elements used to ensure validity and reliability, the use of established research methods and reporting of statistical measures of model performance suggest that the study's findings are credible.</p> +<h2 id="how-did-the-design-of-the-study-compare-to-other-similar-studies-in-the-same-domain"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-did-the-design-of-the-study-compare-to-other-similar-studies-in-the-same-domain">How did the design of the study compare to other similar studies in the same domain?</a></h2> +<p>The paper did not provide a direct comparison of its design to other similar studies in the same domain. However, the use of a prospective cohort design and the application of modern machine learning methods are consistent with other recent studies that have explored the use of machine learning for risk stratification in HCM. Additionally, the paper's focus on a composite outcome of death due to heart failure, heart transplant, and sudden death is similar to other studies that have used composite outcomes to assess the effectiveness of risk stratification methods in HCM. Overall, while the paper did not provide a direct comparison of its design to other similar studies, its use of established research methods and focus on clinically relevant outcomes are consistent with other recent studies in the same domain.</p> +<h2 id="were-there-any-limitations-to-the-design-of-the-study-that-may-have-impacted-the-results-or-conclusions"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#were-there-any-limitations-to-the-design-of-the-study-that-may-have-impacted-the-results-or-conclusions">Were there any limitations to the design of the study that may have impacted the results or conclusions?</a></h2> +<p>The limitations of the paper are summarized in the above <a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#limitations-of-this-paper">limitations section</a>.</p> +<p>Despite these limitations, the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM and suggests several future directions for research.</p> +<h2 id="how-could-the-design-of-the-study-be-improved-in-future-research-to-further-advance-the-understanding-of-the-domain"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-could-the-design-of-the-study-be-improved-in-future-research-to-further-advance-the-understanding-of-the-domain">How could the design of the study be improved in future research to further advance the understanding of the domain?</a></h2> +<p>To further advance the understanding of risk stratification in HCM, future research could consider the following improvements to the study design:</p> +<ul> +<li>Larger sample size: A larger sample size would increase the power of the study and improve the generalizability of the findings to other populations and settings.</li> +<li>Multi-center design: A multi-center design would increase the diversity of the study population and improve the generalizability of the findings to other centers or regions.</li> +<li>Longer follow-up period: A longer follow-up period would allow for the capture of additional relevant outcomes in patients with HCM.</li> +<li>More comprehensive outcome measures: The use of more comprehensive outcome measures, such as all-cause mortality or major adverse cardiac events, would provide a more complete picture of the effectiveness of risk stratification methods in HCM.</li> +<li>More complete data collection: The collection of more complete data on all relevant variables including the genetic testing data, medications, etc., would improve the accuracy of the machine learning models and reduce the risk of bias due to missing data.</li> +</ul> +<p>Overall, these improvements to the study design could help to further advance the understanding of risk stratification in HCM and improve the accuracy of machine learning models for predicting adverse cardiac events.</p> +<h2 id="what-criteria-were-used-for-variable-selection-in-this-research-paper-and-how-were-these-criteria-chosen"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#what-criteria-were-used-for-variable-selection-in-this-research-paper-and-how-were-these-criteria-chosen">What criteria were used for variable selection in this research paper, and how were these criteria chosen?</a></h2> +<p>In this research paper, the criteria for variable selection were based on a combination of random forest classification and a priori knowledge. The random forest classification method was used to identify the most important predictors of adverse cardiac events in patients with HCM, while a priori knowledge was used to select additional predictors that are known to be clinically relevant in HCM. Specifically, the authors identified 20 predictive characteristics based on these criteria, which were then used to develop the machine learning models. Overall, the combination of random forest classification and a priori knowledge allowed for the selection of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.</p> +<p>The top predictors can be found in the Fig 3. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Top_predictor_features.jpeg" alt="top predictor features" /></p> +<h2 id="can-you-explain-the-process-of-variable-selection-in-more-detail-and-how-it-impacted-the-results-of-the-study"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#can-you-explain-the-process-of-variable-selection-in-more-detail-and-how-it-impacted-the-results-of-the-study">Can you explain the process of variable selection in more detail, and how it impacted the results of the study?</a></h2> +<p>In this study, the authors used a combination of random forest classification and a priori knowledge to select the variables that were most predictive of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). Random forest classification is a machine learning method that can identify the most important predictors of an outcome by constructing a large number of decision trees and aggregating their results. A priori knowledge refers to existing knowledge about the disease and its risk factors that can be used to guide variable selection.</p> +<p>The authors identified 20 predictive characteristics based on these criteria, which were then used to develop the machine learning models. These models were compared to a reference model based on logistic regression using known predictors. The results showed that the machine learning models significantly outperformed the reference model in predicting adverse cardiac events in patients with HCM.</p> +<p>Overall, the process of variable selection in this study allowed for the identification of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM. This improved the accuracy of the machine learning models and may enhance identification of high-risk HCM subpopulations.</p> +<h2 id="were-any-statistical-methods-used-to-aid-in-variable-selection-and-if-so-which-ones-were-used-and-why"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#were-any-statistical-methods-used-to-aid-in-variable-selection-and-if-so-which-ones-were-used-and-why">Were any statistical methods used to aid in variable selection, and if so, which ones were used and why?</a></h2> +<p>The authors used random forest classification to identify the most important predictors of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). Random forest classification is a machine learning method that can identify the most important predictors of an outcome by constructing a large number of decision trees and aggregating their results. This method was chosen because it is well-suited to handling complex, high-dimensional data and can identify non-linear relationships between predictors and outcomes. In addition to random forest classification, the authors also used a priori knowledge to select additional predictors that are known to be clinically relevant in HCM. Overall, the combination of these methods allowed for the selection of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.</p> +<h2 id="were-any-limitations-or-challenges-encountered-during-the-variable-selection-process-and-if-so-how-were-these-addressed-by-the-researchers"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#were-any-limitations-or-challenges-encountered-during-the-variable-selection-process-and-if-so-how-were-these-addressed-by-the-researchers">Were any limitations or challenges encountered during the variable selection process, and if so, how were these addressed by the researchers?</a></h2> +<p>The paper did not mention any specific limitations or challenges encountered during the variable selection process. However, the authors did use a combination of random forest classification and a priori knowledge to select the variables that were most predictive of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). This approach allowed for the selection of a comprehensive set of predictors that were both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.</p> +<h2 id="how-did-the-machine-learning-models-perform-compared-to-the-conventional-risk-stratification-methods-in-predicting-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-did-the-machine-learning-models-perform-compared-to-the-conventional-risk-stratification-methods-in-predicting-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy">How did the machine learning models perform compared to the conventional risk stratification methods in predicting adverse cardiac events in patients with hypertrophic cardiomyopathy?</a></h2> +<p>The machine learning models outperformed the reference model in predicting adverse cardiac events by demonstrating a higher predictive accuracy. The reference model had a predictive accuracy of 73%, while the machine learning models had a predictive accuracy of 85%. The machine learning models also had a higher sensitivity and specificity compared to the reference model.</p> +<p>These findings have implications for clinical practice as they suggest that machine learning methods may be useful in identifying high-risk subpopulations of patients with hypertrophic cardiomyopathy. This could help clinicians to tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.</p> +<p>The decision curve analysis of the models can be found in the Fig 2. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Decision_curve_analysis.jpeg" alt="decision curve analysis of the models" /></p> +<h2 id="can-you-explain-the-difference-between-sensitivity-and-specificity-in-the-context-of-the-predictive-accuracy-of-the-reference-model-and-the-machine-learning-models"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#can-you-explain-the-difference-between-sensitivity-and-specificity-in-the-context-of-the-predictive-accuracy-of-the-reference-model-and-the-machine-learning-models">Can you explain the difference between sensitivity and specificity in the context of the predictive accuracy of the reference model and the machine learning models?</a></h2> +<p>Here is the difference between sensitivity and specificity in the context of the predictive accuracy of the reference model and the machine learning models.</p> +<ul> +<li>Sensitivity is the proportion of true positive cases that are correctly identified by the model. In the context of this paper, sensitivity refers to the proportion of patients who actually experienced an adverse cardiac event and were correctly identified as high-risk by the model.</li> +<li>Specificity is the proportion of true negative cases that are correctly identified by the model. In the context of this paper, specificity refers to the proportion of patients who did not experience an adverse cardiac event and were correctly identified as low-risk by the model.</li> +</ul> +<p>The machine learning models had higher sensitivity and specificity compared to the reference model, indicating that they were better at correctly identifying both high-risk and low-risk patients. This suggests that the machine learning models may be more effective at predicting adverse cardiac events in patients with hypertrophic cardiomyopathy compared to conventional risk stratification methods.</p> +<p>The sensitivity analysis of the ML models can be found in the Fig 1. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Sensitivity_Performance_of_ML_models.jpeg" alt="sensitivity analysis" /></p> +<h2 id="how-long-was-the-median-follow-up-period-for-the-cohort-of-adults-with-hypertrophic-cardiomyopathy-and-what-was-the-percentage-of-patients-who-developed-an-outcome-event-during-this-period"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-long-was-the-median-follow-up-period-for-the-cohort-of-adults-with-hypertrophic-cardiomyopathy-and-what-was-the-percentage-of-patients-who-developed-an-outcome-event-during-this-period">How long was the median follow-up period for the cohort of adults with hypertrophic cardiomyopathy, and what was the percentage of patients who developed an outcome event during this period?</a></h2> +<p>The median follow-up period for the cohort of adults with hypertrophic cardiomyopathy was 2.2 years, with an interquartile range of 0.6 to 3.8 years. During this period, 33 out of 183 patients (18%) developed an outcome event, which was a composite of death due to heart failure, heart transplant, and sudden death. The majority of the outcome events (85%) were heart transplants.</p> +<h2 id="what-implications-do-the-results-of-this-study-have-for-the-identification-of-high-risk-subpopulations-of-patients-with-hypertrophic-cardiomyopathy-and-how-might-these-modern-machine-learning-methods-be-applied-in-clinical-practice"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#what-implications-do-the-results-of-this-study-have-for-the-identification-of-high-risk-subpopulations-of-patients-with-hypertrophic-cardiomyopathy-and-how-might-these-modern-machine-learning-methods-be-applied-in-clinical-practice">What implications do the results of this study have for the identification of high-risk subpopulations of patients with hypertrophic cardiomyopathy, and how might these modern machine learning methods be applied in clinical practice?</a></h2> +<p>The results of this study suggest that modern machine learning methods may enhance the identification of high-risk subpopulations of patients with hypertrophic cardiomyopathy (HCM). The machine learning models developed in this study demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification methods.</p> +<p>In clinical practice, these machine learning methods could be used to identify patients with HCM who are at high risk of developing adverse cardiac events, such as heart failure, heart transplant, and sudden death. This could help clinicians to tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.</p> +<h2 id="how-was-the-data-sampling-conducted-in-this-study-and-what-criteria-were-used-to-select-the-patients-with-hypertrophic-cardiomyopathy-hcm-for-the-cohort"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#how-was-the-data-sampling-conducted-in-this-study-and-what-criteria-were-used-to-select-the-patients-with-hypertrophic-cardiomyopathy-hcm-for-the-cohort">How was the data sampling conducted in this study, and what criteria were used to select the patients with hypertrophic cardiomyopathy (HCM) for the cohort?</a></h2> +<p>The data sampling in this study was conducted using a prospective cohort design. Patients with hypertrophic cardiomyopathy (HCM) were recruited from a single center in Japan between 2010 and 2018. The inclusion criteria for the cohort were as follows:</p> +<ul> +<li>Adults aged 18 years or older</li> +<li>Diagnosis of HCM based on echocardiography or cardiac magnetic resonance imaging</li> +<li>Availability of clinical and laboratory data at the time of enrollment</li> +</ul> +<p>Patients with a history of heart transplantation or septal myectomy were excluded from the cohort. Overall, 183 patients with HCM were included in the study.</p> +<p>The primary outcome events modeled can be found in the Table 2. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230304/Primary_outcome_events.jpeg" alt="primary outcome events" /></p> +<h2 id="can-these-modern-machine-learning-methods-be-applied-to-other-cardiovascular-diseases-to-enhance-risk-stratification"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#can-these-modern-machine-learning-methods-be-applied-to-other-cardiovascular-diseases-to-enhance-risk-stratification">Can these modern machine learning methods be applied to other cardiovascular diseases to enhance risk stratification?</a></h2> +<p>Yes, these modern machine learning methods can potentially be applied to other cardiovascular diseases to enhance risk stratification. However, further research is needed to determine the generalizability of these methods to other diseases and to optimize their use in clinical practice.</p> +<h2 id="what-are-the-potential-clinical-implications-of-using-machine-learning-methods-to-identify-high-risk-hcm-subpopulations"><a href="https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/#what-are-the-potential-clinical-implications-of-using-machine-learning-methods-to-identify-high-risk-hcm-subpopulations">What are the potential clinical implications of using machine learning methods to identify high-risk HCM subpopulations?</a></h2> +<p>The potential clinical implications of using machine learning methods to identify high-risk HCM subpopulations are that clinicians can tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. This could help improve patient outcomes and reduce healthcare costs by preventing adverse events and optimizing resource allocation. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.</p> + + + + Paper Review - Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes + 2023-03-03T00:00:00+00:00 + 2023-03-03T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/ + <h1 id="overview"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#overview">Overview</a></h1> +<p>The paper presents a machine learning approach for classification of hypertrophic cardiomyopathy phenotypes using native T1 mapping radiomics.</p> +<h1 id="citation-of-the-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#citation-of-the-paper">Citation of the Paper</a></h1> +<p>Antonopoulos, A.S., Boutsikou, M., Simantiris, S. et al. Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes. Sci Rep 11, 23596 (2021). https://doi.org/10.1038/s41598-021-02971-z</p> +<h1 id="faqs"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#faqs">FAQs</a></h1> +<h2 id="explain-abstract-of-this-paper-in-simple-terms"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#explain-abstract-of-this-paper-in-simple-terms">Explain Abstract of this paper in simple terms</a></h2> +<p>The paper explores the use of machine learning techniques to classify hypertrophic cardiomyopathy (HCM) phenotypes using radiomic features of the left ventricle. Radiomic features are mathematical representations of the texture and intensity of medical images. The study found that these features are useful in identifying different HCM phenotypes, which may have important implications for diagnosis and treatment of the disease.</p> +<h2 id="explain-abstract-of-this-paper-in-2-lines"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#explain-abstract-of-this-paper-in-2-lines">Explain Abstract of this paper in 2 lines</a></h2> +<p>The paper investigates machine learning techniques to identify hypertrophic cardiomyopathy (HCM) phenotypes using radiomic features. The study shows that radiomic features can be used to classify different HCM phenotypes, which could aid in diagnosis and treatment of the disease.</p> +<h2 id="explain-abstract-of-this-paper-like-i-am-five-years-old"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#explain-abstract-of-this-paper-like-i-am-five-years-old">Explain Abstract of this paper like I am five years old</a></h2> +<p>The paper talks about using computers to help doctors identify different types of heart problems. They do this by looking at pictures of the heart and finding patterns in the picture that tell them which type of heart problem it is. This can help doctors give the right treatment to the patient.</p> +<h2 id="what-are-the-contributions-of-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#what-are-the-contributions-of-this-paper">What are the contributions of this paper</a></h2> +<p>The paper shows that radiomic features can be used to classify different types of hypertrophic cardiomyopathy (HCM) phenotypes, which can aid in the diagnosis and treatment of the disease. This demonstrates the potential of machine learning techniques in medical image analysis and highlights the importance of considering radiomic features for clinical decision making.</p> +<h2 id="explain-the-practical-implications-of-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#explain-the-practical-implications-of-this-paper">Explain the practical implications of this paper</a></h2> +<p>The paper suggests that machine learning techniques can be used to improve diagnosis and treatment of hypertrophic cardiomyopathy (HCM) by identifying different HCM phenotypes. This can help doctors give more targeted treatment to patients, potentially improving outcomes and quality of life. The use of radiomic features in medical imaging analysis may also have broader applications in other areas of medicine.</p> +<h2 id="summarize-introduction-of-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#summarize-introduction-of-this-paper">Summarize introduction of this paper</a></h2> +<p>The introduction of this paper provides an overview of hypertrophic cardiomyopathy (HCM), a heart disease that affects the structure of the heart muscle. The authors discuss the limitations of current diagnostic methods, which rely on subjective assessments of echocardiograms and other imaging techniques. They argue that there is a need for more objective and quantitative measures to aid in the diagnosis and classification of HCM. </p> +<p>The authors propose the use of radiomic features, which are mathematical representations of the texture and intensity of medical images, as a potential solution. They describe how these features can capture subtle differences in tissue composition and microstructure that may be indicative of different HCM phenotypes. The authors also highlight the potential of machine learning techniques to analyze large amounts of radiomic data and identify patterns that may not be apparent to the naked eye.</p> +<p>The authors then outline the objectives of the study, which include identifying radiomic features that are stable across different imaging modalities, exploring the relationships between different radiomic features, and using machine learning techniques to classify different HCM phenotypes based on radiomic features. They also describe the study design, which involved two separate cohorts of patients, and the methods used to extract and analyze radiomic data from cardiac MRI scans.</p> +<p>Overall, the introduction provides a detailed background and rationale for the study, highlighting the potential of radiomic features and machine learning techniques to improve the diagnosis and classification of HCM.</p> +<h2 id="methods-used-in-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#methods-used-in-this-paper">Methods used in this paper</a></h2> +<h3 id="study-population"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#study-population">Study Population</a></h3> +<p>The study comprised two arms, with the first arm comprised of 20 CMR scans with available native T1 mapping randomly selected by their archive, which served for the purpose of stability assessment (i.e., inter-observer variability) of extracted radiomic features from T1 maps, which were included in further analysis in Study Arm 2. </p> +<p>Study Arm 2 included a total of 152 consecutive patients undergoing a CMR scan (period 2019–2020) and native T1 mapping as follows: individuals without evidence of structural heart disease on CMR (n = 30), patients with left ventricular hypertrophy (LVH, i.e. increased wall thickness ≥ 12 mm or increased LV mass index) of various causes (athletes, valvular heart disease, hypertension etc., n = 30), patients with known HCM (n = 61) and patients with known cardiac amyloidosis (n = 28). </p> +<p>The complete data pipeline, data sampling and ML workflow can be found in the Fig 1. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/ML_workflow_and_data_sampling.jpeg" alt="ML workflow and data pipeline" /></p> +<h3 id="data-extraction-and-analysis"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#data-extraction-and-analysis">Data Extraction and Analysis</a></h3> +<p>They extracted a total of 850 radiomic features from T1 maps by cardiac magnetic resonance (CMR) and explored their value in disease classification. They applied principal component analysis and unsupervised clustering in exploratory analysis, and then machine learning for feature selection of the best radiomic features that maximized the diagnostic value for cardiac disease classification.</p> +<p>They used the following steps to process the data:</p> +<ul> +<li>Radiomic feature extraction: Radiomic features were extracted from the T1 maps using the PyRadiomics library.</li> +<li>Exploratory analysis: Unsupervised hierarchical clustering was performed on the extracted radiomic features.</li> +<li>Feature selection: The authors used machine learning algorithms to select the best radiomic features for classification of cardiac disease phenotypes. They used a combination of random forests and recursive feature elimination (RFE).</li> +<li>Model validation: The selected radiomic features were used to train a machine learning model for classification of cardiac disease phenotypes. The model was validated using internal and external datasets.</li> +<li>The diagnostic performance of the radiomics model was evaluated using the area under the receiver operating characteristic curve (AUC).</li> +<li>Statistical analysis was performed using chi-squared tests and logistic regression models.</li> +</ul> +<p>The exploratory data analysis can be found in the Fig 2. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/EDA_radiomic_features.jpeg" alt="exploratory data analysis" /></p> +<h2 id="results-of-the-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#results-of-the-paper">Results of the paper</a></h2> +<p>The results of the paper are as follows:</p> +<ul> +<li>The first three principal components of the T1 radiomics were distinctively correlated with cardiac disease type.</li> +<li>Unsupervised hierarchical clustering of the population by myocardial T1 radiomics was significantly associated with myocardial disease type.</li> +<li>After feature selection, internal validation, and external testing, a model of T1 radiomics had good diagnostic performance (AUC 0.753) for multinomial classification of disease phenotype (normal vs. LVH vs. HCM vs. cardiac amyloid).</li> +<li>A subset of six radiomic features outperformed mean native T1 values for classification between myocardial health vs. disease and HCM phenocopies.</li> +</ul> +<p>Therefore, the results of the paper suggest that myocardial texture assessed by native T1 maps is linked to features of cardiac disease, and myocardial radiomic phenotyping could enhance the diagnostic yield of T1 mapping for myocardial disease detection and classification.</p> +<p>The performance analysis anc confusion matrix can be found in the Fig 4. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/Top_T1_radiomic_features_and_confusion_matrix.jpeg" alt="performance analysis" /></p> +<h2 id="conclusions-from-the-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#conclusions-from-the-paper">Conclusions from the paper</a></h2> +<p>The conclusions from the paper are as follows:</p> +<ul> +<li>Radiomic features provide added diagnostic value for distinction between healthy and diseased myocardium, as well as for differentiation between HCM and relevant phenocopies, such as amyloidosis, on top of native T1.</li> +<li>The application of radiomics to standard native T1 mapping is a promising approach for the texture characterization of the human myocardium and for further enhancing the diagnostic value of CMR.</li> +</ul> +<p>Therefore, the paper suggests that myocardial radiomic phenotyping using T1 radiomics analysis could enhance the diagnostic yield of T1 mapping for myocardial disease detection and classification.</p> +<h2 id="limitations-of-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#limitations-of-this-paper">Limitations of this paper</a></h2> +<p>The limitations of this paper are as follows:</p> +<ul> +<li>The study was conducted at a single center with a relatively small sample size, which may limit the generalizability of the findings.</li> +<li>Only the basal slice of the T1 maps was used for texture analysis, which may not fully represent the entire myocardium.</li> +<li>The reproducibility of radiomics features across different scanners/vendors and acquisition sequences is still an issue, which may limit the clinical application of radiomics.</li> +<li>The study did not include a comparison with other imaging modalities or biomarkers, which may limit the assessment of the added diagnostic value of radiomics.</li> +<li>The study did not include a longitudinal follow-up to assess the prognostic value of radiomics features for disease progression or response to treatment.</li> +</ul> +<p>Therefore, these limitations should be taken into consideration when interpreting the results of the study.</p> +<h2 id="future-works-suggested-in-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#future-works-suggested-in-this-paper">Future works suggested in this paper</a></h2> +<p>The future works suggested in this paper are as follows:</p> +<ul> +<li>Further research is needed to harmonize the readouts between different scanners/vendors and acquisition sequences to address the reproducibility issues of radiomics.</li> +<li>Future studies should include a larger sample size and a multi-center design to validate the findings of this study and improve the generalizability of the results.</li> +<li>Future studies should also include a comparison with other imaging modalities or biomarkers to assess the added diagnostic value of radiomics.</li> +<li>Longitudinal follow-up studies are needed to assess the prognostic value of radiomics features for disease progression or response to treatment.</li> +<li>Future studies should also investigate the potential of radiomics for other CMR applications, such as perfusion imaging and late gadolinium enhancement imaging.</li> +</ul> +<p>Therefore, these future works could help to further validate and improve the clinical application of radiomics in CMR.</p> +<h1 id="advanced-questions"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#advanced-questions">Advanced Questions</a></h1> +<h2 id="how-does-the-use-of-radiomics-analysis-enhance-the-diagnostic-value-of-cmr-for-myocardial-texture-phenotyping"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#how-does-the-use-of-radiomics-analysis-enhance-the-diagnostic-value-of-cmr-for-myocardial-texture-phenotyping">How does the use of radiomics analysis enhance the diagnostic value of CMR for myocardial texture phenotyping?</a></h2> +<p>Using radiomic features can improve the ability of CMR to distinguish between healthy and diseased myocardium, as well as between HCM and other similar conditions. Radiomic features provide additional information about the texture and heterogeneity of the myocardium that may not be captured by conventional CMR parameters like native T1 values. Radiomic features are quantitative measures of image texture and heterogeneity that can be extracted from medical images using advanced image processing techniques.</p> +<p>In this study, the authors extracted radiomic features from T1 maps generated by CMR and used machine learning to identify the best radiomic features for classifying cardiac disease. The results showed that a model using T1 radiomics had good diagnostic performance for categorizing different types of cardiac disease. Additionally, a subset of six radiomic features performed better than mean native T1 values for differentiating between healthy and diseased myocardium and identifying HCM phenocopies.</p> +<p>Therefore, using radiomic features can enhance the accuracy of T1 mapping for detecting and classifying myocardial disease.</p> +<p>The population heatmap can be found in the Fig 3. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/Population_heatmap_radiomic_features.jpeg" alt="performance analysis" /></p> +<h2 id="what-were-some-limitations-of-this-study-and-how-might-they-impact-the-generalizability-of-its-findings-to-other-populations-or-imaging-settings"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#what-were-some-limitations-of-this-study-and-how-might-they-impact-the-generalizability-of-its-findings-to-other-populations-or-imaging-settings">What were some limitations of this study, and how might they impact the generalizability of its findings to other populations or imaging settings?</a></h2> +<p>The limitations of the study are summarized above in the <a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#limitations-of-this-paper">limitations section</a>.</p> +<p>These limitations may impact the generalizability of the findings to other populations or imaging settings. Therefore, further studies with larger sample sizes, multi-center designs, and longitudinal follow-up are needed to validate the findings of this study and improve the generalizability of the results. Additionally, the reproducibility of radiomics features across different scanners/vendors and acquisition sequences should be addressed to improve the clinical application of radiomics.</p> +<h2 id="can-you-explain-how-radiomic-features-are-extracted-from-medical-images-and-what-types-of-information-they-can-provide-about-tissue-volume-shape-and-texture"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#can-you-explain-how-radiomic-features-are-extracted-from-medical-images-and-what-types-of-information-they-can-provide-about-tissue-volume-shape-and-texture">Can you explain how radiomic features are extracted from medical images, and what types of information they can provide about tissue volume, shape, and texture?</a></h2> +<p>Radiomic features are quantitative measures of image texture and heterogeneity that can be extracted from medical images using advanced image processing techniques. In this study, radiomic features were extracted from T1 maps by CMR. The process of extracting radiomic features involves the following steps:</p> +<ul> +<li> +<p>Image acquisition: Medical images are acquired using various imaging modalities such as CT, MRI, or PET.</p> +</li> +<li> +<p>Image segmentation: The anatomical volumes of interest are segmented from the background using manual or automated methods.</p> +</li> +<li> +<p>Feature extraction: Radiomic features are extracted from the segmented volumes using mathematical algorithms that analyze the spatial relationship of (dis)similar voxels. These features can provide information on tissue volume, shape, and texture, such as:</p> +</li> +<li> +<p>First-order statistics: Measures of the distribution of pixel/voxel intensities, such as mean, median, standard deviation, skewness, and kurtosis.</p> +</li> +<li> +<p>Second-order statistics: Measures of the spatial relationship between pixels/voxels, such as gray-level co-occurrence matrix (GLCM), gray-level run-length matrix (GLRLM), and gray-level size zone matrix (GLSZM).</p> +</li> +<li> +<p>Higher-order statistics: Measures of the spatial relationship between higher-order features, such as fractal dimension, wavelet transform, and Laplacian of Gaussian (LoG).</p> +</li> +</ul> +<p>Radiomic features can provide additional information about tissue texture and heterogeneity that may not be captured by conventional imaging parameters. Therefore, radiomic analysis has the potential to enhance the diagnostic and prognostic value of medical imaging for various diseases.</p> +<p>The most important radiomic features selected can be found in the Table 2. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/top_radiomic_features.jpeg" alt="diagnostic value" /></p> +<h2 id="in-what-ways-has-radiomic-phenotyping-been-successfully-used-in-other-medical-fields-such-as-clinical-oncology-are-there-any-key-differences-between-these-applications-and-those-explored-in-this-paper"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#in-what-ways-has-radiomic-phenotyping-been-successfully-used-in-other-medical-fields-such-as-clinical-oncology-are-there-any-key-differences-between-these-applications-and-those-explored-in-this-paper">In what ways has radiomic phenotyping been successfully used in other medical fields such as clinical oncology? Are there any key differences between these applications and those explored in this paper?</a></h2> +<p>Radiomic phenotyping has been successfully used in clinical oncology to characterize the distinct biological phenotypes of tumors and provide relevant information for diagnosis, prognosis, and treatment planning. For example, radiomic features extracted from CT or MRI images of lung cancer have been shown to be associated with tumor stage, histology, and patient survival. Similarly, radiomic features extracted from MRI images of glioblastoma have been shown to be associated with tumor grade, molecular subtype, and patient survival.</p> +<p>The key difference between these applications and those explored in this paper is the imaging modality and the disease being studied. In this paper, radiomic features were extracted from T1 maps by CMR to enhance the diagnostic value of T1 mapping for myocardial disease detection and classification. Therefore, the application of radiomic phenotyping in this paper is specific to CMR and myocardial disease. However, the underlying principle of radiomic analysis is the same across different imaging modalities and diseases, which is to extract quantitative measures of image texture and heterogeneity that can provide additional information for disease characterization and management.</p> +<p>The most important radiomic phenotyping predictors data can be found in the Table 1. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/Unsupervised_clustering_radiomic_phenotyping_of_myocardium.jpeg" alt="diagnostic value" /></p> +<h2 id="what-were-the-principal-components-identified-through-the-principal-component-analysis-and-how-were-they-used-to-explore-associations-with-disease-background"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#what-were-the-principal-components-identified-through-the-principal-component-analysis-and-how-were-they-used-to-explore-associations-with-disease-background">What were the principal components identified through the principal component analysis and how were they used to explore associations with disease background?</a></h2> +<p>The principal component analysis (PCA) was performed on the radiomic features extracted from T1 maps by CMR to identify the principal components (PC) that describe most of the phenotypic variation in the study population. The first two components (PC1, PC2) were used to explore associations with disease background in relevant cluster plots. The first three principal components of the T1 radiomics were distinctively correlated with cardiac disease type. The unsupervised hierarchical clustering of the population by myocardial T1 radiomics was significantly associated with myocardial disease type (chi 2 = 55.98, p &lt; 0.0001). Therefore, the PCA helped to identify the most relevant radiomic features that are associated with cardiac disease type and provided a basis for further analysis of the radiomic features.</p> +<p>The pinciple component analysis can be found in the Fig 2. <img src="https://raw.githubusercontent.com/thogiti/thogiti.github.io/master/content/images/20230303/EDA_radiomic_features.jpeg" alt="pinciple component data analysis" /></p> +<h2 id="can-you-explain-the-process-of-stability-assessment-of-extracted-radiomic-features-from-t1-maps-and-how-it-was-used-to-limit-the-analysis-to-radiomic-features-that-could-be-of-value-as-imaging-biomarkers"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#can-you-explain-the-process-of-stability-assessment-of-extracted-radiomic-features-from-t1-maps-and-how-it-was-used-to-limit-the-analysis-to-radiomic-features-that-could-be-of-value-as-imaging-biomarkers">Can you explain the process of stability assessment of extracted radiomic features from T1 maps and how it was used to limit the analysis to radiomic features that could be of value as imaging biomarkers?</a></h2> +<p>The stability assessment of extracted radiomic features from T1 maps was performed to limit the analysis to radiomic features that could be of value as imaging biomarkers. The process involved the following steps:</p> +<ul> +<li>Twenty scans from Study Arm 1 were used to assess the coefficient of variation (CV) of each radiomic feature in multiple delineations by two independent operators.</li> +<li>The CV was calculated as the ratio of the standard deviation to the mean of the radiomic feature across multiple delineations.</li> +<li>Only those radiomic features with multiple delineation CV &lt; 10% were included in further analysis (n = 628).</li> +<li>This step was performed to ensure that the radiomic features were stable and reproducible across different delineations and operators.</li> +<li>The remaining radiomic features were then used for further analysis, including exploratory analysis, feature selection, and machine learning for disease classification.</li> +</ul> +<p>By performing the stability assessment, the study was able to limit the analysis to radiomic features that were stable and reproducible, which could be of value as imaging biomarkers for disease classification. This step helped to ensure that the radiomic features used in the analysis were reliable and could provide meaningful information for disease characterization.</p> +<h2 id="what-specific-machine-learning-algorithms-were-used-in-this-study-for-feature-selection-and-classification-of-cardiac-disease-phenotype"><a href="https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/#what-specific-machine-learning-algorithms-were-used-in-this-study-for-feature-selection-and-classification-of-cardiac-disease-phenotype">What specific machine learning algorithms were used in this study for feature selection and classification of cardiac disease phenotype?</a></h2> +<p>The paper did not provide specific details on the machine learning algorithms used for feature selection and classification of cardiac disease phenotype. However, the paper mentioned that machine learning was used for feature selection of the best radiomic features that maximized the diagnostic value for cardiac disease classification. The paper also mentioned that a model of T1 radiomics had good diagnostic performance (AUC 0.753) for multinomial classification of disease phenotype (normal vs. LVH vs. HCM vs. cardiac amyloid). Therefore, the study used machine learning algorithms for feature selection and classification of cardiac disease phenotype, but the specific algorithms used were not mentioned in the paper.</p> + + + + Different types of Zero Knowledge Proofs (Interactive and Non-interactive) + 2023-03-02T00:00:00+00:00 + 2023-03-02T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/different-types-of-zero-knowledge-proofs/ + <h1 id="overview">Overview</h1> +<p>Zero knowledge proofs (ZKP) are cryptographic protocols that enable one party (the prover) to prove to another party (the verifier) the truth of a statement without revealing any additional information beyond the statement's validity. ZKPs are incredibly useful in scenarios where confidentiality is paramount, such as digital identity verification, electronic voting systems, and secure communication protocols.</p> +<p>There are two types of zero-knowledge proofs: interactive and non-interactive. In this article, we will explore these two types in-depth, including their differences, advantages, and applications.</p> +<h1 id="interactive-zero-knowledge-proofs">Interactive Zero Knowledge Proofs</h1> +<p>Interactive zero-knowledge proofs require communication between the prover and the verifier. The prover and verifier engage in a back-and-forth interaction where the prover sends a series of messages to the verifier. The verifier responds with a challenge message based on the previous messages, and the prover then responds with a corresponding message. This process continues until the verifier is convinced of the statement's truth.</p> +<p>The interactive nature of ZKPs makes them more secure than non-interactive ones since the verifier can adapt its challenges to the prover's behavior, reducing the chance of a successful attack. The downside is that they can be more time-consuming and require more computational resources.</p> +<p>Here are a few examples of interactive zero-knowledge proof algorithms:</p> +<h2 id="schnorr-protocol">Schnorr Protocol</h2> +<p>The Schnorr protocol is an interactive zero-knowledge proof that enables the prover to demonstrate knowledge of a private key associated with a public key without revealing the private key itself. This protocol is used in digital signatures, where the prover must prove they have the private key without revealing it to the verifier.</p> +<p>The protocol works as follows:</p> +<ol> +<li>Commitment:</li> +</ol> +<p>The prover randomly selects a secret value r from the finite field and computes a commitment $ C = g^r$, where $g$ is a generator of the group. The prover sends $C$ to the verifier.</p> +<ol start="2"> +<li>Challenge:</li> +</ol> +<p>The verifier selects a random challenge value e from the finite field and sends it to the prover.</p> +<ol start="3"> +<li>Response:</li> +</ol> +<p>The prover computes the response value $s = r + ex$, where $x$ is the private key corresponding to a public key $y = xg$. The prover sends $s$ to the verifier.</p> +<ol start="4"> +<li>Verification:</li> +</ol> +<p>The verifier checks the validity of the proof by computing $C' = g^s * y^(-e)$, where $y$ is the public key corresponding to the secret key $x$ . If $C' = C$ , the proof is considered valid.</p> +<p>The Schnorr protocol is a non-interactive zero-knowledge proof, meaning that it requires only one message exchange between the prover and verifier. The proof demonstrates that the prover knows the secret key $x$ corresponding to a public key $y$, without revealing any information about $x$ . The protocol is used in various applications, such as digital signatures and authentication schemes.</p> +<p>In summary, the Schnorr zero-knowledge proof protocol works by the prover committing to a secret value, the verifier selecting a random challenge, the prover responding with a value that incorporates both the challenge and the secret, and the verifier checking the validity of the proof using the commitment, the response, and the public key.</p> +<h2 id="zcash-protocol">Zcash Protocol</h2> +<p>The Zcash protocol is an interactive zero-knowledge proof that allows users to prove that a transaction has taken place without revealing the sender, recipient, or transaction amount. The Zcash cryptocurrency uses this protocol to maintain privacy and anonymity in its transactions.</p> +<p>The protocol works as follows:</p> +<ol> +<li>Circuit setup:</li> +</ol> +<p>The prover and verifier agree on a public Boolean circuit that represents the computation that the prover wants to prove. The circuit is transformed into an arithmetic circuit over a finite field, using techniques such as universal circuit constructions.</p> +<ol start="2"> +<li>Input and output encoding:</li> +</ol> +<p>The prover encodes the input and output values of the circuit as elements of the finite field, using techniques such as binary encoding or representation as elliptic curve points. The encoding ensures that the input and output values can be processed by the arithmetic circuit.</p> +<ol start="3"> +<li>Constraint system generation:</li> +</ol> +<p>The prover generates a constraint system that enforces the constraints of the circuit on the input and output values, using techniques such as the Rank 1 Constraint System (R1CS). The constraint system consists of a set of equations that relate the input and output values to intermediate values computed by the circuit.</p> +<ol start="4"> +<li>Public parameters generation:</li> +</ol> +<p>The prover generates a set of public parameters that enable the verifier to check the validity of the proof, without revealing any information about the input and output values. The public parameters consist of a set of group elements and auxiliary data that encode the constraints of the constraint system.</p> +<ol start="5"> +<li>Proving key generation:</li> +</ol> +<p>The prover generates a proving key that enables them to construct a proof of correctness for any input and output values that satisfy the constraint system. The proving key consists of a set of group elements that encode the witness values of the constraint system, which are the values that satisfy the constraints.</p> +<ol start="6"> +<li>Proof construction:</li> +</ol> +<p>The prover constructs a proof of correctness for the input and output values, using the proving key and the public parameters. The proof consists of a set of group elements that encode the intermediate values of the constraint system, and a set of auxiliary data that enable the verifier to check the consistency of the proof.</p> +<ol start="7"> +<li>Proof verification:</li> +</ol> +<p>The verifier checks the validity of the proof, using the public parameters and the proof. The verification process involves checking the consistency of the intermediate values, the satisfiability of the constraints, and the knowledge of the witness values.</p> +<p>If the proof is valid, the verifier is convinced that the prover knows the witness values of the constraint system and has performed the computation correctly, without revealing any information about the witness values or the input and output values. Zcash achieves zero-knowledge properties by using the R1CS constraint system and public key cryptography to encode the constraints and the witness values, and by using efficient cryptographic primitives such as the Groth16 proof system to construct and verify the proofs. The protocol is used in the Zcash cryptocurrency system to enable private transactions that hide the sender, recipient, and amount of the transaction.</p> +<h1 id="non-interactive-zero-knowledge-proofs">Non-Interactive Zero Knowledge Proofs</h1> +<p>Non-interactive zero-knowledge proofs require no interaction between the prover and verifier. The prover creates a proof based on a statement and sends it to the verifier, who verifies its validity. The proof is created by hashing the statement and using a cryptographic algorithm to generate a proof that can be verified using a public key.</p> +<p>Non-interactive ZKPs are faster and require fewer computational resources than interactive ones, but they are less secure since the verifier cannot adapt its challenges to the prover's behavior.</p> +<p>Here are a few examples of non-interactive zero-knowledge proof algorithms:</p> +<h2 id="fiat-shamir-transform">Fiat-Shamir Transform</h2> +<p>The Fiat-Shamir transform is a non-interactive zero-knowledge proof that enables the prover to prove the knowledge of a witness to a statement without interacting with the verifier. This proof is widely used in electronic voting systems, where a voter wants to prove that their vote was correctly recorded without revealing their identity.</p> +<p>The protocol works as follows:</p> +<ol> +<li>The prover selects a random number $r$ and calculates a commitment value $c = H(s || r)$, where $s$ is the witness value.</li> +<li>The prover sends $c$ to the verifier.</li> +<li>The verifier generates a challenge value $e = H(c)$ and sends it to the prover.</li> +<li>The prover calculates the response value $z = r + e*s$ and sends $z$ to the verifier.</li> +<li>The verifier checks that $c = H(s || (z - e * commitment_value))$, where $commitment_value$ is a publicly known value.</li> +</ol> +<p>If the equation holds, the verifier is convinced that the prover knows the witness value $s$ without revealing it.</p> +<h2 id="bulletproofs">Bulletproofs</h2> +<p>Bulletproofs are non-interactive zero-knowledge proofs that are used to verify the validity of range proofs in cryptocurrency transactions. A range proof is a proof that a secret value lies within a certain range.</p> +<p>Bulletproofs are particularly useful in scenarios where computational resources are limited since they can generate smaller proofs than other non-interactive protocols.</p> +<p>The protocol works as follows:</p> +<ol> +<li>Range proof setup:</li> +</ol> +<p>The prover and verifier agree on a range of values that the prover wants to prove, such as the range of a secret value or the range of a transaction amount in a cryptocurrency system. They also agree on a security parameter that determines the soundness and efficiency of the proof.</p> +<ol start="2"> +<li>Pedersen commitment:</li> +</ol> +<p>The prover commits to a value that lies within the range, using a Pedersen commitment scheme that combines the value with a randomly chosen blinding factor. The commitment consists of two group elements, $C = aG + bH$, where $G$ and $H$ are generators of a prime order group, $a$ is the value to be committed, and $b$ is the blinding factor.</p> +<ol start="3"> +<li>Polynomial construction:</li> +</ol> +<p>The prover constructs a polynomial that represents the commitment value, using techniques such as Lagrange interpolation or polynomial division. The polynomial has a degree that is logarithmic in the size of the range.</p> +<ol start="4"> +<li>Inner product argument:</li> +</ol> +<p>The prover constructs an inner product argument that proves the knowledge of two vectors, consisting of the coefficients of the polynomial and the blinding factors. The argument consists of a constant number of group elements, regardless of the size of the vectors.</p> +<ol start="5"> +<li>Range proof verification:</li> +</ol> +<p>The verifier checks whether the commitment value lies within the agreed range, using a combination of range tests and linear equations that depend on the inner product argument. The range tests ensure that the committed value is non-negative and within the specified range, while the linear equations ensure that the commitment value is constructed correctly.</p> +<ol start="6"> +<li>Recursive proof composition:</li> +</ol> +<p>To prove the validity of multiple range proofs, the prover and verifier can recursively compose the inner product arguments and the range tests, by constructing a Merkle tree of the proofs and their associated commitments, and using a single proof and commitment pair as input to the next round.</p> +<p>If all checks pass, the verifier is convinced that the prover knows a value within the agreed range, without revealing any information about the value or the blinding factor. Bulletproofs achieve zero-knowledge properties by using polynomial constructions and inner product arguments that hide the committed value and the blinding factor, and by using recursive proof composition to reduce the size of the proofs and commitments. The protocol is widely used in privacy-preserving applications, such as ring signatures and confidential transactions in cryptocurrency systems.</p> +<h2 id="sonic">Sonic</h2> +<p>Sonic is a non-interactive zero-knowledge proof protocol designed to verify the correctness of computations on private data, such as those performed by smart contracts in blockchain systems. It is known for its efficiency and scalability, making it suitable for large-scale applications.</p> +<p>The protocol works as follows:</p> +<ol> +<li>Circuit setup:</li> +</ol> +<p>The prover and verifier agree on a public Boolean circuit that represents the computation that the prover wants to prove. The circuit is transformed into an arithmetic circuit over a finite field, using techniques such as universal circuit constructions.</p> +<ol start="2"> +<li>Polynomial commitment:</li> +</ol> +<p>The prover commits to a set of polynomials that correspond to the input and output wires of the circuit, using polynomial commitment schemes such as KZG or FFT-based schemes. The commitment consists of a set of group elements that encode the coefficients of the polynomials.</p> +<ol start="3"> +<li>Polynomial evaluation:</li> +</ol> +<p>The prover evaluates the committed polynomials at random field elements, and generates a set of proof values that encode the results of the computation at each gate of the circuit. The proof values consist of group elements that are generated by evaluating linear combinations of the commitment values at the random field elements.</p> +<ol start="4"> +<li>Fast Fourier transform:</li> +</ol> +<p>The prover performs a fast Fourier transform on the proof values, in order to convert them into a form that enables efficient verification using low-degree polynomial evaluations.</p> +<ol start="5"> +<li>Random sampling:</li> +</ol> +<p>The verifier randomly samples a subset of the proof values, and sends the sample points to the prover as a challenge.</p> +<ol start="6"> +<li>Polynomial interpolation:</li> +</ol> +<p>The prover interpolates a low-degree polynomial that matches the sample points and the committed polynomials, using techniques such as Lagrange interpolation or polynomial division.</p> +<ol start="7"> +<li>Polynomial evaluation check:</li> +</ol> +<p>The verifier checks whether the polynomial interpolation matches the proof values at all other points, using techniques such as Reed-Solomon decoding or polynomial evaluation over multiple field extensions.</p> +<ol start="8"> +<li>Circuit check:</li> +</ol> +<p>The verifier checks whether the computed output values match the desired output values of the circuit, using techniques such as binary decision diagrams or straight-line programs.</p> +<p>If all checks pass, the verifier is convinced that the prover knows the input values of the circuit and has performed the computation correctly, without revealing any information about the input values. Sonic achieves zero-knowledge properties by using polynomial commitments to hide the input values and fast Fourier transforms to enable efficient verification. The protocol is particularly suitable for verifying computations on private data, such as those performed by smart contracts in blockchain systems.</p> +<h2 id="groth16">Groth16</h2> +<p>Groth16 is a non-interactive zero-knowledge proof protocol that is commonly used in privacy-preserving applications, such as anonymous credential systems and private transactions in cryptocurrency systems. It is known for its high efficiency and security, making it a popular choice for large-scale applications.</p> +<p>The protocol works as follows:</p> +<ol> +<li>Setup:</li> +</ol> +<p>The prover and verifier agree on a set of elliptic curve parameters, including a prime order group $G$ and a pairing function $e$ that maps elements from $G$ to the multiplicative group of a finite field. They also agree on a public statement that the prover wants to prove, such as the validity of a transaction or the possession of a private key.</p> +<ol start="2"> +<li>Key generation:</li> +</ol> +<p>The prover generates a private key and a corresponding public key. The public key consists of two group elements, $P$ and $Q$, such that $Q = kP$ for some secret scalar $k$.</p> +<ol start="3"> +<li>Commitment:</li> +</ol> +<p>The prover commits to a witness value that satisfies the public statement, such as a transaction input and output or a private key value. The commitment consists of two group elements, $C$ and $D$, such that $C = rP + W$ and $D = rQ$, where $r$ is a randomly chosen scalar and $W$ is the witness value.</p> +<ol start="4"> +<li>Challenge:</li> +</ol> +<p>The verifier generates a random challenge value, $c$, from a secure hash function applied to the public parameters and the commitment values, $c = H(G, e, P, Q, C, D)$.</p> +<ol start="5"> +<li>Response:</li> +</ol> +<p>The prover calculates a response value, $s$, based on the challenge value and the private key, $s = r + kc$, where $k$ is the private key scalar.</p> +<ol start="6"> +<li>Verification:</li> +</ol> +<p>The verifier checks whether the commitment and response values satisfy the public statement, by verifying the following equations:</p> +<p>$e(C, P) = e(D, Q) + e(sP + cW, P)$</p> +<p>This equation ensures that the commitment values are valid and that the response value corresponds to the private key scalar and witness value. If the equation holds, the verifier is convinced that the prover knows the private key and the witness value, without revealing any information about them.</p> +<p>Groth16 achieves zero-knowledge properties by using the pairing function to hide the witness value in the commitment value, and by using the random challenge value to prevent the prover from reusing a previous response value. This protocol is widely used in privacy-preserving applications, such as anonymous credential systems and private transactions in cryptocurrency systems.</p> +<h2 id="aurora">Aurora</h2> +<p>Aurora is a non-interactive zero-knowledge proof protocol designed to verify the validity of computations performed on encrypted data. It is useful in scenarios where multiple parties want to perform computations on sensitive data without revealing the data to each other.</p> +<p>The protocol works as follows:</p> +<ol> +<li>The parties encrypt their data using a public key.</li> +<li>Each party generates a proof of correctness for their computation on the encrypted data.</li> +<li>The verifier checks the proofs to ensure that the computations were performed correctly without revealing any information about the data.</li> +</ol> +<p>Aurora achieves zero-knowledge properties through a combination of homomorphic encryption, zero-knowledge proofs, and other advanced cryptographic techniques.</p> +<h1 id="conclusion">Conclusion</h1> +<p>In conclusion, zero-knowledge proofs are an essential tool in modern cryptography, providing secure and confidential communication protocols in various domains, including digital identity verification, electronic voting systems, and cryptocurrency transactions. Interactive zero-knowledge proofs are more secure but require more computational resources, while non-interactive ones are faster but less secure. It is essential to choose the appropriate type of ZKP for the specific use case, balancing security and performance.</p> + + + + Explanation of the Concept of Zero Knowledge Proofs + 2023-03-01T00:00:00+00:00 + 2023-03-01T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/explanation-of-the-concept-of-zero-knowledge-proofs/ + <h2 id="overview">Overview</h2> +<p>Zero-knowledge proofs (ZKPs) are a groundbreaking concept in cryptography that allows one party to prove to another that a statement is true, without revealing any specific information about the statement itself. This technique is particularly useful in preserving privacy and security in various applications, such as authentication, secure voting systems, and blockchain technology.</p> +<h2 id="properties-of-zkps">Properties of ZKPs</h2> +<p>Originating in the 1980s, ZKPs were first introduced by Shafi Goldwasser, Silvio Micali, and Charles Rackoff. The concept is based on three crucial properties:</p> +<ol> +<li>Completeness: If the statement is true, an honest verifier will always be convinced by a genuine prover.</li> +<li>Soundness: If the statement is false, a dishonest prover cannot convince an honest verifier that it is true.</li> +<li>Zero-knowledge: The verifier gains no additional knowledge about the statement other than its validity.</li> +</ol> +<h2 id="concept-explanation">Concept Explanation</h2> +<p>To illustrate the concept, consider the following analogy: Imagine two individuals, Peggy (the prover) and Victor (the verifier). Peggy wants to convince Victor that she knows the password to a secret vault without revealing the password itself. They use ZKP in the following manner:</p> +<ol> +<li>Peggy enters the vault and locks the door from inside.</li> +<li>Victor randomly chooses one of two possible exit routes (A or B) for Peggy to leave the vault.</li> +<li>Peggy exits the vault through the chosen route, proving she knows the password without revealing it.</li> +</ol> +<p>This process is repeated multiple times, increasing Victor's confidence in Peggy's knowledge of the password. Importantly, Victor learns nothing about the password itself.</p> +<p>In real-world applications, ZKPs are implemented using complex mathematical algorithms and cryptographic techniques. One popular implementation is zk-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge), which is used in various blockchain platforms to ensure privacy and security.</p> +<h2 id="benefits-of-zkps">Benefits of ZKPs</h2> +<p>ZKPs offer several benefits, including:</p> +<ol> +<li>Enhanced Privacy: Sensitive information remains concealed, protecting users' privacy in various applications, such as online transactions and identity verification.</li> +<li>Security: ZKPs reduce the risk of data breaches and identity theft, as sensitive information is never directly shared.</li> +<li>Scalability: ZKPs can be designed to be computationally efficient, making them suitable for large-scale systems, such as blockchain networks.</li> +</ol> +<h2 id="challenges-of-zkps">Challenges of ZKPs</h2> +<p>Despite their advantages, ZKPs also have some limitations:</p> +<ol> +<li>Complexity: Implementing ZKPs requires advanced knowledge of cryptography and mathematics, which can be a barrier for some developers.</li> +<li>Performance: Some ZKP systems may require significant computational resources, potentially affecting the performance of the underlying application.</li> +</ol> +<h2 id="conclusion">Conclusion</h2> +<p>In conclusion, zero-knowledge proofs are a powerful cryptographic tool that allows for secure and private verification of information. While they do have some limitations, their potential applications in various domains, such as finance, healthcare, and voting systems, make them an essential component of modern privacy and security solutions.</p> + + + + A brief introduction to Zero Knowledge Proofs (ZKPs) + 2022-12-25T00:00:00+00:00 + 2022-12-25T00:00:00+00:00 + + Unknown + + + https://thogiti.github.io/intro-zkps/ + <ol> +<li>Introduction +<ul> +<li>A. Definition of Zero Knowledge Proofs (ZKPs)</li> +<li>B. Overview of the Benefits of Using ZKPs</li> +</ul> +</li> +<li>How ZKPs Work +<ul> +<li>A. Overview of the ZKP Process</li> +<li>B. Explanation of the Three Stages of the ZKP Process</li> +</ul> +</li> +<li>Applications of ZKPs +<ul> +<li>A. Cryptocurrency Transactions</li> +<li>B. Identity Management</li> +<li>C. Data Privacy</li> +</ul> +</li> +<li>Challenges with ZKPs +<ul> +<li>A. ODifficulty of Implementation</li> +<li>B. Security and Privacy Concerns</li> +</ul> +</li> +<li>Conclusion +<ul> +<li>A. Summary of ZKP Benefits</li> +<li>B. Outlook on Future of ZKPs</li> +</ul> +</li> +</ol> +<h2 id="overview">Overview</h2> +<p>Zero knowledge proofs (ZKPs) are a powerful technique that allows one person (the prover) to prove to another (the verifier) that they have specific information without actually providing it. Although this idea may seem unusual at first, it has significant implications in the world of cryptography and can be applied to improve the security and privacy of a variety of systems.</p> +<p>ZKPs' &quot;non-interactivity&quot; is one of its fundamental characteristics. As a result, the prover can produce a proof and submit it to the verifier, who can then independently assess the proof's veracity without additional communication. This contrasts with other kinds of proofs, which frequently need for back-and-forth communication between the prover and verifier. </p> +<p>Imagine a person attempting to prove to a bank that they have a certain amount of money in their account without disclosing the exact amount. The individual could show the bank proof that they have at least a certain amount of money without disclosing the exact amount. This would allow the bank to confirm that the person has sufficient funds without learning the details of the person's financial situation. </p> +<p>ZKPs can be built in a variety of ways and used to prove a wide variety of statements. Some common examples include demonstrating that a person knows the solution to a specific problem (such as a password or a puzzle), demonstrating that a person has access to specific data (such as a private key or a document), or demonstrating that a person has performed a specific computation (e.g. a hash function). </p> +<p>There has been a great deal of interest in implementing ZKPs in the Rust programming language in recent years. Rust is a systems programming language that is intended to be safe, concurrent, and fast. It has a growing ecosystem of libraries and tools and is being used in a variety of applications, including blockchain technologies and other security-critical systems. </p> +<p>Rust is an excellent choice for implementing ZKPs for a variety of reasons. Here are three important explanations:</p> +<ul> +<li>For starters, Rust has strong support for low-level programming and memory safety, both of which are critical for implementing complex cryptographic algorithms.</li> +<li>Second, Rust places a strong emphasis on concurrency and parallelism, which can be useful for optimizing the performance of ZKPs.</li> +<li>Finally, Rust has a growing developer community and a well-documented API, which makes building and maintaining ZKP implementations easier. </li> +</ul> +<p>There are already a number of Rust libraries and projects that support ZKPs, such as libzkp, zkp-toolkit, and bellman. These libraries offer a variety of features and support for various ZKP constructions, and can be used to create a wide range of ZKP-based applications. </p> +<p>To summarize, zero knowledge proofs are a powerful tool that can be used to improve the security and privacy of a variety of systems. Because of its emphasis on safety, concurrency, and performance, Rust is an excellent choice for implementing ZKPs, and there are already several libraries and projects that support ZKPs in Rust. We can expect to see even more Rust implementations and applications in the future as the use of ZKPs grows. </p> +<p>So, how do zero knowledge proofs actually work? Let's look at a small Rust example to see how this works. In this example, we will develop a zero knowledge proof that proves the truth of a specific assertion without revealing any underlying facts or information. </p> +<p>Here is the code for our zero knowledge proof:</p> +<pre data-lang="rust" style="background-color:#fefbec;color:#6e6b5e;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b854d4;">extern crate</span><span> rand; +</span><span style="color:#b854d4;">extern crate</span><span> sha2; +</span><span> +</span><span style="color:#b854d4;">use </span><span>rand::{Rng, SeedableRng, OsRng}; +</span><span style="color:#b854d4;">use </span><span>sha2::{Sha256, Digest}; +</span><span> +</span><span style="color:#999580;">// Define the statement we want to prove +</span><span style="color:#b854d4;">const </span><span style="color:#b65611;">STATEMENT</span><span>: &amp;</span><span style="color:#b854d4;">str </span><span>= &quot;</span><span style="color:#60ac39;">I possess the secret key</span><span>&quot;; +</span><span> +</span><span style="color:#999580;">// Define the secret key +</span><span style="color:#b854d4;">const </span><span style="color:#b65611;">SECRET_KEY</span><span>: &amp;[</span><span style="color:#b854d4;">u8</span><span>] = </span><span style="color:#b854d4;">b</span><span>&quot;</span><span style="color:#60ac39;">my_secret_key</span><span>&quot;; +</span><span> +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">main</span><span>() { +</span><span style="color:#999580;">// Generate a random number to use as a nonce +</span><span style="color:#b854d4;">let mut</span><span> rng = OsRng::new().</span><span style="color:#1fad83;">unwrap</span><span>(); +</span><span style="color:#b854d4;">let</span><span> nonce: </span><span style="color:#b854d4;">u64 </span><span>= rng.</span><span style="color:#1fad83;">gen</span><span>(); +</span><span style="color:#999580;">// Hash the nonce and secret key together +</span><span style="color:#b854d4;">let</span><span> input = format!(&quot;</span><span style="color:#b65611;">{}{}</span><span>&quot;, nonce, </span><span style="color:#b65611;">SECRET_KEY</span><span>); +</span><span style="color:#b854d4;">let mut</span><span> hasher = Sha256::new(); +</span><span>hasher.</span><span style="color:#1fad83;">input</span><span>(input); +</span><span style="color:#b854d4;">let</span><span> hash = hasher.</span><span style="color:#1fad83;">result</span><span>(); +</span><span> +</span><span style="color:#999580;">// Generate a proof by hashing the statement and the hash together +</span><span style="color:#b854d4;">let</span><span> input = format!(&quot;</span><span style="color:#b65611;">{}{}</span><span>&quot;, </span><span style="color:#b65611;">STATEMENT</span><span>, hash); +</span><span style="color:#b854d4;">let mut</span><span> hasher = Sha256::new(); +</span><span>hasher.</span><span style="color:#1fad83;">input</span><span>(input); +</span><span style="color:#b854d4;">let</span><span> proof = hasher.</span><span style="color:#1fad83;">result</span><span>(); +</span><span> +</span><span style="color:#999580;">// Send the proof to the verifier +</span><span style="color:#b854d4;">let</span><span> verifier = Verifier::new(); +</span><span style="color:#b854d4;">let</span><span> result = verifier.</span><span style="color:#1fad83;">verify</span><span>(proof, </span><span style="color:#b65611;">STATEMENT</span><span>, </span><span style="color:#b65611;">SECRET_KEY</span><span>); +</span><span> +</span><span style="color:#999580;">// Print the result +</span><span>println!(&quot;</span><span style="color:#60ac39;">Verification result: </span><span style="color:#b65611;">{}</span><span>&quot;, result); +</span><span>} +</span><span> +</span><span style="color:#b854d4;">struct </span><span>Verifier { +</span><span> </span><span style="color:#d73737;">secret_key</span><span>: &amp;</span><span style="color:#b854d4;">&#39;static</span><span> [</span><span style="color:#b854d4;">u8</span><span>], +</span><span>} +</span><span> +</span><span style="color:#b854d4;">impl </span><span>Verifier { +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">new</span><span>() -&gt; Verifier { +</span><span> Verifier { secret_key: </span><span style="color:#b65611;">SECRET_KEY </span><span>} +</span><span>} +</span><span> +</span><span style="color:#b854d4;">fn </span><span style="color:#6684e1;">verify</span><span>(&amp;</span><span style="color:#d73737;">self</span><span>, </span><span style="color:#d73737;">proof</span><span>: Digest, </span><span style="color:#d73737;">statement</span><span>: &amp;</span><span style="color:#b854d4;">str</span><span>, </span><span style="color:#d73737;">secret_key</span><span>: &amp;[</span><span style="color:#b854d4;">u8</span><span>]) -&gt; </span><span style="color:#b854d4;">bool </span><span>{ +</span><span> </span><span style="color:#999580;">// Hash the statement and the secret key together +</span><span> </span><span style="color:#b854d4;">let</span><span> input = format!(&quot;</span><span style="color:#b65611;">{}{}</span><span>&quot;, statement, secret_key); +</span><span> </span><span style="color:#b854d4;">let mut</span><span> hasher = Sha256::new(); +</span><span> hasher.</span><span style="color:#1fad83;">input</span><span>(input); +</span><span> </span><span style="color:#b854d4;">let</span><span> hash = hasher.</span><span style="color:#1fad83;">result</span><span>(); +</span><span> +</span><span> </span><span style="color:#999580;">// Check if the proof matches the hash +</span><span> proof == hash +</span><span>} +</span><span>} +</span><span> +</span></code></pre> +<p>In this code example, we define a constant <code>STATEMENT</code> which represents the statement we want to prove. We also define a constant <code>SECRET_KEY</code> which represents the secret key that we want to prove we possess.</p> +<p>Next, we generate a random number to use as a nonce (a unique value used for one-time use) and hash it together with the secret key using the SHA-256 hash function. This creates a unique hash value that is based on both the nonce and the secret key.</p> +<p>We then generate a proof by hashing the statement and the hash value together using the SHA-256 hash function. This creates a new hash value that is based on both the statement and the original hash value.</p> +<p>We send the proof to the verifier, which then uses the secret key and the statement to recreate the original hash value. If the proof matches the original hash value, then the verifier can be confident that the prover possesses the secret key and that the statement is true.</p> +<p>In this way, zero knowledge proofs allow the prover to demonstrate the truth of a particular statement without actually revealing any of the underlying data or information. This is achieved through the use of cryptographic techniques such as hash functions and digital signatures, which allow the prover to create a proof that is verifiable by the verifier without revealing any of the underlying data or information.</p> + + + diff --git a/different-types-of-zero-knowledge-proofs/index.html b/different-types-of-zero-knowledge-proofs/index.html new file mode 100644 index 00000000..336a4d70 --- /dev/null +++ b/different-types-of-zero-knowledge-proofs/index.html @@ -0,0 +1,404 @@ + + + + + + + +Different types of Zero Knowledge Proofs (Interactive and Non-interactive) | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + +
+ +
+ +

Different types of Zero Knowledge Proofs (Interactive and Non-interactive)

+
+

Overview

+

Zero knowledge proofs (ZKP) are cryptographic protocols that enable one party (the prover) to prove to another party (the verifier) the truth of a statement without revealing any additional information beyond the statement's validity. ZKPs are incredibly useful in scenarios where confidentiality is paramount, such as digital identity verification, electronic voting systems, and secure communication protocols.

+

There are two types of zero-knowledge proofs: interactive and non-interactive. In this article, we will explore these two types in-depth, including their differences, advantages, and applications.

+

Interactive Zero Knowledge Proofs

+

Interactive zero-knowledge proofs require communication between the prover and the verifier. The prover and verifier engage in a back-and-forth interaction where the prover sends a series of messages to the verifier. The verifier responds with a challenge message based on the previous messages, and the prover then responds with a corresponding message. This process continues until the verifier is convinced of the statement's truth.

+

The interactive nature of ZKPs makes them more secure than non-interactive ones since the verifier can adapt its challenges to the prover's behavior, reducing the chance of a successful attack. The downside is that they can be more time-consuming and require more computational resources.

+

Here are a few examples of interactive zero-knowledge proof algorithms:

+

Schnorr Protocol

+

The Schnorr protocol is an interactive zero-knowledge proof that enables the prover to demonstrate knowledge of a private key associated with a public key without revealing the private key itself. This protocol is used in digital signatures, where the prover must prove they have the private key without revealing it to the verifier.

+

The protocol works as follows:

+
    +
  1. Commitment:
  2. +
+

The prover randomly selects a secret value r from the finite field and computes a commitment $ C = g^r$, where $g$ is a generator of the group. The prover sends $C$ to the verifier.

+
    +
  1. Challenge:
  2. +
+

The verifier selects a random challenge value e from the finite field and sends it to the prover.

+
    +
  1. Response:
  2. +
+

The prover computes the response value $s = r + ex$, where $x$ is the private key corresponding to a public key $y = xg$. The prover sends $s$ to the verifier.

+
    +
  1. Verification:
  2. +
+

The verifier checks the validity of the proof by computing $C' = g^s * y^(-e)$, where $y$ is the public key corresponding to the secret key $x$ . If $C' = C$ , the proof is considered valid.

+

The Schnorr protocol is a non-interactive zero-knowledge proof, meaning that it requires only one message exchange between the prover and verifier. The proof demonstrates that the prover knows the secret key $x$ corresponding to a public key $y$, without revealing any information about $x$ . The protocol is used in various applications, such as digital signatures and authentication schemes.

+

In summary, the Schnorr zero-knowledge proof protocol works by the prover committing to a secret value, the verifier selecting a random challenge, the prover responding with a value that incorporates both the challenge and the secret, and the verifier checking the validity of the proof using the commitment, the response, and the public key.

+

Zcash Protocol

+

The Zcash protocol is an interactive zero-knowledge proof that allows users to prove that a transaction has taken place without revealing the sender, recipient, or transaction amount. The Zcash cryptocurrency uses this protocol to maintain privacy and anonymity in its transactions.

+

The protocol works as follows:

+
    +
  1. Circuit setup:
  2. +
+

The prover and verifier agree on a public Boolean circuit that represents the computation that the prover wants to prove. The circuit is transformed into an arithmetic circuit over a finite field, using techniques such as universal circuit constructions.

+
    +
  1. Input and output encoding:
  2. +
+

The prover encodes the input and output values of the circuit as elements of the finite field, using techniques such as binary encoding or representation as elliptic curve points. The encoding ensures that the input and output values can be processed by the arithmetic circuit.

+
    +
  1. Constraint system generation:
  2. +
+

The prover generates a constraint system that enforces the constraints of the circuit on the input and output values, using techniques such as the Rank 1 Constraint System (R1CS). The constraint system consists of a set of equations that relate the input and output values to intermediate values computed by the circuit.

+
    +
  1. Public parameters generation:
  2. +
+

The prover generates a set of public parameters that enable the verifier to check the validity of the proof, without revealing any information about the input and output values. The public parameters consist of a set of group elements and auxiliary data that encode the constraints of the constraint system.

+
    +
  1. Proving key generation:
  2. +
+

The prover generates a proving key that enables them to construct a proof of correctness for any input and output values that satisfy the constraint system. The proving key consists of a set of group elements that encode the witness values of the constraint system, which are the values that satisfy the constraints.

+
    +
  1. Proof construction:
  2. +
+

The prover constructs a proof of correctness for the input and output values, using the proving key and the public parameters. The proof consists of a set of group elements that encode the intermediate values of the constraint system, and a set of auxiliary data that enable the verifier to check the consistency of the proof.

+
    +
  1. Proof verification:
  2. +
+

The verifier checks the validity of the proof, using the public parameters and the proof. The verification process involves checking the consistency of the intermediate values, the satisfiability of the constraints, and the knowledge of the witness values.

+

If the proof is valid, the verifier is convinced that the prover knows the witness values of the constraint system and has performed the computation correctly, without revealing any information about the witness values or the input and output values. Zcash achieves zero-knowledge properties by using the R1CS constraint system and public key cryptography to encode the constraints and the witness values, and by using efficient cryptographic primitives such as the Groth16 proof system to construct and verify the proofs. The protocol is used in the Zcash cryptocurrency system to enable private transactions that hide the sender, recipient, and amount of the transaction.

+

Non-Interactive Zero Knowledge Proofs

+

Non-interactive zero-knowledge proofs require no interaction between the prover and verifier. The prover creates a proof based on a statement and sends it to the verifier, who verifies its validity. The proof is created by hashing the statement and using a cryptographic algorithm to generate a proof that can be verified using a public key.

+

Non-interactive ZKPs are faster and require fewer computational resources than interactive ones, but they are less secure since the verifier cannot adapt its challenges to the prover's behavior.

+

Here are a few examples of non-interactive zero-knowledge proof algorithms:

+

Fiat-Shamir Transform

+

The Fiat-Shamir transform is a non-interactive zero-knowledge proof that enables the prover to prove the knowledge of a witness to a statement without interacting with the verifier. This proof is widely used in electronic voting systems, where a voter wants to prove that their vote was correctly recorded without revealing their identity.

+

The protocol works as follows:

+
    +
  1. The prover selects a random number $r$ and calculates a commitment value $c = H(s || r)$, where $s$ is the witness value.
  2. +
  3. The prover sends $c$ to the verifier.
  4. +
  5. The verifier generates a challenge value $e = H(c)$ and sends it to the prover.
  6. +
  7. The prover calculates the response value $z = r + e*s$ and sends $z$ to the verifier.
  8. +
  9. The verifier checks that $c = H(s || (z - e * commitment_value))$, where $commitment_value$ is a publicly known value.
  10. +
+

If the equation holds, the verifier is convinced that the prover knows the witness value $s$ without revealing it.

+

Bulletproofs

+

Bulletproofs are non-interactive zero-knowledge proofs that are used to verify the validity of range proofs in cryptocurrency transactions. A range proof is a proof that a secret value lies within a certain range.

+

Bulletproofs are particularly useful in scenarios where computational resources are limited since they can generate smaller proofs than other non-interactive protocols.

+

The protocol works as follows:

+
    +
  1. Range proof setup:
  2. +
+

The prover and verifier agree on a range of values that the prover wants to prove, such as the range of a secret value or the range of a transaction amount in a cryptocurrency system. They also agree on a security parameter that determines the soundness and efficiency of the proof.

+
    +
  1. Pedersen commitment:
  2. +
+

The prover commits to a value that lies within the range, using a Pedersen commitment scheme that combines the value with a randomly chosen blinding factor. The commitment consists of two group elements, $C = aG + bH$, where $G$ and $H$ are generators of a prime order group, $a$ is the value to be committed, and $b$ is the blinding factor.

+
    +
  1. Polynomial construction:
  2. +
+

The prover constructs a polynomial that represents the commitment value, using techniques such as Lagrange interpolation or polynomial division. The polynomial has a degree that is logarithmic in the size of the range.

+
    +
  1. Inner product argument:
  2. +
+

The prover constructs an inner product argument that proves the knowledge of two vectors, consisting of the coefficients of the polynomial and the blinding factors. The argument consists of a constant number of group elements, regardless of the size of the vectors.

+
    +
  1. Range proof verification:
  2. +
+

The verifier checks whether the commitment value lies within the agreed range, using a combination of range tests and linear equations that depend on the inner product argument. The range tests ensure that the committed value is non-negative and within the specified range, while the linear equations ensure that the commitment value is constructed correctly.

+
    +
  1. Recursive proof composition:
  2. +
+

To prove the validity of multiple range proofs, the prover and verifier can recursively compose the inner product arguments and the range tests, by constructing a Merkle tree of the proofs and their associated commitments, and using a single proof and commitment pair as input to the next round.

+

If all checks pass, the verifier is convinced that the prover knows a value within the agreed range, without revealing any information about the value or the blinding factor. Bulletproofs achieve zero-knowledge properties by using polynomial constructions and inner product arguments that hide the committed value and the blinding factor, and by using recursive proof composition to reduce the size of the proofs and commitments. The protocol is widely used in privacy-preserving applications, such as ring signatures and confidential transactions in cryptocurrency systems.

+

Sonic

+

Sonic is a non-interactive zero-knowledge proof protocol designed to verify the correctness of computations on private data, such as those performed by smart contracts in blockchain systems. It is known for its efficiency and scalability, making it suitable for large-scale applications.

+

The protocol works as follows:

+
    +
  1. Circuit setup:
  2. +
+

The prover and verifier agree on a public Boolean circuit that represents the computation that the prover wants to prove. The circuit is transformed into an arithmetic circuit over a finite field, using techniques such as universal circuit constructions.

+
    +
  1. Polynomial commitment:
  2. +
+

The prover commits to a set of polynomials that correspond to the input and output wires of the circuit, using polynomial commitment schemes such as KZG or FFT-based schemes. The commitment consists of a set of group elements that encode the coefficients of the polynomials.

+
    +
  1. Polynomial evaluation:
  2. +
+

The prover evaluates the committed polynomials at random field elements, and generates a set of proof values that encode the results of the computation at each gate of the circuit. The proof values consist of group elements that are generated by evaluating linear combinations of the commitment values at the random field elements.

+
    +
  1. Fast Fourier transform:
  2. +
+

The prover performs a fast Fourier transform on the proof values, in order to convert them into a form that enables efficient verification using low-degree polynomial evaluations.

+
    +
  1. Random sampling:
  2. +
+

The verifier randomly samples a subset of the proof values, and sends the sample points to the prover as a challenge.

+
    +
  1. Polynomial interpolation:
  2. +
+

The prover interpolates a low-degree polynomial that matches the sample points and the committed polynomials, using techniques such as Lagrange interpolation or polynomial division.

+
    +
  1. Polynomial evaluation check:
  2. +
+

The verifier checks whether the polynomial interpolation matches the proof values at all other points, using techniques such as Reed-Solomon decoding or polynomial evaluation over multiple field extensions.

+
    +
  1. Circuit check:
  2. +
+

The verifier checks whether the computed output values match the desired output values of the circuit, using techniques such as binary decision diagrams or straight-line programs.

+

If all checks pass, the verifier is convinced that the prover knows the input values of the circuit and has performed the computation correctly, without revealing any information about the input values. Sonic achieves zero-knowledge properties by using polynomial commitments to hide the input values and fast Fourier transforms to enable efficient verification. The protocol is particularly suitable for verifying computations on private data, such as those performed by smart contracts in blockchain systems.

+

Groth16

+

Groth16 is a non-interactive zero-knowledge proof protocol that is commonly used in privacy-preserving applications, such as anonymous credential systems and private transactions in cryptocurrency systems. It is known for its high efficiency and security, making it a popular choice for large-scale applications.

+

The protocol works as follows:

+
    +
  1. Setup:
  2. +
+

The prover and verifier agree on a set of elliptic curve parameters, including a prime order group $G$ and a pairing function $e$ that maps elements from $G$ to the multiplicative group of a finite field. They also agree on a public statement that the prover wants to prove, such as the validity of a transaction or the possession of a private key.

+
    +
  1. Key generation:
  2. +
+

The prover generates a private key and a corresponding public key. The public key consists of two group elements, $P$ and $Q$, such that $Q = kP$ for some secret scalar $k$.

+
    +
  1. Commitment:
  2. +
+

The prover commits to a witness value that satisfies the public statement, such as a transaction input and output or a private key value. The commitment consists of two group elements, $C$ and $D$, such that $C = rP + W$ and $D = rQ$, where $r$ is a randomly chosen scalar and $W$ is the witness value.

+
    +
  1. Challenge:
  2. +
+

The verifier generates a random challenge value, $c$, from a secure hash function applied to the public parameters and the commitment values, $c = H(G, e, P, Q, C, D)$.

+
    +
  1. Response:
  2. +
+

The prover calculates a response value, $s$, based on the challenge value and the private key, $s = r + kc$, where $k$ is the private key scalar.

+
    +
  1. Verification:
  2. +
+

The verifier checks whether the commitment and response values satisfy the public statement, by verifying the following equations:

+

$e(C, P) = e(D, Q) + e(sP + cW, P)$

+

This equation ensures that the commitment values are valid and that the response value corresponds to the private key scalar and witness value. If the equation holds, the verifier is convinced that the prover knows the private key and the witness value, without revealing any information about them.

+

Groth16 achieves zero-knowledge properties by using the pairing function to hide the witness value in the commitment value, and by using the random challenge value to prevent the prover from reusing a previous response value. This protocol is widely used in privacy-preserving applications, such as anonymous credential systems and private transactions in cryptocurrency systems.

+

Aurora

+

Aurora is a non-interactive zero-knowledge proof protocol designed to verify the validity of computations performed on encrypted data. It is useful in scenarios where multiple parties want to perform computations on sensitive data without revealing the data to each other.

+

The protocol works as follows:

+
    +
  1. The parties encrypt their data using a public key.
  2. +
  3. Each party generates a proof of correctness for their computation on the encrypted data.
  4. +
  5. The verifier checks the proofs to ensure that the computations were performed correctly without revealing any information about the data.
  6. +
+

Aurora achieves zero-knowledge properties through a combination of homomorphic encryption, zero-knowledge proofs, and other advanced cryptographic techniques.

+

Conclusion

+

In conclusion, zero-knowledge proofs are an essential tool in modern cryptography, providing secure and confidential communication protocols in various domains, including digital identity verification, electronic voting systems, and cryptocurrency transactions. Interactive zero-knowledge proofs are more secure but require more computational resources, while non-interactive ones are faster but less secure. It is essential to choose the appropriate type of ZKP for the specific use case, balancing security and performance.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/index.html b/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/index.html new file mode 100644 index 00000000..b6e6dcd8 --- /dev/null +++ b/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/index.html @@ -0,0 +1,301 @@ + + + + + + + +Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve

+
+

In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications hackmd.io/@jpw. We will exploit the fact that $(p−1)/2$ is odd to compute the Frobenius automorphism efficiently.

+

What is Frobenius Automorphism?

+

The Frobenius automorphism is an endomorphism that maps a point $(x,y)$ on an elliptic curve defined over a prime field $F_p$ to $(x^p,y^p)$. It is an important property of elliptic curves over finite fields and has various applications in cryptography math.stackexchange.com.

+

Efficient Computation Using Exponentiation by Squaring

+

To compute the Frobenius automorphism efficiently, we will use the exponentiation by squaring technique. This method allows us to compute $x^p$ and $y^p$ more efficiently by exploiting the fact that $(p−1)/2$ is odd.

+

Let's walk through the implementation step by step:

+

Step 1: Define the prime $p$ and the curve constant $b$

+

We first define the prime $p$ and the curve constant $b$, which are the parameters for the BN254 elliptic curve.

+
p = 16798108731015832284940804142231733909889187121439069848933715426072753864723
+b = 3
+
+

Step 2: Construct the elliptic curve $E$ over $F_p$

+

Next, we construct the elliptic curve $E$ over the finite field $F_p$.

+
F_p = GF(p)
+E = EllipticCurve(F_p, [0, b])
+
+

Step 3: Frobenius automorphism using exponentiation by squaring technique

+

We define the Frobenius automorphism by using the property of the prime field and the exponentiation by squaring technique. The exponentiation_by_squaring function computes the result of $x^n % mod$ efficiently.

+
def exponentiation_by_squaring(x, n, mod):
+    result = 1
+    while n > 0:
+        if n % 2 == 1:
+            result = (result * x) % mod
+        x = (x * x) % mod
+        n //= 2
+    return result
+
+def frobenius_on_curve_efficient(P):
+    x, y = P.xy()
+    x_frob = exponentiation_by_squaring(x, p, p)
+    y_frob = exponentiation_by_squaring(y, p, p)
+    return E.point([x_frob, y_frob])
+
+

Step 4: Apply the Frobenius automorphism to a point on the curve

+

Finally, we apply the Frobenius automorphism to a random point $P$ on the elliptic curve.

+
P = E.random_point()
+frob_P_efficient = frobenius_on_curve_efficient(P)
+
+print(f"Point P: {P}")
+print(f"Frobenius(P) (efficient): {frob_P_efficient}")
+
+

Here is the complete code github.com/thogiti for the efficient computation of Frobenius Automorphism on BN254 elliptic curve:

+
# BN254 curve is a pairing-friendly curve defined over a prime field $F_p$, where $p$ is a 254-bit prime. 
+# The curve equation is $y^2=x^3+b$, where $b$ is a curve constant.
+
+# Define the prime $p$ and the curve constant $b$
+p = 16798108731015832284940804142231733909889187121439069848933715426072753864723
+b = 3
+
+# Construct the elliptic curve $E$ over $F_p$
+F_p = GF(p)
+E = EllipticCurve(F_p, [0, b])
+
+# Define the Frobenius automorphism for the elliptic curve using the property of the prime field and the exponentiation by squaring technique
+def exponentiation_by_squaring(x, n, mod):
+    result = 1
+    while n > 0:
+        if n % 2 == 1:
+            result = (result * x) % mod
+        x = (x * x) % mod
+        n //= 2
+    return result
+
+def frobenius_on_curve_efficient(P):
+    x, y = P.xy()
+    x_frob = exponentiation_by_squaring(x, p, p)
+    y_frob = exponentiation_by_squaring(y, p, p)
+    return E.point([x_frob, y_frob])
+
+# Apply the Frobenius automorphism to a point on the curve
+P = E.random_point()
+frob_P_efficient = frobenius_on_curve_efficient(P)
+
+print(f"Point P: {P}")
+print(f"Frobenius(P) (efficient): {frob_P_efficient}")
+
+
+

Here is the link to the github repo which implements the efficient computation of Frobenius Automorphism on BN254 Elliptic Curve, the complete code, explanations and instructions github.com/thogiti.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/enhancing-ethereum-scalability-with-product-codes-and-danksharding/index.html b/enhancing-ethereum-scalability-with-product-codes-and-danksharding/index.html new file mode 100644 index 00000000..41ce1eb7 --- /dev/null +++ b/enhancing-ethereum-scalability-with-product-codes-and-danksharding/index.html @@ -0,0 +1,308 @@ + + + + + + + +Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide

+
+

This article would provide an in-depth understanding of how product codes from algebraic coding theory can be applied to Danksharding to improve Ethereum's scalability. It would cover the fundamentals of product codes, their application in Danksharding, and the potential benefits for Ethereum's network.

+ +

Product Codes and Their Relation to Danksharding in Ethereum

+

Product codes, a concept from algebraic coding theory en.wikipedia.org, can be utilized to enhance the robustness and fault tolerance of data storage and retrieval in Danksharding ethereum.org, a scalability solution for Ethereum. In this article, we will explore the relationship between product codes and Danksharding, and demonstrate how product codes can be applied to this context using SageMath, an open-source mathematics software system.

+

Product Codes in Coding Theory

+

Product codes are block codes that are formed by taking the Cartesian product of two or more simpler block codes en.wikipedia.org such as Hamming codes or Reed-Solomon codes. The resulting code has improved error-correcting capabilities compared to the individual component codes. They are used to increase the number of errors that can be corrected during data transmission. In the context of Danksharding, product codes could be used to add redundancy to data blobs, allowing for better error detection and correction in case of data corruption or loss.

+

Application of Product Codes in Danksharding

+

Consider the data organization process in Danksharding, where data is organized into large blobs that are verifiable and available without interpreting them. By using product codes, it may be possible to add redundancy to the data blobs, enhancing error detection and correction.

+

Moreover, product codes could also play a role in the coefficient extraction and data interpolation processes of Danksharding. By leveraging the algebraic properties of product codes, it may be possible to design more efficient algorithms for extracting relevant information from the data and estimating missing values in data sets.

+

SageMath Example: Implementing Product Codes

+

To demonstrate the application of product codes in Danksharding, let's create a simple example using SageMath. First, we need to install SageMath and import the required libraries:

+

First, let’s create two Hamming codes over the binary field GF(2). We’ll use codeword lengths of 3 and 7 respectively:

+
C1 = codes.HammingCode(GF(2), 2)
+C2 = codes.HammingCode(GF(2), 3)
+
+
+

Next, we’ll combine these two Hamming codes to form a product code:

+
C_product = C1.product_code(C2)
+
+
+

Now let’s generate a random data vector of appropriate length and encode it using our product code:

+
data_blob = random_vector(C_product.base_field(), C_product.dimension()) 
+
+encoded_blob = C_product.encode(data_blob)
+
+
+

We’ll set the error rate for our communication channel to 3:

+
err = 3
+
+
+

Now we can create a communication channel with a static error rate and transmit our encoded data through it. This will introduce errors in the transmitted data:

+
Chan = channels.StaticErrorRateChannel(C_product.ambient_space(), err)
+corrupted_blob = Chan.transmit(encoded_blob)
+
+
+

Finally, we can decode the received data using our product code’s decoding algorithm and unencode it to recover the original message:

+
decoded_blob = C_product.decode_to_code(corrupted_blob)
+
+decoded_blob_msg = C_product.unencode(decoded_blob)
+print("Are the messages same? ", decoded_blob_msg == data_blob)
+
+
+

Now, here is the complete code and the link to the github repo github.com:

+
# Create two Hamming codes over the binary field GF(2), with codeword lengths 2^2-1=3 and 2^3-1=7 respectively
+C1 = codes.HammingCode(GF(2), 2)
+C2 = codes.HammingCode(GF(2), 3)
+
+# Combine the two Hamming codes to form a product code
+C_product = C1.product_code(C2)
+
+# Generate a random data vector of appropriate length
+data_blob = random_vector(C_product.base_field(), C_product.dimension()) 
+print("data_blob: ",data_blob)
+
+# Encode the data using the product code
+encoded_blob = C_product.encode(data_blob)
+print("encoded_blob: ",encoded_blob)
+
+# Set the error rate for the communication channel
+err = 3
+
+# Create a communication channel with a static error rate
+Chan = channels.StaticErrorRateChannel(C_product.ambient_space(), err)
+
+# Transmit the encoded data through the channel, introducing errors
+corrupted_blob = Chan.transmit(encoded_blob)
+print("corrupted_blob: ", corrupted_blob)
+
+# Decode the received data using the product code's decoding algorithm
+decoded_blob = C_product.decode_to_code(corrupted_blob)
+print("decoded_blob: ",decoded_blob)
+print("Are the codes same? ", data_blob == decoded_blob)
+
+# Unencode the decoded codeword to recover the original message
+decoded_blob_msg = C_product.unencode(decoded_blob)
+print("Are the messages same? ", decoded_blob_msg == data_blob)
+
+
+

This SageMath example demonstrates how product codes can be applied to the context of Danksharding, enhancing the robustness and fault tolerance of data storage and retrieval processes.

+

In conclusion, product codes from algebraic coding theory have the potential to improve the error detection and correction capabilities of Danksharding in Ethereum. Further research and development are required to fully understand the benefits and implementation challenges of applying product codes to this context. Nonetheless, this theoretical possibility holds promise for enhancing Ethereum's scalability solutions.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/index.html b/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/index.html new file mode 100644 index 00000000..b8db9126 --- /dev/null +++ b/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/index.html @@ -0,0 +1,320 @@ + + + + + + + +Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability

+
+

Danksharding is an innovative approach to scale Ethereum's blockchain, aiming to achieve over 100,000 transactions per second by enabling rollups to add cheaper data to blocks ethereum.org. As Ethereum moves towards Proto-Danksharding and eventually full Danksharding ethereum.org, data extraction and interpolation become crucial aspects of the block-building process.

+

In this blog post, we will explore the potential of using product codes, a powerful algebraic coding theory tool, for efficient data extraction and interpolation in the context of Danksharding. We will also provide a hands-on example using SageMath to demonstrate the practical applications of product codes in this process.

+ +

What is Danksharding

+

Danksharding is a technique used in Ethereum to improve the efficiency and scalability of data storage and retrieval. The core idea behind danksharding is to distribute data across multiple shards, which allows for faster and more efficient access to specific pieces of data. One of the critical aspects of danksharding is ensuring the integrity and reliability of the data stored within the shards. This is where error-correction codes, specifically Generalized Reed-Solomon Codes (GRS), come into play.

+

Implications for Danksharding

+

As Ethereum moves towards Proto-Danksharding and full Danksharding, the importance of efficient data extraction and interpolation in the block-building process cannot be overstated coindesk.com. The use of product codes, as demonstrated in our SageMath example, offers a promising approach for addressing these challenges by harnessing their algebraic properties.

+

In particular, the error-correcting capabilities of product codes can help ensure the integrity of data in the Ethereum ecosystem, allowing full nodes to present fraud proofs and maintain transparency alchemy.com. Moreover, the structured redundancy provided by product codes can facilitate data availability sampling, a critical requirement for the development of lightweight clients and the proper functioning of Danksharding ethereum.org.

+

Product Codes in Data Extraction and Interpolation

+

The algebraic properties of product codes, such as linearity, error-correcting capabilities, and structured redundancy, can be harnessed for efficient data extraction and interpolation in the block-building process of Danksharding. These properties enable the development of techniques that extract relevant information from data sets and interpolate missing values, which are essential for ensuring data availability and integrity in the Ethereum ecosystem alchemy.com.

+

Generalized Reed-Solomon Codes

+

Generalized Reed-Solomon Codes, GRS, codes are an extension of Reed-Solomon codes wikipedia.org, which are widely used in error-correcting codes. They are particularly useful for data extraction and data interpolation stages in danksharding, as they are capable of correcting errors and filling in missing values in the data blobs math.msu.edu.

+

Data Extraction and Data Interpolation in Danksharding

+

Data extraction is the process of retrieving specific pieces of data from the shards, while data interpolation is the process of filling in missing values in the data blobs. GRS codes can be used to ensure the integrity of the data during these processes by encoding the data before storage and decoding it upon retrieval.

+

To illustrate the potential of product codes and GRS codes in the context of Danksharding, let's consider an example using SageMath SageMath.org, an open-source mathematics software system. The code is intended for use in data extraction, data interpolation stages of danksharding in Ethereum, and error corrections of data blobs arxiv.org.

+

Example of Error Correction Codes in Danksharding

+

Algebraic properties of product codes that are useful in coefficient extraction and missing data analysis include linearity, error-correcting capabilities, and structured redundancy. These properties enable efficient techniques for extracting information from data sets and interpolating missing values. In this example, we will use SageMath to demonstrate how these properties can be applied to extract coefficients and estimate missing data.

+
    +
  1. Creating the Generalized Reed-Solomon Code:
  2. +
+
C = codes.GeneralizedReedSolomonCode(GF(59).list()[1:41], 3, GF(59).list()[1:41])
+
+
+
    +
  • GF(59) creates a Galois Field of order 59
  • +
  • .list()[1:41] generates a list of elements from the Galois Field, excluding the first element (0).
  • +
  • codes.GeneralizedReedSolomonCode() creates a GRS code over the specified Galois Field with the given parameters.
  • +
+
    +
  1. Creating a random message vector and encoding it using the GRS code:
  2. +
+
msg = random_vector(C.base_field(), C.dimension())
+print("Original message:", msg)
+c = C.encode(msg)
+
+
+
    +
  1. Simulating the transmission of the encoded message with a static error rate of 3:
  2. +
+
err = 3
+Chan = channels.StaticErrorRateChannel(C.ambient_space(), err)
+Chan
+r = Chan.transmit(c)
+
+
+
    +
  1. Decoding the received message to the code and checking if it's equal to the original encoded message:
  2. +
+
c_dec = C.decode_to_code(r)
+print("Are the decoded received message to the code and the original encoded message equal?",c_dec == c)
+
+
+
    +
  1. Decoding the received message to the original message and checking if it's equal to the original message:
  2. +
+
m_unenc2 = C.decode_to_message(r)
+print("Decoded received message", m_unenc2)
+print("Are the decoded received message to the message and the original message equal?",m_unenc2 == msg)
+
+
+

Now, here is the complete code and the link to the github repo github.com:

+
# Create a Generalized Reed-Solomon Code over GF(59) with parameters
+C = codes.GeneralizedReedSolomonCode(GF(59).list()[1:41], 3, GF(59).list()[1:41])
+
+# Create a random message vector and encode it using the GRS code
+msg = random_vector(C.base_field(), C.dimension())
+print("Original message:", msg)
+c = C.encode(msg)
+
+# Simulate the transmission of the encoded message with a static error rate of 3
+err = 3
+Chan = channels.StaticErrorRateChannel(C.ambient_space(), err)
+Chan
+r = Chan.transmit(c)
+
+# Decode the received message to the code and check if it's equal to the original encoded message
+c_dec = C.decode_to_code(r)
+print("Are the decoded received message to the code and the original encoded message equal?",c_dec == c)
+
+# Decode the received message to the original message and check if it's equal to the original message
+m_unenc2 = C.decode_to_message(r)
+print("Decoded received message", m_unenc2)
+print("Are the decoded received message to the message and the original message equal?",m_unenc2 == msg)
+
+
+
+

In this example, we demonstrated the encoding, transmission, and decoding process of data using Generalized Reed-Solomon Codes for error correction which can be used to extract coefficients and estimate missing values or perform error correction in a dataset. By leveraging the algebraic properties of product codes, we can design efficient algorithms for extracting relevant information and interpolating missing values, which are crucial aspects of the block-building process in Danksharding.

+

Conclusion

+

In summary, product codes offer a powerful and efficient approach for data extraction and interpolation in the context of Danksharding, helping Ethereum achieve its scalability goals. By leveraging the algebraic properties of product codes and utilizing tools like SageMath, we can develop efficient algorithms to address the challenges associated with the block-building process in Danksharding. As Ethereum continues to evolve, the integration of product codes in the block-building process will be instrumental in realizing the full potential of Danksharding and achieving a truly scalable blockchain.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/explanation-of-the-concept-of-zero-knowledge-proofs/index.html b/explanation-of-the-concept-of-zero-knowledge-proofs/index.html new file mode 100644 index 00000000..6cc9bcbf --- /dev/null +++ b/explanation-of-the-concept-of-zero-knowledge-proofs/index.html @@ -0,0 +1,256 @@ + + + + + + + +Explanation of the Concept of Zero Knowledge Proofs | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Explanation of the Concept of Zero Knowledge Proofs

+
+

Overview

+

Zero-knowledge proofs (ZKPs) are a groundbreaking concept in cryptography that allows one party to prove to another that a statement is true, without revealing any specific information about the statement itself. This technique is particularly useful in preserving privacy and security in various applications, such as authentication, secure voting systems, and blockchain technology.

+

Properties of ZKPs

+

Originating in the 1980s, ZKPs were first introduced by Shafi Goldwasser, Silvio Micali, and Charles Rackoff. The concept is based on three crucial properties:

+
    +
  1. Completeness: If the statement is true, an honest verifier will always be convinced by a genuine prover.
  2. +
  3. Soundness: If the statement is false, a dishonest prover cannot convince an honest verifier that it is true.
  4. +
  5. Zero-knowledge: The verifier gains no additional knowledge about the statement other than its validity.
  6. +
+

Concept Explanation

+

To illustrate the concept, consider the following analogy: Imagine two individuals, Peggy (the prover) and Victor (the verifier). Peggy wants to convince Victor that she knows the password to a secret vault without revealing the password itself. They use ZKP in the following manner:

+
    +
  1. Peggy enters the vault and locks the door from inside.
  2. +
  3. Victor randomly chooses one of two possible exit routes (A or B) for Peggy to leave the vault.
  4. +
  5. Peggy exits the vault through the chosen route, proving she knows the password without revealing it.
  6. +
+

This process is repeated multiple times, increasing Victor's confidence in Peggy's knowledge of the password. Importantly, Victor learns nothing about the password itself.

+

In real-world applications, ZKPs are implemented using complex mathematical algorithms and cryptographic techniques. One popular implementation is zk-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge), which is used in various blockchain platforms to ensure privacy and security.

+

Benefits of ZKPs

+

ZKPs offer several benefits, including:

+
    +
  1. Enhanced Privacy: Sensitive information remains concealed, protecting users' privacy in various applications, such as online transactions and identity verification.
  2. +
  3. Security: ZKPs reduce the risk of data breaches and identity theft, as sensitive information is never directly shared.
  4. +
  5. Scalability: ZKPs can be designed to be computationally efficient, making them suitable for large-scale systems, such as blockchain networks.
  6. +
+

Challenges of ZKPs

+

Despite their advantages, ZKPs also have some limitations:

+
    +
  1. Complexity: Implementing ZKPs requires advanced knowledge of cryptography and mathematics, which can be a barrier for some developers.
  2. +
  3. Performance: Some ZKP systems may require significant computational resources, potentially affecting the performance of the underlying application.
  4. +
+

Conclusion

+

In conclusion, zero-knowledge proofs are a powerful cryptographic tool that allows for secure and private verification of information. While they do have some limitations, their potential applications in various domains, such as finance, healthcare, and voting systems, make them an essential component of modern privacy and security solutions.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/fonts.css b/fonts.css new file mode 100644 index 00000000..c8b8a622 --- /dev/null +++ b/fonts.css @@ -0,0 +1 @@ +@font-face{font-family:"Unbounded-Regular";font-style:normal;font-weight:400;src:url("./assets/Unbounded-Regular.woff2"),local("woff2");font-display:swap}@font-face{font-family:"Unbounded-Bold";font-style:normal;font-weight:400;src:url("./assets/Unbounded-Bold.woff2"),local("woff2");font-display:swap}@font-face{font-family:"Unbounded-Black";font-style:normal;font-weight:400;src:url("./assets/Unbounded-Black.woff2"),local("woff2");font-display:swap}@font-face{font-family:"Unbounded-Medium";font-style:normal;font-weight:400;src:url("./assets/Unbounded-Medium.woff2"),local("woff2");font-display:swap} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..062ad200 --- /dev/null +++ b/index.html @@ -0,0 +1,316 @@ + + + + + + + +Home | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ +

Mastering Rank One Constraint System R1CS with Circom Examples

+
+

In Draft Mode +Overview +Rank-1 Constraint Systems, or R1CS, are a critical component in cryptographic protocols, especially those related to zero-knowledge proofs such as zk-SNARKS. They are a system of equations used to represent computations, and are particularly useful in scena…

+
+
+
+ +

Paper Review - Zero Knowledge Proofs for Decision Tree Predictions and Accuracy

+
+

IN DRAFT MODE +Summary +Machine learning has become increasingly prominent and is widely used in various applications in practice. Despite its great success, the integrity of machine learning predictions and accuracy is a rising concern. The reproducibility of machine learning mode…

+
+
+
+ +

Unlocking the Power of ElGamal Encryption: Implementing and Enhancing Security with SageMath

+
+

+Introduction +ElGamal Encryption +Enhancing Security of ElGamal Encryption +Finding a Safe Generator +Practical Applications of ElGamal Encryption +Conclusion + +Introduction +ElGamal encryption is a widely-used public key encryption algorithm that provides confidentiality and security …

+
+
+
+ +

Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit

+
+

Rate Limiting Nullifier (RLN) Review +I recently had the pleasure of conducting my first security audit of a Zero Knowledge Proofs (ZKP) protocol. The protocol in question was the Rate Limiting Nullifier (RLN) Zero Knowledge Proofs Protocol, with its circuits written in Circom. My…

+
+
+
+ +

Unveiling the Weighted Set Cover Problem: Optimizing Resource Allocation

+
+

+Introduction +Problem Explanation +Problem Definition Weighted Set Cover +Solution Greedy Algorithm +Implementation in SageMath +Example Scenario +Applications in Blockchain Technology and Machine Learning + +Blockchain Transaction Fee Optimization +Machine Learning Feature Selection + + +R…

+
+
+
+ +

Understanding Caulk Protocol: A Beginner's Guide to Sublinear Time Lookup Arguments (In Draft Mode)

+
+

Note: This article is in draft mode and I didn't finish writing the sections of the Caulk protocol, proof read, test the code for correctness and adding references. Please check it again in 1-2 weeks before I publish it. +Introduction +In this blog we will review Caulk protocol for…

+
+
+
+ +

Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples

+
+

+Introduction Demystifying Elliptic Curves and Their Applications + +The Power of Elliptic Curve Cryptography (ECC) +Unlocking the Potential of ECC with SageMath + + +Understanding the Fundamentals of Elliptic Curves + +Definition of an Elliptic Curve +Points on an Elliptic Curve +Visualiz…

+
+
+
+ +

Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability

+
+

Danksharding is an innovative approach to scale Ethereum's blockchain, aiming to achieve over 100,000 transactions per second by enabling rollups to add cheaper data to blocks ethereum.org. As Ethereum moves towards Proto-Danksharding and eventually full Danksharding ethereum.org…

+
+
+
+ +

Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide

+
+

This article would provide an in-depth understanding of how product codes from algebraic coding theory can be applied to Danksharding to improve Ethereum's scalability. It would cover the fundamentals of product codes, their application in Danksharding, and the potential benefits…

+
+
+
+ +

Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve

+
+

In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications hackmd.io/@jpw. We will exploit the fact that $(p−1)/2…

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/intro-zkps/index.html b/intro-zkps/index.html new file mode 100644 index 00000000..7738bc5e --- /dev/null +++ b/intro-zkps/index.html @@ -0,0 +1,335 @@ + + + + + + + +A brief introduction to Zero Knowledge Proofs (ZKPs) | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

A brief introduction to Zero Knowledge Proofs (ZKPs)

+
+
    +
  1. Introduction +
      +
    • A. Definition of Zero Knowledge Proofs (ZKPs)
    • +
    • B. Overview of the Benefits of Using ZKPs
    • +
    +
  2. +
  3. How ZKPs Work +
      +
    • A. Overview of the ZKP Process
    • +
    • B. Explanation of the Three Stages of the ZKP Process
    • +
    +
  4. +
  5. Applications of ZKPs +
      +
    • A. Cryptocurrency Transactions
    • +
    • B. Identity Management
    • +
    • C. Data Privacy
    • +
    +
  6. +
  7. Challenges with ZKPs +
      +
    • A. ODifficulty of Implementation
    • +
    • B. Security and Privacy Concerns
    • +
    +
  8. +
  9. Conclusion +
      +
    • A. Summary of ZKP Benefits
    • +
    • B. Outlook on Future of ZKPs
    • +
    +
  10. +
+

Overview

+

Zero knowledge proofs (ZKPs) are a powerful technique that allows one person (the prover) to prove to another (the verifier) that they have specific information without actually providing it. Although this idea may seem unusual at first, it has significant implications in the world of cryptography and can be applied to improve the security and privacy of a variety of systems.

+

ZKPs' "non-interactivity" is one of its fundamental characteristics. As a result, the prover can produce a proof and submit it to the verifier, who can then independently assess the proof's veracity without additional communication. This contrasts with other kinds of proofs, which frequently need for back-and-forth communication between the prover and verifier.

+

Imagine a person attempting to prove to a bank that they have a certain amount of money in their account without disclosing the exact amount. The individual could show the bank proof that they have at least a certain amount of money without disclosing the exact amount. This would allow the bank to confirm that the person has sufficient funds without learning the details of the person's financial situation.

+

ZKPs can be built in a variety of ways and used to prove a wide variety of statements. Some common examples include demonstrating that a person knows the solution to a specific problem (such as a password or a puzzle), demonstrating that a person has access to specific data (such as a private key or a document), or demonstrating that a person has performed a specific computation (e.g. a hash function).

+

There has been a great deal of interest in implementing ZKPs in the Rust programming language in recent years. Rust is a systems programming language that is intended to be safe, concurrent, and fast. It has a growing ecosystem of libraries and tools and is being used in a variety of applications, including blockchain technologies and other security-critical systems.

+

Rust is an excellent choice for implementing ZKPs for a variety of reasons. Here are three important explanations:

+
    +
  • For starters, Rust has strong support for low-level programming and memory safety, both of which are critical for implementing complex cryptographic algorithms.
  • +
  • Second, Rust places a strong emphasis on concurrency and parallelism, which can be useful for optimizing the performance of ZKPs.
  • +
  • Finally, Rust has a growing developer community and a well-documented API, which makes building and maintaining ZKP implementations easier.
  • +
+

There are already a number of Rust libraries and projects that support ZKPs, such as libzkp, zkp-toolkit, and bellman. These libraries offer a variety of features and support for various ZKP constructions, and can be used to create a wide range of ZKP-based applications.

+

To summarize, zero knowledge proofs are a powerful tool that can be used to improve the security and privacy of a variety of systems. Because of its emphasis on safety, concurrency, and performance, Rust is an excellent choice for implementing ZKPs, and there are already several libraries and projects that support ZKPs in Rust. We can expect to see even more Rust implementations and applications in the future as the use of ZKPs grows.

+

So, how do zero knowledge proofs actually work? Let's look at a small Rust example to see how this works. In this example, we will develop a zero knowledge proof that proves the truth of a specific assertion without revealing any underlying facts or information.

+

Here is the code for our zero knowledge proof:

+
extern crate rand;
+extern crate sha2;
+
+use rand::{Rng, SeedableRng, OsRng};
+use sha2::{Sha256, Digest};
+
+// Define the statement we want to prove
+const STATEMENT: &str = "I possess the secret key";
+
+// Define the secret key
+const SECRET_KEY: &[u8] = b"my_secret_key";
+
+fn main() {
+// Generate a random number to use as a nonce
+let mut rng = OsRng::new().unwrap();
+let nonce: u64 = rng.gen();
+// Hash the nonce and secret key together
+let input = format!("{}{}", nonce, SECRET_KEY);
+let mut hasher = Sha256::new();
+hasher.input(input);
+let hash = hasher.result();
+
+// Generate a proof by hashing the statement and the hash together
+let input = format!("{}{}", STATEMENT, hash);
+let mut hasher = Sha256::new();
+hasher.input(input);
+let proof = hasher.result();
+
+// Send the proof to the verifier
+let verifier = Verifier::new();
+let result = verifier.verify(proof, STATEMENT, SECRET_KEY);
+
+// Print the result
+println!("Verification result: {}", result);
+}
+
+struct Verifier {
+    secret_key: &'static [u8],
+}
+
+impl Verifier {
+fn new() -> Verifier {
+    Verifier { secret_key: SECRET_KEY }
+}
+
+fn verify(&self, proof: Digest, statement: &str, secret_key: &[u8]) -> bool {
+    // Hash the statement and the secret key together
+    let input = format!("{}{}", statement, secret_key);
+    let mut hasher = Sha256::new();
+    hasher.input(input);
+    let hash = hasher.result();
+
+    // Check if the proof matches the hash
+    proof == hash
+}
+}
+
+
+

In this code example, we define a constant STATEMENT which represents the statement we want to prove. We also define a constant SECRET_KEY which represents the secret key that we want to prove we possess.

+

Next, we generate a random number to use as a nonce (a unique value used for one-time use) and hash it together with the secret key using the SHA-256 hash function. This creates a unique hash value that is based on both the nonce and the secret key.

+

We then generate a proof by hashing the statement and the hash value together using the SHA-256 hash function. This creates a new hash value that is based on both the statement and the original hash value.

+

We send the proof to the verifier, which then uses the secret key and the statement to recreate the original hash value. If the proof matches the original hash value, then the verifier can be confident that the prover possesses the secret key and that the statement is true.

+

In this way, zero knowledge proofs allow the prover to demonstrate the truth of a particular statement without actually revealing any of the underlying data or information. This is achieved through the use of cryptographic techniques such as hash functions and digital signatures, which allow the prover to create a proof that is verifiable by the verifier without revealing any of the underlying data or information.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/main.css b/main.css new file mode 100644 index 00000000..232adf3c --- /dev/null +++ b/main.css @@ -0,0 +1 @@ +@import 'fonts.css';@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&display=swap");@import url("https://cdn.jsdelivr.net/npm/jetbrains-mono@1.0.6/css/jetbrains-mono.min.css");*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;line-height:1.5}html,body{color:#555;margin:0;padding:0}html{font-family:"Libre Baskerville","Times New Roman",Times,"Source Serif Pro","Helvetica Neue",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3","Microsoft YaHei UI","Microsoft YaHei","微软雅黑","思源黑体",SYHT,"WenQuanYi Micro Hei",serif;font-size:14px;overflow-y:scroll}@media (min-width: 600px){html{font-size:16px}}body{-webkit-text-size-adjust:100%}h1,h2,h3,h4,h5,h6{color:#353535;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;line-height:normal}a{color:#4a9ae1;text-decoration:none}blockquote{border-left:.25rem solid #e5e5e5;color:#979797;margin:.8rem 0;padding:.5rem 1rem}blockquote p:last-child{margin-bottom:0}@media (min-width: 600px){blockquote{padding:0 5rem 0 1.25rem}}img{display:block;margin:0 0 1rem;max-width:100%}td{vertical-align:top}code{font-family:var(--code-font);font-size:15px;background-color:var(--bg-1);padding:.1em .2em;border-radius:5px;border:1px solid var(--border-color)}pre{border-radius:5px;border:1px solid var(--border-color);line-height:1.4;overflow-x:auto;padding:1em}pre code{background-color:rgba(0,0,0,0);color:inherit;font-size:80%;padding:0;border:0}pre{font-family:var(--code-font);position:relative;-webkit-overflow-scrolling:touch}pre code[class*=language-]{-webkit-overflow-scrolling:touch}pre code[class*=language-]::before{background:#000;border-radius:0 0 .25rem .25rem;color:#fff;font-size:12px;letter-spacing:.025rem;padding:.1rem .5rem;position:absolute;right:.1rem;margin-top:.1rem;text-align:right;text-transform:uppercase;top:0}pre code[class=language-javaScript]::before,pre code[class=language-js]::before{content:"js";background:#f7df1e;color:#000}pre code[class*=language-yml]::before,pre code[class*=language-yaml]::before{content:"yaml";background:#f71e6a;color:#fff}pre code[class*=language-shell]::before,pre code[class*=language-bash]::before,pre code[class*=language-sh]::before{content:"shell";background:green;color:#fff}pre code[class*=language-json]::before{content:"json";background:#1e90ff;color:#000}pre code[class*=language-python]::before,pre code[class*=language-py]::before{content:"py";background:blue;color:#ff0}pre code[class*=language-css]::before{content:"css";background:cyan;color:#000}pre code[class*=language-go]::before{content:"Go";background:cyan;color:#4169e1}pre code[class*=language-md]::before,pre code[class*=language-md]::before{content:"Markdown";background:#4169e1;color:#f5f5f5}pre code[class*=language-rust]::before,pre code[class*=language-rs]::before{background:#fff8f6;color:#ff4647}.post{padding:3rem 0}.post-info{color:#aaa;font-family:Palatino,"Palatino LT STD","Palatino Linotype","Book Antiqua","Georgia",serif;letter-spacing:.5px;text-align:center}.post-info span{font-style:italic}.post-title{color:#353535;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-size:4rem;margin:1rem 0;text-align:center}.post-line{border-top:.4rem solid #353535;display:block;margin:0 auto 3rem;width:4rem}.post p{margin:0 0 1rem;text-align:justify}.post a:hover{text-decoration:underline}.post img{margin:0 auto .5rem}.post img+em{color:#aaa;display:block;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-size:.9rem;font-style:normal;text-align:center}.post img.emoji{display:inline-block;left:0;transform:none;width:1rem;height:1rem;vertical-align:text-top;padding:0;margin:0}.post hr{margin-top:2em;margin-bottom:1.5em}.footnote-definition sup{top:-.2 .5em;font-size:.75em;display:inline}.footnote-definition p{display:inline}.highlight .hll{background-color:#ffc}.highlight .c{color:#999}.highlight .err{color:#a00;background-color:#faa}.highlight .k{color:#069}.highlight .o{color:#555}.highlight .cm{color:#09f;font-style:italic}.highlight .cp{color:#099}.highlight .c1{color:#999}.highlight .cs{color:#999}.highlight .gd{background-color:#fcc;border:1px solid #c00}.highlight .ge{font-style:italic}.highlight .gr{color:red}.highlight .gh{color:#030}.highlight .gi{background-color:#cfc;border:1px solid #0c0}.highlight .go{color:#aaa}.highlight .gp{color:#009}.highlight .gu{color:#030}.highlight .gt{color:#9c6}.highlight .kc{color:#069}.highlight .kd{color:#069}.highlight .kn{color:#069}.highlight .kp{color:#069}.highlight .kr{color:#069}.highlight .kt{color:#078}.highlight .m{color:#f60}.highlight .s{color:#d44950}.highlight .na{color:#4f9fcf}.highlight .nb{color:#366}.highlight .nc{color:#0a8}.highlight .no{color:#360}.highlight .nd{color:#99f}.highlight .ni{color:#999}.highlight .ne{color:#c00}.highlight .nf{color:#c0f}.highlight .nl{color:#99f}.highlight .nn{color:#0cf}.highlight .nt{color:#2f6f9f}.highlight .nv{color:#033}.highlight .ow{color:#000}.highlight .w{color:#bbb}.highlight .mf{color:#f60}.highlight .mh{color:#f60}.highlight .mi{color:#f60}.highlight .mo{color:#f60}.highlight .sb{color:#c30}.highlight .sc{color:#c30}.highlight .sd{color:#c30;font-style:italic}.highlight .s2{color:#c30}.highlight .se{color:#c30}.highlight .sh{color:#c30}.highlight .si{color:#a00}.highlight .sx{color:#c30}.highlight .sr{color:#3aa}.highlight .s1{color:#c30}.highlight .ss{color:#fc3}.highlight .bp{color:#366}.highlight .vc{color:#033}.highlight .vg{color:#033}.highlight .vi{color:#033}.highlight .il{color:#f60}.css .o,.css .o+.nt,.css .nt+.nt{color:#999}.container{margin:0 auto;max-width:800px;width:80%}main,footer,.nav-container{display:block;margin:0 auto;max-width:800px;width:80%}.nav{box-shadow:0 2px 2px -2px rgba(0,0,0,.2);overflow:auto}.nav-container{margin:1rem auto;position:relative;text-align:center}.nav-title{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;color:#555;display:inline-block;margin:0;padding-right:.2rem}.nav-title:hover,.nav-title:focus{opacity:.6}.nav ul{list-style-type:none;margin:1rem 0 0;padding:0;text-align:center}.nav li{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;color:#555;display:inline-block;opacity:.6;padding:0 2rem 0 0}.nav li:last-child{padding-right:0}.nav li:hover,.nav li:focus{opacity:1}.nav a{color:#555;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif}@media (min-width: 600px){.nav-container{text-align:left}.nav ul{bottom:0;position:absolute;right:0}}footer{font-family:Palatino,"Palatino LT STD","Palatino Linotype","Book Antiqua","Georgia",serif;padding:2rem 0;text-align:center}footer span{color:#555;font-size:.8rem}.pagination{border-top:.5px solid #e5e5e5;font-family:Palatino,"Palatino LT STD","Palatino Linotype","Book Antiqua","Georgia",serif;padding-top:2rem;position:relative;text-align:center}.pagination span{color:#353535;font-size:1.1rem}.pagination .top{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;color:#555;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-size:1.1rem;opacity:.6}.pagination .top:hover{opacity:1}.pagination .arrow{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;color:#555;position:absolute}.pagination .arrow:hover,.pagination .arrow:focus{opacity:.6;text-decoration:none}.pagination .left{left:0}.pagination .right{right:0}.catalogue-item{border-bottom:1px solid #e5e5e5;color:#555;display:block;padding:2rem 0}.catalogue-item:hover .catalogue-line,.catalogue-item:focus .catalogue-line{width:5rem}.catalogue-item:last-child{border:0}.catalogue-pinned{color:#aaa;font-family:Palatino,"Palatino LT STD","Palatino Linotype","Book Antiqua","Georgia",serif;letter-spacing:.5px}.catalogue-time{color:#aaa;font-family:Palatino,"Palatino LT STD","Palatino Linotype","Book Antiqua","Georgia",serif;letter-spacing:.5px}.catalogue-title{color:#353535;display:block;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-size:2rem;font-weight:700;margin:.5rem 0}.catalogue-line{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;border-top:.2rem solid #353535;display:block;width:2rem}.notfound{position:relative;text-align:center;margin:4rem 0}.notfound-error{font-size:4rem;margin:1rem 0}.notfound-line{border-top:.4rem solid #353535;display:block;margin:0 auto 3rem;width:4rem}.notfound-message{max-width:25rem;margin:0 auto}.tags-header-title{color:#353535;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;font-size:4rem;margin:1rem 0;text-align:center}.tags-header-line{border-top:.4rem solid #353535;display:block;margin:0 auto 3rem;width:4rem}.tags-clouds{text-align:center;font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif}.tags-clouds a{display:inline-block;margin:0 .1rem .2rem;padding:.2rem .5rem;background:rgba(0,0,0,.05);border-radius:5px;color:#555;text-decoration:none}.tags-clouds a:hover,.tags-clouds a:active{background:rgba(0,0,0,.1)}.tags-item-icon{height:1rem}.tags-item-label{display:inline-block;margin:2rem 0 .5rem}.tags-item-label a{font-family:"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif;color:#555}.tags-post{display:flex;justify-content:space-between;padding:5px 0}.tags-post-title{color:#555;text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tags-post-line{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;border-top:.1rem solid #353535;display:block;width:0}.tags-post-meta{color:#aaa;text-align:right;white-space:nowrap}.tags-post:hover .tags-post-line,.tags-post:active .tags-post-line{width:3rem}.tags-post:hover .tags-post-meta,.tags-post:active .tags-post-meta{color:#353535}:root{--border-color: #00000000;--text-font: "Inter";--header-font: "Inter";--code-font: "Jetbrains Mono"}html{background-color:rgba(0,0,0,0);color:rgba(0,0,0,0);font-family:"Inter";line-height:1.6em}.content{max-width:944px;margin:0 auto;padding:0 24px;word-wrap:break-word}.post-title{font-family:"Unbounded-Bold";font-size:30px;text-align:left}.post-info{font-family:"Unbounded-Regular";text-align:left}.post-line{margin-top:1rem;margin-bottom:1rem;margin-left:1rem}h1{font-family:"Unbounded-Medium";font-size:25px}h2{font-family:"Unbounded-Medium";font-size:25px}.catalogue-title{font-family:"Unbounded-Bold";font-size:30px}.catalogue-time{font-family:"Unbounded-Regular"}.nav a{font-family:"Unbounded-Medium"}.pagination .top{font-family:"Unbounded-Medium"}.tags-header-title{font-family:"Unbounded-Bold";font-size:25px}.tags-item-label a{font-family:"Unbounded-Bold";font-size:20px}footer{font-family:"Unbounded-Medium"}.post-preview{margin-bottom:2rem}.post-preview h3.post-title{margin-bottom:0;font-size:25px;text-align:left}.post-preview .summary{margin-top:.8rem}@media all and (min-width: 640px){html{font-size:16.5px}}@media all and (min-width: 720px){html{font-size:17px}}@media all and (min-width: 960px){html{font-size:18px}} \ No newline at end of file diff --git a/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/index.html b/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/index.html new file mode 100644 index 00000000..4250cc39 --- /dev/null +++ b/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/index.html @@ -0,0 +1,665 @@ + + + + + + + +Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples

+
+ +

Introduction Demystifying Elliptic Curves and Their Applications

+

Elliptic curves are a fascinating area of mathematics that have found numerous applications in modern cryptography, particularly in the field of Elliptic Curve Cryptography (ECC). ECC has gained popularity due to its ability to provide the same level of security as traditional cryptographic methods, such as RSA, but with smaller key sizes. This results in faster computations and reduced storage requirements, making ECC an attractive choice for securing communications in resource-constrained environments.

+

In this blog post, we aim to provide a comprehensive introduction to elliptic curve arithmetic and its applications in cryptography. We will explore the basics of elliptic curves, delve into the arithmetic operations performed on them, and demonstrate how to work with elliptic curves using the powerful SageMath software. By the end of this post, you will have a solid understanding of the fundamentals of elliptic curve arithmetic and be well-equipped to explore more advanced topics in ECC.

+

The Power of Elliptic Curve Cryptography (ECC)

+

ECC is a public-key cryptosystem that relies on the algebraic structure of elliptic curves over finite fields. It offers several advantages over traditional cryptosystems, such as:

+
    +
  1. +

    Smaller key sizes: ECC provides the same level of security as RSA with significantly smaller key sizes. For example, a 256-bit ECC key is considered to be as secure as a 3072-bit RSA key.

    +
  2. +
  3. +

    Faster computations: Due to the smaller key sizes, ECC operations are generally faster than their RSA counterparts, making ECC more suitable for resource-constrained devices.

    +
  4. +
  5. +

    Improved security: ECC is believed to be more resistant to certain types of attacks, such as quantum computing attacks, compared to traditional cryptosystems. This makes ECC a forward-looking choice for securing communications in the face of evolving threats.

    +
  6. +
+

Unlocking the Potential of ECC with SageMath

+

SageMath sagemath.org is an open-source mathematics software system that provides a powerful environment for working with various mathematical structures, including elliptic curves. It offers a rich set of tools and libraries for performing arithmetic operations on elliptic curves, making it an ideal platform for learning and experimenting with ECC.

+

Elliptic Curve Example

+

Throughout this blog post, we will cover the following topics:

+
    +
  • Basics of elliptic curves: definition, points, and example plots
  • +
  • Elliptic curve arithmetic: point addition, doubling, scalar multiplication, and inverse of a point
  • +
  • Working with elliptic curves in SageMath: defining, plotting, and finding points on curves
  • +
  • Implementing elliptic curve arithmetic in SageMath: code examples for point addition, doubling, scalar multiplication, and inverse of a point
  • +
  • Applications of elliptic curve arithmetic: securing communications (ECC), digital signatures (ECDSA), and key exchange (ECDH), blockchain protocols, zero knowledge proofs (ZKP), zero knowledge machine learning
  • +
+

By the end of this post, you will have a solid foundation in elliptic curve arithmetic and be well-prepared to explore more advanced topics in ECC and its applications in cryptography.

+

Understanding the Fundamentals of Elliptic Curves

+

Elliptic curves are algebraic structures that play a crucial role in modern cryptography. To understand the basics of elliptic curves, let's start with their definition.

+

Definition of an Elliptic Curve

+

An elliptic curve is defined by an equation of the form:

+

$$y^2 = x^3 + ax + b$$

+

where $a$ and $b$ are constants, and the curve must satisfy the condition $4a^3 + 27b^2 \neq 0$ to ensure that it has no singularities (i.e., no self-intersections or cusps). In the context of cryptography, we often work with elliptic curves over finite fields, which means that the coordinates $(x, y)$ and the constants $a$ and $b$ are elements of a finite field.

+

Points on an Elliptic Curve

+

A point $(x, y)$ on an elliptic curve satisfies the curve's equation. In addition to the points that lie on the curve, there is an additional "point at infinity" denoted by $\mathcal{O}$, which serves as the identity element for the elliptic curve group (more on this later).

+

Visualizing Points on an Elliptic Curve

+

To visualize an elliptic curve, we can plot the points that satisfy the curve's equation. Let's use SageMath to plot an example of an elliptic curve over the real numbers.

+
a, b = -1, 1
+E = EllipticCurve([a, b])
+plot(E, xmin=-3, xmax=3, ymin=-3, ymax=3)
+
+

Elliptic Curve Plot

+

An example of an elliptic curve plot generated using SageMath.

+

Exploring the Structure of Elliptic Curve Groups

+

Elliptic curves have an inherent group structure, which is the foundation for elliptic curve arithmetic. The group operation is defined as the addition of points on the curve. The point at infinity, $\mathcal{O}$, serves as the identity element, meaning that for any point $P$ on the curve, $P + \mathcal{O} = P$.

+

The group operation has the following properties:

+
    +
  1. Closure: The sum of any two points on the curve is also a point on the curve.
  2. +
  3. Associativity: For any points $P$, $Q$, and $R$ on the curve, $(P + Q) + R = P + (Q + R)$.
  4. +
  5. Identity: There exists an identity element $\mathcal{O}$ such that for any point $P$ on the curve, $P + \mathcal{O} = P$.
  6. +
  7. Inverse: For any point $P$ on the curve, there exists an inverse point $-P$ such that $P + (-P) = \mathcal{O}$.
  8. +
+

The group structure of elliptic curves is what enables us to perform arithmetic operations on points, which is the basis for elliptic curve cryptography.

+

In the next sections, we will delve deeper into elliptic curve arithmetic and demonstrate how to work with elliptic curves using SageMath. By understanding the fundamentals of elliptic curves and their group structure, you will be well-prepared to explore more advanced topics in elliptic curve cryptography and its applications.

+

Elliptic Curve Arithmetic

+

Elliptic curve arithmetic is the foundation for elliptic curve cryptography. In this section, we will cover the following topics:

+
    +
  • Performing point addition on elliptic curves
  • +
  • Mastering point doubling techniques
  • +
  • Efficient scalar multiplication algorithms
  • +
  • Computing the inverse of a point
  • +
  • Verifying associativity and commutativity in elliptic curve arithmetic
  • +
+

Performing Point Addition on Elliptic Curves

+

Point addition is the primary operation in elliptic curve arithmetic. Given two points $P$ and $Q$ on an elliptic curve, their sum $R = P + Q$ is computed as follows:

+
    +
  1. Find the line $L$ that passes through $P$ and $Q$.
  2. +
  3. Find the third point of intersection $R'$ between $L$ and the elliptic curve.
  4. +
  5. Reflect $R'$ across the x-axis to obtain $R$.
  6. +
+

Point addition on Elliptic Curve

+

A geometrical visualization of a point addition on elliptic curve.

+

In SageMath, point addition can be performed using the + operator:

+
p = 2^256 - 2^32 - 977
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+P = E.random_element()
+Q = E.random_element()
+R = P + Q
+print (" P+Q = ", R)
+
+

Mastering Point Doubling Techniques

+

Point doubling is a special case of point addition where $P = Q$. In this case, the line $L$ is the tangent to the curve at point $P$. The process for computing $R = 2P$ is similar to point addition:

+
    +
  1. Find the tangent line $L$ at point $P$.
  2. +
  3. Find the second point of intersection $R'$ between $L$ and the elliptic curve.
  4. +
  5. Reflect $R'$ across the x-axis to obtain $R$.
  6. +
+

Point doubling on Elliptic Curve

+

A geometrical visualization of a point addition on elliptic curve.

+

In SageMath, point doubling can be performed using the * operator:

+
p = 2^256 - 2^32 - 977
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+P = E.random_element()
+R = 2 * P
+print (" 2*P = ", R)
+
+

Efficient Scalar Multiplication Algorithms

+

Scalar multiplication is the operation of adding a point $P$ to itself $k$ times, denoted as $[k]P$. Efficient algorithms for scalar multiplication, such as the double-and-add algorithm, can significantly improve the performance of elliptic curve cryptography.

+

In SageMath, scalar multiplication can be performed using the * operator:

+
p = 2^256 - 2^32 - 977
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+P = E.random_element()
+k = randint(1, E.order() - 1)
+R = k * P
+print(" k*P = ", R)
+
+

Computing the Inverse of a Point

+

The inverse of a point $P = (x, y)$ on an elliptic curve is the point $-P = (x, -y)$. The inverse is used in elliptic curve arithmetic to compute the difference between two points.

+

In SageMath, the inverse of a point can be computed using the neg method:

+
p = 2^256 - 2^32 - 977
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+P = E.random_element()
+P_inv = -P
+print(" P_inv = ", P_inv)
+
+

Verifying Associativity and Commutativity in Elliptic Curve Arithmetic

+

Associativity and commutativity are essential properties of elliptic curve arithmetic. To verify these properties, we can perform arithmetic operations on random points and check if the results satisfy the properties.

+

In SageMath, we can verify associativity and commutativity as follows:

+
P = E.random_element()
+Q = E.random_element()
+R = E.random_element()
+
+# Verify associativity: (P + Q) + R == P + (Q + R)
+print ((P + Q) + R == P + (Q + R))
+
+# Verify commutativity: P + Q == Q + P
+print (P + Q == Q + P)
+
+

By understanding the fundamentals of elliptic curve arithmetic and mastering the techniques for point addition, point doubling, scalar multiplication, and computing the inverse of a point, you will be well-prepared to explore more advanced topics in elliptic curve cryptography and its applications.

+

Visualizing Elliptic Curve Arithmetic Operations

+

To better understand the arithmetic operations on elliptic curves, we can visualize the process of point addition, point doubling, and scalar multiplication using graphs.

+

In SageMath, we can plot the elliptic curve and the points involved in the arithmetic operations:

+
p = 13
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+
+def plot_points_on_curve(E, points, labels, colors):
+    curve_plot = plot(E, xmin=-5, xmax=5, ymin=-5, ymax=5)
+    real_points = [(float(pt[0]), float(pt[1])) for pt in points]
+    point_plots = [point2d(pt, color=colors[i], size=30, zorder=5) + text(labels[i], pt, fontsize=10, color=colors[i], horizontal_alignment='left', vertical_alignment='bottom') for i, pt in enumerate(real_points)]
+    return curve_plot + sum(point_plots)
+
+P = E.random_element()
+Q = E.random_element()
+R = P + Q
+
+plot_points_on_curve(E, [P.xy(), Q.xy(), R.xy()], ['P', 'Q', 'R'], ['red', 'blue', 'green'])
+
+

Elliptic Curve Arithmetic Visualization

+

An example of an elliptic curve plot with points P, Q, and R generated using SageMath.

+

By visualizing the arithmetic operations on elliptic curves, we can gain a deeper understanding of the underlying mathematical concepts and their applications in cryptography.

+

We have covered the fundamentals of elliptic curve arithmetic, including point addition, point doubling, scalar multiplication, computing the inverse of a point, and verifying associativity and commutativity. We have also demonstrated how to perform these operations using SageMath and visualize the results to improve understanding.

+

By mastering these concepts and techniques, you will be well-equipped to explore more advanced topics in elliptic curve cryptography, such as key exchange, digital signatures, and secure communication protocols.

+

Working with Elliptic Curves in SageMath

+

SageMath is a powerful open-source mathematics software system that provides extensive support for working with elliptic curves. In this section, we will cover the following topics:

+
    +
  • Defining and visualizing elliptic curves with SageMath
  • +
  • Uncovering points on elliptic curves
  • +
  • Manipulating elliptic curve groups in SageMath
  • +
+

Defining and Visualizing Elliptic Curves with SageMath

+

To define an elliptic curve in SageMath, we can use the EllipticCurve function, which takes a list of coefficients [a, b] for the curve equation $y^2 = x^3 + ax + b$:

+
a, b = -1, 1
+E = EllipticCurve([a, b])
+
+

To visualize the elliptic curve, we can use the plot function:

+
plot(E, xmin=-5, xmax=5, ymin=-5, ymax=5)
+
+

Elliptic Curve Plot

+

An example of an elliptic curve plot generated using SageMath.

+

Uncovering Points on Elliptic Curves

+

To find points on an elliptic curve, we can use the points method, which returns a list of points on the curve over a finite field:

+
p = 13
+F = IntegerModRing(p)
+E = EllipticCurve(F, [0, 7])
+points = E.points()
+print(points)
+
+

Output:

+
[(0 : 1 : 0), (7 : 5 : 1), (7 : 8 : 1), (8 : 5 : 1), (8 : 8 : 1), (11 : 5 : 1), (11 : 8 : 1)]
+
+

Manipulating Elliptic Curve Groups in SageMath

+

Elliptic curves have an inherent group structure, which allows us to perform arithmetic operations on points. SageMath provides various methods to manipulate elliptic curve groups, such as point addition, point doubling, and scalar multiplication.

+

Point Addition

+

To add two points on an elliptic curve, we can use the + operator:

+
P = E.random_element()
+Q = E.random_element()
+R = P + Q
+
+

Point Doubling

+

To double a point on an elliptic curve, we can use the * operator:

+
P = E.random_element()
+R = 2 * P
+
+

Scalar Multiplication

+

To perform scalar multiplication on a point, we can use the * operator:

+
P = E.random_point()
+k = randint(1, E.order() - 1)
+R = k * P
+
+

Multiscalar Multiplication

+

Multiscalar multiplication is an operation that computes a linear combination of points on an elliptic curve with given scalar coefficients. Given points $P_1, P_2, \dots, P_n$ on an elliptic curve and scalars $k_1, k_2, \dots, k_n$, the multiscalar multiplication computes the result $R = k_1P_1 + k_2P_2 + \dots + k_nP_n$. Efficient algorithms for multiscalar multiplication, such as the Pippenger's algorithm or the interleaved window method, can significantly improve the performance of elliptic curve cryptography.

+

In SageMath, we can perform multiscalar multiplication using a loop and the + and * operators:

+
points = [E.random_element() for _ in range(5)]
+scalars = [randint(1, E.order() - 1) for _ in range(5)]
+
+R = E(0)  # Initialize R as the identity element of the elliptic curve group
+for i in range(len(points)):
+    R += scalars[i] * points[i]
+print (" Multiscalar Multipliciation: ", R)
+
+

Alternatively, we can use the sum function and a list comprehension to achieve the same result:

+
R = sum(scalars[i] * points[i] for i in range(len(points)))
+print (" Multiscalar Multipliciation: ", R)
+
+

By understanding multiscalar multiplication and its efficient algorithms, you can further optimize elliptic curve operations and enhance the performance of cryptographic protocols based on elliptic curves.

+

There are several efficient algorithms for computing multi-scalar multiplication (MSM) in Elliptic Curve Cryptography. Five popular algorithms are:

+
    +
  1. +

    Double-and-add algorithm: This is the most basic algorithm for scalar multiplication, similar to the square-and-multiply algorithm for modular exponentiation. It computes kP by iterating through the bits of k, doubling the current point at each step, and adding P if the corresponding bit in k is 1 en.wikipedia.org.

    +
  2. +
  3. +

    Montgomery Ladder: This algorithm computes scalar multiplication using a ladder-like structure, which is efficient and resistant to side-channel attacks. It operates on x-coordinates only, making it well-suited for curves in Montgomery form en.wikipedia.org.

    +
  4. +
  5. +

    wNAF (Windowed Non-Adjacent Form) method: This algorithm computes scalar multiplication using a windowed non-adjacent form, which is a signed binary representation of the scalar. It allows for faster calculations by reducing the number of point additions required en.wikipedia.org.

    +
  6. +
  7. +

    Straus' algorithm (also known as Shamir's trick): This algorithm computes multi-scalar multiplication (kP + lQ) more efficiently than performing two separate scalar multiplications. It combines the double-and-add algorithm with interleaving, allowing simultaneous computation of kP and lQ eprint.iacr.org.

    +
  8. +
  9. +

    Pippenger's algorithm: This algorithm is a generalization of Straus' algorithm for computing multi-scalar multiplication with more than two points. It divides the scalars into smaller groups and computes the scalar multiplication for each group separately before combining the results cr.yp.to.

    +
  10. +
+

We have explored how to work with elliptic curves in SageMath, including defining and visualizing elliptic curves, uncovering points on elliptic curves, and manipulating elliptic curve groups. By understanding these concepts and techniques, you will be well-equipped to explore more advanced topics in elliptic curve cryptography and its applications.

+

SageMath provides a powerful and user-friendly environment for working with elliptic curves, making it an invaluable tool for researchers, students, and practitioners in the field of cryptography. By mastering the use of SageMath for elliptic curve operations, you will be able to efficiently implement and analyze cryptographic algorithms based on elliptic curves, paving the way for secure and efficient communication in the digital world.

+

Applications of Elliptic Curve Arithmetic

+

Elliptic curve arithmetic plays a crucial role in various cryptographic applications, including securing communications, ensuring data integrity, establishing secure connections, and enabling privacy-preserving protocols. In this section, we will discuss the following applications of elliptic curve arithmetic:

+
    +
  • Elliptic Curve Cryptography (ECC)
  • +
  • Digital Signatures (ECDSA)
  • +
  • Key Exchange (ECDH)
  • +
  • Ethereum Blockchain Applications
  • +
  • Zero Knowledge Voting using Plonk
  • +
+

Securing Communications with Elliptic Curve Cryptography ECC

+

Elliptic Curve Cryptography (ECC) is a public-key cryptosystem that relies on the algebraic structure of elliptic curves over finite fields. ECC provides the same level of security as traditional cryptosystems like RSA, but with smaller key sizes, making it more efficient and suitable for resource-constrained environments.

+
# Generate an elliptic curve and a base point
+E = EllipticCurve(GF(2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1), [0, 7])
+G = E.random_point()
+
+# Generate a private-public key pair for Alice
+a = randint(1, E.order() - 1)
+A = a * G
+
+# Generate a private-public key pair for Bob
+b = randint(1, E.order() - 1)
+B = b * G
+
+# Alice and Bob compute the shared secret
+shared_secret_A = a * B
+shared_secret_B = b * A
+print ("shared_secret_A == shared_secret_B? ", shared_secret_A == shared_secret_B)
+
+
+

Ensuring Data Integrity with Digital Signatures ECDSA

+

The Elliptic Curve Digital Signature Algorithm (ECDSA) is a widely-used digital signature scheme that provides data integrity and authentication. ECDSA signatures are smaller and faster to compute than RSA signatures, making them suitable for various applications.

+
from hashlib import sha256
+
+E = EllipticCurve(GF(2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1), [0, 7])
+G = E.random_point()
+
+# Generate a private-public key pair for the signer
+d = randint(1, E.order() - 1)
+Q = d * G
+
+# Sign a message
+message = b"Hello, world!"
+hash_value = int.from_bytes(sha256(message).digest(), 'big')
+k = randint(1, E.order() - 1)
+R = k * G
+r = Integer(R[0]) % E.order()  # Convert R[0] to an integer before performing modulo
+s = ((hash_value + d * r) * inverse_mod(k, E.order())) % E.order()
+
+# Verify the signature
+w = inverse_mod(s, E.order())
+u1 = (hash_value * w) % E.order()
+u2 = (r * w) % E.order()
+X = u1 * G + u2 * Q
+print("Are the signatures same? ", r % E.order() == Integer(X[0]) % E.order())  # Convert X[0] to an integer before performing modulo
+
+
+

Establishing Secure Connections with Key Exchange ECDH

+

The Elliptic Curve Diffie-Hellman (ECDH) key exchange protocol enables two parties to establish a shared secret over an insecure channel. ECDH provides the same level of security as traditional Diffie-Hellman, but with smaller key sizes and faster computations.

+
# Define the Elliptic Curve
+E = EllipticCurve(GF(2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1), [0, 7])
+G = E.random_point()
+
+# Generate a private-public key pair for Alice
+a = randint(1, E.order() - 1)
+A = a * G
+
+# Generate a private-public key pair for Bob
+b = randint(1, E.order() - 1)
+B = b * G
+
+# Alice and Bob compute the shared secret
+shared_secret_A = a * B
+shared_secret_B = b * A
+print (" shared_secret_A == shared_secret_B? ", shared_secret_A == shared_secret_B)
+
+
+

Ethereum Blockchain Applications

+

Elliptic curve arithmetic is widely used in Ethereum blockchain applications, such as smart contracts and zero-knowledge proofs. Ethereum uses the secp256k1 elliptic curve for its cryptographic operations, including generating addresses and signing transactions.

+
from hashlib import sha256
+
+# Define the secp256k1 elliptic curve
+p = 2^256 - 2^32 - 977
+E = EllipticCurve(GF(p), [0, 7])
+G = E.lift_x(55066263022277343669578718895168534326250603453777594175500187360389116729240)
+
+# Generate a private-public key pair for an Ethereum user
+private_key = randint(1, E.order() - 1)
+public_key = private_key * G
+
+# Ethereum address generation (simplified)
+address = sha256(str(public_key).encode()).hexdigest()[-40:]
+print("Ethereum address:", "0x"+address)
+
+
+

Zero Knowledge Voting using Plonk

+

Plonk is a highly efficient zero-knowledge proof system that leverages elliptic curve arithmetic to enable privacy-preserving protocols, such as zero-knowledge voting. Plonk uses the Kate-Zaverucha-Goldberg (KZG) polynomial commitment scheme, which is based on elliptic curves.

+
# Define an elliptic curve and a base point for Plonk
+p = 2^256 - 2^32 - 977
+E = EllipticCurve(GF(p), [0, 7])
+G = E.lift_x(55066263022277343669578718895168534326250603453777594175500187360389116729240)
+
+# Generate a KZG commitment to a polynomial
+def kzg_commit(poly_coeffs, G):
+    return sum(coeff * (G * i) for i, coeff in enumerate(poly_coeffs))
+
+# Example polynomial and its commitment
+poly_coeffs = [1, 2, 3, 4]
+C = kzg_commit(poly_coeffs, G)
+print(C)
+
+
+

In a zero-knowledge voting system using Plonk, voters can prove that their votes are valid without revealing their actual choices. This ensures both privacy and integrity in the voting process.

+

In conclusion, elliptic curve arithmetic is a fundamental building block for various cryptographic applications, including securing communications, ensuring data integrity, establishing secure connections, and enabling privacy-preserving protocols. By understanding and implementing these applications using SageMath, you can harness the power of elliptic curve cryptography to develop secure and efficient solutions for real-world problems.

+

Reflecting on the Power of Elliptic Curve Arithmetic

+

Elliptic curve arithmetic has proven to be a powerful tool in modern cryptography, providing efficient and secure solutions for various applications. Its smaller key sizes and faster computations make it an attractive choice for resource-constrained environments and privacy-preserving protocols.

+

Expanding Your Knowledge with Advanced ECC Topics

+

To further enhance your understanding of elliptic curve cryptography, consider exploring advanced topics such as:

+
    +
  • Pairing-based cryptography: Utilizing bilinear pairings on elliptic curves to enable novel cryptographic primitives, such as Identity-Based Encryption (IBE) and Attribute-Based Encryption (ABE).
  • +
  • Lattice-based cryptography: Investigating the connections between elliptic curve cryptography and lattice-based cryptography, which is believed to be resistant to quantum attacks.
  • +
  • Isogeny-based cryptography: Studying isogenies between elliptic curves, which can be used to construct post-quantum cryptographic schemes.
  • +
+

Exploring Further Resources and Learning Materials

+

To dive deeper into elliptic curve arithmetic and its applications, consider the following resources:

+ +

By expanding your knowledge in elliptic curve arithmetic and exploring advanced topics, you can stay at the forefront of cryptography and contribute to the development of secure and efficient solutions for real-world problems.

+

You can find the complete sagemath code at the github repo github.com/thogiti.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/mastering-rank-one-constraint-system-r1cs-with-circom-examples/index.html b/mastering-rank-one-constraint-system-r1cs-with-circom-examples/index.html new file mode 100644 index 00000000..e6416f49 --- /dev/null +++ b/mastering-rank-one-constraint-system-r1cs-with-circom-examples/index.html @@ -0,0 +1,691 @@ + + + + + + + +Mastering Rank One Constraint System R1CS with Circom Examples | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Mastering Rank One Constraint System R1CS with Circom Examples

+
+

In Draft Mode

+

Overview

+

Rank-1 Constraint Systems, or R1CS, are a critical component in cryptographic protocols, especially those related to zero-knowledge proofs such as zk-SNARKS. They are a system of equations used to represent computations, and are particularly useful in scenarios where we want to prove that a certain computation was done correctly, without revealing any other information about the inputs or the computation itself.

+

In the context of zk-SNARKS, an arithmetic circuit is converted into a R1CS. Each constraint in the R1CS corresponds to one logic gate in the circuit. The "rank-1" refers to the rank of the matrix produced in this conversion process.

+

In the previous blog post, we saw a process flow of creating a Zero Knowledge Proof system. Here is the high level view of this flow:

+

Zero Knowledge Proof Process Flow

+

Constraint systems are collections of arithmetic constraints over a set of variables. They play an essential role in computational problems, particularly in the realm of cryptographic protocols and zero-knowledge proofs. In a constraint system, there are two types of variables: high-level variables (the secret inputs) and low-level variables (the internal inputs and outputs of the multiplication gates).

+

[Understanding the Role of R1CS in Zero-Knowledge Protocols]

+

Zero-Knowledge (ZK) protocols, which are commonly used in cryptography, require provers to demonstrate that they know a solution to a computational problem. This problem is often expressed as a Rank-1 Constraint System (R1CS).

+

An R1CS is essentially a collection of non-linear arithmetic constraints over a set of variables, also referred to as signals. The security of an R1CS primarily relies on its non-linear components, as these are the parts of the system that are challenging for an attacker to solve.

+

In contrast, the linear (additive) constraints, despite being part of the system, do not significantly contribute to its security. This is because these constraints are relatively straightforward to solve, making them less effective as a defense against potential attacks.

+

[Definition and Explanation of R1CS]

+

A Rank-1 Constraint System (R1CS) is a specific type of constraint system. It consists of two sets of constraints: multiplicative constraints and linear constraints. Each multiplicative constraint takes the form a_L * a_R = a_O, while each linear constraint takes the form W_L * a_L + W_R * a_R + W_O * a_O = W_V * (v + c). Here, a_L, a_R, and a_O represent the left input, right input, and output of each gate in the circuit. W_L, W_R, W_O, and W_V are weights applied to their respective inputs and outputs.

+

[Relation to Circuits of Logical Gates]

+

In the context of zk-SNARKs, an arithmetic circuit is converted into an R1CS. Each constraint corresponds to one logic gate in the circuit. This conversion is crucial because zk-SNARKs require computational problems to be expressed as a set of quadratic constraints, which are closely related to circuits of logical gates.

+

[Constructing R1CS for Zero Knowledge Proofs]

+

We'll delve into numerous examples illustrating how to construct Rank-1 Constraint Systems (R1CS) for given polynomial equations or statements, particularly when creating Zero Knowledge Proofs.

+

We'll utilize Circom and snarkjs, two powerful tools that facilitate the representation and handling of non-linear and linear constraints. These will help us understand how circuits are compiled and how a witness is created.

+

Please note, to follow along with this tutorial, you need to have snarkjs and Circom installed. You can install them using Node.js as follows:

+
npm install snarkjs
+
+

For Circom installation, follow the official documentation at docs.circom.io.

+

[Circom R1CS Examples]

+

Before we can create an r1cs, our polynomials and constraints need to be of the form

+

r1cs-form

+

Also, Circom expects the constraints to be of the form $Aw * Bw - Cw = 0$, where $A$ is the left hand side of matrix, $B$ is the right hand side of matrix and $C$ is the output matrix forms. The variable $w$ is witness vector. Here the witness $w$ will be of the form $[1, out, x, y, ...]$

+

The matrices $A$, $B$, and $C$ have the same number of columns as the witness venctor $w$, and each column represents the same variable the index is using.

+

We will see and verify this form by Circom when we compiled the Circom circuits and see the info on the constraints.

+

[Example 1]

+

Circuit $out = x*y$

+

Since our equation is already in the form of quadratic constraint, $out = x * y$ or $A*B-C=0$, where $x$ is the left hand side matrix $A$, $y$ is the right hand side matrix $B$ and $out$ is the results matrix.

+

The witness $w$ will be $[1, out, x, y]$.

+

Remember that the matrices $A$, $B$, and $C$ will share the same columns as the witness vector $w$.

+

$A$ is [0, 0, 1, 0], because only $x$ is present, and no other variables in the polynomial. +$B$ is [0, 0, 0, 1] because the variables in the right hand side are just $y$. +$C$ is [0, 1, 0, 0] because we only have the $out$ variable.

+

Now, we can verify that $Aw * Bw - Cw = 0$.

+

You can verify the above calculations of the matrices by running the below sagemath code.

+
# define the matrices
+C = matrix(ZZ, [[0,1,0,0]])
+A = matrix(ZZ, [[0,0,1,0]])
+B = matrix(ZZ, [[0,0,0,1]])
+
+x = randint(1,100000)
+y = randint(1,100000)
+out = x * y
+
+# witness vector
+witness = vector([1, out, x, y])
+
+# Calculate the results
+A_witness = A * witness
+B_witness = B * witness
+C_witness = C * witness
+AB_witness = vector([A_witness.dot_product(B_witness)])
+
+# Print the results
+print(f"A * witness = {A_witness}")
+print(f"B * witness = {B_witness}")
+print(f"C * witness = {C_witness}")
+print(f"(A * witness) * (B * witness) = {AB_witness}")
+
+# Check the equality
+result = C_witness == AB_witness
+print(f"result: ",result)
+
+# Check that the equality is true
+assert result, "result contains an inequality"
+
+
+

The output will look like below:

+
A * witness = (15189)
+B * witness = (90533)
+C * witness = (1375105737)
+(A * witness) * (B * witness) = (1375105737)
+result:  True
+
+
+

The Circom circuit template for this will look like below:

+
pragma circom 2.1.4;
+
+template Multiply2() {
+    signal input x;
+    signal input y;
+    signal output out;
+
+    out <== x * y;
+ }
+
+component main = Multiply2();
+
+/* INPUT = {
+    "X": "5",
+    "y": "77"
+} */
+
+

Let's compile this file with Circom compiler and create r1cs file. Run the below commands at the terminal.

+
circom multiply2.circom --r1cs --sym
+snarkjs r1cs print multiply2.r1cs
+
+

Here is the output from the above commands:

+

multiply2-r1cs

+

We should be expecting $xy-out=0$ because Circom shows the constraints as $AB-C=0$.

+
    +
  • Why do we this very big number 21888242871839275222246405745257275088548364400416034343698204186575808495616?
  • +
  • What is this number?
  • +
+

In Circom, math is done modulo 21888242871839275222246405745257275088548364400416034343698204186575808495617. The above number 21888242871839275222246405745257275088548364400416034343698204186575808495616 is equivalent to -1 in Circom.

+
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
+
+# 1 - 2 = -1
+(1 - 2) % p
+
+

The output is as below:

+
21888242871839275222246405745257275088548364400416034343698204186575808495616
+
+

So, the snarkjs command output is equivalent to $out - x*y =0$.

+

Our matrices are:

+

$A = [0, 0, -1, 0]$, $B = [0, 0, 0, 1]$, $C = [0, -1, 0, 0]$

+

Let’s recompile our circuit with a wasm solver:

+
circom multiply2.circom --r1cs --wasm --sym
+
+cd multiply2_js
+
+

We create the input.json file:

+
echo '{"x": "11", "y": "9"}' > input.json
+
+

Now, compute the witness:

+
node generate_witness.js multiply2.wasm input.json witness.wtns
+
+snarkjs wtns export json witness.wtns witness.json
+
+cat witness.json
+
+

We can check that circom is using the same column layout for witness $w$ we have been using: $[1, out, x, y]$, as $x$ was set to 11 and $y$ to 9 in our input.json.

+

multiply2-r1cs-wasm-witness

+

We can manually check our matrices if they satisfy the constraint $Aw*Bw = Cw$.

+

$w = [1, 99, 11, 9]$, $A = [0, 0, -1, 0]$, $B = [0, 0, 0, 1]$, $C = [0, -1, 0, 0]$

+

$Aw = -11$, $Bw = 9$, $Cw = -99$, $Aw*Bw = -99$.

+

[Example 2]

+

Circuit $out = {x * y * u * v}$

+

Remember that in R1CS, you can only have at most one multiplication in the constraint. The above equation has three multiplications. We use intermediate variables to flatten the polynomial like below.

+

$$u1 = x * y$$ +$$u2 = u * v$$ +$$out = u1 * u2$$

+

The witness vector will be $[1, out, x, y, u, v, u1, u2]$. This makes our matrices $A$, $B$, and $C$ will have eight columns, the same columns as $w$.

+

We have three constraints, hene we will have three rows in the matrices $A$, $B$, and $C$. Each row representing the corresponding constraint as written above.

+

r1cs-ex2

+

Constructing Matrix A from left hand terms

+

The witness vector is $[1, out, x, y, u, v, u1, u2]$.

+

The matrix A will be of the form:

+
A_{3,8} = 
+\begin{pmatrix}
+a_{1,1} & a_{1,2} & a_{1,3} & a_{1,4} & a_{1,5} & a_{1,6} & a_{1,7} & a_{1,8} \\
+
+a_{2,1} & a_{2,2} & a_{2,3} & a_{2,4} & a_{2,5} & a_{2,6} & a_{2,7} & a_{2,8} \\
+
+a_{3,1} & a_{3,2} & a_{3,3} & a_{3,4} & a_{3,5} & a_{3,6} & a_{3,7} & a_{3,8} 
+\end{pmatrix}
+
+

Now, let's fill the matrix $A$ for the first row (first constraint).

+

$$u1 = x * y$$

+

Since, there is only $x$ in the left hand terms. the first row of A will $[0, 0, 1, 0, 0, 0, 0, 0]$.

+

Hence, after the first constraint, we get

+
A_{3,8} = 
+\begin{pmatrix}
+0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
+
+a_{2,1} & a_{2,2} & a_{2,3} & a_{2,4} & a_{2,5} & a_{2,6} & a_{2,7} & a_{2,8} \\
+
+a_{3,1} & a_{3,2} & a_{3,3} & a_{3,4} & a_{3,5} & a_{3,6} & a_{3,7} & a_{3,8} 
+\end{pmatrix}
+
+

Now, let's fill the matrix $A$ for the second row (second constraint).

+

$$u2 = u * v$$

+

Since there is $u$ in the left hand side term, we get the second row of A to be $[0, 0, 0, 0, 1, 0, 0, 0]$.

+

Hence, after the second constraint, we get

+
A_{3,8} = 
+\begin{pmatrix}
+0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
+
+0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
+
+a_{3,1} & a_{3,2} & a_{3,3} & a_{3,4} & a_{3,5} & a_{3,6} & a_{3,7} & a_{3,8} 
+\end{pmatrix}
+
+

Now, let's fill the matrix $A$ for the third row (third constraint).

+

$$out = u1 * u2$$

+

Since there is $u1$ in the left hand side term, we get the third row of A to be $[0, 0, 0, 0, 0, 0, 1, 0]$.

+

Hence, after the third constraint, we get the final form of matrix $A$.

+
A = 
+\begin{array}{c}
+\begin{matrix}
+1&out & x & y & u & v & u1 & u2
+\end{matrix}\\
+\begin{bmatrix}
+    0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 
+\end{bmatrix}
+\color{red}\begin{matrix}R_1\\R_2\\R_3\end{matrix}\hspace{-1em}\\
+\end{array}
+
+

Here is the final matrix A in the tabular form:

+ + + + +
1outxyuvu1u2
R100100000
R200001000
R300000010
+

[Method 2]

+

Alternatively, we can express the left hand side terms in the three constraints as a linear combination of the witness vector.

+

$$u1 = x * y$$ +$$u2 = u * v$$ +$$out = u1 * u2$$

+

Here we can expand the left hand side terms using the witness vector $w$ and form the matrix $A$ as below.

+

$$u1 = (0.1 + 0.out + 1.x + 0.y + 0.u + 0.v + 0.u1 + 0.u2) * y$$ +$$u2 = (0.1 + 0.out + 0.x + 0.y + 1.u + 0.v + 0.u1 + 0.u2) * v$$ +$$out = (0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 1.u1 + 0.u2) * u2$$

+

Hence, the matrix $A$ can be written as

+
A = 
+\begin{bmatrix}
+    0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 
+\end{bmatrix}
+
+

Constructing Matrix B from right hand terms

+

We can follow the above steps but now we reduce the rhight hand side terms.

+

$$u1 = x * (0.1 + 0.out + 0.x + 1.y + 0.u + 0.v + 0.u1 + 0.u2)$$ +$$u2 = u * (0.1 + 0.out + 0.x + 0.y + 0.u + 1.v + 0.u1 + 0.u2)$$ +$$out = u1 * (0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 1.u2)$$

+

Hence, the matrix $B$ will as follows:

+
B = 
+\begin{bmatrix}
+    0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
+    0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 
+\end{bmatrix}
+
+

Constructing Matrix C from output terms

+

We can follow the above steps but now we reduce the output terms.

+

$$(0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 1.u1 + 0.u2) = x * y$$ +$$(0.1 + 0.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 1.u2) = u * v$$ +$$(0.1 + 1.out + 0.x + 0.y + 0.u + 0.v + 0.u1 + 0.u2) = u1 * u2$$

+

Hence, the matrix $B$ will as follows:

+
C = 
+\begin{bmatrix}
+    0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\
+    0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
+    0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 
+\end{bmatrix}
+
+

We can verify the above using the below sagemath code:

+

+# define the matrices
+A = matrix([[0,0,1,0,0,0,0,0],
+            [0,0,0,0,1,0,0,0],
+            [0,0,0,0,0,0,1,0]])
+
+B = matrix([[0,0,0,1,0,0,0,0],
+            [0,0,0,0,0,1,0,0],
+            [0,0,0,0,0,0,0,1]])
+
+C = matrix([[0,0,0,0,0,0,1,0],
+            [0,0,0,0,0,0,0,1],
+            [0,1,0,0,0,0,0,0]])
+
+x = randint(1,100000)
+y = randint(1,100000)
+z = randint(1,100000)
+u = randint(1,100000)
+
+# reductions
+out = x * y * z * u
+v1 = x * y
+v2 = z * u
+
+
+# witness vector
+witness = vector([1, out, x, y, z, u, v1, v2])
+
+
+# Calculate the results
+A_witness = A*witness
+B_witness = B*witness
+C_witness = C*witness
+AB_witness = A_witness.pairwise_product(B_witness)
+
+# Print the results
+print(f"A * witness = {A_witness}")
+print(f"B * witness = {B_witness}")
+print(f"C * witness = {C_witness}")
+print(f"(A * witness) * (B * witness) = {AB_witness}")
+
+# Check the equality
+result = C_witness == AB_witness
+print(f"result: ",result)
+
+# Check that the equality is true
+assert result, "result contains an inequality"
+
+
+

The output will look like below:

+
A * witness = (85530, 65887, 6198615690)
+B * witness = (72473, 49454, 3258375698)
+C * witness = (6198615690, 3258375698, 20197418725537501620)
+(A * witness) * (B * witness) = (6198615690, 3258375698, 20197418725537501620)
+result:  True
+
+

Here is the Circom Circuit for this example:

+
pragma circom 2.1.4;
+
+template Multiply4() {
+    signal input x;
+    signal input y;
+    signal input u;
+    signal input v;
+    
+    signal u1;
+    signal u2;
+    
+    signal out;
+    
+    u1 <== x * y;
+    u2 <== u * v;   
+    out <== u1 * u2;
+}
+
+component main = Multiply4();
+
+/* INPUT = {
+    "X": "5",
+    "y": "10",
+    "u": "3",
+    "v": "4",
+} */
+
+
+

Let's compile this and generate a witness.

+
circom multiply4.circom --r1cs --wasm --sym
+
+snarkjs r1cs print multiply4.r1cs
+
+cd multiply4_js
+
+echo '{"x": "5", "y": "10", "u": "3", "v": "4"}' > input.json
+
+node generate_witness.js multiply4.wasm input.json witness.wtns
+
+snarkjs wtns export json witness.wtns witness.json
+
+cat witness.json
+
+
+

We get the following output.

+

multiply4-r1cs-wasm-witness-output

+

[Example 3]

+

Circuit $out = x*y + 2$

+

We can repeat the above reduction process and get the matrices. We write the matrices for $out-2=x*y$. We have one constraint and witness vector will be $w = [1, out, x, y]$.

+

$A = [0, 0, 1, 0]$, $B = [0, 0, 0, 1], $C = [-2, 1, 0, 0]

+

[Example 4]

+

Circuit $out = 2x^2 + y$

+

We write the matrices for $out-y=2x^2$. We have one constraint and witness vector will be $w = [1, out, x, y]$.

+

$A = [0, 0, 2, 0]$, $B = [0, 0, 1, 0], $C = [0, 1, 0, -1]

+

[Example 5]

+

Circuit $out = 3x^2y + 5xy - x - 2y + 3$

+

We can reduce the equations to below:

+

$$u1 = 3xx$$ +$$u2 = u1*y$$ +$$x+2y-3-u2+out = 5xy$$

+

We have three constraints. Our witness vector will be $w = [1, out, x, y, u1, u2]$.

+

Hence, the our matrices $A$, $B$, and $C$ can be written as

+
A = 
+\begin{bmatrix}
+    0 & 0 & 3 & 0 & 0 & 0  \\
+    0 & 0 & 0 & 0 & 1 & 0  \\
+    0 & 0 & 5 & 0 & 0 & 0 
+\end{bmatrix}
+
+
B = 
+\begin{bmatrix}
+    0 & 0 & 1 & 0 & 0 & 0  \\
+    0 & 0 & 0 & 1 & 1 & 0  \\
+    0 & 0 & 0 & 1 & 0 & 0 
+\end{bmatrix}
+
+
C = 
+\begin{bmatrix}
+    0 & 0 & 0 & 0 & 1 & 0  \\
+    0 & 0 & 0 & 0 & 0 & 1  \\
+    -3 & 1 & 1 & 2 & 0 & -1 
+\end{bmatrix}
+
+

We can check these matrices with below sagemath code:

+

+# define the matrices
+
+A = matrix([[0,0,3,0,0,0],
+               [0,0,0,0,1,0],
+               [0,0,1,0,0,0]])
+
+B = matrix([[0,0,1,0,0,0],
+               [0,0,0,1,0,0],
+               [0,0,0,5,0,0]])
+
+C = matrix([[0,0,0,0,1,0],
+               [0,0,0,0,0,1],
+               [-3,1,1,2,0,-1]])
+
+x = randint(1,100000)
+y = randint(1,100000)
+
+
+# reductions
+out = 3 * x * x * y + 5 * x * y - x- 2*y + 3
+# the intermediate variables
+u1 = 3*x*x
+u2 = u1 * y
+
+
+# witness vector
+witness = vector([1, out, x, y, u1, u2])
+
+
+# Calculate the results
+A_witness = A*witness
+B_witness = B*witness
+C_witness = C*witness
+AB_witness = A_witness.pairwise_product(B_witness)
+
+# Print the results
+print(f"A * witness = {A_witness}")
+print(f"B * witness = {B_witness}")
+print(f"C * witness = {C_witness}")
+print(f"(A * witness) * (B * witness) = {AB_witness}")
+
+# Check the equality
+result = C_witness == AB_witness
+print(f"result: ",result)
+
+# Check that the equality is true
+assert result, "result contains an inequality"
+
+

We will see the output:

+
A * witness = (133875, 5974171875, 44625)
+B * witness = (44625, 61540, 307700)
+C * witness = (5974171875, 367650537187500, 13731112500)
+(A * witness) * (B * witness) = (5974171875, 367650537187500, 13731112500)
+result:  True
+
+

Let's compile this and generate a witness.

+
circom Example5.circom --r1cs --wasm --sym
+
+snarkjs r1cs print Example5.r1cs
+
+cd Example5_js
+
+echo '{"x": "5", "y": "10"}' > input.json
+
+node generate_witness.js Example5.wasm input.json witness.wtns
+
+snarkjs wtns export json witness.wtns witness.json
+
+cat witness.json
+
+
+

We get the following output.

+

multiply4-r1cs-wasm-witness-output

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/page/1/index.html b/page/1/index.html new file mode 100644 index 00000000..0e64fd1c --- /dev/null +++ b/page/1/index.html @@ -0,0 +1,6 @@ + + + + +Redirect +

Click here to be redirected.

diff --git a/page/2/index.html b/page/2/index.html new file mode 100644 index 00000000..b61e540e --- /dev/null +++ b/page/2/index.html @@ -0,0 +1,276 @@ + + + + + + + +Home | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ +

Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors

+
+

Overview +We will implement dot product of two vectors of size N using Zero Knowledge Proofs (ZKP) in Circom, Halo2, . According to k12.libretexts.org, the dot product of two vectors A and B of size N is given by: +A.B = a1*b1 + a2*b2 + ... + aN*bN + + +Overview +Process Flow of a Zero…

+
+
+
+ +

Paper Review - Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning

+
+

Overview +The paper aimed to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM) using machine learning methods. The study found that machine learning models demonstrated a superior ability to predict adverse cardiac events compared …

+
+
+
+ +

Paper Review - Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes

+
+

Overview +The paper presents a machine learning approach for classification of hypertrophic cardiomyopathy phenotypes using native T1 mapping radiomics. +Citation of the Paper +Antonopoulos, A.S., Boutsikou, M., Simantiris, S. et al. Machine learning of native T1 mapping radiomics f…

+
+
+
+ +

Different types of Zero Knowledge Proofs (Interactive and Non-interactive)

+
+

Overview +Zero knowledge proofs (ZKP) are cryptographic protocols that enable one party (the prover) to prove to another party (the verifier) the truth of a statement without revealing any additional information beyond the statement's validity. ZKPs are incredibly useful in scenar…

+
+
+
+ +

Explanation of the Concept of Zero Knowledge Proofs

+
+

Overview +Zero-knowledge proofs (ZKPs) are a groundbreaking concept in cryptography that allows one party to prove to another that a statement is true, without revealing any specific information about the statement itself. This technique is particularly useful in preserving privac…

+
+
+
+ +

A brief introduction to Zero Knowledge Proofs (ZKPs)

+
+

+Introduction + +A. Definition of Zero Knowledge Proofs (ZKPs) +B. Overview of the Benefits of Using ZKPs + + +How ZKPs Work + +A. Overview of the ZKP Process +B. Explanation of the Three Stages of the ZKP Process + + +Applications of ZKPs + +A. Cryptocurrency Transactions +B. Identity Manageme…

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/index.html b/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/index.html new file mode 100644 index 00000000..5a25d645 --- /dev/null +++ b/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/index.html @@ -0,0 +1,349 @@ + + + + + + + +Paper Review - Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Paper Review - Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes

+
+

Overview

+

The paper presents a machine learning approach for classification of hypertrophic cardiomyopathy phenotypes using native T1 mapping radiomics.

+

Citation of the Paper

+

Antonopoulos, A.S., Boutsikou, M., Simantiris, S. et al. Machine learning of native T1 mapping radiomics for classification of hypertrophic cardiomyopathy phenotypes. Sci Rep 11, 23596 (2021). https://doi.org/10.1038/s41598-021-02971-z

+

FAQs

+

Explain Abstract of this paper in simple terms

+

The paper explores the use of machine learning techniques to classify hypertrophic cardiomyopathy (HCM) phenotypes using radiomic features of the left ventricle. Radiomic features are mathematical representations of the texture and intensity of medical images. The study found that these features are useful in identifying different HCM phenotypes, which may have important implications for diagnosis and treatment of the disease.

+

Explain Abstract of this paper in 2 lines

+

The paper investigates machine learning techniques to identify hypertrophic cardiomyopathy (HCM) phenotypes using radiomic features. The study shows that radiomic features can be used to classify different HCM phenotypes, which could aid in diagnosis and treatment of the disease.

+

Explain Abstract of this paper like I am five years old

+

The paper talks about using computers to help doctors identify different types of heart problems. They do this by looking at pictures of the heart and finding patterns in the picture that tell them which type of heart problem it is. This can help doctors give the right treatment to the patient.

+

What are the contributions of this paper

+

The paper shows that radiomic features can be used to classify different types of hypertrophic cardiomyopathy (HCM) phenotypes, which can aid in the diagnosis and treatment of the disease. This demonstrates the potential of machine learning techniques in medical image analysis and highlights the importance of considering radiomic features for clinical decision making.

+

Explain the practical implications of this paper

+

The paper suggests that machine learning techniques can be used to improve diagnosis and treatment of hypertrophic cardiomyopathy (HCM) by identifying different HCM phenotypes. This can help doctors give more targeted treatment to patients, potentially improving outcomes and quality of life. The use of radiomic features in medical imaging analysis may also have broader applications in other areas of medicine.

+

Summarize introduction of this paper

+

The introduction of this paper provides an overview of hypertrophic cardiomyopathy (HCM), a heart disease that affects the structure of the heart muscle. The authors discuss the limitations of current diagnostic methods, which rely on subjective assessments of echocardiograms and other imaging techniques. They argue that there is a need for more objective and quantitative measures to aid in the diagnosis and classification of HCM.

+

The authors propose the use of radiomic features, which are mathematical representations of the texture and intensity of medical images, as a potential solution. They describe how these features can capture subtle differences in tissue composition and microstructure that may be indicative of different HCM phenotypes. The authors also highlight the potential of machine learning techniques to analyze large amounts of radiomic data and identify patterns that may not be apparent to the naked eye.

+

The authors then outline the objectives of the study, which include identifying radiomic features that are stable across different imaging modalities, exploring the relationships between different radiomic features, and using machine learning techniques to classify different HCM phenotypes based on radiomic features. They also describe the study design, which involved two separate cohorts of patients, and the methods used to extract and analyze radiomic data from cardiac MRI scans.

+

Overall, the introduction provides a detailed background and rationale for the study, highlighting the potential of radiomic features and machine learning techniques to improve the diagnosis and classification of HCM.

+

Methods used in this paper

+

Study Population

+

The study comprised two arms, with the first arm comprised of 20 CMR scans with available native T1 mapping randomly selected by their archive, which served for the purpose of stability assessment (i.e., inter-observer variability) of extracted radiomic features from T1 maps, which were included in further analysis in Study Arm 2.

+

Study Arm 2 included a total of 152 consecutive patients undergoing a CMR scan (period 2019–2020) and native T1 mapping as follows: individuals without evidence of structural heart disease on CMR (n = 30), patients with left ventricular hypertrophy (LVH, i.e. increased wall thickness ≥ 12 mm or increased LV mass index) of various causes (athletes, valvular heart disease, hypertension etc., n = 30), patients with known HCM (n = 61) and patients with known cardiac amyloidosis (n = 28).

+

The complete data pipeline, data sampling and ML workflow can be found in the Fig 1. ML workflow and data pipeline

+

Data Extraction and Analysis

+

They extracted a total of 850 radiomic features from T1 maps by cardiac magnetic resonance (CMR) and explored their value in disease classification. They applied principal component analysis and unsupervised clustering in exploratory analysis, and then machine learning for feature selection of the best radiomic features that maximized the diagnostic value for cardiac disease classification.

+

They used the following steps to process the data:

+
    +
  • Radiomic feature extraction: Radiomic features were extracted from the T1 maps using the PyRadiomics library.
  • +
  • Exploratory analysis: Unsupervised hierarchical clustering was performed on the extracted radiomic features.
  • +
  • Feature selection: The authors used machine learning algorithms to select the best radiomic features for classification of cardiac disease phenotypes. They used a combination of random forests and recursive feature elimination (RFE).
  • +
  • Model validation: The selected radiomic features were used to train a machine learning model for classification of cardiac disease phenotypes. The model was validated using internal and external datasets.
  • +
  • The diagnostic performance of the radiomics model was evaluated using the area under the receiver operating characteristic curve (AUC).
  • +
  • Statistical analysis was performed using chi-squared tests and logistic regression models.
  • +
+

The exploratory data analysis can be found in the Fig 2. exploratory data analysis

+

Results of the paper

+

The results of the paper are as follows:

+
    +
  • The first three principal components of the T1 radiomics were distinctively correlated with cardiac disease type.
  • +
  • Unsupervised hierarchical clustering of the population by myocardial T1 radiomics was significantly associated with myocardial disease type.
  • +
  • After feature selection, internal validation, and external testing, a model of T1 radiomics had good diagnostic performance (AUC 0.753) for multinomial classification of disease phenotype (normal vs. LVH vs. HCM vs. cardiac amyloid).
  • +
  • A subset of six radiomic features outperformed mean native T1 values for classification between myocardial health vs. disease and HCM phenocopies.
  • +
+

Therefore, the results of the paper suggest that myocardial texture assessed by native T1 maps is linked to features of cardiac disease, and myocardial radiomic phenotyping could enhance the diagnostic yield of T1 mapping for myocardial disease detection and classification.

+

The performance analysis anc confusion matrix can be found in the Fig 4. performance analysis

+

Conclusions from the paper

+

The conclusions from the paper are as follows:

+
    +
  • Radiomic features provide added diagnostic value for distinction between healthy and diseased myocardium, as well as for differentiation between HCM and relevant phenocopies, such as amyloidosis, on top of native T1.
  • +
  • The application of radiomics to standard native T1 mapping is a promising approach for the texture characterization of the human myocardium and for further enhancing the diagnostic value of CMR.
  • +
+

Therefore, the paper suggests that myocardial radiomic phenotyping using T1 radiomics analysis could enhance the diagnostic yield of T1 mapping for myocardial disease detection and classification.

+

Limitations of this paper

+

The limitations of this paper are as follows:

+
    +
  • The study was conducted at a single center with a relatively small sample size, which may limit the generalizability of the findings.
  • +
  • Only the basal slice of the T1 maps was used for texture analysis, which may not fully represent the entire myocardium.
  • +
  • The reproducibility of radiomics features across different scanners/vendors and acquisition sequences is still an issue, which may limit the clinical application of radiomics.
  • +
  • The study did not include a comparison with other imaging modalities or biomarkers, which may limit the assessment of the added diagnostic value of radiomics.
  • +
  • The study did not include a longitudinal follow-up to assess the prognostic value of radiomics features for disease progression or response to treatment.
  • +
+

Therefore, these limitations should be taken into consideration when interpreting the results of the study.

+

Future works suggested in this paper

+

The future works suggested in this paper are as follows:

+
    +
  • Further research is needed to harmonize the readouts between different scanners/vendors and acquisition sequences to address the reproducibility issues of radiomics.
  • +
  • Future studies should include a larger sample size and a multi-center design to validate the findings of this study and improve the generalizability of the results.
  • +
  • Future studies should also include a comparison with other imaging modalities or biomarkers to assess the added diagnostic value of radiomics.
  • +
  • Longitudinal follow-up studies are needed to assess the prognostic value of radiomics features for disease progression or response to treatment.
  • +
  • Future studies should also investigate the potential of radiomics for other CMR applications, such as perfusion imaging and late gadolinium enhancement imaging.
  • +
+

Therefore, these future works could help to further validate and improve the clinical application of radiomics in CMR.

+

Advanced Questions

+

How does the use of radiomics analysis enhance the diagnostic value of CMR for myocardial texture phenotyping?

+

Using radiomic features can improve the ability of CMR to distinguish between healthy and diseased myocardium, as well as between HCM and other similar conditions. Radiomic features provide additional information about the texture and heterogeneity of the myocardium that may not be captured by conventional CMR parameters like native T1 values. Radiomic features are quantitative measures of image texture and heterogeneity that can be extracted from medical images using advanced image processing techniques.

+

In this study, the authors extracted radiomic features from T1 maps generated by CMR and used machine learning to identify the best radiomic features for classifying cardiac disease. The results showed that a model using T1 radiomics had good diagnostic performance for categorizing different types of cardiac disease. Additionally, a subset of six radiomic features performed better than mean native T1 values for differentiating between healthy and diseased myocardium and identifying HCM phenocopies.

+

Therefore, using radiomic features can enhance the accuracy of T1 mapping for detecting and classifying myocardial disease.

+

The population heatmap can be found in the Fig 3. performance analysis

+

What were some limitations of this study, and how might they impact the generalizability of its findings to other populations or imaging settings?

+

The limitations of the study are summarized above in the limitations section.

+

These limitations may impact the generalizability of the findings to other populations or imaging settings. Therefore, further studies with larger sample sizes, multi-center designs, and longitudinal follow-up are needed to validate the findings of this study and improve the generalizability of the results. Additionally, the reproducibility of radiomics features across different scanners/vendors and acquisition sequences should be addressed to improve the clinical application of radiomics.

+

Can you explain how radiomic features are extracted from medical images, and what types of information they can provide about tissue volume, shape, and texture?

+

Radiomic features are quantitative measures of image texture and heterogeneity that can be extracted from medical images using advanced image processing techniques. In this study, radiomic features were extracted from T1 maps by CMR. The process of extracting radiomic features involves the following steps:

+
    +
  • +

    Image acquisition: Medical images are acquired using various imaging modalities such as CT, MRI, or PET.

    +
  • +
  • +

    Image segmentation: The anatomical volumes of interest are segmented from the background using manual or automated methods.

    +
  • +
  • +

    Feature extraction: Radiomic features are extracted from the segmented volumes using mathematical algorithms that analyze the spatial relationship of (dis)similar voxels. These features can provide information on tissue volume, shape, and texture, such as:

    +
  • +
  • +

    First-order statistics: Measures of the distribution of pixel/voxel intensities, such as mean, median, standard deviation, skewness, and kurtosis.

    +
  • +
  • +

    Second-order statistics: Measures of the spatial relationship between pixels/voxels, such as gray-level co-occurrence matrix (GLCM), gray-level run-length matrix (GLRLM), and gray-level size zone matrix (GLSZM).

    +
  • +
  • +

    Higher-order statistics: Measures of the spatial relationship between higher-order features, such as fractal dimension, wavelet transform, and Laplacian of Gaussian (LoG).

    +
  • +
+

Radiomic features can provide additional information about tissue texture and heterogeneity that may not be captured by conventional imaging parameters. Therefore, radiomic analysis has the potential to enhance the diagnostic and prognostic value of medical imaging for various diseases.

+

The most important radiomic features selected can be found in the Table 2. diagnostic value

+

In what ways has radiomic phenotyping been successfully used in other medical fields such as clinical oncology? Are there any key differences between these applications and those explored in this paper?

+

Radiomic phenotyping has been successfully used in clinical oncology to characterize the distinct biological phenotypes of tumors and provide relevant information for diagnosis, prognosis, and treatment planning. For example, radiomic features extracted from CT or MRI images of lung cancer have been shown to be associated with tumor stage, histology, and patient survival. Similarly, radiomic features extracted from MRI images of glioblastoma have been shown to be associated with tumor grade, molecular subtype, and patient survival.

+

The key difference between these applications and those explored in this paper is the imaging modality and the disease being studied. In this paper, radiomic features were extracted from T1 maps by CMR to enhance the diagnostic value of T1 mapping for myocardial disease detection and classification. Therefore, the application of radiomic phenotyping in this paper is specific to CMR and myocardial disease. However, the underlying principle of radiomic analysis is the same across different imaging modalities and diseases, which is to extract quantitative measures of image texture and heterogeneity that can provide additional information for disease characterization and management.

+

The most important radiomic phenotyping predictors data can be found in the Table 1. diagnostic value

+

What were the principal components identified through the principal component analysis and how were they used to explore associations with disease background?

+

The principal component analysis (PCA) was performed on the radiomic features extracted from T1 maps by CMR to identify the principal components (PC) that describe most of the phenotypic variation in the study population. The first two components (PC1, PC2) were used to explore associations with disease background in relevant cluster plots. The first three principal components of the T1 radiomics were distinctively correlated with cardiac disease type. The unsupervised hierarchical clustering of the population by myocardial T1 radiomics was significantly associated with myocardial disease type (chi 2 = 55.98, p < 0.0001). Therefore, the PCA helped to identify the most relevant radiomic features that are associated with cardiac disease type and provided a basis for further analysis of the radiomic features.

+

The pinciple component analysis can be found in the Fig 2. pinciple component data analysis

+

Can you explain the process of stability assessment of extracted radiomic features from T1 maps and how it was used to limit the analysis to radiomic features that could be of value as imaging biomarkers?

+

The stability assessment of extracted radiomic features from T1 maps was performed to limit the analysis to radiomic features that could be of value as imaging biomarkers. The process involved the following steps:

+
    +
  • Twenty scans from Study Arm 1 were used to assess the coefficient of variation (CV) of each radiomic feature in multiple delineations by two independent operators.
  • +
  • The CV was calculated as the ratio of the standard deviation to the mean of the radiomic feature across multiple delineations.
  • +
  • Only those radiomic features with multiple delineation CV < 10% were included in further analysis (n = 628).
  • +
  • This step was performed to ensure that the radiomic features were stable and reproducible across different delineations and operators.
  • +
  • The remaining radiomic features were then used for further analysis, including exploratory analysis, feature selection, and machine learning for disease classification.
  • +
+

By performing the stability assessment, the study was able to limit the analysis to radiomic features that were stable and reproducible, which could be of value as imaging biomarkers for disease classification. This step helped to ensure that the radiomic features used in the analysis were reliable and could provide meaningful information for disease characterization.

+

What specific machine learning algorithms were used in this study for feature selection and classification of cardiac disease phenotype?

+

The paper did not provide specific details on the machine learning algorithms used for feature selection and classification of cardiac disease phenotype. However, the paper mentioned that machine learning was used for feature selection of the best radiomic features that maximized the diagnostic value for cardiac disease classification. The paper also mentioned that a model of T1 radiomics had good diagnostic performance (AUC 0.753) for multinomial classification of disease phenotype (normal vs. LVH vs. HCM vs. cardiac amyloid). Therefore, the study used machine learning algorithms for feature selection and classification of cardiac disease phenotype, but the specific algorithms used were not mentioned in the paper.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/index.html b/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/index.html new file mode 100644 index 00000000..309cd944 --- /dev/null +++ b/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/index.html @@ -0,0 +1,371 @@ + + + + + + + +Paper Review - Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Paper Review - Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning

+
+

Overview

+

The paper aimed to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM) using machine learning methods. The study found that machine learning models demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification. The authors suggest that these modern machine learning methods may enhance identification of high-risk HCM subpopulations.

+

Citation of the Paper

+

Stephanie M. Kochav, Yoshihiko Raita, Michael A. Fifer, Hiroo Takayama, Jonathan Ginns, Mathew S. Maurer, Muredach P. Reilly, Kohei Hasegawa, Yuichi J. Shimada, Predicting the development of adverse cardiac events in patients with hypertrophic cardiomyopathy using machine learning, International Journal of Cardiology, Volume 327, 2021, Pages 117-124, ISSN 0167-5273, https://doi.org/10.1016/j.ijcard.2020.11.003.

+

FAQs

+

Explain Abstract of this paper in simple terms

+

This paper is about using machine learning to predict adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study found that machine learning models were better at predicting these events than traditional methods. The authors suggest that these new methods could help identify high-risk patients with HCM.

+

Explain Abstract of this paper in 2 lines

+

This paper aimed to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM) using machine learning methods. The study found that machine learning models demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification.

+

Explain Abstract of this paper like I am five years old

+

This paper is about using a computer to help doctors predict if someone with a heart problem called hypertrophic cardiomyopathy (HCM) might get very sick or die. The computer was better at predicting this than the doctors were.

+

What are the contributions of this paper

+

The contributions of this paper are:

+
    +
  1. Using machine learning methods to improve the prediction of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM).
  2. +
  3. Demonstrating that machine learning models were better at predicting adverse cardiac events compared to traditional methods.
  4. +
  5. Suggesting that these new methods could help identify high-risk patients with HCM.
  6. +
+

Explain the practical implications of this paper

+

The practical implications of this paper are significant for patients with hypertrophic cardiomyopathy (HCM) and their healthcare providers. The paper proposes the use of machine learning methods to improve the prediction of adverse cardiac events in patients with HCM. The development of accurate risk stratification methods can help identify high-risk patients who may benefit from more intensive monitoring or treatment. This can lead to better patient outcomes and improved quality of life. The machine learning models developed in this paper outperformed conventional risk stratification methods, demonstrating their potential to enhance the identification of high-risk HCM subpopulations. The use of machine learning methods in clinical practice can also help healthcare providers make more informed decisions about patient care and resource allocation. Overall, this paper highlights the potential of machine learning methods to improve risk stratification and patient outcomes in HCM.

+

Summarize introduction of this paper

+

The introduction of this paper provides an overview of hypertrophic cardiomyopathy (HCM), which is a heart condition characterized by thickening of the heart muscle. HCM is a common cause of sudden cardiac death in young people and athletes. The paper highlights that current methods for predicting adverse cardiac events in patients with HCM are not very accurate, and there is a need for better risk stratification methods. The authors propose using machine learning methods to improve the prediction of adverse cardiac events in patients with HCM. The paper aims to develop and evaluate machine learning models that can identify high-risk patients with HCM and improve patient outcomes. The authors suggest that these new methods could enhance the identification of high-risk HCM subpopulations and improve patient care.

+

Methods used in this paper

+

In this paper, the authors used a prospective cohort study design to evaluate the use of machine learning methods for predicting adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study included 183 adults with HCM who were followed up for a median of 2.2 years. The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death.

+

The authors used a logistic regression model as the reference model, which included known predictors of adverse cardiac events in HCM. They also used random forest classification to identify 20 predictive characteristics based on a priori knowledge and machine learning methods. Four machine learning models were developed using different algorithms, including elastic net regression, support vector machines, random forest, and gradient boosting.

+

The performance of the machine learning models was evaluated using measures such as sensitivity, specificity, and the area under the receiver-operating-characteristic curve (AUC-ROC). The results showed that all four machine learning models outperformed the reference model in predicting adverse cardiac events in patients with HCM. The elastic net regression model had the highest AUC-ROC of 0.93, compared to 0.79 for the reference model. The authors concluded that machine learning methods have the potential to enhance risk stratification and improve patient outcomes in HCM.

+

Study Population

+

The study population in this paper consisted of 183 adults with hypertrophic cardiomyopathy (HCM). The study design was a prospective cohort study, which followed up the patients for a median of 2.2 years to evaluate the use of machine learning methods for predicting adverse cardiac events in patients with HCM.

+

Data Extraction and Analysis

+

The data extraction in this paper involved collecting clinical and demographic data from the study participants, including age, sex, family history, medical history, and echocardiographic measurements. The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death.

+

The analysis in this paper involved the use of machine learning methods to develop predictive models for adverse cardiac events in patients with HCM. The authors used a logistic regression model as the reference model and developed four machine learning models using different algorithms, including elastic net regression, support vector machines, random forest, and gradient boosting. The performance of the models was evaluated using measures such as sensitivity, specificity, and the area under the receiver-operating-characteristic curve (AUC-ROC).

+

The baseline clinical characteristics can be found in the Table 1. clinical characteristics

+

Results of the paper

+

The results of the paper showed that all four machine learning models outperformed the reference model in predicting adverse cardiac events in patients with HCM. The elastic net regression model had the highest AUC-ROC of 0.93, compared to 0.79 for the reference model. The sensitivity and specificity of the elastic net regression model were 88% and 84%, respectively. The majority of the outcome events (85%) were heart transplants. The authors concluded that machine learning methods have the potential to enhance risk stratification and improve patient outcomes in HCM.

+

The predictive performance analysis can be found in the Table 3. predictive performance analysis

+

Conclusions from the paper

+

The paper concluded that machine learning methods have the potential to improve risk stratification and predict adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). The study found that the machine learning models outperformed the conventional logistic regression model in predicting adverse cardiac events. The elastic net regression model had the highest predictive accuracy, with an AUC-ROC of 0.93, sensitivity of 88%, and specificity of 84%. The authors suggest that these modern machine learning methods may enhance identification of high-risk HCM subpopulations and improve patient outcomes.

+

The confusion matrix can be found the Table 4. confusion matrix

+

Limitations of this paper

+

There are several limitations to this paper, including:

+
    +
  1. +

    The sample size of the study was relatively small, which may limit the generalizability of the findings to larger populations.

    +
  2. +
  3. +

    The study was conducted at a single center, which may limit the generalizability of the findings to other settings.

    +
  4. +
  5. +

    The outcome of interest was a composite of death due to heart failure, heart transplant, and sudden death, which may not capture all adverse cardiac events that are relevant to patients with HCM.

    +
  6. +
  7. +

    The study did not include genetic testing, which is an important factor in the diagnosis and management of HCM.

    +
  8. +
  9. +

    The study did not include data on the use of implantable cardioverter-defibrillators (ICDs), which are commonly used in the management of HCM.

    +
  10. +
  11. +

    The study did not include data on the use of medications, such as beta-blockers and calcium channel blockers, which are commonly used in the management of HCM.

    +
  12. +
  13. +

    The study did not include data on the presence of comorbidities, such as hypertension and diabetes, which may affect the risk of adverse cardiac events in patients with HCM.

    +
  14. +
+

Overall, while the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM, further research is needed to validate these findings in larger, more diverse populations and to address the limitations of the study.

+

Future works suggested in this paper

+

The paper suggests several future directions for research, including:

+
    +
  1. +

    Validation of the machine learning models in larger, more diverse populations to assess their generalizability.

    +
  2. +
  3. +

    Incorporation of genetic testing data into the machine learning models to improve risk stratification.

    +
  4. +
  5. +

    Inclusion of data on the use of medications and implantable cardioverter-defibrillators (ICDs) in the machine learning models to improve risk stratification.

    +
  6. +
  7. +

    Development of machine learning models that can predict specific adverse cardiac events, such as sudden death or heart failure, rather than a composite outcome.

    +
  8. +
  9. +

    Exploration of the use of machine learning models in combination with other risk stratification tools, such as cardiac magnetic resonance imaging (MRI) and exercise stress testing.

    +
  10. +
  11. +

    Investigation of the potential of machine learning models to guide treatment decisions, such as the use of ICDs or the timing of surgical interventions.

    +
  12. +
+

Overall, the paper suggests that machine learning methods have the potential to improve risk stratification and patient outcomes in HCM, and that further research is needed to fully realize this potential.

+

Advanced Questions

+

How did the design of the research study impact the results and conclusions drawn from the data?

+

The design of the research study impacted the results and conclusions drawn from the data in several ways. The use of a prospective cohort design allowed for the collection of detailed clinical and demographic data, which was essential for the development of the machine learning models. However, the small sample size and single-center design of the study may limit the generalizability of the findings to other populations and settings. Additionally, the use of a composite outcome may not capture all relevant adverse cardiac events, which may limit the clinical utility of the machine learning models. Despite these limitations, the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM and suggests several future directions for research.

+

What specific design elements were used to ensure the validity and reliability of the study findings?

+

The paper did not provide specific information on the design elements used to ensure the validity and reliability of the study's findings. However, the use of a prospective cohort design and the application of modern machine learning methods are generally considered to be rigorous approaches to data collection and analysis. Additionally, the paper reported statistical measures of model performance, such as sensitivity, specificity, and area under the receiver-operating-characteristic curve, which provide information on the accuracy of the machine learning models. Overall, while the paper did not provide detailed information on the design elements used to ensure validity and reliability, the use of established research methods and reporting of statistical measures of model performance suggest that the study's findings are credible.

+

How did the design of the study compare to other similar studies in the same domain?

+

The paper did not provide a direct comparison of its design to other similar studies in the same domain. However, the use of a prospective cohort design and the application of modern machine learning methods are consistent with other recent studies that have explored the use of machine learning for risk stratification in HCM. Additionally, the paper's focus on a composite outcome of death due to heart failure, heart transplant, and sudden death is similar to other studies that have used composite outcomes to assess the effectiveness of risk stratification methods in HCM. Overall, while the paper did not provide a direct comparison of its design to other similar studies, its use of established research methods and focus on clinically relevant outcomes are consistent with other recent studies in the same domain.

+

Were there any limitations to the design of the study that may have impacted the results or conclusions?

+

The limitations of the paper are summarized in the above limitations section.

+

Despite these limitations, the study provides valuable insights into the potential of machine learning methods to improve risk stratification in HCM and suggests several future directions for research.

+

How could the design of the study be improved in future research to further advance the understanding of the domain?

+

To further advance the understanding of risk stratification in HCM, future research could consider the following improvements to the study design:

+
    +
  • Larger sample size: A larger sample size would increase the power of the study and improve the generalizability of the findings to other populations and settings.
  • +
  • Multi-center design: A multi-center design would increase the diversity of the study population and improve the generalizability of the findings to other centers or regions.
  • +
  • Longer follow-up period: A longer follow-up period would allow for the capture of additional relevant outcomes in patients with HCM.
  • +
  • More comprehensive outcome measures: The use of more comprehensive outcome measures, such as all-cause mortality or major adverse cardiac events, would provide a more complete picture of the effectiveness of risk stratification methods in HCM.
  • +
  • More complete data collection: The collection of more complete data on all relevant variables including the genetic testing data, medications, etc., would improve the accuracy of the machine learning models and reduce the risk of bias due to missing data.
  • +
+

Overall, these improvements to the study design could help to further advance the understanding of risk stratification in HCM and improve the accuracy of machine learning models for predicting adverse cardiac events.

+

What criteria were used for variable selection in this research paper, and how were these criteria chosen?

+

In this research paper, the criteria for variable selection were based on a combination of random forest classification and a priori knowledge. The random forest classification method was used to identify the most important predictors of adverse cardiac events in patients with HCM, while a priori knowledge was used to select additional predictors that are known to be clinically relevant in HCM. Specifically, the authors identified 20 predictive characteristics based on these criteria, which were then used to develop the machine learning models. Overall, the combination of random forest classification and a priori knowledge allowed for the selection of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.

+

The top predictors can be found in the Fig 3. top predictor features

+

Can you explain the process of variable selection in more detail, and how it impacted the results of the study?

+

In this study, the authors used a combination of random forest classification and a priori knowledge to select the variables that were most predictive of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). Random forest classification is a machine learning method that can identify the most important predictors of an outcome by constructing a large number of decision trees and aggregating their results. A priori knowledge refers to existing knowledge about the disease and its risk factors that can be used to guide variable selection.

+

The authors identified 20 predictive characteristics based on these criteria, which were then used to develop the machine learning models. These models were compared to a reference model based on logistic regression using known predictors. The results showed that the machine learning models significantly outperformed the reference model in predicting adverse cardiac events in patients with HCM.

+

Overall, the process of variable selection in this study allowed for the identification of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM. This improved the accuracy of the machine learning models and may enhance identification of high-risk HCM subpopulations.

+

Were any statistical methods used to aid in variable selection, and if so, which ones were used and why?

+

The authors used random forest classification to identify the most important predictors of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). Random forest classification is a machine learning method that can identify the most important predictors of an outcome by constructing a large number of decision trees and aggregating their results. This method was chosen because it is well-suited to handling complex, high-dimensional data and can identify non-linear relationships between predictors and outcomes. In addition to random forest classification, the authors also used a priori knowledge to select additional predictors that are known to be clinically relevant in HCM. Overall, the combination of these methods allowed for the selection of a comprehensive set of predictors that are both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.

+

Were any limitations or challenges encountered during the variable selection process, and if so, how were these addressed by the researchers?

+

The paper did not mention any specific limitations or challenges encountered during the variable selection process. However, the authors did use a combination of random forest classification and a priori knowledge to select the variables that were most predictive of adverse cardiac events in patients with hypertrophic cardiomyopathy (HCM). This approach allowed for the selection of a comprehensive set of predictors that were both statistically significant and clinically relevant for predicting adverse cardiac events in patients with HCM.

+

How did the machine learning models perform compared to the conventional risk stratification methods in predicting adverse cardiac events in patients with hypertrophic cardiomyopathy?

+

The machine learning models outperformed the reference model in predicting adverse cardiac events by demonstrating a higher predictive accuracy. The reference model had a predictive accuracy of 73%, while the machine learning models had a predictive accuracy of 85%. The machine learning models also had a higher sensitivity and specificity compared to the reference model.

+

These findings have implications for clinical practice as they suggest that machine learning methods may be useful in identifying high-risk subpopulations of patients with hypertrophic cardiomyopathy. This could help clinicians to tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.

+

The decision curve analysis of the models can be found in the Fig 2. decision curve analysis of the models

+

Can you explain the difference between sensitivity and specificity in the context of the predictive accuracy of the reference model and the machine learning models?

+

Here is the difference between sensitivity and specificity in the context of the predictive accuracy of the reference model and the machine learning models.

+
    +
  • Sensitivity is the proportion of true positive cases that are correctly identified by the model. In the context of this paper, sensitivity refers to the proportion of patients who actually experienced an adverse cardiac event and were correctly identified as high-risk by the model.
  • +
  • Specificity is the proportion of true negative cases that are correctly identified by the model. In the context of this paper, specificity refers to the proportion of patients who did not experience an adverse cardiac event and were correctly identified as low-risk by the model.
  • +
+

The machine learning models had higher sensitivity and specificity compared to the reference model, indicating that they were better at correctly identifying both high-risk and low-risk patients. This suggests that the machine learning models may be more effective at predicting adverse cardiac events in patients with hypertrophic cardiomyopathy compared to conventional risk stratification methods.

+

The sensitivity analysis of the ML models can be found in the Fig 1. sensitivity analysis

+

How long was the median follow-up period for the cohort of adults with hypertrophic cardiomyopathy, and what was the percentage of patients who developed an outcome event during this period?

+

The median follow-up period for the cohort of adults with hypertrophic cardiomyopathy was 2.2 years, with an interquartile range of 0.6 to 3.8 years. During this period, 33 out of 183 patients (18%) developed an outcome event, which was a composite of death due to heart failure, heart transplant, and sudden death. The majority of the outcome events (85%) were heart transplants.

+

What implications do the results of this study have for the identification of high-risk subpopulations of patients with hypertrophic cardiomyopathy, and how might these modern machine learning methods be applied in clinical practice?

+

The results of this study suggest that modern machine learning methods may enhance the identification of high-risk subpopulations of patients with hypertrophic cardiomyopathy (HCM). The machine learning models developed in this study demonstrated a superior ability to predict adverse cardiac events compared to conventional risk stratification methods.

+

In clinical practice, these machine learning methods could be used to identify patients with HCM who are at high risk of developing adverse cardiac events, such as heart failure, heart transplant, and sudden death. This could help clinicians to tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.

+

How was the data sampling conducted in this study, and what criteria were used to select the patients with hypertrophic cardiomyopathy (HCM) for the cohort?

+

The data sampling in this study was conducted using a prospective cohort design. Patients with hypertrophic cardiomyopathy (HCM) were recruited from a single center in Japan between 2010 and 2018. The inclusion criteria for the cohort were as follows:

+
    +
  • Adults aged 18 years or older
  • +
  • Diagnosis of HCM based on echocardiography or cardiac magnetic resonance imaging
  • +
  • Availability of clinical and laboratory data at the time of enrollment
  • +
+

Patients with a history of heart transplantation or septal myectomy were excluded from the cohort. Overall, 183 patients with HCM were included in the study.

+

The primary outcome events modeled can be found in the Table 2. primary outcome events

+

Can these modern machine learning methods be applied to other cardiovascular diseases to enhance risk stratification?

+

Yes, these modern machine learning methods can potentially be applied to other cardiovascular diseases to enhance risk stratification. However, further research is needed to determine the generalizability of these methods to other diseases and to optimize their use in clinical practice.

+

What are the potential clinical implications of using machine learning methods to identify high-risk HCM subpopulations?

+

The potential clinical implications of using machine learning methods to identify high-risk HCM subpopulations are that clinicians can tailor treatment plans and interventions to individual patients based on their predicted risk of adverse events. This could help improve patient outcomes and reduce healthcare costs by preventing adverse events and optimizing resource allocation. However, further research is needed to validate these findings and to determine the optimal use of machine learning methods in clinical practice.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/index.html b/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/index.html new file mode 100644 index 00000000..b02b8f3b --- /dev/null +++ b/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/index.html @@ -0,0 +1,335 @@ + + + + + + + +Paper Review - Zero Knowledge Proofs for Decision Tree Predictions and Accuracy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Paper Review - Zero Knowledge Proofs for Decision Tree Predictions and Accuracy

+
+

IN DRAFT MODE

+

Summary

+

Machine learning has become increasingly prominent and is widely used in various applications in practice. Despite its great success, the integrity of machine learning predictions and accuracy is a rising concern. The reproducibility of machine learning models that are claimed to achieve high accuracy remains challenging, and the correctness and consistency of machine learning predictions in real products lack any security guarantees. In this paper, the authors initiate the study of zero knowledge machine learning (ZKML) and propose protocols for zero knowledge decision tree predictions and accuracy tests.

+
    +
  • This paper presents a novel way of proving that a decision tree can make a correct prediction on a given data point without revealing anything about the decision tree itself. This is called a zero knowledge decision tree prediction protocol.
  • +
  • The protocol has two phases: a setup phase and a proving phase. In the setup phase, the decision tree is encoded in a way that takes linear time in the size of the tree. In the proving phase, the prediction is computed in a way that only depends on the length of the prediction path and the number of features of the data point.
  • +
  • The protocol uses several advanced techniques from the field of zero knowledge proofs for computations in the RAM model, but adapts them in non-black-box ways to suit the decision tree setting.
  • +
  • The protocol converts the decision tree prediction to a small circuit of size $O(d + h)$, where $d$ is the number of features and $h$ is the height of the tree.
  • +
  • The paper also extends the protocol to prove the accuracy of a decision tree on a testing dataset, which is called a zero knowledge decision tree accuracy protocol.
  • +
  • The accuracy protocol has two optimizations that reduce the number of hashes in the zero knowledge proof backend to be exactly equal to the number of nodes in the decision tree. This number does not depend on the size of the testing dataset and can be much smaller than $2^h$ if the tree is unbalanced.
  • +
  • The paper implements and evaluates both protocols on several real-world datasets. The results show that for a large decision tree with 23 levels and 1,029 nodes, it takes only 250 seconds to generate a proof for its accuracy on a testing dataset with 5,000 data points and 54 features. The proof size is 287KB, and it takes 15.6 seconds to verify it.
  • +
+

Citation of the Paper

+

Jiaheng Zhang, Zhiyong Fang, Yupeng Zhang, and Dawn Song. 2020. Zero Knowledge Proofs for Decision Tree Predictions and Accuracy. In Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security (CCS '20). Association for Computing Machinery, New York, NY, USA, 2039–2053. https://doi.org/10.1145/3372297.3417278

+

Zero Knowledge Proofs

+

The paper proposes the use of zero knowledge proofs (ZKP) to ensure the integrity of machine learning predictions and accuracy without leaking any information about the model itself. A zero knowledge proof allows a prover to produce a short proof that can convince any verifier that the result of a public function on the public input and secret input of the prover is correct. The secret input is usually referred to as the witness or auxiliary input. Zero knowledge proofs guarantee that the verifier rejects with overwhelming probability if the prover cheats on computing the result, while the proof reveals no extra information about the secret beyond the result.

+
    +
  • A zero-knowledge argument of knowledge for an $NP$ relation $R$ using a tuple of algorithms $(G, P, V)$ with the following properties.
  • +
  • The first property of this argument system is completeness, which means that for every public parameter $pp$ generated by $G(1^λ)$, if $(x; w) ∈ R$ and $π ← P(x, w, pp)$, then the probability that Verifier $V$ accepts the proof $(x, π, pp)$ as valid is $1$.
  • +
  • The second property is knowledge soundness, which ensures that any computationally-bounded prover $P^∗$ cannot convince $V$ of a false statement $(x; w) ∉ R$ without possessing a witness $w$. This property is guaranteed by the existence of a $PPT$ (probabilistic polynomial time) extractor $E$ that can extract $w$ from the executing process and randomness of $P^∗$ with negligible probability.
  • +
  • The third property is zero knowledge, which means that there exists a $PPT$ simulator $S$ that can simulate the view of any verifier $V^∗$ without knowing the witness $w$ or any information about $(x; w)$. This property ensures that the proof does not reveal any information about the witness or the statement beyond what is already known.
  • +
  • Finally, the definition introduces the concept of a succinct argument system, which limits the total communication between $P$ and $V$ (proof size) to be polynomial in the security parameter $λ$, the size of the input $x$, and the logarithm of the witness size $|w|$. This property ensures that the proof can be efficiently verified and transmitted without revealing any additional information.
  • +
+

Zero Knowledge Decision Tree

+

The model introduces a knowledgeable prover equipped with a pre-trained decision tree. The prover takes the initiative by committing to the decision tree upfront. Subsequently, the verifier raises queries about the predictions of data samples. To validate its accuracy, the prover generates a convincing proof alongside the results.

+

But first, let's introduce some concepts and definitions: $F$, a finite field; $T$, a binary decision tree with a height $h$ and $N$ nodes $(N ≤ 2^h −1)$; and $D$, the test dataset containing data points with $d$ features, where each data point, $a ∈ F^d$. Moreover, we have $[M]$, representing the set of all target classifications. The decision tree algorithm, denoted as $T : F^d → [M]$, is responsible for mapping data points to their corresponding classifications. When a data point $a ∈ D$ is fed into the decision tree, $T(a) ∈ [M]$ is the classification prediction.

+

Embracing transparency, the scheme assumes that both parties are aware of the height (or an upper bound) of the decision tree. Furthermore, they denote $comT$ as the commitment of the decision tree, $y_a$ as the class returned by the decision tree for data point $a$, and $π$ as the proof ingeniously crafted by the prover. Finally, ${0, 1}$ represents the verifier's output, indicating whether to accept or reject the classification and proof.

+

The zero-knowledge decision tree scheme (zkDT) consists of the four algorithms, $G$, $Commit$, $P$, and $V$:

+
    +
  1. +

    The $pp ← zkDT.G(1^λ)$ algorithm: With the security parameter given, generate the public parameter $pp$.

    +
  2. +
  3. +

    The $comT ← zkDT.Commit(T , pp, r)$ algorithm: This step involves the prover committing to the decision tree $T$ using a random point $r$.

    +
  4. +
  5. +

    The $(y_a, π ) ← zkDT.P(T , a, pp)$ algorithm: When given a data point $a$, the decision tree algorithm is executed, producing $y_a = T(a)$ and an accompanying proof $π$.

    +
  6. +
  7. +

    The ${0, 1} ← zkDT.V(comT , h, a, y_a, π , pp)$ algorithm: At this stage, the Verifier validates the prediction of $a$, the classification $y_a$, and the proof $π$ provided by the prover.

    +
  8. +
+

Intuition of the construction of zkDT

+

Here is a sequence diagram describing the specific construction of zkDT.

+

Intuition of the construction of zkDT

+
    +
  • The general idea of the construction of zkDT involves the prover $P$ sending the commitment of a decision tree $T$, $comT$, to the verifier $V$.
  • +
  • After receiving the data sample $a$ from the verifier, the prover computes $y_a$ and the corresponding witness $w$ for proving $y_a = T(a)$, then sends $y_a$ to the verifier.
  • +
  • This relationship $R = ((ya, a, comT); w)$ is treated as a $NP$ relationship as described above in the ZKP.
  • +
  • The verifier and the prover then invoke the backend zero-knowledge proofs protocol to verify the relationship $R$ without leaking any information of $T$ except for $y_a$.
  • +
  • This approach ensures that the privacy of the decision tree is preserved while still allowing for accurate predictions to be made and verified.
  • +
+

Authenticated Decision Tree

+

The paper introduces the concept of an Authenticated Decision Tree (ADT), which is a decision tree that has been authenticated by a commitment scheme. The ADT is used in the proposed protocols for zero knowledge decision tree predictions and accuracy tests. The ADT is constructed by hashing the root of the decision tree concatenated with a random point, which is used as the commitment.

+
    +
  • A naive approach to committing to a decision tree is to compute the hash of the entire tree, but this would result in high overhead when proving predictions.
  • +
  • Another approach is to use a Merkle hash tree on all the nodes in the decision tree, but this would still introduce overhead in the zero knowledge proof backend.
  • +
+

Construction of ADT

+

The paper describes the construction of the ADT, which involves hashing the root of the decision tree concatenated with a random point to produce the commitment. The paper notes that the commitment must be randomized in order to prove the zero knowledge property of the scheme later.

+

Construction of ADT

+
    +
  • Each node in ADT contains three pieces of information: the attribute $(v.att)$, the threshold $(v.thr)$, and pointers to the left and right children $(lc, rc)$.
  • +
  • The construction of ADT is illustrated in the above figure, which shows how the hash of an intermediate node is computed using the hashes of its children and its own attribute and threshold values.
  • +
  • The inclusion of the attribute and threshold values in the hash computation ensures that the integrity of the decision tree is maintained, and any tampering with the tree structure or values will be detected during verification.
  • +
  • The verification algorithm for ADT is similar to that of the Merkle hash tree, where the proof includes the prediction path from the root to the leaf node that outputs the prediction result, as well as the hashes of the siblings of the nodes along the prediction path.
  • +
  • With the proof, the verifier can recompute the root hash and compare it with the commitment to ensure the validity of the prediction.
  • +
  • The advantage of using ADT over Merkle hash tree is that the verification of ADT only requires $O(h)$ hashes, where $h$ is the height of the decision tree, whereas Merkle hash tree requires $O(h log N)$ hashes, where $N$ is the number of nodes in the tree.
  • +
  • The construction of zkDT uses ADT to efficiently turn decision tree predictions and accuracy into statements of zero knowledge proofs, which allows the owner of a decision tree model to convince others of its accuracy without revealing any information about the model itself.
  • +
+

With the construction of ADT, we can update our methodology of the algorithms used in the ADT for zero knowledge proofs of decision tree predictions and accuracy.

+
    +
  • In order to prove the zero knowledge property of the scheme, the commitment has to be randomized. This means that a random point $r$ is added to the root of the decision tree and the hash of the root concatenated with r is used as the final commitment. This is shown in the above figure.
  • +
  • This ADT described in the paper does not have to support dynamic insertions and deletions for the purpose of the application, which simplifies the construction significantly.
  • +
  • The first algorithm, $pp ← ADT.G(1^λ)$, samples a collision-resistant hash function from the family of hash functions.
  • +
  • The second algorithm, $comADT ← ADT.Commit(T, pp, r)$, computes hashes from leaf nodes to the root of $T$ with the random point $r$ as shown in the above figure.
  • +
  • The third algorithm, $πADT ← ADT.P(T, Path, pp)$, given a path in $T$, contains all siblings of the nodes along the path Path and the randomness $r$ in the above figure.
  • +
  • The fourth algorithm, ${0, 1} ← ADT.V(comADT, Path, πADT, pp)$, given Path and $πADT$, recomputes hashes along Path with $πADT$ as the same progress in the above figure and compares the root hash with $comADT$. It outputs $1$ if they are the same, otherwise, $0$.
  • +
  • These algorithms are used to efficiently turn decision tree predictions and accuracy into statements of zero knowledge proofs.
  • +
+

Proving the Validity of the Prediction

+

The protocol for proving the correctness of the prediction in a decision tree involves using a zero knowledge proof on top of the validation process to keep the prediction path and sibling hashes confidential (zero knowledge). This protocol ensures that the verifier only receives a binary output $(1 or 0)$ indicating whether all the checks are satisfied or not, making it both sound and zero knowledge.

+

Zero knowledge decision tree prediction

+

The below steps explain the design of an efficient zero knowledge proof protocol proposed in the paper for validating decision tree predictions.

+
    +
  • The protocol reduces the validity of the prediction using a committed decision tree to an arithmetic circuit.
  • +
  • The public input of the circuit includes the data sample $a$, the commitment of the decision tree $comT$, and the prediction result $y_a$.
  • +
  • The secret witness from the prover includes the prediction path $a$ and the randomness $r$ used in the commitment of ADT.
  • +
  • To improve efficiency, the prover inputs the siblings of nodes on the prediction path and the permutation $\hat{a}$ of the data sample $a$ ordered by $v.att$ of the nodes on the prediction path as part of the witness.
  • +
  • The purpose of the extended witness is to check the permutation between the data sample and the ordered sample and to validate the prediction path in the committed decision tree.
  • +
  • The whole circuit consists of three parts: validating the prediction algorithm of the decision tree, checking the permutation between the data sample $a$ and the ordered sample $\hat{a}$, and checking the validity of the prediction path in the committed decision tree.
  • +
  • The output of the circuit is either $1$ or $0$, denoting whether all the conditions are satisfied or some check fails.
  • +
+

Decision Tree Prediction

+

The above figure 2 describes the zero knowledge decision tree prediction.

+
    +
  • The validation process is efficiently implemented using an arithmetic circuit with the help of auxiliary input $\hat{a}$.
  • +
  • The representation of a and $\hat{a}$ is slightly modified to be index-value pairs, where $a = (1, a[1]), . . . , (d, a[d])$ and $a = (i_1, a[i_1]), . . . , (i_d , a[i_d])$.
  • +
  • The circuit checks for every internal node $v_j$ on the prediction path $(j = 1, . . . , h−1)$ that (1) $v_j.att = i_j$, and (2) if $a[i_j ] < v$j.thr$, $v_j+1 = v_j.left$, otherwise $v_j+1 = v_j.right$.
  • +
  • The equality tests and comparisons are computed using standard techniques in the literature of circuit-based zero knowledge proof with the help of auxiliary input.
  • +
  • Finally, the circuit checks if ya = vh .class. The circuit outputs 1 if all the checks pass, and outputs 0 otherwise.
  • +
  • The total number of gates in this part is O(d + h), which is asymptotically the same as the plain decision tree prediction in Algorithm 1.
  • +
  • If h < d, which is usually true in practice, the circuit only checks the indices of the first h − 1 pairs in ̄a. The rest of the indices are arbitrary, as long as ̄a is a permutation of a.
  • +
  • The prover and the verifier can either agree on the length of the prediction path and construct a separate circuit for every data sample, or use the height of the tree as an upper-bound to construct the same circuit for all data samples.
  • +
  • Both options are supported by the scheme, and the asymptotic complexity is the same. However, the former is more efficient but leaks the length of the prediction paths.
  • +
+

Permuitation Test

+

Path Validation

+

Zero Knowledge Decision Tree Prediction Protocol

+

Zero Knowledge Decision Tree Accuracy

+

Validating Decision Tree Accuracy

+

The paper proposes a protocol for validating decision tree accuracy using a zero knowledge proof. The protocol involves the prover generating a proof that the decision tree

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/index.html b/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/index.html new file mode 100644 index 00000000..e7af29fb --- /dev/null +++ b/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/index.html @@ -0,0 +1,428 @@ + + + + + + + +Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit

+
+

Rate Limiting Nullifier (RLN) Review

+

I recently had the pleasure of conducting my first security audit of a Zero Knowledge Proofs (ZKP) protocol. The protocol in question was the Rate Limiting Nullifier (RLN) Zero Knowledge Proofs Protocol, with its circuits written in Circom. My main focus during this review was on the Circom Circuits of the Zero Knowledge Proofs gadgets. And let me tell you, it was quite the adventure! I mean, who knew math could be so exciting?

+

During my review of the RLN Zero Knowledge Proofs Protocol, I learned a great deal about the intricacies of the RLN specifications, the verifications, and how to identify underconstraint systems. My mathematical background proved to be invaluable in helping me understand these complex concepts. It’s like they always say, “mathematics is the language of the universe”! But seriously, who comes up with this stuff? Additionally, I gained a deeper understanding of ZKP primitives attack vectors and other potential vulnerabilities in the system. It’s like being a detective, but for ZKP systems! And let me tell you, it’s not as easy as it looks.

+

Review Resources:

+ +

Auditors:

+ +

Table of Contents

+

Executive Summary

+

Scope

+

Explanation of Findings

+

Critical Findings

+

High Findings

+

Medium Findings

+

Low Findings

+

Final Remarks

+

Executive Summary

+
    +
  • There are no critical or high impact bugs in the code.
  • +
  • There were some low impact bugs mainly under constrained input variables between the Circom circuits and their corresponding Solidity contracts.
  • +
+

Rate Limiting Nullifier

+

Rate limiting nullifier (RLN) is a construct based on zero-knowledge proofs (sometimes called ZKP gadget) that provides an anonymous rate-limited signaling/messaging framework suitable for decentralized (and centralized) environments using Secret Shamir Sharing (SSS) scheme.

+

Motivation +Some applications of rate limiting nullifier in anonymous decentralized networks include:

+
    +
  1. Decentralized voting applications: RLN helps prevent voting outcomes from being manipulated by spam or sybil attacks, ensuring the integrity of the voting process.
  2. +
  3. Anonymous group chat applications: By preventing users from spamming or polluting group chats, RLN enhances the user experience in these applications.
  4. +
  5. Direct anonymous attestation: RLN can be used in combination with Direct Anonymous Attestation (DAA) to implement service rate-limiting in a scenario where messages between users and the service are sent anonymously while preserving message unlinkability
  6. +
  7. Blockchain-based social networks: RLN can be applied to decentralized social media networks to prevent spam, sybil attacks, and other types of abuse targeting APIs and applications, thus enhancing the overall security and reliability of these networks.
  8. +
  9. Rate limiting in web applications: RLN can be integrated with Web Application Firewalls (WAF) to protect against denial-of-service attacks, brute-force login attempts, and API traffic surges, providing a more secure and reliable web application experience.
  10. +
+

RLN V2 +The RLN V2 protocol is a more general construct, that allows to set various limits for an epoch (it’s 1 message per epoch in RLN-V1) while remaining almost as simple as it predecessor. Moreover, it allows to set different rate-limits for different RLN app users based on some public data, e.g. stake.

+

The RLN Circom circuits were reviewed over 13 days. The code review was performed between May 31 and June 12, 2023. The RLN repository was under active development during the review, but the review was limited to the latest commit, 37073131b9 at the start of the review.

+

The official documentation for the RLN circuits was located at rate-limiting-nullifier.github.io.

+

Flow

+

Here is the complete flow diagram of RLN protocol for the Circom circuits.

+

RLN Protocol Flow

+

+    graph TD
+        ext_null>External Nullifier] --> h1(hash)
+        secret{{Secret Trapdoor & nullifier}} --> h0(hash) --> a_0
+        a_0{{Secret hashed a_0}} --> h1
+        msg_id>Message_ID `k`] --> h1
+        msg_id --> limit_check(Message Limit Check)
+        msg_limit>Message Limit] --> limit_check
+        h1 --> a_1 --> h2(hash) --> int_null([Internal Nullifier])
+        a_1 --> times
+        m>Message] --> h3(hash) --> times(*) --> plus(+)
+        a_0 --> plus --> sss([Shamir's Share y_share])
+        a_0 --> h4(hash) --> id_com([id_commitment])
+        h4 --> merkle(MerkleProof)
+
+
+

Scope

+

The scope of the review consisted of the following circuits at the specific commit:

+ +

After the findings were presented to the RLN team, fixes were made and included in several PRs.

+

This review is a code review to identify potential vulnerabilities in the code. The reviewers did not investigate security practices or operational security and assumed that privileged accounts could be trusted. The reviewers did not evaluate the security of the code relative to a standard or specification. The review may not have identified all potential attack vectors or areas of vulnerability.

+

yAcademy and the auditors make no warranties regarding the security of the code and do not warrant that the code is free from defects. yAcademy and the auditors do not represent nor imply to third parties that the code has been audited nor that the code is free from defects. By deploying or using the code, RLN and users of the contracts agree to use the code at their own risk.

+

Code Evaluation Matrix

+ + + + + + + + + + +
CategoryMarkDescription
Access ControlNot applicableThe code does not explicitly implement access control mechanisms. It does not have specific checks or restrictions on who can access or modify the data.
MathematicsGoodThe code includes mathematical operations such as addition, multiplication, and hashing using the Poseidon function. It also includes range checks and bit manipulation operations.
ComplexityGoodThe complexity of the code is relatively low. It consists of basic mathematical operations and includes a Merkle tree inclusion proof and range checks.
LibrariesAverageThe code includes the Circomlib library, specifically the Poseidon circuit, which is used for hashing.
DecentralizationNot applicableThe code does not explicitly address decentralization. It does not include mechanisms for distributed consensus or interaction with a decentralized network.
Code stabilityGoodThe code appears to be well-structured and follows the Circom syntax. It does not contain any obvious errors or issues that would affect its stability.
DocumentationLowThe code does not include extensive documentation. There are some comments explaining the purpose of certain components, but more detailed documentation would be beneficial.
MonitoringAverageThe code does not include specific monitoring mechanisms. It does not have built-in logging or tracking of events or performance metrics.
Testing and verificationAverageThe code includes some basic range checks and a Merkle tree inclusion proof, which are important for ensuring the correctness of the code. However, it does not include comprehensive testing or verification procedures.
+

Explanation of Findings

+

Findings are broken down into sections by their respective impact:

+
    +
  • Critical, High, Medium, Low impact +
      +
    • These are findings that range from attacks that may cause loss of funds, impact control/ownership of the contracts, or cause any unintended consequences/actions that are outside the scope of the requirements
    • +
    +
  • +
  • Gas savings +
      +
    • Findings that can improve the gas efficiency of the contracts
    • +
    +
  • +
  • Informational +
      +
    • Findings including recommendations and best practices
    • +
    +
  • +
+
+

Critical Findings

+

1. Critical - identitySecret gets revealed for certain inputs x (hash of the message)

+

The identitySecret gets revealed when the input signal x, the hash of the message, is 0 modulo prime p of the scalar field used. When the x is 0 or 21888242871839275222246405745257275088548364400416034343698204186575808495617 (in Ethereum) or the prime p, the order of the scalar field $Fp$ arithmetic circuits, the product a1 * x becomes zero thus revealing the identitySecret.

+
    +
  • This prime p is the order of the scalar field of the $BN254$ curve.
  • +
  • Circom 2.0.6 introduces two new prime numbers to work with +
      +
    • The order of the scalar field of the $BLS12-381$. +
        +
      • 52435875175126190479447740508185965837690552500527637822603658699938581184513
      • +
      +
    • +
    • The goldilocks prime 18446744069414584321, originally used in $Plonky2$.
    • +
    +
  • +
+

Recommended Solution

+

Constraint on the input signal x and also on the product a1 * x to be non-zero modulo prime p.

+
isZero(x).out === 0
+isZero(a1*x).out === 0
+
+
+

High Findings

+

None.

+

Medium Findings

+

None.

+

Low Findings

+

1. Low - Incosistency between RLN contract and RLN circuit on the number of bits for userMessageLimit

+

In RLN.sol, the messageLimit can take upto 2256 - 1 values whereas messageId & userMessageLimit values in circuits is restricted to 216 - 1 .

+

rln.circom

+
template RLN(DEPTH, LIMIT_BIT_SIZE) {
+...
+    // messageId range check
+    RangeCheck(LIMIT_BIT_SIZE)(messageId, userMessageLimit);
+...
+}
+component main { public [x, externalNullifier] } = RLN(20, 16);
+
+

rln.sol

+
uint256 messageLimit = amount / MINIMAL_DEPOSIT;
+
+

Recommended Solution

+

Update the relevant code at rln.sol with something like below:

+
function register(uint256 identityCommitment, uint256 amount) external {
+        ...
+        uint256 messageLimit = amount / MINIMAL_DEPOSIT;
+        require( messageLimit <= type(uint16).max , "Max length of your message limit is 65535");
+        ...
+    }
+
+

2. Low - Unused address input signal in the Withdraw circuit

+

The input signal address was declared but not used in the output calculation.

+
    signal input address;
+
+

Recommended Solution +Assign a local computation for the unused input signal address. For example:

+
   signal addressDoubled <== address + address;
+
+

3. Low - Missing rangechecks for the data inputs

+

The Circom circuits are missing explicit rangechecks for several input parameters suchh as DEPTH, address, LIMIT_BIT_SIZE, etc.

+

Recommended Solution +Perform explcit range checks and constrain the data input parameters to improve the soundness of the ZKP system.

+

Informational Findings

+

The Circom circuits are further tested for Weak Verification soundness property using Ecne tool from 0xParc. This tests if, given the input variables in a QAP (R1CS constraints), the output variables have uniquely determined values. An underconstrained circuit admits valid proofs for multiple different outputs, given the same input. In the worst case, an attacker can generate a valid proof for an underconstrained circuit for any output--meaning that an attacker would be able to convince a verifier who (incorrectly) believes the circuit to be properly-constrained that the attacker knows the pre-image of arbitrary outputs.

+

Ecne Findings

+

The Circom cuits were compiled to non-optimized R1CS constraints system and then they were tested for Weak Verification to check for any bad constraints or underconstraints. All the circuits passed the Ecne tests without any bad or underconstraints. This verifies that R1CS equations of the given circuits uniquely determine outputs given inputs (i.e. that the constraints are sound).

+

Error Handling

+

Consider adding below error handling to check for specific conditions and throw an error or return an error code when those conditions are not met. This helps provide meaningful error messages or handle exceptional cases in a controlled manner.

+

rln.circom

+
// Add error handling for Merkle tree inclusion proof
+root <== MerkleTreeInclusionProof(DEPTH)(rateCommitment, identityPathIndex, pathElements);
+assert(root !== 0, "Invalid Merkle tree inclusion proof"); // Throw an error if the Merkle tree inclusion proof is invalid
+
+
+

withdraw.circom

+
// Add error handling for address length check
+assert(address.length == EXPECTED_ADDRESS_LENGTH, "Invalid address length"); // Throw an error if the address length is not as expected
+
+
+

utils.circom

+

+// Add error handling for length check
+assert(leaf.length == EXPECTED_LEAF_LENGTH, "Invalid leaf length"); // Throw an error if the leaf length is not as expected
+
+

POSEIDON and Some Additional Remarks

+
    +
  • The RLN circuit assumes that the underlying hash function (Poseidon) is: +
      +
    • Collision-resistant
    • +
    • Resistant to differential, algebraic, and interpolation attacks
    • +
    • Behaves as a random oracle
    • +
    +
  • +
  • The Merkle tree used for membership proof is assumed to be secure against second-preimage attacks.
  • +
  • The security of the circuit depends on the security of the cryptographic primitives used for range checks and SSS share calculations.
  • +
  • The security of the circuit also depends on the secrecy of the identitySecret signal, which is assumed to be kept secret by the user.
  • +
  • Social engineering attacks are still a valid way to break the system.
  • +
  • An attacker can obtain the identitySecret signal of a user by using methods such as social engineering, phishing attacks, or exploiting vulnerabilities in the user's system.
  • +
  • Once the attacker has obtained the identitySecret signal, they can calculate the identityCommitment, rateCommitment, a1, and y signals for that user, and use them to break the security of the RLN circuit.
  • +
+

Final remarks

+

Overall, the code demonstrates good implementation of mathematical operations and basic functionality. However, it could benefit from more extensive documentation and additional testing and verification procedures.

+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000..39d067d5 --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: +Allow: / +Sitemap: https://thogiti.github.io/sitemap.xml diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..f4a7b94d --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,379 @@ + + + + https://thogiti.github.io/ + + + https://thogiti.github.io/about/ + + + https://thogiti.github.io/different-types-of-zero-knowledge-proofs/ + 2023-03-02 + + + https://thogiti.github.io/efficient-computation-of-frobenius-automorphism-on-bn254-elliptic-curve/ + 2023-04-30 + + + https://thogiti.github.io/enhancing-ethereum-scalability-with-product-codes-and-danksharding/ + 2023-05-07 + + + https://thogiti.github.io/error-correction-in-danksharding-harnessing-the-power-of-generalized-reed-solomon-codes-for-ethereum-scalability/ + 2023-05-08 + + + https://thogiti.github.io/explanation-of-the-concept-of-zero-knowledge-proofs/ + 2023-03-01 + + + https://thogiti.github.io/intro-zkps/ + 2022-12-25 + + + https://thogiti.github.io/mastering-elliptic-curve-arithmetic-a-comprehensive-guide-with-sagemath-examples/ + 2023-05-09 + + + https://thogiti.github.io/mastering-rank-one-constraint-system-r1cs-with-circom-examples/ + 2023-08-14 + + + https://thogiti.github.io/page/1/ + + + https://thogiti.github.io/page/2/ + + + https://thogiti.github.io/paperreview-machine-learning-of-native-t1-mapping-radiomics-for-classification-of-hypertrophic-cardiomyopathy-phenotypes/ + 2023-03-03 + + + https://thogiti.github.io/paperreview-predicting-the-development-of-adverse-cardiac-events-in-patients-with-hypertrophic-cardiomyopathy-using-machine-learning/ + 2023-03-04 + + + https://thogiti.github.io/paperreview-zero-knowledge-proofs-for-decision-tree-predictions-and-accuracy/ + 2023-07-24 + + + https://thogiti.github.io/rate-limiting-nullifier-rln-protocol-circom-circuits-security-audit/ + 2023-06-14 + + + https://thogiti.github.io/tags/ + + + https://thogiti.github.io/tags/ai-for-cardiology/ + + + https://thogiti.github.io/tags/ai-for-cardiomyopathy/ + + + https://thogiti.github.io/tags/ai-for-imaging/ + + + https://thogiti.github.io/tags/ai/ + + + https://thogiti.github.io/tags/algebraic-coding-theory/ + + + https://thogiti.github.io/tags/block-transaction-fee-optimization/ + + + https://thogiti.github.io/tags/blockchain-transaction-fee-optimization/ + + + https://thogiti.github.io/tags/bn254-elliptic-curve/ + + + https://thogiti.github.io/tags/bn254/ + + + https://thogiti.github.io/tags/cardiology/ + + + https://thogiti.github.io/tags/cardiomyopathy/ + + + https://thogiti.github.io/tags/caulk/ + + + https://thogiti.github.io/tags/circom-circuits/ + + + https://thogiti.github.io/tags/circom/ + + + https://thogiti.github.io/tags/classification-of-cardiomyopathy/ + + + https://thogiti.github.io/tags/classification-of-hypertrophic-cardiomyopathy/ + + + https://thogiti.github.io/tags/coefficient-extraction/ + + + https://thogiti.github.io/tags/constraint-system/ + + + https://thogiti.github.io/tags/danksharding/ + + + https://thogiti.github.io/tags/data-extraction/ + + + https://thogiti.github.io/tags/data-interpolation/ + + + https://thogiti.github.io/tags/decision-tree/ + + + https://thogiti.github.io/tags/diagnostic-markers/ + + + https://thogiti.github.io/tags/different-types-of-zero-knowledge-proofs/ + + + https://thogiti.github.io/tags/discrete-logarithm-problem/ + + + https://thogiti.github.io/tags/dotproduct-of-two-vectors-in-zkp/ + + + https://thogiti.github.io/tags/ecadd/ + + + https://thogiti.github.io/tags/ecdbl/ + + + https://thogiti.github.io/tags/ecdh/ + + + https://thogiti.github.io/tags/ecdsa/ + + + https://thogiti.github.io/tags/ecne/ + + + https://thogiti.github.io/tags/efficient-zkp/ + + + https://thogiti.github.io/tags/elgamal-encryption-and-decryption/ + + + https://thogiti.github.io/tags/elgamal-key-generation/ + + + https://thogiti.github.io/tags/elgamal/ + + + https://thogiti.github.io/tags/elliptic-curve/ + + + https://thogiti.github.io/tags/enhancing-elgamal-security/ + + + https://thogiti.github.io/tags/ensuring-data-integrity-with-digital-signatures/ + + + https://thogiti.github.io/tags/error-correction/ + + + https://thogiti.github.io/tags/establishing-secure-connections-with-ecc/ + + + https://thogiti.github.io/tags/ethereum-s-scalability/ + + + https://thogiti.github.io/tags/ethereum-scalability/ + + + https://thogiti.github.io/tags/ethereum/ + + + https://thogiti.github.io/tags/executive-summary/ + + + https://thogiti.github.io/tags/explanation-of-the-concept/ + + + https://thogiti.github.io/tags/frobenius-automorphism/ + + + https://thogiti.github.io/tags/generalized-reed-solomon-codes/ + + + https://thogiti.github.io/tags/greedy-algorithm/ + + + https://thogiti.github.io/tags/halo2/ + + + https://thogiti.github.io/tags/karp-reduction/ + + + https://thogiti.github.io/tags/kzg/ + + + https://thogiti.github.io/tags/lookup-arguments/ + + + https://thogiti.github.io/tags/machine-learning-feature-selection/ + + + https://thogiti.github.io/tags/mathematical-software/ + + + https://thogiti.github.io/tags/missing-value-analysis/ + + + https://thogiti.github.io/tags/ml-for-cardiomyopathy/ + + + https://thogiti.github.io/tags/ml/ + + + https://thogiti.github.io/tags/multiscalar-multiplication/ + + + https://thogiti.github.io/tags/noir/ + + + https://thogiti.github.io/tags/non-linear-constraints/ + + + https://thogiti.github.io/tags/optimization-algorithms/ + + + https://thogiti.github.io/tags/paper-review/ + + + https://thogiti.github.io/tags/point-addition/ + + + https://thogiti.github.io/tags/point-doubling/ + + + https://thogiti.github.io/tags/point-operations/ + + + https://thogiti.github.io/tags/poseidon/ + + + https://thogiti.github.io/tags/privacy-preserving-machine-learning/ + + + https://thogiti.github.io/tags/privacy/ + + + https://thogiti.github.io/tags/problem-solving-techniques/ + + + https://thogiti.github.io/tags/product-code/ + + + https://thogiti.github.io/tags/public-key-cryptography/ + + + https://thogiti.github.io/tags/r1cs/ + + + https://thogiti.github.io/tags/radiomics/ + + + https://thogiti.github.io/tags/rate-limiting-nullifier/ + + + https://thogiti.github.io/tags/reed-solomon-codes/ + + + https://thogiti.github.io/tags/resource-allocation-optimization/ + + + https://thogiti.github.io/tags/rln/ + + + https://thogiti.github.io/tags/rust/ + + + https://thogiti.github.io/tags/sagemath-implementation/ + + + https://thogiti.github.io/tags/sagemath/ + + + https://thogiti.github.io/tags/secure-communication-with-elgamal/ + + + https://thogiti.github.io/tags/securing-communications-with-ecc/ + + + https://thogiti.github.io/tags/security-audit/ + + + https://thogiti.github.io/tags/sublinear-lookup-arguments/ + + + https://thogiti.github.io/tags/technology-applications/ + + + https://thogiti.github.io/tags/understanding-zero-knowledge-proofs/ + + + https://thogiti.github.io/tags/weighted-set-cover-problem/ + + + https://thogiti.github.io/tags/writing-zero-knowledge-proofs/ + + + https://thogiti.github.io/tags/yacademy/ + + + https://thogiti.github.io/tags/yaudit-zk-fellowship/ + + + https://thogiti.github.io/tags/zero-knowledge-decision-tree-accuracy-tests/ + + + https://thogiti.github.io/tags/zero-knowledge-decision-tree-predictions/ + + + https://thogiti.github.io/tags/zero-knowledge-proofs/ + + + https://thogiti.github.io/tags/zk-fellowship/ + + + https://thogiti.github.io/tags/zk/ + + + https://thogiti.github.io/tags/zkml/ + + + https://thogiti.github.io/tags/zkp-dotproduct/ + + + https://thogiti.github.io/tags/zkp-security-audit/ + + + https://thogiti.github.io/tags/zkp/ + + + https://thogiti.github.io/understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/ + 2023-05-20 + + + https://thogiti.github.io/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/ + 2023-06-23 + + + https://thogiti.github.io/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/ + 2023-05-25 + + + https://thogiti.github.io/writing-zero-knowledge-proofs-and-circuits-in-four-languages/ + 2023-04-12 + + diff --git a/tags/ai-for-cardiology/index.html b/tags/ai-for-cardiology/index.html new file mode 100644 index 00000000..412b3444 --- /dev/null +++ b/tags/ai-for-cardiology/index.html @@ -0,0 +1,224 @@ + + + + + + + +AI for Cardiology | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

AI for Cardiology

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ai-for-cardiomyopathy/index.html b/tags/ai-for-cardiomyopathy/index.html new file mode 100644 index 00000000..7f365d3b --- /dev/null +++ b/tags/ai-for-cardiomyopathy/index.html @@ -0,0 +1,224 @@ + + + + + + + +AI for Cardiomyopathy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

AI for Cardiomyopathy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ai-for-imaging/index.html b/tags/ai-for-imaging/index.html new file mode 100644 index 00000000..a39aee4e --- /dev/null +++ b/tags/ai-for-imaging/index.html @@ -0,0 +1,224 @@ + + + + + + + +AI for Imaging | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

AI for Imaging

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ai/index.html b/tags/ai/index.html new file mode 100644 index 00000000..f8401ad7 --- /dev/null +++ b/tags/ai/index.html @@ -0,0 +1,234 @@ + + + + + + + +AI | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

AI

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/algebraic-coding-theory/index.html b/tags/algebraic-coding-theory/index.html new file mode 100644 index 00000000..28b23ce2 --- /dev/null +++ b/tags/algebraic-coding-theory/index.html @@ -0,0 +1,220 @@ + + + + + + + +algebraic coding theory | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

algebraic coding theory

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/block-transaction-fee-optimization/index.html b/tags/block-transaction-fee-optimization/index.html new file mode 100644 index 00000000..292f998f --- /dev/null +++ b/tags/block-transaction-fee-optimization/index.html @@ -0,0 +1,225 @@ + + + + + + + +block transaction fee optimization | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

block transaction fee optimization

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/blockchain-transaction-fee-optimization/index.html b/tags/blockchain-transaction-fee-optimization/index.html new file mode 100644 index 00000000..2d233412 --- /dev/null +++ b/tags/blockchain-transaction-fee-optimization/index.html @@ -0,0 +1,225 @@ + + + + + + + +blockchain transaction fee optimization | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

blockchain transaction fee optimization

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/bn254-elliptic-curve/index.html b/tags/bn254-elliptic-curve/index.html new file mode 100644 index 00000000..2e50b203 --- /dev/null +++ b/tags/bn254-elliptic-curve/index.html @@ -0,0 +1,212 @@ + + + + + + + +BN254 Elliptic Curve | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

BN254 Elliptic Curve

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/bn254/index.html b/tags/bn254/index.html new file mode 100644 index 00000000..b90c7a4c --- /dev/null +++ b/tags/bn254/index.html @@ -0,0 +1,212 @@ + + + + + + + +BN254 | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

BN254

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/cardiology/index.html b/tags/cardiology/index.html new file mode 100644 index 00000000..da6b2190 --- /dev/null +++ b/tags/cardiology/index.html @@ -0,0 +1,224 @@ + + + + + + + +Cardiology | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Cardiology

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/cardiomyopathy/index.html b/tags/cardiomyopathy/index.html new file mode 100644 index 00000000..ece8f54e --- /dev/null +++ b/tags/cardiomyopathy/index.html @@ -0,0 +1,224 @@ + + + + + + + +Cardiomyopathy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Cardiomyopathy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/caulk/index.html b/tags/caulk/index.html new file mode 100644 index 00000000..02da2e44 --- /dev/null +++ b/tags/caulk/index.html @@ -0,0 +1,214 @@ + + + + + + + +Caulk | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Caulk

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/circom-circuits/index.html b/tags/circom-circuits/index.html new file mode 100644 index 00000000..aba2b24f --- /dev/null +++ b/tags/circom-circuits/index.html @@ -0,0 +1,213 @@ + + + + + + + +Circom Circuits | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Circom Circuits

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/circom/index.html b/tags/circom/index.html new file mode 100644 index 00000000..1681ca18 --- /dev/null +++ b/tags/circom/index.html @@ -0,0 +1,228 @@ + + + + + + + +Circom | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Circom

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/classification-of-cardiomyopathy/index.html b/tags/classification-of-cardiomyopathy/index.html new file mode 100644 index 00000000..d8f58eb4 --- /dev/null +++ b/tags/classification-of-cardiomyopathy/index.html @@ -0,0 +1,224 @@ + + + + + + + +Classification of Cardiomyopathy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Classification of Cardiomyopathy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/classification-of-hypertrophic-cardiomyopathy/index.html b/tags/classification-of-hypertrophic-cardiomyopathy/index.html new file mode 100644 index 00000000..fdd6c106 --- /dev/null +++ b/tags/classification-of-hypertrophic-cardiomyopathy/index.html @@ -0,0 +1,224 @@ + + + + + + + +Classification of Hypertrophic Cardiomyopathy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Classification of Hypertrophic Cardiomyopathy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/coefficient-extraction/index.html b/tags/coefficient-extraction/index.html new file mode 100644 index 00000000..785a2dea --- /dev/null +++ b/tags/coefficient-extraction/index.html @@ -0,0 +1,212 @@ + + + + + + + +Coefficient Extraction | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Coefficient Extraction

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/constraint-system/index.html b/tags/constraint-system/index.html new file mode 100644 index 00000000..9a2587b5 --- /dev/null +++ b/tags/constraint-system/index.html @@ -0,0 +1,214 @@ + + + + + + + +Constraint system | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Constraint system

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/danksharding/index.html b/tags/danksharding/index.html new file mode 100644 index 00000000..fabb23b7 --- /dev/null +++ b/tags/danksharding/index.html @@ -0,0 +1,239 @@ + + + + + + + +Danksharding | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Danksharding

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/data-extraction/index.html b/tags/data-extraction/index.html new file mode 100644 index 00000000..419e317c --- /dev/null +++ b/tags/data-extraction/index.html @@ -0,0 +1,212 @@ + + + + + + + +Data Extraction | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Data Extraction

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/data-interpolation/index.html b/tags/data-interpolation/index.html new file mode 100644 index 00000000..fa6bc1b1 --- /dev/null +++ b/tags/data-interpolation/index.html @@ -0,0 +1,212 @@ + + + + + + + +Data Interpolation | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Data Interpolation

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/decision-tree/index.html b/tags/decision-tree/index.html new file mode 100644 index 00000000..cd46935a --- /dev/null +++ b/tags/decision-tree/index.html @@ -0,0 +1,214 @@ + + + + + + + +Decision Tree | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Decision Tree

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/diagnostic-markers/index.html b/tags/diagnostic-markers/index.html new file mode 100644 index 00000000..13c78522 --- /dev/null +++ b/tags/diagnostic-markers/index.html @@ -0,0 +1,224 @@ + + + + + + + +Diagnostic markers | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Diagnostic markers

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/different-types-of-zero-knowledge-proofs/index.html b/tags/different-types-of-zero-knowledge-proofs/index.html new file mode 100644 index 00000000..2f8e6c0c --- /dev/null +++ b/tags/different-types-of-zero-knowledge-proofs/index.html @@ -0,0 +1,213 @@ + + + + + + + +Different types of Zero Knowledge Proofs | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Different types of Zero Knowledge Proofs

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/discrete-logarithm-problem/index.html b/tags/discrete-logarithm-problem/index.html new file mode 100644 index 00000000..a526a7bb --- /dev/null +++ b/tags/discrete-logarithm-problem/index.html @@ -0,0 +1,221 @@ + + + + + + + +Discrete Logarithm Problem | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Discrete Logarithm Problem

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/dotproduct-of-two-vectors-in-zkp/index.html b/tags/dotproduct-of-two-vectors-in-zkp/index.html new file mode 100644 index 00000000..ee7dab3f --- /dev/null +++ b/tags/dotproduct-of-two-vectors-in-zkp/index.html @@ -0,0 +1,218 @@ + + + + + + + + Dotproduct of Two Vectors in ZKP | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Dotproduct of Two Vectors in ZKP

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ecadd/index.html b/tags/ecadd/index.html new file mode 100644 index 00000000..3fcd0119 --- /dev/null +++ b/tags/ecadd/index.html @@ -0,0 +1,223 @@ + + + + + + + +ECADD | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ECADD

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ecdbl/index.html b/tags/ecdbl/index.html new file mode 100644 index 00000000..b59ff754 --- /dev/null +++ b/tags/ecdbl/index.html @@ -0,0 +1,223 @@ + + + + + + + +ECDBL | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ECDBL

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ecdh/index.html b/tags/ecdh/index.html new file mode 100644 index 00000000..ef1cd836 --- /dev/null +++ b/tags/ecdh/index.html @@ -0,0 +1,223 @@ + + + + + + + +ECDH | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ECDH

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ecdsa/index.html b/tags/ecdsa/index.html new file mode 100644 index 00000000..6bfdf244 --- /dev/null +++ b/tags/ecdsa/index.html @@ -0,0 +1,223 @@ + + + + + + + +ECDSA | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ECDSA

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ecne/index.html b/tags/ecne/index.html new file mode 100644 index 00000000..91551c42 --- /dev/null +++ b/tags/ecne/index.html @@ -0,0 +1,213 @@ + + + + + + + +Ecne | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Ecne

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/efficient-zkp/index.html b/tags/efficient-zkp/index.html new file mode 100644 index 00000000..59d70c98 --- /dev/null +++ b/tags/efficient-zkp/index.html @@ -0,0 +1,214 @@ + + + + + + + +Efficient ZKP | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Efficient ZKP

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/elgamal-encryption-and-decryption/index.html b/tags/elgamal-encryption-and-decryption/index.html new file mode 100644 index 00000000..77168829 --- /dev/null +++ b/tags/elgamal-encryption-and-decryption/index.html @@ -0,0 +1,221 @@ + + + + + + + +ElGamal Encryption and Decryption | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ElGamal Encryption and Decryption

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/elgamal-key-generation/index.html b/tags/elgamal-key-generation/index.html new file mode 100644 index 00000000..c425ebea --- /dev/null +++ b/tags/elgamal-key-generation/index.html @@ -0,0 +1,221 @@ + + + + + + + +ElGamal Key Generation | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ElGamal Key Generation

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/elgamal/index.html b/tags/elgamal/index.html new file mode 100644 index 00000000..c5cb4866 --- /dev/null +++ b/tags/elgamal/index.html @@ -0,0 +1,221 @@ + + + + + + + +ElGamal | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ElGamal

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/elliptic-curve/index.html b/tags/elliptic-curve/index.html new file mode 100644 index 00000000..01ab8067 --- /dev/null +++ b/tags/elliptic-curve/index.html @@ -0,0 +1,212 @@ + + + + + + + +Elliptic Curve | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Elliptic Curve

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/enhancing-elgamal-security/index.html b/tags/enhancing-elgamal-security/index.html new file mode 100644 index 00000000..525666f2 --- /dev/null +++ b/tags/enhancing-elgamal-security/index.html @@ -0,0 +1,221 @@ + + + + + + + +Enhancing ElGamal Security | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Enhancing ElGamal Security

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ensuring-data-integrity-with-digital-signatures/index.html b/tags/ensuring-data-integrity-with-digital-signatures/index.html new file mode 100644 index 00000000..f222208d --- /dev/null +++ b/tags/ensuring-data-integrity-with-digital-signatures/index.html @@ -0,0 +1,223 @@ + + + + + + + +Ensuring Data Integrity with Digital Signatures | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Ensuring Data Integrity with Digital Signatures

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/error-correction/index.html b/tags/error-correction/index.html new file mode 100644 index 00000000..1302190f --- /dev/null +++ b/tags/error-correction/index.html @@ -0,0 +1,212 @@ + + + + + + + +Error Correction | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Error Correction

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/establishing-secure-connections-with-ecc/index.html b/tags/establishing-secure-connections-with-ecc/index.html new file mode 100644 index 00000000..c924e6e5 --- /dev/null +++ b/tags/establishing-secure-connections-with-ecc/index.html @@ -0,0 +1,223 @@ + + + + + + + +Establishing Secure Connections with ECC | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Establishing Secure Connections with ECC

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ethereum-s-scalability/index.html b/tags/ethereum-s-scalability/index.html new file mode 100644 index 00000000..53ed1b90 --- /dev/null +++ b/tags/ethereum-s-scalability/index.html @@ -0,0 +1,212 @@ + + + + + + + +Ethereum's scalability | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Ethereum's scalability

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ethereum-scalability/index.html b/tags/ethereum-scalability/index.html new file mode 100644 index 00000000..3f33c8c2 --- /dev/null +++ b/tags/ethereum-scalability/index.html @@ -0,0 +1,241 @@ + + + + + + + +Ethereum scalability | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Ethereum scalability

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ethereum/index.html b/tags/ethereum/index.html new file mode 100644 index 00000000..fb65f315 --- /dev/null +++ b/tags/ethereum/index.html @@ -0,0 +1,258 @@ + + + + + + + +Ethereum | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Ethereum

+
+
+
+ +
+ +
+ Pinned · + +

Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit

+
+

Rate Limiting Nullifier (RLN) Review +I recently had the pleasure of conducting my first security audit of a Zero Knowledge Proofs (ZKP) protocol. The protocol in question was the Rate Limiting Nullifier (RLN) Zero Knowledge Proofs Protocol, with its circuits written in Circom. My…

+
+
+
+ Pinned · + +

Understanding Caulk Protocol: A Beginner's Guide to Sublinear Time Lookup Arguments (In Draft Mode)

+
+

Note: This article is in draft mode and I didn't finish writing the sections of the Caulk protocol, proof read, test the code for correctness and adding references. Please check it again in 1-2 weeks before I publish it. +Introduction +In this blog we will review Caulk protocol for…

+
+
+
+ Pinned · + +

Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples

+
+

+Introduction Demystifying Elliptic Curves and Their Applications + +The Power of Elliptic Curve Cryptography (ECC) +Unlocking the Potential of ECC with SageMath + + +Understanding the Fundamentals of Elliptic Curves + +Definition of an Elliptic Curve +Points on an Elliptic Curve +Visualiz…

+
+
+
+ Pinned · + +

Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability

+
+

Danksharding is an innovative approach to scale Ethereum's blockchain, aiming to achieve over 100,000 transactions per second by enabling rollups to add cheaper data to blocks ethereum.org. As Ethereum moves towards Proto-Danksharding and eventually full Danksharding ethereum.org…

+
+
+
+ Pinned · + +

Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide

+
+

This article would provide an in-depth understanding of how product codes from algebraic coding theory can be applied to Danksharding to improve Ethereum's scalability. It would cover the fundamentals of product codes, their application in Danksharding, and the potential benefits…

+
+
+
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/executive-summary/index.html b/tags/executive-summary/index.html new file mode 100644 index 00000000..33d5f9cf --- /dev/null +++ b/tags/executive-summary/index.html @@ -0,0 +1,228 @@ + + + + + + + +Executive Summary | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Executive Summary

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/explanation-of-the-concept/index.html b/tags/explanation-of-the-concept/index.html new file mode 100644 index 00000000..05d714af --- /dev/null +++ b/tags/explanation-of-the-concept/index.html @@ -0,0 +1,213 @@ + + + + + + + +Explanation of the concept | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Explanation of the concept

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/frobenius-automorphism/index.html b/tags/frobenius-automorphism/index.html new file mode 100644 index 00000000..901fff60 --- /dev/null +++ b/tags/frobenius-automorphism/index.html @@ -0,0 +1,212 @@ + + + + + + + +Frobenius Automorphism | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Frobenius Automorphism

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/generalized-reed-solomon-codes/index.html b/tags/generalized-reed-solomon-codes/index.html new file mode 100644 index 00000000..8a01682c --- /dev/null +++ b/tags/generalized-reed-solomon-codes/index.html @@ -0,0 +1,212 @@ + + + + + + + +Generalized Reed-Solomon Codes | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Generalized Reed-Solomon Codes

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/greedy-algorithm/index.html b/tags/greedy-algorithm/index.html new file mode 100644 index 00000000..babce48e --- /dev/null +++ b/tags/greedy-algorithm/index.html @@ -0,0 +1,225 @@ + + + + + + + +greedy algorithm | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

greedy algorithm

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/halo2/index.html b/tags/halo2/index.html new file mode 100644 index 00000000..e9ec923f --- /dev/null +++ b/tags/halo2/index.html @@ -0,0 +1,218 @@ + + + + + + + +Halo2 | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Halo2

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 00000000..057739e9 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,2701 @@ + + + + + + + +Tags | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Tags

+
+
+
+ AIAI for CardiologyAI for CardiomyopathyAI for Imagingalgebraic coding theoryblock transaction fee optimizationblockchain transaction fee optimizationBN254BN254 Elliptic CurveCardiologyCardiomyopathyCaulkCircomCircom CircuitsClassification of CardiomyopathyClassification of Hypertrophic CardiomyopathyCoefficient ExtractionConstraint systemDankshardingData ExtractionData InterpolationDecision TreeDiagnostic markersDifferent types of Zero Knowledge ProofsDiscrete Logarithm Problem Dotproduct of Two Vectors in ZKPECADDECDBLECDHECDSAEcneEfficient ZKPElGamalElGamal Encryption and DecryptionElGamal Key GenerationElliptic CurveEnhancing ElGamal SecurityEnsuring Data Integrity with Digital SignaturesError CorrectionEstablishing Secure Connections with ECCEthereumEthereum's scalabilityEthereum scalabilityExecutive SummaryExplanation of the conceptFrobenius AutomorphismGeneralized Reed-Solomon Codesgreedy algorithmHalo2Karp reductionKZGLookup Argumentsmachine learning feature selectionmathematical softwareMissing Value AnalysisMLML for CardiomyopathyMultiscalar MultiplicationNoirNon-linear constraintsoptimization algorithmsPaper ReviewPoint AdditionPoint Doubling Point OperationsPoseidonprivacyprivacy preserving machine learningproblem-solving techniquesProduct codePublic Key CryptographyR1CSRadiomicsRate Limiting NullifierReed-Solomon Codesresource allocation optimizationRLNRustSageMathSageMath ImplementationSecure Communication with ElGamalSecuring Communications with ECCSecurity AuditSublinear Lookup Argumentstechnology applicationsUnderstanding Zero Knowledge Proofsweighted set cover problemWriting Zero Knowledge Proofsyacademyyaudit ZK Fellowshipzero knowledge decision tree accuracy testszero knowledge decision tree predictionsZero Knowledge ProofszkZK FellowshipZKMLZKPZKP dotproductZKP Security Audit +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/karp-reduction/index.html b/tags/karp-reduction/index.html new file mode 100644 index 00000000..eb7e86bc --- /dev/null +++ b/tags/karp-reduction/index.html @@ -0,0 +1,225 @@ + + + + + + + +Karp reduction | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Karp reduction

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/kzg/index.html b/tags/kzg/index.html new file mode 100644 index 00000000..220dcfe3 --- /dev/null +++ b/tags/kzg/index.html @@ -0,0 +1,214 @@ + + + + + + + +KZG | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

KZG

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/lookup-arguments/index.html b/tags/lookup-arguments/index.html new file mode 100644 index 00000000..ce0b4b57 --- /dev/null +++ b/tags/lookup-arguments/index.html @@ -0,0 +1,214 @@ + + + + + + + +Lookup Arguments | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Lookup Arguments

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/machine-learning-feature-selection/index.html b/tags/machine-learning-feature-selection/index.html new file mode 100644 index 00000000..522e2766 --- /dev/null +++ b/tags/machine-learning-feature-selection/index.html @@ -0,0 +1,225 @@ + + + + + + + +machine learning feature selection | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

machine learning feature selection

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/mathematical-software/index.html b/tags/mathematical-software/index.html new file mode 100644 index 00000000..077333b7 --- /dev/null +++ b/tags/mathematical-software/index.html @@ -0,0 +1,225 @@ + + + + + + + +mathematical software | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

mathematical software

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/missing-value-analysis/index.html b/tags/missing-value-analysis/index.html new file mode 100644 index 00000000..9a49612b --- /dev/null +++ b/tags/missing-value-analysis/index.html @@ -0,0 +1,212 @@ + + + + + + + +Missing Value Analysis | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Missing Value Analysis

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ml-for-cardiomyopathy/index.html b/tags/ml-for-cardiomyopathy/index.html new file mode 100644 index 00000000..8a03c969 --- /dev/null +++ b/tags/ml-for-cardiomyopathy/index.html @@ -0,0 +1,224 @@ + + + + + + + +ML for Cardiomyopathy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ML for Cardiomyopathy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/ml/index.html b/tags/ml/index.html new file mode 100644 index 00000000..31f03939 --- /dev/null +++ b/tags/ml/index.html @@ -0,0 +1,234 @@ + + + + + + + +ML | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ML

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/multiscalar-multiplication/index.html b/tags/multiscalar-multiplication/index.html new file mode 100644 index 00000000..2538117d --- /dev/null +++ b/tags/multiscalar-multiplication/index.html @@ -0,0 +1,223 @@ + + + + + + + +Multiscalar Multiplication | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Multiscalar Multiplication

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/noir/index.html b/tags/noir/index.html new file mode 100644 index 00000000..14b548b6 --- /dev/null +++ b/tags/noir/index.html @@ -0,0 +1,218 @@ + + + + + + + +Noir | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Noir

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/non-linear-constraints/index.html b/tags/non-linear-constraints/index.html new file mode 100644 index 00000000..17791802 --- /dev/null +++ b/tags/non-linear-constraints/index.html @@ -0,0 +1,214 @@ + + + + + + + +Non-linear constraints | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Non-linear constraints

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/optimization-algorithms/index.html b/tags/optimization-algorithms/index.html new file mode 100644 index 00000000..bca4c1f8 --- /dev/null +++ b/tags/optimization-algorithms/index.html @@ -0,0 +1,225 @@ + + + + + + + +optimization algorithms | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

optimization algorithms

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/paper-review/index.html b/tags/paper-review/index.html new file mode 100644 index 00000000..a7e10fce --- /dev/null +++ b/tags/paper-review/index.html @@ -0,0 +1,234 @@ + + + + + + + +Paper Review | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Paper Review

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/point-addition/index.html b/tags/point-addition/index.html new file mode 100644 index 00000000..8cb36bd7 --- /dev/null +++ b/tags/point-addition/index.html @@ -0,0 +1,223 @@ + + + + + + + +Point Addition | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Point Addition

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/point-doubling/index.html b/tags/point-doubling/index.html new file mode 100644 index 00000000..3e33a910 --- /dev/null +++ b/tags/point-doubling/index.html @@ -0,0 +1,223 @@ + + + + + + + +Point Doubling | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Point Doubling

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/point-operations/index.html b/tags/point-operations/index.html new file mode 100644 index 00000000..133e8231 --- /dev/null +++ b/tags/point-operations/index.html @@ -0,0 +1,223 @@ + + + + + + + +Point Operations | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Point Operations

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/poseidon/index.html b/tags/poseidon/index.html new file mode 100644 index 00000000..a157e362 --- /dev/null +++ b/tags/poseidon/index.html @@ -0,0 +1,213 @@ + + + + + + + +Poseidon | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Poseidon

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/privacy-preserving-machine-learning/index.html b/tags/privacy-preserving-machine-learning/index.html new file mode 100644 index 00000000..fdfe0771 --- /dev/null +++ b/tags/privacy-preserving-machine-learning/index.html @@ -0,0 +1,214 @@ + + + + + + + +privacy preserving machine learning | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

privacy preserving machine learning

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/privacy/index.html b/tags/privacy/index.html new file mode 100644 index 00000000..bd90155b --- /dev/null +++ b/tags/privacy/index.html @@ -0,0 +1,214 @@ + + + + + + + +privacy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

privacy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/problem-solving-techniques/index.html b/tags/problem-solving-techniques/index.html new file mode 100644 index 00000000..85f78592 --- /dev/null +++ b/tags/problem-solving-techniques/index.html @@ -0,0 +1,225 @@ + + + + + + + +problem-solving techniques | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

problem-solving techniques

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/product-code/index.html b/tags/product-code/index.html new file mode 100644 index 00000000..c4026497 --- /dev/null +++ b/tags/product-code/index.html @@ -0,0 +1,220 @@ + + + + + + + +Product code | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Product code

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/public-key-cryptography/index.html b/tags/public-key-cryptography/index.html new file mode 100644 index 00000000..a4e4879f --- /dev/null +++ b/tags/public-key-cryptography/index.html @@ -0,0 +1,221 @@ + + + + + + + +Public Key Cryptography | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Public Key Cryptography

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/r1cs/index.html b/tags/r1cs/index.html new file mode 100644 index 00000000..63f52a0d --- /dev/null +++ b/tags/r1cs/index.html @@ -0,0 +1,214 @@ + + + + + + + +R1CS | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

R1CS

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/radiomics/index.html b/tags/radiomics/index.html new file mode 100644 index 00000000..154ba654 --- /dev/null +++ b/tags/radiomics/index.html @@ -0,0 +1,224 @@ + + + + + + + +Radiomics | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Radiomics

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/rate-limiting-nullifier/index.html b/tags/rate-limiting-nullifier/index.html new file mode 100644 index 00000000..efc6e7c1 --- /dev/null +++ b/tags/rate-limiting-nullifier/index.html @@ -0,0 +1,213 @@ + + + + + + + +Rate Limiting Nullifier | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Rate Limiting Nullifier

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/reed-solomon-codes/index.html b/tags/reed-solomon-codes/index.html new file mode 100644 index 00000000..a84d53fc --- /dev/null +++ b/tags/reed-solomon-codes/index.html @@ -0,0 +1,212 @@ + + + + + + + +Reed-Solomon Codes | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Reed-Solomon Codes

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/resource-allocation-optimization/index.html b/tags/resource-allocation-optimization/index.html new file mode 100644 index 00000000..4076a4ac --- /dev/null +++ b/tags/resource-allocation-optimization/index.html @@ -0,0 +1,225 @@ + + + + + + + +resource allocation optimization | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

resource allocation optimization

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/rln/index.html b/tags/rln/index.html new file mode 100644 index 00000000..501e5ff6 --- /dev/null +++ b/tags/rln/index.html @@ -0,0 +1,213 @@ + + + + + + + +RLN | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

RLN

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/rust/index.html b/tags/rust/index.html new file mode 100644 index 00000000..d14b2322 --- /dev/null +++ b/tags/rust/index.html @@ -0,0 +1,238 @@ + + + + + + + +Rust | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Rust

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/sagemath-implementation/index.html b/tags/sagemath-implementation/index.html new file mode 100644 index 00000000..966bda13 --- /dev/null +++ b/tags/sagemath-implementation/index.html @@ -0,0 +1,221 @@ + + + + + + + +SageMath Implementation | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

SageMath Implementation

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/sagemath/index.html b/tags/sagemath/index.html new file mode 100644 index 00000000..912ca2f5 --- /dev/null +++ b/tags/sagemath/index.html @@ -0,0 +1,285 @@ + + + + + + + +SageMath | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

SageMath

+
+
+
+ +
+ +
+ Pinned · + +

Unveiling the Weighted Set Cover Problem: Optimizing Resource Allocation

+
+

+Introduction +Problem Explanation +Problem Definition Weighted Set Cover +Solution Greedy Algorithm +Implementation in SageMath +Example Scenario +Applications in Blockchain Technology and Machine Learning + +Blockchain Transaction Fee Optimization +Machine Learning Feature Selection + + +R…

+
+
+
+ Pinned · + +

Unlocking the Power of ElGamal Encryption: Implementing and Enhancing Security with SageMath

+
+

+Introduction +ElGamal Encryption +Enhancing Security of ElGamal Encryption +Finding a Safe Generator +Practical Applications of ElGamal Encryption +Conclusion + +Introduction +ElGamal encryption is a widely-used public key encryption algorithm that provides confidentiality and security …

+
+
+
+ Pinned · + +

Mastering Elliptic Curve Arithmetic: A Comprehensive Guide with SageMath Examples

+
+

+Introduction Demystifying Elliptic Curves and Their Applications + +The Power of Elliptic Curve Cryptography (ECC) +Unlocking the Potential of ECC with SageMath + + +Understanding the Fundamentals of Elliptic Curves + +Definition of an Elliptic Curve +Points on an Elliptic Curve +Visualiz…

+
+
+
+ Pinned · + +

Error Correction in Ethereum's Danksharding: Harnessing the Power of Generalized Reed-Solomon Codes for Ethereum's Scalability

+
+

Danksharding is an innovative approach to scale Ethereum's blockchain, aiming to achieve over 100,000 transactions per second by enabling rollups to add cheaper data to blocks ethereum.org. As Ethereum moves towards Proto-Danksharding and eventually full Danksharding ethereum.org…

+
+
+
+ Pinned · + +

Enhancing Ethereum Scalability with Product Codes and Danksharding: A Comprehensive Guide

+
+

This article would provide an in-depth understanding of how product codes from algebraic coding theory can be applied to Danksharding to improve Ethereum's scalability. It would cover the fundamentals of product codes, their application in Danksharding, and the potential benefits…

+
+
+
+ Pinned · + +

Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve

+
+

In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications hackmd.io/@jpw. We will exploit the fact that $(p−1)/2…

+
+
+
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/secure-communication-with-elgamal/index.html b/tags/secure-communication-with-elgamal/index.html new file mode 100644 index 00000000..5bf2001d --- /dev/null +++ b/tags/secure-communication-with-elgamal/index.html @@ -0,0 +1,221 @@ + + + + + + + +Secure Communication with ElGamal | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Secure Communication with ElGamal

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/securing-communications-with-ecc/index.html b/tags/securing-communications-with-ecc/index.html new file mode 100644 index 00000000..07e35bb6 --- /dev/null +++ b/tags/securing-communications-with-ecc/index.html @@ -0,0 +1,223 @@ + + + + + + + +Securing Communications with ECC | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Securing Communications with ECC

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/security-audit/index.html b/tags/security-audit/index.html new file mode 100644 index 00000000..492d1ddd --- /dev/null +++ b/tags/security-audit/index.html @@ -0,0 +1,213 @@ + + + + + + + +Security Audit | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Security Audit

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/sublinear-lookup-arguments/index.html b/tags/sublinear-lookup-arguments/index.html new file mode 100644 index 00000000..149d0d29 --- /dev/null +++ b/tags/sublinear-lookup-arguments/index.html @@ -0,0 +1,214 @@ + + + + + + + +Sublinear Lookup Arguments | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Sublinear Lookup Arguments

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/technology-applications/index.html b/tags/technology-applications/index.html new file mode 100644 index 00000000..ce8b5478 --- /dev/null +++ b/tags/technology-applications/index.html @@ -0,0 +1,225 @@ + + + + + + + +technology applications | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

technology applications

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/understanding-zero-knowledge-proofs/index.html b/tags/understanding-zero-knowledge-proofs/index.html new file mode 100644 index 00000000..1301a6ee --- /dev/null +++ b/tags/understanding-zero-knowledge-proofs/index.html @@ -0,0 +1,222 @@ + + + + + + + +Understanding Zero Knowledge Proofs | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Understanding Zero Knowledge Proofs

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/weighted-set-cover-problem/index.html b/tags/weighted-set-cover-problem/index.html new file mode 100644 index 00000000..bb1308bd --- /dev/null +++ b/tags/weighted-set-cover-problem/index.html @@ -0,0 +1,225 @@ + + + + + + + +weighted set cover problem | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

weighted set cover problem

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/writing-zero-knowledge-proofs/index.html b/tags/writing-zero-knowledge-proofs/index.html new file mode 100644 index 00000000..f910441c --- /dev/null +++ b/tags/writing-zero-knowledge-proofs/index.html @@ -0,0 +1,226 @@ + + + + + + + +Writing Zero Knowledge Proofs | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Writing Zero Knowledge Proofs

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/yacademy/index.html b/tags/yacademy/index.html new file mode 100644 index 00000000..67077832 --- /dev/null +++ b/tags/yacademy/index.html @@ -0,0 +1,225 @@ + + + + + + + +yacademy | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

yacademy

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/yaudit-zk-fellowship/index.html b/tags/yaudit-zk-fellowship/index.html new file mode 100644 index 00000000..b19d33cf --- /dev/null +++ b/tags/yaudit-zk-fellowship/index.html @@ -0,0 +1,225 @@ + + + + + + + +yaudit ZK Fellowship | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

yaudit ZK Fellowship

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zero-knowledge-decision-tree-accuracy-tests/index.html b/tags/zero-knowledge-decision-tree-accuracy-tests/index.html new file mode 100644 index 00000000..f8bb9dfa --- /dev/null +++ b/tags/zero-knowledge-decision-tree-accuracy-tests/index.html @@ -0,0 +1,214 @@ + + + + + + + +zero knowledge decision tree accuracy tests | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

zero knowledge decision tree accuracy tests

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zero-knowledge-decision-tree-predictions/index.html b/tags/zero-knowledge-decision-tree-predictions/index.html new file mode 100644 index 00000000..cc0208ac --- /dev/null +++ b/tags/zero-knowledge-decision-tree-predictions/index.html @@ -0,0 +1,214 @@ + + + + + + + +zero knowledge decision tree predictions | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

zero knowledge decision tree predictions

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zero-knowledge-proofs/index.html b/tags/zero-knowledge-proofs/index.html new file mode 100644 index 00000000..f7e10f3c --- /dev/null +++ b/tags/zero-knowledge-proofs/index.html @@ -0,0 +1,233 @@ + + + + + + + +Zero Knowledge Proofs | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

Zero Knowledge Proofs

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zk-fellowship/index.html b/tags/zk-fellowship/index.html new file mode 100644 index 00000000..67e29667 --- /dev/null +++ b/tags/zk-fellowship/index.html @@ -0,0 +1,225 @@ + + + + + + + +ZK Fellowship | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ZK Fellowship

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zk/index.html b/tags/zk/index.html new file mode 100644 index 00000000..345bb727 --- /dev/null +++ b/tags/zk/index.html @@ -0,0 +1,268 @@ + + + + + + + +zk | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

zk

+
+
+
+ +
+ +
+ Pinned · + +

Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve

+
+

In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications hackmd.io/@jpw. We will exploit the fact that $(p−1)/2…

+
+
+
+ Pinned · + +

Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors

+
+

Overview +We will implement dot product of two vectors of size N using Zero Knowledge Proofs (ZKP) in Circom, Halo2, . According to k12.libretexts.org, the dot product of two vectors A and B of size N is given by: +A.B = a1*b1 + a2*b2 + ... + aN*bN + + +Overview +Process Flow of a Zero…

+
+
+
+ Pinned · + +

Different types of Zero Knowledge Proofs (Interactive and Non-interactive)

+
+

Overview +Zero knowledge proofs (ZKP) are cryptographic protocols that enable one party (the prover) to prove to another party (the verifier) the truth of a statement without revealing any additional information beyond the statement's validity. ZKPs are incredibly useful in scenar…

+
+
+
+ Pinned · + +

Explanation of the Concept of Zero Knowledge Proofs

+
+

Overview +Zero-knowledge proofs (ZKPs) are a groundbreaking concept in cryptography that allows one party to prove to another that a statement is true, without revealing any specific information about the statement itself. This technique is particularly useful in preserving privac…

+
+
+
+ Pinned · + +

A brief introduction to Zero Knowledge Proofs (ZKPs)

+
+

+Introduction + +A. Definition of Zero Knowledge Proofs (ZKPs) +B. Overview of the Benefits of Using ZKPs + + +How ZKPs Work + +A. Overview of the ZKP Process +B. Explanation of the Three Stages of the ZKP Process + + +Applications of ZKPs + +A. Cryptocurrency Transactions +B. Identity Manageme…

+
+
+
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zkml/index.html b/tags/zkml/index.html new file mode 100644 index 00000000..e4349a67 --- /dev/null +++ b/tags/zkml/index.html @@ -0,0 +1,214 @@ + + + + + + + +ZKML | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ZKML

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zkp-dotproduct/index.html b/tags/zkp-dotproduct/index.html new file mode 100644 index 00000000..426ededf --- /dev/null +++ b/tags/zkp-dotproduct/index.html @@ -0,0 +1,218 @@ + + + + + + + +ZKP dotproduct | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ZKP dotproduct

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zkp-security-audit/index.html b/tags/zkp-security-audit/index.html new file mode 100644 index 00000000..6bedd597 --- /dev/null +++ b/tags/zkp-security-audit/index.html @@ -0,0 +1,213 @@ + + + + + + + +ZKP Security Audit | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ZKP Security Audit

+
+
+
+ + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/tags/zkp/index.html b/tags/zkp/index.html new file mode 100644 index 00000000..ecc033e1 --- /dev/null +++ b/tags/zkp/index.html @@ -0,0 +1,273 @@ + + + + + + + +ZKP | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

ZKP

+
+
+
+ +
+ +
+ Pinned · + +

Mastering Rank One Constraint System R1CS with Circom Examples

+
+

In Draft Mode +Overview +Rank-1 Constraint Systems, or R1CS, are a critical component in cryptographic protocols, especially those related to zero-knowledge proofs such as zk-SNARKS. They are a system of equations used to represent computations, and are particularly useful in scena…

+
+
+
+ Pinned · + +

Paper Review - Zero Knowledge Proofs for Decision Tree Predictions and Accuracy

+
+

IN DRAFT MODE +Summary +Machine learning has become increasingly prominent and is widely used in various applications in practice. Despite its great success, the integrity of machine learning predictions and accuracy is a rising concern. The reproducibility of machine learning mode…

+
+
+
+ Pinned · + +

Rate Limiting Nullifier (RLN) Protocol: Circom Circuits Security Audit

+
+

Rate Limiting Nullifier (RLN) Review +I recently had the pleasure of conducting my first security audit of a Zero Knowledge Proofs (ZKP) protocol. The protocol in question was the Rate Limiting Nullifier (RLN) Zero Knowledge Proofs Protocol, with its circuits written in Circom. My…

+
+
+
+ Pinned · + +

Efficient Computation of Frobenius Automorphism on BN254 Elliptic Curve

+
+

In this blog post, we will explore an efficient method to compute the Frobenius automorphism for the BN254 elliptic curve. The BN254 curve is a pairing-friendly elliptic curve that is widely used in cryptographic applications hackmd.io/@jpw. We will exploit the fact that $(p−1)/2…

+
+
+
+ Pinned · + +

Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors

+
+

Overview +We will implement dot product of two vectors of size N using Zero Knowledge Proofs (ZKP) in Circom, Halo2, . According to k12.libretexts.org, the dot product of two vectors A and B of size N is given by: +A.B = a1*b1 + a2*b2 + ... + aN*bN + + +Overview +Process Flow of a Zero…

+
+
+
+ Pinned · + +

Different types of Zero Knowledge Proofs (Interactive and Non-interactive)

+
+

Overview +Zero knowledge proofs (ZKP) are cryptographic protocols that enable one party (the prover) to prove to another party (the verifier) the truth of a statement without revealing any additional information beyond the statement's validity. ZKPs are incredibly useful in scenar…

+
+
+
+ Pinned · + +

Explanation of the Concept of Zero Knowledge Proofs

+
+

Overview +Zero-knowledge proofs (ZKPs) are a groundbreaking concept in cryptography that allows one party to prove to another that a statement is true, without revealing any specific information about the statement itself. This technique is particularly useful in preserving privac…

+
+
+
+ +
+ + +
+ © 0xnagu. +
+ + + diff --git a/understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/index.html b/understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/index.html new file mode 100644 index 00000000..2e389cd0 --- /dev/null +++ b/understanding-caulk-protocol-a-beginner-guide-to-sublinear-time-lookup-arguments/index.html @@ -0,0 +1,269 @@ + + + + + + + +Understanding Caulk Protocol: A Beginner's Guide to Sublinear Time Lookup Arguments (In Draft Mode) | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Understanding Caulk Protocol: A Beginner's Guide to Sublinear Time Lookup Arguments (In Draft Mode)

+
+

Note: This article is in draft mode and I didn't finish writing the sections of the Caulk protocol, proof read, test the code for correctness and adding references. Please check it again in 1-2 weeks before I publish it.

+

Introduction

+

In this blog we will review Caulk protocol for computing efficient lookup arguments in sublinear time.

+

The Caulk protocol offers a significant improvement over existing cryptographic solutions for vector commitment schemes, providing a more efficient and secure approach to position-hiding linkability. Its potential impact on future cryptographic systems and applications is immense, paving the way for more scalable and practical solutions in privacy-preserving applications, verifiable computation schemes, and lookup tables.

+

Full citation of the paper: +@misc{cryptoeprint:2022/621, +author = {Arantxa Zapico and Vitalik Buterin and Dmitry Khovratovich and Mary Maller and Anca Nitulescu and Mark Simkin}, +title = {Caulk: Lookup Arguments in Sublinear Time}, +howpublished = {Cryptology ePrint Archive, Paper 2022/621}, +year = {2022}, +note = {\url{https://eprint.iacr.org/2022/621}}, +url = {https://eprint.iacr.org/2022/621} +}

+

What is the Caulk protocol and why it matters

+

The Caulk protocol is a groundbreaking cryptographic solution that addresses the challenges of vector commitment schemes in a more efficient and secure manner. It is designed to provide position-hiding linkability for vector commitment schemes, allowing users to prove in zero-knowledge that one or multiple values belong to a committed vector. This innovative approach has significant implications for privacy-preserving applications, verifiable computation schemes, and lookup tables.

+

Vector commitment schemes play a crucial role in cryptography, as they enable the creation of compact data structures that can store large numbers of elements while allowing users to prove that specific elements have been committed to. The Caulk protocol enhances these schemes by offering sublinear time lookup arguments, drastically reducing the computational overhead and making them more practical for real-world applications.

+

The role of vector commitment schemes in cryptography

+

Vector commitment schemes are fundamental cryptographic primitives that underpin numerous constructions and protocols. They allow users to commit to a potentially large set of elements in a compact manner and later prove that a specific element is part of the committed set. These proofs should be succinct, unforgeable, and ideally, zero-knowledge, meaning that they do not reveal any information about the committed element.

+

Some common applications of vector commitment schemes include privacy-preserving cryptocurrencies, membership proofs, ring signatures, and anonymous credentials. In these scenarios, it is essential to provide efficient and secure solutions that can scale with the growing demands of modern cryptographic systems.

+

Challenges with existing cryptographic solutions

+

Existing cryptographic solutions for vector commitment schemes often rely on heavy cryptography machinery, which can result in significant computational overheads and limit their scalability and adoption. For example, the first version of the Zcash cryptocurrency used a SHA-2-based Merkle tree and the Groth16 SNARK to prove coin ownership, resulting in a prover time of 40 seconds, which was barely usable in practice.

+

The Caulk protocol addresses these challenges by offering a more efficient and secure alternative to existing solutions. By leveraging the KZG polynomial commitment scheme and introducing position-hiding linkability, the Caulk protocol can drastically reduce the prover time and proof size, making it more practical for real-world applications.

+

Here's a simple example of Rust code to demonstrate the creation of a commitment using the Caulk protocol:

+

First, add the following dependencies to your Cargo.toml file:

+
[dependencies]
+arkworks-gadgets = "0.3.0"
+arkworks-utils = "0.3.0"
+caulk = { git = "https://github.com/caulk-crypto/caulk" }
+
+

Then, use the following Rust code to create a commitment using the Caulk protocol:

+
use ark_bls12_381::Bls12_381;
+use ark_ff::UniformRand;
+use ark_std::rand::rngs::OsRng;
+use caulk::commitment::{CaulkCommitment, Commitment};
+use caulk::srs::SRS;
+
+fn main() {
+    let vector = vec![1, 2, 3, 4, 5];
+    let rng = &mut OsRng;
+    let srs = SRS::<Bls12_381>::dummy(32);
+
+    let caulk_commitment = CaulkCommitment::<Bls12_381>::new(&srs, &vector);
+    let (commitment, randomness) = caulk_commitment.commit(rng);
+    println!("Commitment: {:?}", commitment);
+}
+
+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/index.html b/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/index.html new file mode 100644 index 00000000..d90484ad --- /dev/null +++ b/unlocking-the-power-of-elgamal-encryption-implementing-and-enhancing-security-with-sagemath/index.html @@ -0,0 +1,340 @@ + + + + + + + +Unlocking the Power of ElGamal Encryption: Implementing and Enhancing Security with SageMath | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Unlocking the Power of ElGamal Encryption: Implementing and Enhancing Security with SageMath

+
+ +

Introduction

+

ElGamal encryption is a widely-used public key encryption algorithm that provides confidentiality and security in communication systems. It was proposed by Taher ElGamal in 1985 and is based on the Diffie-Hellman key exchange protocol. In this guide, I will walk through the key components of the ElGamal encryption scheme, including key generation, encryption, and decryption. I will also demonstrate how to implement the algorithm using the SageMath software and enhance the security of the system by using a 256-bit random prime number.

+

ElGamal Encryption

+

Key Components The ElGamal encryption scheme consists of three main components:

+
    +
  • Key Generation: The process of generating a pair of public and private keys for the encryption and decryption process.
  • +
  • Encryption: The process of transforming plaintext into ciphertext using the public key.
  • +
  • Decryption: The process of recovering the plaintext from the ciphertext using the private key.
  • +
+

In ElGamal encryption, the public key is used for encrypting the message, while the private key is used for decrypting it. The security of the ElGamal encryption scheme is based on the difficulty of solving the discrete logarithm problem.

+

Let's consider an example of the ElGamal encryption process:

+
    +
  • Alice and Bob agree on a large prime number $p$ and a primitive root $g modulo p$.
  • +
  • Bob chooses a random private key $x$ and computes his public key $Y = g^x mod p$.
  • +
  • Alice wants to send a message $M$ to Bob. She chooses a random integer $k$ and computes the ciphertext $(a, b) = (g^k mod p, M * Y^k mod p)$.
  • +
  • Bob receives the ciphertext and decrypts it using his private key: $M = b * a^{-x}\ mod\ p$.
  • +
+

Flow of the ElGamal encryption

+

Here is the complete flow diagram of ElGamal encryption.

+

ElGamal encryption Flow

+
sequenceDiagram 
+
+Alice->>Bob: Generate key pair (public key, private key) 
+Note right of Alice: (g^a mod p, a) 
+Note right of Bob: (g^b mod p, b) 
+Alice->>Bob: Send public key (g^a mod p) 
+Bob->>Alice: Encrypt message with Alice's public key 
+Note right of Bob: Encrypted message: (g^b mod p, M * (g^a)^b mod p) 
+Alice->>Alice: Decrypt message with private key 
+Note right of Alice: Decrypted message: M = (g^a)^(-b) * (M * (g^a)^b mod p) mod p
+
+

Implementing ElGamal Encryption with SageMath SageMath is an open-source mathematics software that provides a powerful environment for implementing various cryptographic algorithms, including ElGamal encryption. To get started with SageMath, you can install it on your local machine or use the online version available at sagemath.org.

+

Once you have SageMath installed and running, you can implement the ElGamal encryption process as follows:

+
   from sage.all import *
+
+   # Key Generation
+   p = 23  # Prime number
+   g = 5   # Generator
+   x = 6   # Bob's private key
+   Y = power_mod(g, x, p)  # Bob's public key
+
+   # Encryption (Alice)
+   M = 12  # Message
+   k = 3   # Random value
+   a = power_mod(g, k, p)
+   b = (power_mod(Y, k, p) * M) % p
+
+   # Decryption (Bob)
+   M_decrypted = (b * power_mod(a, -x, p)) % p
+
+   print("Original message:", M)
+   print("Encrypted message:", (a, b))
+   print("Decrypted message:", M_decrypted)
+
+

This example demonstrates the basic ElGamal encryption process with a fixed prime number $p$. The output shows the original message, the encrypted message, and the decrypted message.

+

Enhancing Security of ElGamal Encryption

+

Choosing a 256-bit Random Prime Using large prime numbers in the ElGamal encryption process is crucial for ensuring the security of the system. Larger prime numbers make it more difficult for an attacker to solve the discrete logarithm problem, which is the basis of the ElGamal encryption scheme's security.

+

To generate a 256-bit random prime number in SageMath, you can use the random_prime() function:

+
   p = random_prime(2^256, lbound=2^255, proof=False)  # 256-bit prime number
+
+

By updating the previous SageMath code with this new prime number generation method, you can enhance the security of the ElGamal encryption process.

+

Finding a Safe Generator

+

In the ElGamal encryption scheme, selecting a safe generator $g$ is crucial for the security of the system. A safe generator is a number that generates a cyclic subgroup of the multiplicative group $modulo p$, where $p$ is a large prime number.

+

To find a safe generator $g$, follow these steps:

+
    +
  1. First, select a large prime number $p$ and compute $(p-1)/2$, which should also be prime. This new prime number is denoted as $q$.
  2. +
  3. Now, choose a random number $g$ from the set ${2, 3, ... , p-2}$.
  4. +
  5. Calculate $(g^q) mod p$. If the result is not equal to 1, then g is a safe generator.
  6. +
+

Here's an example of how to find a safe generator using SageMath:

+
# Find a safe generator $g$ for a given prime $p$
+def find_safe_generator(p):
+    q = (p - 1) // 2
+    g = 2
+    while True:
+        if power_mod(g, q, p) != 1:
+            return g
+        g += 1
+
+# Example: Finding a safe generator for a 256-bit prime number
+p = random_prime(2^256, 2^255)
+g = find_safe_generator(p)
+print("Safe generator (g):", g)
+
+

By following this method, you can ensure that the chosen generator $g$ is safe and suitable for use in the ElGamal encryption scheme.

+

Practical Applications of ElGamal Encryption

+

ElGamal encryption has numerous practical applications, including:

+
    +
  • Secure communication: ElGamal encryption can be used to ensure confidentiality in communication systems, such as email and instant messaging.
  • +
  • Digital signatures: ElGamal encryption can be adapted for use in digital signature schemes, providing integrity and non-repudiation for electronic documents and transactions.
  • +
  • Key exchange: ElGamal can be used as a key exchange protocol, allowing two parties to establish a shared secret key over an insecure channel.
  • +
  • Secure voting systems: ElGamal encryption can be employed in secure electronic voting systems to maintain voter privacy and ensure that votes are accurately counted.
  • +
+

Despite its benefits, ElGamal encryption has some limitations that should be considered when choosing a cryptographic solution:

+
    +
  • Computational complexity: ElGamal encryption and decryption require modular exponentiation operations, which can be computationally expensive, especially for large prime numbers.
  • +
  • Message expansion: The ciphertext in ElGamal encryption consists of two elements, resulting in a message expansion factor of two compared to the original plaintext size.
  • +
  • Lack of built-in authentication: ElGamal encryption does not provide built-in message authentication or integrity checking, which may require additional mechanisms to ensure data integrity.
  • +
+

Conclusion

+

In this article, I have provided an in-depth explanation of ElGamal encryption and its key components, including key generation, encryption, and decryption. I have also demonstrated how to implement the ElGamal encryption algorithm using SageMath and enhance the security of the system by using a 256-bit random prime number.

+

ElGamal encryption is an essential tool in the field of cryptography, with numerous practical applications in secure communication, digital signatures, key exchange, and secure voting systems. However, it is crucial to consider its limitations and choose the most suitable encryption scheme for your specific needs.

+

I encourage you to experiment with ElGamal encryption using SageMath and explore its potential in various applications. By understanding the fundamentals of ElGamal encryption and its implementation, you can build more secure and robust cryptographic systems.

+

You can find the full code in the github repo github.com/thogiti.

+

References

+
    +
  1. ElGamal, T. (1985). A public key cryptosystem and a signature scheme based on discrete logarithms. IEEE Transactions on Information Theory, 31(4), 469-472.
  2. +
  3. Diffie, W., & Hellman, M. E. (1976). New directions in cryptography. IEEE Transactions on Information Theory, 22(6), 644-654.
  4. +
+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/index.html b/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/index.html new file mode 100644 index 00000000..dfa122b2 --- /dev/null +++ b/unveiling-the-weighted-set-cover-problem-optimizing-resource-allocation/index.html @@ -0,0 +1,369 @@ + + + + + + + +Unveiling the Weighted Set Cover Problem: Optimizing Resource Allocation | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Unveiling the Weighted Set Cover Problem: Optimizing Resource Allocation

+
+ +

Introduction

+

Welcome, fellow adventurers, to a captivating journey through the realms of the weighted set cover problem (WSC)! Imagine yourself as a wise ruler of a vast kingdom, yearning to promote tourism and showcase the wonders of your realm. But with a limited budget, how do you ensure that every precious gem in your kingdom receives the attention it deserves? Fear not! The weighted set cover problem comes to your rescue, providing a strategy to maximize coverage while minimizing cost. Let's embark on this quest together!

+

Problem Explanation

+

In this kingdom, attractions are like gleaming gems scattered across the land, and subsets represent different regions or provinces. The goal is to select a set of travel packages (subsets) that cover all the attractions (items) while keeping the total cost (weight) within your budget. Mathematically, we define the weighted set cover problem using set notation and equations. Let $U$ be the set of items, $S$ be the collection of subsets, $w(i)$ be the weight associated with item i, and $B$ be the budget. Our objective is to find a minimum-weight set cover such that the total weight is minimized $(∑w(i)$ for $i$ in $C$) and within the budget $(∑w(i)$ for $i$ in $C ≤ B$).

+

Now, let's understand this step by step:

+

Problem Definition Weighted Set Cover

+

Weighted Set Cover Example

+

Given:

+
    +
  • A universe $U$ of $n$ items (attractions in our analogy).
  • +
  • A collection $S$ of m subsets (regions/provinces).
  • +
  • A weight $w(i)$ associated with each item $i$, indicating its cost.
  • +
  • A budget $B$.
  • +
+

Find:

+
    +
  • A minimum-weight set cover, which is a collection of subsets that covers all the items in $U$, such that the total weight of the selected subsets is less than or equal to the budget $B$.
  • +
+

Mathematically, we can represent the problem as follows:

+

Let $U = {1, 2, 3, ..., n}$ be the set of items. +Let $S = {S₁, S₂, ..., Sₘ}$ be the collection of subsets. +Let $w(i)$ be the weight associated with item $i$. +Let $B$ be the budget.

+

The objective is to find a set $C$ of subsets such that:

+
    +
  • $C$ covers all items in $U$.
  • +
  • The total weight of the subsets in $C$ is minimized: $∑w(i)$ for i in $C$ is minimized.
  • +
  • The total weight of the subsets in $C$ is less than or equal to the budget $B: ∑w(i)$ for $i$ in $C ≤ B$.
  • +
+

To solve this problem, we can use various algorithms, and one popular approach is the greedy algorithm. The idea behind the greedy algorithm is to iteratively select the subset that covers the maximum number of uncovered items while keeping the total weight within the budget. We can repeat this process until all items are covered.

+

Solution Greedy Algorithm

+

Imagine you're accompanied by a knowledgeable tour guide who knows the ins and outs of each region. The guide suggests using the greedy algorithm, a tried-and-true strategy. At each step, the algorithm selects the subset that covers the maximum number of uncovered items, ensuring the greatest coverage for your budget. This iterative process continues until all items are covered. Picture a sequence diagram where the tour guide carefully evaluates subsets and intelligently selects the most promising ones.

+

Implementation in SageMath

+

Enter SageMath, your trusty advisor equipped with mathematical prowess! SageMath is a powerful mathematical software that enables us to implement the weighted set cover algorithm with ease. Let's dive into the code and unravel its secrets.

+
# Import the required modules
+from sage.all import *
+
+def weighted_set_cover(U, S, w, B):
+    C = []  # Selected subsets
+    uncovered = set(U)  # Initially, all items are uncovered
+
+    while uncovered:
+        best_subset = None
+        max_covered = 0
+
+        for subset in S:
+            covered = uncovered.intersection(subset)
+            if len(covered) > max_covered:
+                best_subset = subset
+                max_covered = len(covered)
+
+        C.append(best_subset)
+        uncovered -= best_subset
+
+    total_weight = sum(w[i] for subset in C for i in subset)
+    return C, total_weight
+
+

In this code snippet, we start by importing the necessary modules from SageMath. The weighted_set_cover function takes four parameters: U (the set of items), S (the collection of subsets), w (the dictionary representing the weights of items), and B (the budget).

+

Inside the function, we initialize an empty list C to store the selected subsets. We also create a set uncovered containing all the items initially, as none of them are covered.

+

Next, we enter a loop that continues until all items are covered. Within this loop, we search for the best subset that covers the maximum number of uncovered items. To accomplish this, we iterate through each subset and find the intersection with the uncovered items. If the number of covered items is greater than the previous maximum, we update the best_subset and max_covered variables accordingly.

+

After selecting the best subset, we add it to our list of selected subsets C and remove the covered items from the uncovered set.

+

Finally, we calculate the total weight of the selected subsets by summing the weights of the items within each subset in C.

+

Example Scenario

+

Let's consider a whimsical example to bring this problem to life. In your kingdom, you have five enchanting items (1, 2, 3, 4, 5) and four distinct regions or provinces: {1, 2}, {2, 3, 4}, {1, 3, 5}, and {4, 5}. Each item carries a unique weight: item 1 has a weight of 3, item 2 has a weight of 5, item 3 has a weight of 2, item 4 has a weight of 4, and item 5 has a weight of 1. Your budget for promoting these treasures is set at 10.

+

Let's invoke our trusty SageMath code to find the optimal solution:

+
U = {1, 2, 3, 4, 5}  # Set of items
+S = [{1, 2}, {2, 3, 4}, {1, 3, 5}, {4, 5}]  # Collection of subsets
+w = {1: 3, 2: 5, 3: 2, 4: 4, 5: 1}  # Weight associated with each item
+B = 10  # Budget
+
+selected_subsets, total_weight = weighted_set_cover(U, S, w, B)
+
+print("Selected Subsets:")
+for subset in selected_subsets:
+    print(subset)
+
+print("Total Weight:", total_weight)
+
+

Executing this code will display the result of our royal decree: the selected subsets and their total weight. The output will provide valuable insights into which regions or provinces you should include in your travel packages to maximize coverage while keeping costs under control.

+

Applications in Blockchain Technology and Machine Learning

+

The weighted set cover problem finds its applications in various technological domains, where efficient resource allocation and optimization are crucial. Let's explore two intriguing examples in the blockchain and machine learning fields.

+

Blockchain Transaction Fee Optimization

+

In the realm of blockchain technology, the weighted set cover problem can be employed to optimize transaction fee calculations. In blockchain networks like Bitcoin or Ethereum, users must pay transaction fees to incentivize miners or validators to include their transactions in the next block.

+

Consider a scenario where a user wants to perform multiple transactions while minimizing the total transaction fee paid. Each transaction corresponds to an item, and the available subsets represent different sets of transactions that can be included in a block. The weights associated with the items can represent the transaction fees.

+

By solving the weighted set cover problem, blockchain systems can identify the optimal set of transactions to include in a block, maximizing the number of transactions while minimizing the total fee paid by the user.

+

Machine Learning Feature Selection

+

Feature selection plays a vital role in machine learning, where the goal is to identify the most relevant features or attributes that contribute to accurate predictions or classifications. The weighted set cover problem can be utilized to solve feature selection challenges efficiently. In Machine Learning, there are different kinds of techniques to identify the best predictors to explain the data.

+

Imagine a dataset with a large number of features, each representing a potential attribute. By treating the features as items and subsets as different combinations of feature subsets, the weighted set cover problem can help identify the minimal set of features that provide optimal predictive power.

+

Solving the weighted set cover problem in the context of machine learning allows for efficient feature selection, reducing computational complexity, and improving model performance and interpretability.

+

These are just two glimpses into the vast applications of the weighted set cover problem in the technological landscape. Whether in blockchain, machine learning, or other domains, this problem provides valuable insights and optimization strategies for resource allocation, decision-making, and problem-solving. As technology advances, the weighted set cover problem continues to contribute to innovative solutions and efficient resource utilization.

+

Relating to Karp Reduction

+

The weighted set cover problem has an intriguing connection to Karp reduction, a fundamental concept in computational complexity theory. We can formally express this relationship using mathematical notation.

+

In computational complexity theory, Karp reduction is denoted by the symbol $\leq_{\text{Karp}}$, indicating that one problem can be reduced to another. In our case, we can demonstrate that the weighted set cover problem is Karp reducible to the Set Cover problem.

+

Let's define the two problems mathematically:

+
    +
  1. +

    Weighted Set Cover Problem (WSC):

    +
      +
    • Given a universe of items $U$, a collection of subsets $S$, weights $w(i)$ for each item $i \in U$, and a budget $B$,
    • +
    • The objective is to find a minimum-weight set cover $C$ such that $\sum_{i \in C} w(i) \leq B$.
    • +
    +
  2. +
  3. +

    Set Cover Problem (SC):

    +
      +
    • Given a universe of items $U$ and a collection of subsets $S$,
    • +
    • The objective is to find the smallest collection of subsets $C$ such that $\bigcup_{X \in C} X = U$.
    • +
    +
  4. +
+

To establish the Karp reduction from the WSC problem to the SC problem, we construct an instance of the SC problem using the same universe $U$ and subsets $S$ as in the WSC problem. Additionally, we assign unit weights to all items in the SC problem.

+

Formally, we can express the Karp reduction as follows:

+

$WSC \leq_{\text{Karp}} SC$

+

This reduction shows that the WSC problem can be transformed into the SC problem, indicating that the WSC problem is at least as hard as the SC problem. Since the SC problem is known to be NP-complete, this implies that the WSC problem is also NP-complete.

+

Understanding this mathematical relationship between the WSC problem and Karp reduction provides valuable insights into the computational complexity of the problem and establishes connections with other NP-complete problems. It allows us to leverage existing algorithms and problem-solving techniques developed for the SC problem when tackling the WSC problem.

+

Conclusion

+

Congratulations! You have successfully embarked on a journey through the fascinating world of the weighted set cover problem. We began our adventure by imagining ourselves as rulers, seeking to promote tourism in our kingdom. We learned about the problem's formulation using mathematical notation and equations, and we employed the greedy algorithm as our trusted tour guide to select subsets that covered the maximum number of attractions while staying within our budget.

+

With the help of SageMath, we implemented the weighted set cover algorithm, carefully considering the code's structure and functionality. We then applied our implementation to an example scenario, where we discovered the optimal subsets and their total weight.

+

The weighted set cover problem holds great importance in various real-world applications, such as optimization, resource allocation, and data analysis. It provides a valuable framework for decision-making and problem-solving.

+

As you venture forth, remember to explore further, experiment with different scenarios, and adapt the code to your specific needs. May your kingdom thrive with flourishing tourism and abundant gem-filled travel packages!

+

Happy covering, noble ruler!

+

You can find the complete sagemath code at the github repo github.com/thogiti.

+

Additional References

+
    +
  1. optimization.cbe.cornell.edu
  2. +
  3. cs.cornell.edu
  4. +
  5. en.wikipedia.org
  6. +
  7. en.wikipedia.org
  8. +
  9. courses.engr.illinois.edu
  10. +
+ +
+ + + + + +
+ + +
+ © 0xnagu. +
+ + + diff --git a/writing-zero-knowledge-proofs-and-circuits-in-four-languages/index.html b/writing-zero-knowledge-proofs-and-circuits-in-four-languages/index.html new file mode 100644 index 00000000..a04b4fdd --- /dev/null +++ b/writing-zero-knowledge-proofs-and-circuits-in-four-languages/index.html @@ -0,0 +1,540 @@ + + + + + + + +Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors | Dare to Know - AI, Machine Learning, and Blockchain Technology Insights + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +

Writing Zero Knowledge Proofs and Circuits in Four Different Languages - Dotproduct of Two Vectors

+
+

Overview

+

We will implement dot product of two vectors of size N using Zero Knowledge Proofs (ZKP) in Circom, Halo2, . According to k12.libretexts.org, the dot product of two vectors A and B of size N is given by:

+
A.B = a1*b1 + a2*b2 + ... + aN*bN
+
+ +

Process Flow of a Zero Knowledge Proof

+

The below diagram describes a typical process flow in creating a Zero Knowledge Proof system. Zero Knowledge Proof Process Flow

+

To create zero-knowledge proofs and circuits using different libraries like Circom, Noir, and Halo2, follow these steps:

+
    +
  1. Define the problem: Identify the problem you want to prove using zero-knowledge proofs. For instance, prove that you are a member of top 100 Uniswap liquidity provider without revealing any additional information or that you identified a critical bug in a smart contract without revealing any additional information.
  2. +
  3. Choose the appropriate ZKP library: Select the library that suits your needs, such as Circom, Noir, or Halo2 or others. Each library has its own set of features and trade-offs: +
      +
    • Circom: A domain-specific language (DSL) designed for creating circuits in a simple and intuitive way. It's useful for creating zk-SNARK circuits. For more details on Circom, visit the official documentation.
    • +
    • Noir: A high-level, general-purpose language for creating zero-knowledge proofs. It's easy to understand and has a growing ecosystem. For more details on Noir, visit the official documentation.
    • +
    • Halo2: A library for constructing zk-SNARKs without a trusted setup, providing a more secure and efficient alternative to some other libraries. For more details on Halo2, visit the official documentation.
    • +
    +
  4. +
  5. Create the circuit: Design the circuit that represents the problem using the chosen library. This involves defining the inputs, outputs, and constraints that must be satisfied for the proof to be valid.
  6. +
  7. Generate the proof: Using the library's tools, generate the zero-knowledge proof that demonstrates the statement is true without revealing any additional information.
  8. +
  9. Verify the proof: Implement the verification process to ensure that the proof is valid and the statement is true, without learning any additional information.
  10. +
+

Circom Circuit for Dotproduct of Two Vectors

+

In this example we will investigate how to write a Circom circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof withoit revealing any additional information.

+

Circom Setup and Installation

+

The complete and latest documentation for installing the Circom ecosystem can be found here. The older versions of Circom can be also installed from the old circom repository.

+

Circom Install dependencies

+

The Circom compiler is written in Rust. To have Rust available in your system, you can install rustup. If you’re using Linux or macOS, open a terminal and enter the following command:

+
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
+
+

You also need the latest version of Node.js (or yarn). You can install them from here.

+

Install Circom

+

First, clone the circom repository:

+
git clone https://github.com/iden3/circom.git
+
+

Enter the circom directory and use the cargo build to compile:

+
cargo build --release
+
+

The installation takes around 3 minutes to be completed. When the command successfully finishes, it generates the circom binary in the directory target/release. You can install this binary as follows:

+
cargo install --path circom
+
+

The previous command will install the circom binary in the directory $HOME/.cargo/bin.

+

Install Snarkjs

+

You can install snarkjs with the following command:

+
npm install -g snarkjs
+
+

Implementing Circom Circuit for the Dotproduct of Two Vectors

+

To implement the dotproduct of two vectors in Circom, we can follow the steps below:

+
    +
  1. Define the two vectors A and B of size N.
  2. +
  3. Define a variable to store the dot product.
  4. +
  5. Calculate the dot product by multiplying the corresponding components of A and B and adding them together.
  6. +
  7. Output the dot product.
  8. +
+

Here's what the code would look like in Circom:

+

+template DotProduct(N: number) {
+    signal A[N];
+    signal B[N];
+    signal result;
+
+    component multiply[N];
+    component add[N-1];
+
+    for (i = 0; i < N; i++) {
+        multiply[i] A[i] * B[i] -> add[i];
+    }
+
+    for (i = 0; i < N-1; i++) {
+        add[i] + add[i+1] -> add[i+1];
+    }
+
+    add[N-2] -> result;
+}
+
+
+

In the above code, we define two input signals A and B of size N, which represent the two vectors. We also define an output signal result, which will store the dot product.

+

We then define two components, multiply and add. The multiply component multiplies the corresponding components of A and B, while the add component adds them together. We use a loop to connect the outputs of the multiply components to the inputs of the add components. We also use a loop to connect the outputs of the add components to each other, until we reach the final output signal result.

+

To use this template, we can simply instantiate it and provide values for the A and B signals:

+

+template Main() {
+    signal A[4] = [3, -5, 4, 2];
+    signal B[4] = [2, 6, 5, 1];
+    signal result;
+
+    DotProduct(4)()
+        .A(A)
+        .B(B)
+        .result(result);
+
+    print(result);
+}
+
+
+

In the above code, we define the two input signals A and B of size 4, and an output signal result. We then instantiate the DotProduct template with a size of 4, and connect its A and B signals to the corresponding input signals. We also connect its result signal to our output signal. Finally, we print the result signal.

+

Halo2 Circuit for Dotproduct of Two Vectors

+

In this example we will investigate how to write a Halo2 circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof without revealing any additional information.

+

Halo2 Setup and Installation

+

Halo2 requires the latest Rust. You can find more about developing using Halo2 at the official halo2 documentation.

+

Implementing Halo2 Circuit for the Dotproduct of Two Vectors

+

To implement the dotproduct of two vectors in Halo2, we first need to define our circuit in Halo2. Here is the code for this:

+

+use halo2::{
+    circuit::{Layouter, SimpleFloorPlanner},
+    plonk::{Circuit, ConstraintSystem, Error},
+    poly::Rotation,
+};
+
+// Define the circuit struct
+#[derive(Debug)]
+struct DotProduct<'a> {
+    a: &'a [u64],
+    b: &'a [u64],
+    result: &'a mut [u64],
+}
+
+// Implement the Circuit trait for our circuit
+impl<'a> Circuit<SimpleFloorPlanner> for DotProduct<'a> {
+    type Config = ();
+    type FloorPlanner = SimpleFloorPlanner;
+
+    fn without_witnesses(&self) -> Self {
+        DotProduct {
+            a: self.a,
+            b: self.b,
+            result: &mut [0; N],
+        }
+    }
+
+    fn configure(
+        _config: Self::Config,
+        meta: &mut ConstraintSystem<SimpleFloorPlanner>,
+    ) -> Result<(), Error> {
+        // Define the input signals A and B
+        let a = meta.advice_column();
+        let b = meta.advice_column();
+
+        // Define the intermediate signals for multiplication
+        let mul = (0..N)
+            .map(|_| meta.advice_column())
+            .collect::<Vec<_>>();
+
+        // Define the intermediate signals for addition
+        let add = (0..N - 1)
+            .map(|_| meta.advice_column())
+            .collect::<Vec<_>>();
+
+        // Define the output signal result
+        let result = meta.advice_column();
+
+        // Constrain the input signals to the values provided
+        for (i, &value) in self.a.iter().enumerate() {
+            meta.enable_constant(a[i], value.into())?;
+        }
+        for (i, &value) in self.b.iter().enumerate() {
+            meta.enable_constant(b[i], value.into())?;
+        }
+
+        // Constrain the multiplication signals to the product 
+        // of the corresponding components of A and B
+        for i in 0..N {
+            meta.multiply(
+                Rotation::prev(),
+                &[a[i], b[i]],
+                mul[i],
+            )?;
+        }
+
+        // Constrain the addition signals to the sum of the 
+        // corresponding multiplication signals
+        for i in 0..N - 1 {
+            meta.add(
+                Rotation::cur(),
+                &[mul[i], mul[i + 1]],
+                add[i],
+            )?;
+        }
+
+        // Constrain the output signal to the last addition signal
+        meta.copy(
+            Rotation::cur(),
+            add[N - 2],
+            result,
+        )?;
+
+        // Constrain the output signal to the value provided
+        for (i, &value) in self.result.iter().enumerate() {
+            meta.constrain_equal(result, value.into())?;
+        }
+
+        Ok(())
+    }
+}
+
+
+

In this code, we define our circuit struct DotProduct, which contains the input signals a and b, and an output signal result. We also implement the Circuit trait for our circuit, which defines how the circuit should be constructed and constrained.

+

We define the input signals a and b using meta.advice_column(), which creates a new advice column in the circuit. We also define the intermediate signals mul and add, which will be used to perform the multiplication and addition operations. Finally, we define the output signal result.

+

We constrain the input signals to the values provided using meta.enable_constant(), which constrains the advice column to a constant value. We then constrain the multiplication signals using meta.multiply(), which constrains the product of the corresponding components of a and b to the corresponding multiplication signal. We then constrain the addition signals using meta.add(), which constrains the sum of the corresponding multiplication signals to the corresponding addition signal. Finally, we constrain the output signal to the last addition signal using meta.copy(), and constrain it to the value provided using meta.constrain_equal().

+

To use this circuit, we can instantiate it with the values for a and b, and an empty vector for result. We can then create a proof using Prover::prove(), and verify the proof using Verifier::verify(). Here's an example:

+

+use halo2::{
+    dev::MockProver,
+    plonk::{Circuit, ConstraintSystem, Verifier},
+};
+
+// Define the size of our vectors
+const N: usize = 4;
+
+// Define our main function
+fn main() {
+    // Define the input signals A and B
+    let a = [3, 5, 4, 2];
+    let b = [2, 6, 5, 1];
+
+    // Define the output signal result
+    let mut result = [0; N];
+
+    // Instantiate the circuit
+    let circuit = DotProduct {
+        a: &a,
+        b: &b,
+        result: &mut result,
+    };
+
+    // Create a proof
+    let prover = MockProver::run(N, &circuit, vec![]).unwrap();
+    let proof = prover.proof;
+
+    // Verify the proof
+    let verifier = Verifier::new(N, &circuit, &proof).unwrap();
+    assert!(verifier.verify().is_ok());
+
+    // Print the result
+    println!("{:?}", result);
+}
+
+
+

In this code, we define the input signals a and b and the output signal result. We then instantiate the DotProduct circuit with these values. We create a proof using MockProver::run(), which simulates the circuit execution and generates a proof. We then verify the proof using Verifier::new() and verify(). Finally, we print the result.

+

Note that in this example, we use MockProver to generate a proof and verify it. In a real-world application, we would use a trusted setup to generate the proving and verifying keys, and use those keys to generate and verify proofs. We would also need to ensure that the inputs and outputs of the circuit are properly encrypted and decrypted to prevent information leakage. However, these details are beyond the scope of this example.

+

What is a trusted setup and why is it necessary in a real-world application?

+

A trusted setup is a process used in some zero-knowledge proof systems, including Halo2, to generate the proving and verifying keys that are used to generate and verify proofs. The trusted setup involves a group of trusted individuals or entities who collectively generate and destroy a secret value that is used to generate the keys. The secret value is destroyed after the keys are generated, so that no one can learn it and use it to generate fake proofs.

+

The trusted setup is necessary in a real-world application because it ensures that the proving and verifying keys are generated in a way that is secure and unbiased. Without a trusted setup, an attacker could potentially generate their own keys and use them to generate fake proofs that are accepted by the system. The trusted setup ensures that the keys are generated in a way that is independent of the attacker, and that the attacker cannot learn the secret value used to generate the keys.

+

In Halo2, the trusted setup involves generating a random permutation of the circuit's columns, and using this permutation to generate the keys. The permutation is generated using a multiparty computation protocol, where each participant contributes a random value that is combined to generate the final permutation. The permutation ensures that the circuit's columns are mixed together in a way that prevents an attacker from learning anything about the circuit by observing the keys.

+

Once the trusted setup is complete, the proving and verifying keys are distributed to the users of the system, who can use them to generate and verify proofs. The users do not need to trust each other or the system, because the keys were generated in a way that is secure and unbiased. However, the users must ensure that the inputs and outputs of the circuit are properly encrypted and decrypted, to prevent information leakage.

+

In summary, a trusted setup is a process used to generate the proving and verifying keys for a zero-knowledge proof system, and is necessary in a real-world application to ensure that the keys are generated in a way that is secure and unbiased.

+

Noir Circuit for Dotproduct of Two Vectors

+

In this example we will investigate how to write a Noir circuit for the dotproduct of two vectors, create a Zero Knowledge Proof and verify the proof without revealing any additional information.

+

For more details about Noir programming language, visit the official documentation.

+

Installing Noir

+

Noir is a Rust based language. You can visit the official documentation for installation instructions.

+

Implementing Noir Circuit for the Dotproduct of Two Vectors

+

To implement the dotproduct of two vectors in Noir, we first need to define our circuit in Noir. Here is the code for this:

+
// Noir does not have a built-in dot product function, so we create one
+fn dot_product(vect_A: [field], vect_B: [field]) -> field {
+    let mut result: field = 0;
+    let N = vect_A.len();
+
+    for i in 0..N {
+        result += vect_A[i] * vect_B[i];
+    }
+
+    return result;
+}
+
+// Example usage
+fn main() {
+    let vect_A: [field] = [1, 2, 3, 4];
+    let vect_B: [field] = [5, 6, 7, 8];
+
+    let result: field = dot_product(vect_A, vect_B);
+
+    // The result should be 70 (1*5 + 2*6 + 3*7 + 4*8)
+    assert_eq!(result, 70);
+}
+
+
+
    +
  1. The dot_product function is defined with two input parameters, vect_A and vect_B, both of which are arrays of fields (a field is a type in Noir representing a finite field element). The function returns a field.
  2. +
  3. Inside the dot_product function, a mutable variable result is initialized with a value of 0, and the length of vect_A is stored in the variable N.
  4. +
  5. A for loop iterates through the indices of both input arrays, from 0 to N-1. In each iteration, the corresponding elements of the two arrays are multiplied and added to the result.
  6. +
  7. The result is returned as the output of the dot_product function.
  8. +
  9. The main function demonstrates how to use the dot_product function. Two arrays, vect_A and vect_B, are defined, and their dot product is calculated using the dot_product function.
  10. +
  11. Finally, an assertion checks that the result is equal to 70, which is the expected dot product value (15 + 26 + 37 + 48).
  12. +
+

The following steps will build the ZKP program and creates proofs and verifies the proof without any additional information.

+
    +
  • Build: nargo check
  • +
  • Prove: Enter the inputs in Prover.toml and run nargo prove p -v. Or, nargo prove --show-output p to show println logs.
  • +
  • Verify: nargo verify p
  • +
+ +
+ + + + + +
+ + + + + +