From 4dd7f6f89c4b47e278626f2b0934ab5cdb0c1502 Mon Sep 17 00:00:00 2001 From: Joshua <62268199+minimalsm@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:13:42 +0000 Subject: [PATCH] i18n(mr): translation import part 09 of 13 (23 files) --- .../developers/tutorials/short-abi/index.md | 585 +++++ .../index.md | 91 + .../tutorials/stealth-addr/index.md | 436 ++++ .../index.md | 314 +++ .../token-integration-checklist/index.md | 86 + .../index.md | 314 +++ .../index.md | 177 ++ .../uniswap-v2-annotated-code/index.md | 1898 +++++++++++++++++ .../tutorials/using-websockets/index.md | 245 +++ .../index.md | 300 +++ .../index.md | 204 ++ .../index.md | 199 ++ .../tutorials/yellow-paper-evm/index.md | 278 +++ public/content/translations/mr/eips/index.md | 78 + .../mr/energy-consumption/index.md | 86 + .../translations/mr/eth/supply/index.md | 80 + .../translations/mr/ethereum-forks/index.md | 663 ++++++ .../translations/mr/foundation/index.md | 33 + .../content/translations/mr/gaming/index.md | 70 + .../content/translations/mr/glossary/index.md | 505 +++++ .../translations/mr/governance/index.md | 184 ++ .../index.md | 75 + .../mr/guides/how-to-id-scam-tokens/index.md | 94 + 23 files changed, 6995 insertions(+) create mode 100644 public/content/translations/mr/developers/tutorials/short-abi/index.md create mode 100644 public/content/translations/mr/developers/tutorials/smart-contract-security-guidelines/index.md create mode 100644 public/content/translations/mr/developers/tutorials/stealth-addr/index.md create mode 100644 public/content/translations/mr/developers/tutorials/the-graph-fixing-web3-data-querying/index.md create mode 100644 public/content/translations/mr/developers/tutorials/token-integration-checklist/index.md create mode 100644 public/content/translations/mr/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/understand-the-erc-20-token-smart-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/uniswap-v2-annotated-code/index.md create mode 100644 public/content/translations/mr/developers/tutorials/using-websockets/index.md create mode 100644 public/content/translations/mr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md create mode 100644 public/content/translations/mr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md create mode 100644 public/content/translations/mr/developers/tutorials/waffle-test-simple-smart-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/yellow-paper-evm/index.md create mode 100644 public/content/translations/mr/eips/index.md create mode 100644 public/content/translations/mr/energy-consumption/index.md create mode 100644 public/content/translations/mr/eth/supply/index.md create mode 100644 public/content/translations/mr/ethereum-forks/index.md create mode 100644 public/content/translations/mr/foundation/index.md create mode 100644 public/content/translations/mr/gaming/index.md create mode 100644 public/content/translations/mr/glossary/index.md create mode 100644 public/content/translations/mr/governance/index.md create mode 100644 public/content/translations/mr/guides/how-to-create-an-ethereum-account/index.md create mode 100644 public/content/translations/mr/guides/how-to-id-scam-tokens/index.md diff --git a/public/content/translations/mr/developers/tutorials/short-abi/index.md b/public/content/translations/mr/developers/tutorials/short-abi/index.md new file mode 100644 index 00000000000..5c32c7c8482 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/short-abi/index.md @@ -0,0 +1,585 @@ +--- +title: "कॉलडेटा ऑप्टिमायझेशनसाठी लहान ABI" +description: "ऑप्टिमिस्टिक रोलअपसाठी स्मार्ट कॉन्ट्रॅक्ट्स ऑप्टिमाइझ करणे" +author: Ori Pomerantz +lang: mr +tags: [ "स्तर 2" ] +skill: intermediate +published: 2022-04-01 +--- + +## प्रस्तावना {#introduction} + +या लेखात, आपण [optimistic rollups](/developers/docs/scaling/optimistic-rollups) बद्दल शिकाल, त्यावरील व्यवहारांची किंमत, आणि ती वेगळी किंमत संरचना Ethereum मेननेटपेक्षा आपल्याला वेगवेगळ्या गोष्टींसाठी ऑप्टिमाइझ करण्याची आवश्यकता कशी निर्माण करते. +हे ऑप्टिमायझेशन कसे लागू करायचे हे देखील आपण शिकाल. + +### संपूर्ण प्रकटीकरण {#full-disclosure} + +मी एक पूर्णवेळ [Optimism](https://www.optimism.io/) कर्मचारी आहे, त्यामुळे या लेखातील उदाहरणे Optimism वर चालतील. +तथापि, येथे स्पष्ट केलेले तंत्र इतर रोलअपसाठी देखील तितकेच चांगले कार्य करेल. + +### परिभाषा {#terminology} + +रोलअपवर चर्चा करताना, 'स्तर 1' (L1) ही संज्ञा मेननेटसाठी वापरली जाते, जे उत्पादन Ethereum नेटवर्क आहे. +'स्तर 2' (L2) ही संज्ञा रोलअप किंवा इतर कोणत्याही प्रणालीसाठी वापरली जाते जी सुरक्षिततेसाठी L1 वर अवलंबून असते परंतु तिची बहुतेक प्रक्रिया ऑफचेन करते. + +## आपण L2 व्यवहारांची किंमत आणखी कशी कमी करू शकतो? {#how-can-we-further-reduce-the-cost-of-L2-transactions} + +[ऑप्टिमिस्टिक रोलअप्सना](/developers/docs/scaling/optimistic-rollups) प्रत्येक ऐतिहासिक व्यवहाराचा रेकॉर्ड जतन करावा लागतो जेणेकरून कोणीही त्यातून जाऊन सध्याची स्थिती योग्य आहे हे सत्यापित करू शकेल. +Ethereum मेननेटमध्ये डेटा मिळवण्याचा सर्वात स्वस्त मार्ग म्हणजे तो कॅलडेटा म्हणून लिहिणे. +हे समाधान [Optimism](https://help.optimism.io/hc/en-us/articles/4413163242779-What-is-a-rollup-) आणि [Arbitrum](https://developer.offchainlabs.com/docs/rollup_basics#intro-to-rollups) या दोघांनी निवडले होते. + +### L2 व्यवहारांची किंमत {#cost-of-l2-transactions} + +L2 व्यवहारांच्या किंमतीत दोन घटक असतात: + +1. L2 प्रक्रिया, जी सहसा अत्यंत स्वस्त असते +2. L1 स्टोरेज, जे मेननेट गॅस खर्चाशी जोडलेले आहे + +मी हे लिहित असताना, Optimism वर L2 गॅसची किंमत 0.001 [Gwei](/developers/docs/gas/#pre-london) आहे. +दुसरीकडे, L1 गॅसची किंमत अंदाजे 40 gwei आहे. +[आपण सध्याच्या किमती येथे पाहू शकता](https://public-grafana.optimism.io/d/9hkhMxn7z/public-dashboard?orgId=1&refresh=5m). + +कॅलडेटाच्या एका बाइटला एकतर 4 गॅस (जर तो शून्य असेल तर) किंवा 16 गॅस (जर ते इतर कोणतेही मूल्य असेल तर) लागतात. +EVM वरील सर्वात महागड्या क्रियांपैकी एक म्हणजे स्टोरेजमध्ये लिहिणे. +L2 वर स्टोरेजमध्ये 32-बाइट शब्द लिहिण्याची कमाल किंमत 22100 गॅस आहे. सध्या, हे 22.1 gwei आहे. +म्हणून जर आपण कॅलडेटाचा एक शून्य बाइट वाचवू शकलो, तर आपण स्टोरेजमध्ये सुमारे 200 बाइट्स लिहू शकू आणि तरीही फायद्यात राहू. + +### ABI {#the-abi} + +बहुतेक व्यवहार बाह्य-मालकीच्या खात्यातून करारावर प्रवेश करतात. +बहुतेक कॉन्ट्रॅक्ट्स Solidity मध्ये लिहिलेले आहेत आणि [ऍप्लिकेशन बायनरी इंटरफेस (ABI)](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding) नुसार त्यांचे डेटा फील्ड इंटरप्रिट करतात. + +तथापि, ABI हे L1 साठी डिझाइन केले होते, जिथे कॅलडेटाच्या एका बाइटची किंमत अंदाजे चार अंकगणितीय क्रियांइतकी असते, L2 साठी नाही, जिथे कॅलडेटाच्या एका बाइटची किंमत हजारहून अधिक अंकगणितीय क्रियांइतकी असते. +कॅलडेटा खालीलप्रमाणे विभागलेला आहे: + +| विभाग | लांबी | बाइट्स | वाया गेलेले बाइट्स | वाया गेलेला गॅस | आवश्यक बाइट्स | आवश्यक गॅस | +| --------------- | ----: | -----: | -----------------: | --------------: | ------------: | ---------: | +| फंक्शन सिलेक्टर | 4 | 0-3 | 3 | 48 | 1 | 16 | +| शून्य | 12 | 4-15 | 12 | 48 | 0 | 0 | +| गंतव्य पत्ता | 20 | 16-35 | 0 | 0 | 20 | 320 | +| रक्कम | 32 | 36-67 | 17 | 64 | 15 | 240 | +| एकूण | 68 | | | 160 | | 576 | + +स्पष्टीकरण: + +- **फंक्शन सिलेक्टर**: कॉन्ट्रॅक्टमध्ये 256 पेक्षा कमी फंक्शन्स आहेत, त्यामुळे आपण त्यांना एका बाइटने वेगळे करू शकतो. + हे बाइट्स सहसा गैर-शून्य असतात आणि त्यामुळे [सोळा गॅस खर्च येतो](https://eips.ethereum.org/EIPS/eip-2028). +- **शून्य**: हे बाइट्स नेहमी शून्य असतात कारण वीस-बाइट पत्त्याला ठेवण्यासाठी बत्तीस-बाइट शब्दाची आवश्यकता नसते. + शून्य धारण करणार्‍या बाइट्सना चार गॅस खर्च येतो ([पिवळे पेपर पहा](https://ethereum.github.io/yellowpaper/paper.pdf), परिशिष्ट G, + पृ. 27, `G``txdatazero` चे मूल्य). +- **रक्कम**: जर आपण असे गृहीत धरले की या कॉन्ट्रॅक्टमध्ये `decimals` अठरा आहे (सामान्य मूल्य) आणि आपण हस्तांतरित करत असलेल्या टोकन्सची कमाल रक्कम 1018 असेल, तर आपल्याला 1036 ची कमाल रक्कम मिळते. + 25615 > 1036, म्हणून पंधरा बाइट्स पुरेसे आहेत. + +L1 वर 160 गॅसचा अपव्यय सहसा नगण्य असतो. एका व्यवहाराला किमान [21,000 गॅस](https://yakkomajuri.medium.com/blockchain-definition-of-the-week-ethereum-gas-2f976af774ed) खर्च येतो, त्यामुळे अतिरिक्त 0.8% ने काही फरक पडत नाही. +तथापि, L2 वर, गोष्टी वेगळ्या आहेत. व्यवहाराचा जवळजवळ संपूर्ण खर्च तो L1 वर लिहिण्याचा असतो. +व्यवहार कॅलडेटा व्यतिरिक्त, 109 बाइट्सचे व्यवहार हेडर (गंतव्य पत्ता, स्वाक्षरी, इ.) आहे. +म्हणून एकूण खर्च `109*16+576+160=2480` आहे, आणि आपण त्यापैकी सुमारे 6.5% वाया घालवत आहोत. + +## जेव्हा आपण गंतव्यस्थानावर नियंत्रण ठेवत नाही तेव्हा खर्च कमी करणे {#reducing-costs-when-you-dont-control-the-destination} + +आपले गंतव्य कॉन्ट्रॅक्टवर नियंत्रण नाही असे गृहीत धरून, आपण तरीही [यासारखा](https://github.com/qbzzt/ethereum.org-20220330-shortABI) उपाय वापरू शकता. +चला संबंधित फाइल्स पाहूया. + +### Token.sol {#token-sol} + +[हे गंतव्य कॉन्ट्रॅक्ट आहे](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/Token.sol). +हे एक मानक ERC-20 कॉन्ट्रॅक्ट आहे, ज्यात एक अतिरिक्त वैशिष्ट्य आहे. +हे `faucet` फंक्शन कोणत्याही वापरकर्त्याला वापरण्यासाठी काही टोकन मिळवू देते. +हे एका उत्पादन ERC-20 कॉन्ट्रॅक्टला निरुपयोगी बनवेल, परंतु जेव्हा एखादे ERC-20 केवळ चाचणी सुलभ करण्यासाठी अस्तित्वात असते तेव्हा ते जीवन सोपे करते. + +```solidity + /** + * @dev कॉलरला खेळण्यासाठी 1000 टोकन देते + */ + function faucet() external { + _mint(msg.sender, 1000); + } // फंक्शन फॉसेट +``` + +### CalldataInterpreter.sol {#calldatainterpreter-sol} + +[हे ते कॉन्ट्रॅक्ट आहे ज्याला व्यवहारांनी लहान कॅलडेटासह कॉल करणे अपेक्षित आहे](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/contracts/CalldataInterpreter.sol). +चला ओळीनुसार पाहूया. + +```solidity +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + + +import { OrisUselessToken } from "./Token.sol"; +``` + +त्याला कसे कॉल करायचे हे जाणून घेण्यासाठी आम्हाला टोकन फंक्शनची आवश्यकता आहे. + +```solidity +contract CalldataInterpreter { + + OrisUselessToken public immutable token; +``` + +ज्या टोकनसाठी आम्ही प्रॉक्सी आहोत त्याचा पत्ता. + +```solidity + + /** + * @dev टोकनचा पत्ता निर्दिष्ट करा + * @param tokenAddr_ ERC-20 कॉन्ट्रॅक्टचा पत्ता + */ + constructor( + address tokenAddr_ + ) { + token = OrisUselessToken(tokenAddr_); + } // कन्स्ट्रक्टर +``` + +आम्हाला निर्दिष्ट करण्याची आवश्यकता असलेला टोकन पत्ता हा एकमेव पॅरामीटर आहे. + +```solidity + function calldataVal(uint startByte, uint length) + private pure returns (uint) { +``` + +कॅलडेटा मधून मूल्य वाचा. + +```solidity + uint _retVal; + + require(length < 0x21, + "calldataVal लांबीची मर्यादा 32 बाइट्स आहे"); + + require(length + startByte <= msg.data.length, + "calldataVal calldatasize च्या पलीकडे वाचण्याचा प्रयत्न करत आहे"); +``` + +आपण मेमरीमध्ये एकच 32-बाइट (256-बिट) शब्द लोड करणार आहोत आणि जे बाइट्स आपल्याला हव्या असलेल्या फील्डचा भाग नाहीत ते काढून टाकणार आहोत. +हे अल्गोरिदम 32 बाइटपेक्षा जास्त लांबीच्या मूल्यांसाठी कार्य करत नाही, आणि अर्थातच आपण कॅलडेटाच्या शेवटाच्या पुढे वाचू शकत नाही. +L1 वर गॅस वाचवण्यासाठी या चाचण्या वगळणे आवश्यक असू शकते, परंतु L2 वर गॅस अत्यंत स्वस्त आहे, ज्यामुळे आपण विचार करू शकणाऱ्या कोणत्याही सॅनिटी तपासण्या शक्य होतात. + +```solidity + assembly { + _retVal := calldataload(startByte) + } +``` + +आपण `fallback()` (खाली पहा) च्या कॉलमधून डेटा कॉपी करू शकलो असतो, परंतु EVM ची असेंब्ली भाषा [Yul](https://docs.soliditylang.org/en/v0.8.12/yul.html) वापरणे सोपे आहे. + +येथे आपण स्टॅकमध्ये `startByte` ते `startByte+31` बाइट्स वाचण्यासाठी [CALLDATALOAD ऑपकोड](https://www.evm.codes/#35) वापरतो. +सर्वसाधारणपणे, Yul मधील ऑपकोडचे सिंटॅक्स `(,...)` असे आहे. + +```solidity + + _retVal = _retVal >> (256-length*8); +``` + +केवळ सर्वात लक्षणीय `length` बाइट्स फील्डचा भाग आहेत, म्हणून आपण इतर मूल्ये काढून टाकण्यासाठी [राइट-शिफ्ट](https://en.wikipedia.org/wiki/Logical_shift) करतो. +याचा अतिरिक्त फायदा असा आहे की ते मूल्य फील्डच्या उजवीकडे हलवते, त्यामुळे ते मूल्य स्वतःच आहे, 256something पट मूल्य नाही. + +```solidity + + return _retVal; + } + + + fallback() external { +``` + +जेव्हा Solidity कॉन्ट्रॅक्टला केलेला कॉल कोणत्याही फंक्शन सिग्नेचरशी जुळत नाही, तेव्हा ते (एक आहे असे गृहीत धरून) [`fallback()` फंक्शन](https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function) कॉल करते. +`CalldataInterpreter` च्या बाबतीत, _कोणताही_ कॉल येथे येतो कारण इतर कोणतेही `external` किंवा `public` फंक्शन्स नाहीत. + +```solidity + uint _func; + + _func = calldataVal(0, 1); +``` + +कॅलडेटाचा पहिला बाइट वाचा, जो आपल्याला फंक्शन सांगतो. +येथे एखादे फंक्शन उपलब्ध नसण्याची दोन कारणे आहेत: + +1. `pure` किंवा `view` असणारी फंक्शन्स स्थिती बदलत नाहीत आणि त्यांना गॅस लागत नाही (जेव्हा ऑफचेन कॉल केले जाते). + त्यांचा गॅस खर्च कमी करण्याचा प्रयत्न करण्यात काही अर्थ नाही. +2. [`msg.sender`](https://docs.soliditylang.org/en/v0.8.12/units-and-global-variables.html#block-and-transaction-properties) वर अवलंबून असलेली फंक्शन्स. + `msg.sender` चे मूल्य `CalldataInterpreter` चा पत्ता असेल, कॉलरचा नाही. + +दुर्दैवाने, [ERC-20 स्पेसिफिकेशन्स पाहिल्यास](https://eips.ethereum.org/EIPS/eip-20), फक्त एकच फंक्शन उरते, `transfer`. +यामुळे आपल्याकडे फक्त दोन फंक्शन्स उरतात: `transfer` (कारण आपण `transferFrom` कॉल करू शकतो) आणि `faucet` (कारण आपण ज्याने आपल्याला कॉल केला आहे त्याला टोकन परत हस्तांतरित करू शकतो). + +```solidity + + // कॅलडेटामधील माहिती वापरून टोकनच्या स्थिती बदलणाऱ्या पद्धतींना कॉल करा + // + + // फॉसेट + if (_func == 1) { +``` + +`faucet()` ला कॉल, ज्यामध्ये पॅरामीटर्स नाहीत. + +```solidity + token.faucet(); + token.transfer(msg.sender, + token.balanceOf(address(this))); + } +``` + +आपण `token.faucet()` कॉल केल्यावर आपल्याला टोकन्स मिळतात. तथापि, प्रॉक्सी कॉन्ट्रॅक्ट म्हणून, आम्हाला टोकनची **गरज** नाही. +आपल्याला कॉल करणार्‍या EOA (बाह्य मालकीच्या खात्याला) किंवा कॉन्ट्रॅक्टला गरज आहे. +म्हणून आम्ही आमचे सर्व टोकन ज्याने आम्हाला कॉल केला आहे त्याला हस्तांतरित करतो. + +```solidity + // हस्तांतरण (आपल्याकडे त्यासाठी भत्ता आहे असे गृहीत धरा) + if (_func == 2) { +``` + +टोकन हस्तांतरित करण्यासाठी दोन पॅरामीटर्स आवश्यक आहेत: गंतव्य पत्ता आणि रक्कम. + +```solidity + token.transferFrom( + msg.sender, +``` + +आम्ही फक्त कॉल करणाऱ्यांना त्यांच्या मालकीचे टोकन हस्तांतरित करण्याची परवानगी देतो + +```solidity + address(uint160(calldataVal(1, 20))), +``` + +गंतव्य पत्ता बाइट #1 पासून सुरू होतो (बाइट #0 हे फंक्शन आहे). +एक पत्ता म्हणून, तो 20-बाइट लांब आहे. + +```solidity + calldataVal(21, 2) +``` + +या विशिष्ट कॉन्ट्रॅक्टसाठी आपण असे गृहीत धरतो की कोणीही हस्तांतरित करू इच्छित असलेल्या टोकनची कमाल संख्या दोन बाइटमध्ये (65536 पेक्षा कमी) बसते. + +```solidity + ); + } +``` + +एकंदरीत, हस्तांतरणासाठी 35 बाइट्सचा कॅलडेटा लागतो: + +| विभाग | लांबी | बाइट्स | +| --------------- | ----: | -----: | +| फंक्शन सिलेक्टर | 1 | 0 | +| गंतव्य पत्ता | 32 | 1-32 | +| रक्कम | 2 | 33-34 | + +```solidity + } // फॉलबॅक + +} // कॉन्ट्रॅक्ट CalldataInterpreter +``` + +### test.js {#test-js} + +[हे JavaScript युनिट टेस्ट](https://github.com/qbzzt/ethereum.org-20220330-shortABI/blob/master/test/test.js) आपल्याला हे तंत्र कसे वापरावे (आणि ते योग्यरित्या कार्य करते की नाही हे कसे सत्यापित करावे) हे दाखवते. +मी असे गृहीत धरणार आहे की तुम्हाला [chai](https://www.chaijs.com/) आणि [ethers](https://docs.ethers.io/v5/) समजतात आणि केवळ कॉन्ट्रॅक्टवर विशेषतः लागू होणारे भाग स्पष्ट करणार आहे. + +```js +const { expect } = require("chai"); + +describe("CalldataInterpreter", function () { + it("Should let us use tokens", async function () { + const Token = await ethers.getContractFactory("OrisUselessToken") + const token = await Token.deploy() + await token.deployed() + console.log("Token addr:", token.address) + + const Cdi = await ethers.getContractFactory("CalldataInterpreter") + const cdi = await Cdi.deploy(token.address) + await cdi.deployed() + console.log("CalldataInterpreter addr:", cdi.address) + + const signer = await ethers.getSigner() +``` + +आपण दोन्ही कॉन्ट्रॅक्ट्स तैनात करून सुरुवात करतो. + +```javascript + // खेळण्यासाठी टोकन मिळवा + const faucetTx = { +``` + +आम्ही व्यवहार तयार करण्यासाठी सामान्यतः वापरत असलेली उच्च-स्तरीय फंक्शन्स (जसे की `token.faucet()`) वापरू शकत नाही, कारण आम्ही ABI चे पालन करत नाही. +त्याऐवजी, आपल्याला स्वतः व्यवहार तयार करून तो पाठवावा लागेल. + +```javascript + to: cdi.address, + data: "0x01" +``` + +व्यवहारासाठी आपल्याला दोन पॅरामीटर्स द्यावे लागतील: + +1. `to`, गंतव्य पत्ता. + हा कॅलडेटा इंटरप्रिटर कॉन्ट्रॅक्ट आहे. +2. `data`, पाठवण्यासाठी कॅलडेटा. + फॉसेट कॉलच्या बाबतीत, डेटा एकच बाइट आहे, `0x01`. + +```javascript + + } + await (await signer.sendTransaction(faucetTx)).wait() +``` + +आम्ही [साईनरच्या `sendTransaction` पद्धतीला](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) कॉल करतो कारण आम्ही आधीच गंतव्य (`faucetTx.to`) निर्दिष्ट केले आहे आणि आम्हाला व्यवहार स्वाक्षरी केलेला हवा आहे. + +```javascript +// फॉसेट टोकन योग्यरित्या पुरवतो का ते तपासा +expect(await token.balanceOf(signer.address)).to.equal(1000) +``` + +येथे आपण शिल्लक तपासतो. +`view` फंक्शन्सवर गॅस वाचवण्याची गरज नाही, म्हणून आपण त्यांना सामान्यपणे चालवतो. + +```javascript +// CDI ला भत्ता द्या (मंजुरी प्रॉक्सी केली जाऊ शकत नाही) +const approveTX = await token.approve(cdi.address, 10000) +await approveTX.wait() +expect(await token.allowance(signer.address, cdi.address)).to.equal(10000) +``` + +हस्तांतरण करण्यासाठी कॅलडेटा इंटरप्रिटरला भत्ता द्या. + +```javascript +// टोकन हस्तांतरित करा +const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" +const transferTx = { + to: cdi.address, + data: "0x02" + destAddr.slice(2, 42) + "0100", +} +``` + +एक हस्तांतरण व्यवहार तयार करा. पहिला बाइट "0x02" आहे, त्यानंतर गंतव्य पत्ता आणि शेवटी रक्कम (0x0100, जे दशांश मध्ये 256 आहे). + +```javascript + await (await signer.sendTransaction(transferTx)).wait() + + // तपासा की आपल्याकडे 256 टोकन कमी आहेत + expect (await token.balanceOf(signer.address)).to.equal(1000-256) + + // आणि ते आपल्या गंतव्यस्थानाला मिळाले आहेत + expect (await token.balanceOf(destAddr)).to.equal(256) + }) // ते +}) // वर्णन करा +``` + +## जेव्हा तुम्ही गंतव्य कॉन्ट्रॅक्टवर नियंत्रण ठेवता तेव्हा खर्च कमी करणे {#reducing-the-cost-when-you-do-control-the-destination-contract} + +जर तुमचे गंतव्य कॉन्ट्रॅक्टवर नियंत्रण असेल तर तुम्ही अशी फंक्शन्स तयार करू शकता जी `msg.sender` तपासण्यांना बायपास करतात कारण ते कॅलडेटा इंटरप्रिटरवर विश्वास ठेवतात. +[हे कसे कार्य करते याचे उदाहरण तुम्ही येथे पाहू शकता, `control-contract` शाखेत](https://github.com/qbzzt/ethereum.org-20220330-shortABI/tree/control-contract). + +जर कॉन्ट्रॅक्ट केवळ बाह्य व्यवहारांना प्रतिसाद देत असेल, तर आपण फक्त एका कॉन्ट्रॅक्टने काम चालवू शकलो असतो. +तथापि, ते [कंपोझिबिलिटी](/developers/docs/smart-contracts/composability/) खंडित करेल. +सामान्य ERC-20 कॉल्सला प्रतिसाद देणारा एक कॉन्ट्रॅक्ट आणि लहान कॉल डेटासह व्यवहारांना प्रतिसाद देणारा दुसरा कॉन्ट्रॅक्ट असणे खूप चांगले आहे. + +### Token.sol {#token-sol-2} + +या उदाहरणात आपण `Token.sol` मध्ये बदल करू शकतो. +हे आपल्याला अनेक फंक्शन्स ठेवण्याची परवानगी देते जे फक्त प्रॉक्सी कॉल करू शकते. +हे नवीन भाग आहेत: + +```solidity + // CalldataInterpreter पत्ता निर्दिष्ट करण्याची परवानगी असलेला एकमेव पत्ता + address owner; + + // CalldataInterpreter पत्ता + address proxy = address(0); +``` + +ERC-20 कॉन्ट्रॅक्टला अधिकृत प्रॉक्सीची ओळख माहित असणे आवश्यक आहे. +तथापि, आपण हे व्हेरिएबल कन्स्ट्रक्टरमध्ये सेट करू शकत नाही, कारण आपल्याला अद्याप मूल्य माहित नाही. +हा कॉन्ट्रॅक्ट प्रथम इन्स्टंटिएट केला जातो कारण प्रॉक्सीला त्याच्या कन्स्ट्रक्टरमध्ये टोकनच्या पत्त्याची अपेक्षा असते. + +```solidity + /** + * @dev ERC20 कन्स्ट्रक्टरला कॉल करते. + */ + constructor( + ) ERC20("Oris useless token-2", "OUT-2") { + owner = msg.sender; + } +``` + +निर्मात्याचा पत्ता (ज्याला `owner` म्हणतात) येथे संग्रहित केला जातो कारण प्रॉक्सी सेट करण्याची परवानगी असलेला तो एकमेव पत्ता आहे. + +```solidity + /** + * @dev प्रॉक्सीसाठी (CalldataInterpreter) पत्ता सेट करा. + * मालकाद्वारे फक्त एकदाच कॉल केले जाऊ शकते + */ + function setProxy(address _proxy) external { + require(msg.sender == owner, "फक्त मालकाद्वारे कॉल केले जाऊ शकते"); + require(proxy == address(0), "प्रॉक्सी आधीच सेट आहे"); + + proxy = _proxy; + } // फंक्शन setProxy +``` + +प्रॉक्सीला विशेषाधिकारित प्रवेश आहे, कारण ते सुरक्षा तपासण्या बायपास करू शकते. +आपण प्रॉक्सीवर विश्वास ठेवू शकतो याची खात्री करण्यासाठी, आम्ही फक्त `owner` ला हे फंक्शन कॉल करू देतो, आणि फक्त एकदाच. +एकदा `proxy` चे वास्तविक मूल्य (शून्य नाही) आले की, ते मूल्य बदलू शकत नाही, त्यामुळे मालकाने बदमाश होण्याचा निर्णय घेतला तरी, किंवा त्यासाठीचा मेमोनिक उघड झाला तरी, आपण तरीही सुरक्षित आहोत. + +```solidity + /** + * @dev काही फंक्शन्स फक्त प्रॉक्सीद्वारे कॉल केली जाऊ शकतात. + */ + modifier onlyProxy { +``` + +हे एक [`modifier` फंक्शन](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) आहे, ते इतर फंक्शन्सच्या कार्यपद्धतीत बदल करते. + +```solidity + require(msg.sender == proxy); +``` + +प्रथम, सत्यापित करा की आपल्याला प्रॉक्सीने आणि इतर कोणीही कॉल केलेला नाही. +नसल्यास, `revert` करा. + +```solidity + _; + } +``` + +तसे असल्यास, आपण सुधारित करत असलेले फंक्शन चालवा. + +```solidity + /* फंक्शन्स जे प्रॉक्सीला खात्यांसाठी प्रत्यक्षात प्रॉक्सी करण्याची परवानगी देतात */ + + function transferProxy(address from, address to, uint256 amount) + public virtual onlyProxy() returns (bool) + { + _transfer(from, to, amount); + return true; + } + + function approveProxy(address from, address spender, uint256 amount) + public virtual onlyProxy() returns (bool) + { + _approve(from, spender, amount); + return true; + } + + function transferFromProxy( + address spender, + address from, + address to, + uint256 amount + ) public virtual onlyProxy() returns (bool) + { + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } +``` + +या तीन क्रिया आहेत ज्यांना सामान्यतः टोकन हस्तांतरित करणाऱ्या किंवा भत्ता मंजूर करणाऱ्या घटकाकडून थेट संदेश येण्याची आवश्यकता असते. +येथे आमच्याकडे या ऑपरेशन्सची प्रॉक्सी आवृत्ती आहे जी: + +1. `onlyProxy()` द्वारे सुधारित केले आहे जेणेकरून इतर कोणालाही त्यांना नियंत्रित करण्याची परवानगी नाही. +2. जो पत्ता सामान्यतः `msg.sender` असतो तो अतिरिक्त पॅरामीटर म्हणून मिळवतो. + +### CalldataInterpreter.sol {#calldatainterpreter-sol-2} + +कॅलडेटा इंटरप्रिटर वरील इंटरप्रिटरसारखाच आहे, फक्त प्रॉक्सी केलेल्या फंक्शन्सना `msg.sender` पॅरामीटर मिळतो आणि `transfer` साठी भत्त्याची गरज नसते. + +```solidity + // हस्तांतरण (भत्त्याची गरज नाही) + if (_func == 2) { + token.transferProxy( + msg.sender, + address(uint160(calldataVal(1, 20))), + calldataVal(21, 2) + ); + } + + // मंजूर करा + if (_func == 3) { + token.approveProxy( + msg.sender, + address(uint160(calldataVal(1, 20))), + calldataVal(21, 2) + ); + } + + // transferFrom + if (_func == 4) { + token.transferFromProxy( + msg.sender, + address(uint160(calldataVal( 1, 20))), + address(uint160(calldataVal(21, 20))), + calldataVal(41, 2) + ); + } +``` + +### Test.js {#test-js-2} + +मागील टेस्टिंग कोड आणि या कोडमध्ये काही बदल आहेत. + +```js +const Cdi = await ethers.getContractFactory("CalldataInterpreter") +const cdi = await Cdi.deploy(token.address) +await cdi.deployed() +await token.setProxy(cdi.address) +``` + +आम्हाला ERC-20 कॉन्ट्रॅक्टला कोणत्या प्रॉक्सीवर विश्वास ठेवावा हे सांगावे लागेल + +```js +console.log("CalldataInterpreter addr:", cdi.address) + +// भत्ते तपासण्यासाठी दोन स्वाक्षरीकर्त्यांची आवश्यकता आहे +const signers = await ethers.getSigners() +const signer = signers[0] +const poorSigner = signers[1] +``` + +`approve()` आणि `transferFrom()` तपासण्यासाठी आम्हाला दुसऱ्या स्वाक्षरीकर्त्याची आवश्यकता आहे. +आम्ही त्याला `poorSigner` म्हणतो कारण त्याला आमचे कोणतेही टोकन मिळत नाहीत (अर्थात, त्याच्याकडे ETH असणे आवश्यक आहे). + +```js +// टोकन हस्तांतरित करा +const destAddr = "0xf5a6ead936fb47f342bb63e676479bddf26ebe1d" +const transferTx = { + to: cdi.address, + data: "0x02" + destAddr.slice(2, 42) + "0100", +} +await (await signer.sendTransaction(transferTx)).wait() +``` + +कारण ERC-20 कॉन्ट्रॅक्ट प्रॉक्सी (`cdi`) वर विश्वास ठेवतो, आम्हाला हस्तांतरण रिले करण्यासाठी भत्त्याची गरज नाही. + +```js +// मंजूरी आणि transferFrom +const approveTx = { + to: cdi.address, + data: "0x03" + poorSigner.address.slice(2, 42) + "00FF", +} +await (await signer.sendTransaction(approveTx)).wait() + +const destAddr2 = "0xE1165C689C0c3e9642cA7606F5287e708d846206" + +const transferFromTx = { + to: cdi.address, + data: "0x04" + signer.address.slice(2, 42) + destAddr2.slice(2, 42) + "00FF", +} +await (await poorSigner.sendTransaction(transferFromTx)).wait() + +// approve / transferFrom कॉम्बो योग्यरित्या केले होते की नाही हे तपासा +expect(await token.balanceOf(destAddr2)).to.equal(255) +``` + +दोन नवीन फंक्शन्सची चाचणी घ्या. +लक्षात घ्या की `transferFromTx` ला दोन पत्ता पॅरामीटर्स आवश्यक आहेत: भत्त्याचा दाता आणि स्वीकारकर्ता. + +## निष्कर्ष {#conclusion} + +दोन्ही [Optimism](https://medium.com/ethereum-optimism/the-road-to-sub-dollar-transactions-part-2-compression-edition-6bb2890e3e92) आणि [Arbitrum](https://developer.offchainlabs.com/docs/special_features) L1 वर लिहिलेल्या कॅलडेटाचा आकार आणि त्यामुळे व्यवहारांची किंमत कमी करण्याचे मार्ग शोधत आहेत. +तथापि, सामान्य उपायांचा शोध घेणारे पायाभूत सुविधा प्रदाते म्हणून, आमच्या क्षमता मर्यादित आहेत. +dapp डेव्हलपर म्हणून, आपल्याकडे अनुप्रयोगा-विशिष्ट ज्ञान आहे, जे आपल्याला सामान्य समाधानापेक्षा आपले कॅलडेटा अधिक चांगल्या प्रकारे ऑप्टिमाइझ करू देते. +आशा आहे की, हा लेख आपल्याला आपल्या गरजांसाठी आदर्श समाधान शोधण्यात मदत करेल. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). + diff --git a/public/content/translations/mr/developers/tutorials/smart-contract-security-guidelines/index.md b/public/content/translations/mr/developers/tutorials/smart-contract-security-guidelines/index.md new file mode 100644 index 00000000000..4a0a076996e --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/smart-contract-security-guidelines/index.md @@ -0,0 +1,91 @@ +--- +title: "स्मार्ट कॉन्ट्रॅक्ट सुरक्षा मार्गदर्शक तत्त्वे" +description: "तुमचे डॅप तयार करताना विचारात घेण्यासाठी सुरक्षा मार्गदर्शक तत्त्वांची तपासणी सूची" +author: "Trailofbits" +tags: [ "सॉलिडिटी", "स्मार्ट कॉन्ट्रॅक्ट", "सुरक्षा" ] +skill: intermediate +lang: mr +published: 2020-09-06 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/guidelines.md +--- + +अधिक सुरक्षित स्मार्ट कॉन्ट्रॅक्ट तयार करण्यासाठी या उच्च-स्तरीय शिफारशींचे अनुसरण करा. + +## डिझाइन मार्गदर्शक तत्त्वे {#design-guidelines} + +कोडची कोणतीही ओळ लिहिण्यापूर्वी कॉन्ट्रॅक्टच्या डिझाइनवर वेळेपूर्वी चर्चा केली पाहिजे. + +### दस्तऐवजीकरण आणि विशिष्टता {#documentation-and-specifications} + +दस्तऐवजीकरण वेगवेगळ्या स्तरांवर लिहिले जाऊ शकते आणि कॉन्ट्रॅक्ट्सची अंमलबजावणी करताना ते अपडेट केले पाहिजे: + +- **सिस्टमचे सोपे इंग्रजी वर्णन**, जे कॉन्ट्रॅक्ट्स काय करतात आणि कोडबेसवरील कोणतीही गृहितके यांचे वर्णन करते. +- **स्कीमा आणि आर्किटेक्चरल डायग्राम**, ज्यात कॉन्ट्रॅक्टमधील परस्परसंवाद आणि सिस्टमचे स्टेट मशीन समाविष्ट आहे. [स्लिदर प्रिंटर्स](https://github.com/crytic/slither/wiki/Printer-documentation) हे स्कीमा तयार करण्यासाठी मदत करू शकतात. +- **संपूर्ण कोड दस्तऐवजीकरण**, सॉलिडिटीसाठी [Natspec फॉरमॅट](https://docs.soliditylang.org/en/develop/natspec-format.html) वापरला जाऊ शकतो. + +### ऑनचेन विरुद्ध ऑफचेन गणना {#onchain-vs-offchain-computation} + +- **तुम्ही शक्य तितका कोड ऑफचेन ठेवा.** ऑनचेन लेयर लहान ठेवा. ऑफचेन कोडसह डेटावर अशा प्रकारे पूर्व-प्रक्रिया करा की ऑनचेन पडताळणी सोपी होईल. तुम्हाला क्रमबद्ध यादीची आवश्यकता आहे का? यादी ऑफचेन लावा, मग फक्त तिचा क्रम ऑनचेन तपासा. + +### अपग्रेडेबिलिटी {#upgradeability} + +आम्ही [आमच्या ब्लॉगपोस्टमध्ये](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/) वेगवेगळ्या अपग्रेडेबिलिटी सोल्यूशन्सवर चर्चा केली आहे. कोणताही कोड लिहिण्यापूर्वी अपग्रेडेबिलिटीला सपोर्ट करायचा की नाही, याची हेतुपुरस्सर निवड करा. तुम्ही तुमचा कोड कसा संरचित करता यावर हा निर्णय प्रभाव टाकेल. सर्वसाधारणपणे, आम्ही शिफारस करतो: + +- **अपग्रेडेबिलिटीपेक्षा [कॉन्ट्रॅक्ट मायग्रेशनला](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) प्राधान्य द्या.** मायग्रेशन सिस्टम्समध्ये अपग्रेड करण्यायोग्य सिस्टमसारखेच अनेक फायदे आहेत, पण त्यांचे तोटे नाहीत. +- **डेलिगेट कॉल प्रॉक्सी पॅटर्नपेक्षा डेटा सेपरेशन पॅटर्न वापरा.** जर तुमच्या प्रोजेक्टमध्ये स्पष्ट ॲब्स्ट्रॅक्शन सेपरेशन असेल, तर डेटा सेपरेशन वापरून अपग्रेडेबिलिटीसाठी फक्त काही समायोजन आवश्यक असतील. डेलिगेट कॉल प्रॉक्सीसाठी EVM तज्ञतेची आवश्यकता असते आणि ते खूप त्रुटी-प्रवण आहे. +- **डिप्लॉयमेंट करण्यापूर्वी मायग्रेशन/अपग्रेड प्रक्रिया डॉक्युमेंट करा.** जर तुम्हाला कोणत्याही मार्गदर्शक तत्त्वांशिवाय तणावाखाली प्रतिक्रिया द्यावी लागली, तर तुम्ही चुका कराल. अनुसरण्याची प्रक्रिया वेळेपूर्वीच लिहा. त्यात समाविष्ट असावे: + - नवीन कॉन्ट्रॅक्ट्स सुरू करणारे कॉल्स + - कीज कुठे साठवल्या आहेत आणि त्या कशा ऍक्सेस करायच्या + - डिप्लॉयमेंट कशी तपासावी! डिप्लॉयमेंट-नंतरची स्क्रिप्ट विकसित करा आणि तपासा. + +## अंमलबजावणीची मार्गदर्शक तत्त्वे {#implementation-guidelines} + +**साधेपणासाठी प्रयत्न करा.** नेहमी सर्वात सोपा उपाय वापरा जो तुमच्या उद्देशाला अनुकूल असेल. तुमच्या टीममधील कोणत्याही सदस्याला तुमचा उपाय समजू शकला पाहिजे. + +### फंक्शन कंपोझिशन {#function-composition} + +तुमच्या कोडबेसचे आर्किटेक्चर असे असावे की ज्यामुळे तुमचा कोड तपासणे सोपे होईल. असे आर्किटेक्चरल पर्याय टाळा जे त्याच्या अचूकतेबद्दल तर्क करण्याची क्षमता कमी करतात. + +- **तुमच्या सिस्टमच्या लॉजिकचे विभाजन करा**, एकतर अनेक कॉन्ट्रॅक्ट्सद्वारे किंवा समान फंक्शन्स एकत्र गटबद्ध करून (उदाहरणार्थ, ऑथेंटिकेशन, अंकगणित, ...). +- **स्पष्ट उद्देशाने लहान फंक्शन्स लिहा.** यामुळे पुनरावलोकन सोपे होईल आणि वैयक्तिक घटकांची चाचणी घेता येईल. + +### इनहेरिटन्स {#inheritance} + +- **इनहेरिटन्स व्यवस्थापनीय ठेवा.** लॉजिकचे विभाजन करण्यासाठी इनहेरिटन्सचा वापर केला पाहिजे, तथापि, तुमच्या प्रोजेक्टने इनहेरिटन्स ट्रीची खोली आणि रुंदी कमी करण्याचे ध्येय ठेवले पाहिजे. +- **कॉन्ट्रॅक्ट्सची हायरार्की तपासण्यासाठी स्लिदरचा [इनहेरिटन्स प्रिंटर](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph) वापरा.** इनहेरिटन्स प्रिंटर तुम्हाला हायरार्कीचा आकार तपासण्यात मदत करेल. + +### इव्हेंट्स {#events} + +- **सर्व महत्त्वाच्या ऑपरेशन्स लॉग करा.** इव्हेंट्स डेव्हलपमेंट दरम्यान कॉन्ट्रॅक्ट डीबग करण्यास आणि डिप्लॉयमेंटनंतर त्यावर लक्ष ठेवण्यास मदत करतील. + +### ज्ञात धोके टाळा {#avoid-known-pitfalls} + +- **सर्वात सामान्य सुरक्षा समस्यांबद्दल जागरूक रहा.** सामान्य समस्यांबद्दल जाणून घेण्यासाठी अनेक ऑनलाइन संसाधने आहेत, जसे की [Ethernaut CTF](https://ethernaut.openzeppelin.com/), [कॅप्चर द इथर](https://capturetheether.com/), किंवा [नॉट सो स्मार्ट कॉन्ट्रॅक्ट्स](https://github.com/crytic/not-so-smart-contracts/). +- **[Solidity दस्तऐवजीकरणामधील](https://docs.soliditylang.org/en/latest/) चेतावणी विभागांबद्दल जागरूक रहा.** चेतावणी विभाग तुम्हाला भाषेच्या अस्पष्ट वर्तनाबद्दल माहिती देतील. + +### डिपेंडन्सीज {#dependencies} + +- **चांगल्या प्रकारे तपासलेल्या लायब्ररी वापरा.** चांगल्या प्रकारे तपासलेल्या लायब्ररीमधून कोड इम्पोर्ट केल्याने तुम्ही सदोष कोड लिहिण्याची शक्यता कमी होईल. जर तुम्हाला ERC20 कॉन्ट्रॅक्ट लिहायचा असेल, तर [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20) वापरा. +- **डिपेंडन्सी मॅनेजर वापरा; कोड कॉपी-पेस्ट करणे टाळा.** जर तुम्ही बाह्य स्त्रोतावर अवलंबून असाल, तर तुम्ही ते मूळ स्त्रोतासह अद्ययावत ठेवले पाहिजे. + +### चाचणी आणि पडताळणी {#testing-and-verification} + +- **संपूर्ण युनिट-टेस्ट्स लिहा.** उच्च-गुणवत्तेचे सॉफ्टवेअर तयार करण्यासाठी एक विस्तृत टेस्ट सूट महत्त्वपूर्ण आहे. +- **[स्लिदर](https://github.com/crytic/slither), [एकिडना](https://github.com/crytic/echidna) आणि [मॅन्टिकोर](https://github.com/trailofbits/manticore) कस्टम चेक्स आणि प्रॉपर्टीज लिहा.** स्वयंचलित टूल्स तुमचा कॉन्ट्रॅक्ट सुरक्षित असल्याची खात्री करण्यास मदत करतील. कार्यक्षम चेक्स आणि प्रॉपर्टीज कसे लिहायचे हे जाणून घेण्यासाठी या मार्गदर्शकाचा उर्वरित भाग तपासा. +- **[crytic.io](https://crytic.io/) वापरा.** क्रिटिक GitHub सह समाकलित होते, खाजगी स्लिदर डिटेक्टरना ऍक्सेस प्रदान करते, आणि एकिडनामधून कस्टम प्रॉपर्टी चेक्स चालवते. + +### Solidity {#solidity} + +- **0.4 आणि 0.6 पेक्षा सॉलिडिटी 0.5 ला प्राधान्य द्या.** आमच्या मते, सॉलिडिटी 0.5 अधिक सुरक्षित आहे आणि 0.4 पेक्षा त्यात अधिक चांगल्या बिल्ट-इन पद्धती आहेत. सॉलिडिटी 0.6 उत्पादनासाठी खूपच अस्थिर सिद्ध झाले आहे आणि त्याला परिपक्व होण्यासाठी वेळ लागेल. +- **कंपाइल करण्यासाठी स्थिर रिलीझ वापरा; चेतावणी तपासण्यासाठी नवीनतम रिलीझ वापरा.** नवीनतम कंपाइलर आवृत्तीसह तुमच्या कोडमध्ये कोणतीही नोंदवलेली समस्या नाही याची खात्री करा. तथापि, सॉलिडिटीचे रिलीझ चक्र वेगवान आहे आणि त्यात कंपाइलर बग्सचा इतिहास आहे, म्हणून आम्ही डिप्लॉयमेंटसाठी नवीनतम आवृत्तीची शिफारस करत नाही (स्लिदरची [solc आवृत्ती शिफारस](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-33) पहा). +- **इनलाइन असेंब्ली वापरू नका.** असेंब्लीसाठी EVM तज्ञतेची आवश्यकता असते. जर तुम्ही यलो पेपरवर _प्रभुत्व_ मिळवले नसेल तर EVM कोड लिहू नका. + +## डिप्लॉयमेंट मार्गदर्शक तत्त्वे {#deployment-guidelines} + +एकदा कॉन्ट्रॅक्ट विकसित आणि डिप्लॉय झाल्यानंतर: + +- **तुमच्या कॉन्ट्रॅक्ट्सवर लक्ष ठेवा.** लॉग्स पहा आणि कॉन्ट्रॅक्ट किंवा वॉलेटशी तडजोड झाल्यास प्रतिक्रिया देण्यासाठी तयार रहा. +- **तुमची संपर्क माहिती [ब्लॉकचेन-सुरक्षा-संपर्क](https://github.com/crytic/blockchain-security-contacts) मध्ये जोडा.** जर एखादी सुरक्षा त्रुटी आढळल्यास ही यादी तृतीय-पक्षांना तुमच्याशी संपर्क साधण्यास मदत करते. +- **विशेषाधिकार असलेल्या वापरकर्त्यांचे वॉलेट्स सुरक्षित करा.** जर तुम्ही हार्डवेअर वॉलेट्समध्ये कीज साठवत असाल तर आमच्या [सर्वोत्तम पद्धतींचे](https://blog.trailofbits.com/2018/11/27/10-rules-for-the-secure-use-of-cryptocurrency-hardware-wallets/) अनुसरण करा. +- **घटनेला प्रतिसाद देण्यासाठी एक योजना तयार ठेवा.** तुमचे स्मार्ट कॉन्ट्रॅक्ट्स धोक्यात येऊ शकतात याचा विचार करा. जरी तुमचे कॉन्ट्रॅक्ट्स बग-मुक्त असले तरी, एक हल्लेखोर कॉन्ट्रॅक्ट मालकाच्या कीजचा ताबा घेऊ शकतो. diff --git a/public/content/translations/mr/developers/tutorials/stealth-addr/index.md b/public/content/translations/mr/developers/tutorials/stealth-addr/index.md new file mode 100644 index 00000000000..1c3b5e5ff16 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/stealth-addr/index.md @@ -0,0 +1,436 @@ +--- +title: "गुप्त पत्त्यांचा वापर" +description: "गुप्त पत्ते वापरकर्त्यांना अज्ञातपणे मालमत्ता हस्तांतरित करण्याची परवानगी देतात. हा लेख वाचल्यानंतर, तुम्ही हे करू शकाल: गुप्त पत्ते काय आहेत आणि ते कसे कार्य करतात हे स्पष्ट करू शकाल, अनामिकता जपणाऱ्या पद्धतीने गुप्त पत्त्यांचा वापर कसा करायचा हे समजू शकाल, आणि गुप्त पत्त्यांचा वापर करणारे वेब-आधारित ॲप्लिकेशन लिहू शकाल." +author: Ori Pomerantz +tags: [ "गुप्त पत्ता", "गोपनीयता", "कूटलेखन", "rust", "wasm" ] +skill: intermediate +published: 2025-11-30 +lang: mr +sidebarDepth: 3 +--- + +तुम्ही बिल आहात. ज्या कारणांमध्ये आपण जाणार नाही, त्या कारणास्तव, तुम्हाला "Alice for Queen of the World" मोहिमेसाठी देणगी द्यायची आहे आणि तुम्ही देणगी दिली आहे हे ॲलिसला कळावे असे तुम्हाला वाटते, जेणेकरून ती जिंकल्यास तुम्हाला बक्षीस देईल. दुर्दैवाने, तिचा विजय निश्चित नाही. एक प्रतिस्पर्धी मोहीम आहे, "Carol for Empress of the Solar System". जर कॅरोल जिंकली आणि तिला कळले की तुम्ही ॲलिसला देणगी दिली आहे, तर तुम्ही अडचणीत याल. म्हणून तुम्ही तुमच्या खात्यातून ॲलिसच्या खात्यात फक्त 200 ETH हस्तांतरित करू शकत नाही. + +[ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) मध्ये याचे समाधान आहे. हे ERC अज्ञात हस्तांतरणासाठी [गुप्त पत्त्यांचा](https://nerolation.github.io/stealth-utils) वापर कसा करायचा हे स्पष्ट करते. + +**चेतावणी**: गुप्त पत्त्यांमागील कूटलेखन, आमच्या माहितीनुसार, सुरक्षित आहे. तथापि, संभाव्य साइड-चॅनल हल्ले होऊ शकतात. [खाली](#go-wrong), हा धोका कमी करण्यासाठी तुम्ही काय करू शकता ते तुम्हाला दिसेल. + +## गुप्त पत्ते कसे कार्य करतात {#how} + +हा लेख गुप्त पत्ते दोन प्रकारे स्पष्ट करण्याचा प्रयत्न करेल. पहिले म्हणजे [त्यांचा वापर कसा करायचा](#how-use). लेखाचा उर्वरित भाग समजून घेण्यासाठी हा भाग पुरेसा आहे. त्यानंतर, [त्यामागील गणिताचे स्पष्टीकरण](#how-math) आहे. जर तुम्हाला कूटलेखनात रस असेल, तर हा भाग देखील वाचा. + +### साधी आवृत्ती (गुप्त पत्त्यांचा वापर कसा करायचा) {#how-use} + +ॲलिस दोन खाजगी की तयार करते आणि संबंधित सार्वजनिक की प्रकाशित करते (ज्या एकाच दुप्पट-लांबीच्या मेटा-पत्त्यामध्ये एकत्र केल्या जाऊ शकतात). बिल देखील एक खाजगी की तयार करतो आणि संबंधित सार्वजनिक की प्रकाशित करतो. + +एका पक्षाची सार्वजनिक की आणि दुसऱ्याची खाजगी की वापरून, तुम्ही एक सामायिक गुप्त (shared secret) मिळवू शकता जे केवळ ॲलिस आणि बिल यांनाच माहीत आहे (ते केवळ सार्वजनिक कीमधून मिळवता येत नाही). हे सामायिक गुप्त वापरून, बिलला गुप्त पत्ता मिळतो आणि तो त्यावर मालमत्ता पाठवू शकतो. + +ॲलिसला सामायिक गुप्तानंतर पत्ता मिळतो, परंतु तिने प्रकाशित केलेल्या सार्वजनिक कींच्या खाजगी की तिला माहीत असल्यामुळे, तिला त्या पत्त्यावरून पैसे काढण्यासाठी खाजगी की देखील मिळू शकते. + +### गणित (गुप्त पत्ते असे का कार्य करतात) {#how-math} + +मानक गुप्त पत्ते [एलिप्टिक-कर्व्ह क्रिप्टोग्राफी (ECC)](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/#elliptic-curves-building-blocks-of-a-better-trapdoor) वापरतात ज्यामुळे कमी की बिट्ससह चांगली कामगिरी मिळते, आणि त्याच वेळी सुरक्षेची पातळी कायम राहते. परंतु बहुतेक वेळा आपण त्याकडे दुर्लक्ष करू शकतो आणि आपण नियमित अंकगणित वापरत आहोत असे भासवू शकतो. + +एक संख्या आहे जी प्रत्येकाला माहीत आहे, _G_. तुम्ही _G_ ने गुणू शकता. परंतु ECC च्या स्वरूपामुळे, _G_ ने भागणे व्यावहारिकदृष्ट्या अशक्य आहे. Ethereum मध्ये सार्वजनिक की कूटलेखन सामान्यतः ज्या प्रकारे कार्य करते ते म्हणजे, तुम्ही व्यवहार स्वाक्षरी करण्यासाठी एक खाजगी की, _Ppriv_ वापरू शकता, जे नंतर सार्वजनिक की, _Ppub = GPpriv_ द्वारे सत्यापित केले जातात. + +ॲलिस दोन खाजगी की तयार करते, _Kpriv_ आणि _Vpriv_. _Kpriv_ चा वापर गुप्त पत्त्यामधून पैसे खर्च करण्यासाठी केला जाईल, आणि _Vpriv_ चा वापर ॲलिसच्या मालकीचे पत्ते पाहण्यासाठी केला जाईल. त्यानंतर ॲलिस सार्वजनिक की प्रकाशित करते: _Kpub = GKpriv_ आणि _Vpub = GVpriv_ + +बिल तिसरी खाजगी की, _Rpriv_ तयार करतो, आणि _Rpub = GRpriv_ एका केंद्रीय नोंदणीमध्ये प्रकाशित करतो (बिलने ते ॲलिसला देखील पाठवले असते, परंतु आम्ही असे गृहीत धरतो की कॅरोल ऐकत आहे). + +बिल _RprivVpub = GRprivVpriv_ ची गणना करतो, जे ॲलिसला देखील माहीत असेल अशी त्याला अपेक्षा आहे (खाली स्पष्ट केले आहे). या मूल्याला _S_, म्हणजेच सामायिक गुप्त (shared secret) म्हणतात. यामुळे बिलला एक सार्वजनिक की मिळते, _Ppub = Kpub+G\*hash(S)_. या सार्वजनिक कीमधून, तो एक पत्ता मोजू शकतो आणि त्याला हवी असलेली कोणतीही संसाधने त्यावर पाठवू शकतो. भविष्यात, जर ॲलिस जिंकली, तर बिल तिला _Rpriv_ सांगून संसाधने त्याच्याकडून आली आहेत हे सिद्ध करू शकतो. + +ॲलिस _RpubVpriv = GRprivVpriv_ ची गणना करते. यामुळे तिला तेच सामायिक गुप्त, _S_ मिळते. तिला खाजगी की, _Kpriv_ माहीत असल्यामुळे, ती _Ppriv = Kpriv+hash(S)_ ची गणना करू शकते. ही की तिला _Ppub = GPpriv = GKpriv+G\*hash(S) = Kpub+G\*hash(S)_ मधून मिळणाऱ्या पत्त्यातील मालमत्तांमध्ये प्रवेश करू देते. + +आमच्याकडे एक वेगळी व्ह्यूइंग की (viewing key) आहे, जी ॲलिसला डेव्हच्या वर्ल्ड डॉमिनेशन कॅम्पेन सर्व्हिसेसला उपकंत्राट देण्यास अनुमती देते. ॲलिस डेव्हला सार्वजनिक पत्ते कळवण्यास आणि अधिक पैसे उपलब्ध झाल्यावर तिला माहिती देण्यास तयार आहे, परंतु तिने तिच्या मोहिमेचे पैसे खर्च करावेत असे तिला वाटत नाही. + +पाहणे आणि खर्च करणे यासाठी स्वतंत्र की वापरल्या जातात, त्यामुळे ॲलिस डेव्हला _Vpriv_ देऊ शकते. त्यानंतर डेव्ह _S = RpubVpriv = GRprivVpriv_ ची गणना करू शकतो आणि त्याद्वारे सार्वजनिक की (_Ppub = Kpub+G\*hash(S)_) मिळवू शकतो. परंतु _Kpriv_ शिवाय डेव्ह खाजगी की मिळवू शकत नाही. + +सारांश, ही मूल्ये विविध सहभागींना ज्ञात आहेत. + +| ॲलिस | प्रकाशित | बिल | डेव्ह | | +| ------------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------- | +| G | G | G | G | | +| _Kpriv_ | - | - | - | | +| _Vpriv_ | - | - | _Vpriv_ | | +| _Kpub = GKpriv_ | _Kpub_ | _Kpub_ | _Kpub_ | | +| _Vpub = GVpriv_ | _Vpub_ | _Vpub_ | _Vpub_ | | +| - | - | _Rpriv_ | - | | +| _Rpub_ | _Rpub_ | _Rpub = GRpriv_ | _Rpub_ | | +| _S = RpubVpriv = GRprivVpriv_ | - | _S = RprivVpub = GRprivVpriv_ | _S = _RpubVpriv_ = GRprivVpriv_ | | +| _Ppub = Kpub+G\*hash(S)_ | - | _Ppub = Kpub+G\*hash(S)_ | _Ppub = Kpub+G\*hash(S)_ | | +| _पत्ता=f(Ppub)_ | - | _पत्ता=f(Ppub)_ | _पत्ता=f(Ppub)_ | _पत्ता=f(Ppub)_ | +| _Ppriv = Kpriv+hash(S)_ | - | - | - | | + +## जेव्हा गुप्त पत्ते चुकीचे ठरतात {#go-wrong} + +_ब्लॉकचेनवर कोणतीही रहस्ये नसतात_. जरी गुप्त पत्ते तुम्हाला गोपनीयता देऊ शकतात, तरीही ती गोपनीयता ट्रॅफिक विश्लेषणासाठी असुरक्षित असते. एक सोपे उदाहरण घ्यायचे झाल्यास, कल्पना करा की बिल एका पत्त्याला निधी देतो आणि लगेच _Rpub_ मूल्य प्रकाशित करण्यासाठी एक व्यवहार पाठवतो. ॲलिसच्या _Vpriv_ शिवाय, हा एक गुप्त पत्ता आहे याची खात्री आपण करू शकत नाही, परंतु तसा अंदाज लावता येतो. त्यानंतर, आम्हाला आणखी एक व्यवहार दिसतो जो त्या पत्त्यावरून सर्व ETH ॲलिसच्या मोहीम निधी पत्त्यावर हस्तांतरित करतो. आम्ही ते सिद्ध करू शकत नाही, परंतु बहुधा बिलने नुकतीच ॲलिसच्या मोहिमेला देणगी दिली आहे. कॅरोलला नक्कीच असे वाटेल. + +बिलसाठी _Rpub_ चे प्रकाशन आणि गुप्त पत्त्यासाठी निधी देणे हे वेगळे करणे सोपे आहे (हे वेगवेगळ्या वेळी, वेगवेगळ्या पत्त्यांवरून करा). तथापि, ते पुरेसे नाही. कॅरोल जो पॅटर्न शोधते तो असा आहे की बिल एका पत्त्याला निधी देतो, आणि नंतर ॲलिसचा मोहीम निधी त्यातून पैसे काढतो. + +एक उपाय म्हणजे ॲलिसच्या मोहिमेने थेट पैसे काढू नये, तर ते तिसऱ्या पक्षाला पैसे देण्यासाठी वापरावे. जर ॲलिसची मोहीम डेव्हच्या वर्ल्ड डॉमिनेशन कॅम्पेन सर्व्हिसेसला 10 ETH पाठवते, तर कॅरोलला फक्त एवढेच कळते की बिलने डेव्हच्या एका ग्राहकाला देणगी दिली आहे. जर डेव्हकडे पुरेसे ग्राहक असतील, तर कॅरोलला हे कळू शकणार नाही की बिलने तिच्याशी स्पर्धा करणाऱ्या ॲलिसला देणगी दिली की ॲडम, अल्बर्ट किंवा ॲबिगेल यांना, ज्यांची कॅरोलला पर्वा नाही. ॲलिस पेमेंटसोबत एक हॅश केलेले मूल्य समाविष्ट करू शकते, आणि नंतर डेव्हला प्रीइमेज देऊ शकते, हे सिद्ध करण्यासाठी की ती तिची देणगी होती. वैकल्पिकरित्या, वर नमूद केल्याप्रमाणे, जर ॲलिसने डेव्हला तिची _Vpriv_ दिली, तर त्याला आधीच कळते की पेमेंट कोणाकडून आले आहे. + +या उपायातील मुख्य समस्या अशी आहे की, जेव्हा ती गुप्तता बिलच्या फायद्याची असते तेव्हा ॲलिसने गुप्ततेची काळजी घेणे आवश्यक असते. ॲलिसला तिची प्रतिष्ठा टिकवून ठेवायची असेल, जेणेकरून बिलचा मित्र बॉब देखील तिला देणगी देईल. परंतु हे देखील शक्य आहे की तिला बिलला उघड करण्यास हरकत नसेल, कारण मग कॅरोल जिंकल्यास काय होईल याची त्याला भीती वाटेल. बिल कदाचित ॲलिसला आणखी जास्त पाठिंबा देऊ शकेल. + +### अनेक गुप्त स्तरांचा वापर करणे {#multi-layer} + +बिलची गोपनीयता जपण्यासाठी ॲलिसवर अवलंबून राहण्याऐवजी, बिल ते स्वतः करू शकतो. तो बॉब आणि बेला या काल्पनिक लोकांसाठी अनेक मेटा-पत्ते तयार करू शकतो. बिल नंतर बॉबला ETH पाठवतो, आणि "बॉब" (जो खरं तर बिल आहे) ते बेलाला पाठवतो. "बेला" (जो बिलच आहे) ते ॲलिसला पाठवते. + +कॅरोल तरीही ट्रॅफिक विश्लेषण करू शकते आणि बिल-ते-बॉब-ते-बेला-ते-ॲलिस पाइपलाइन पाहू शकते. तथापि, जर "बॉब" आणि "बेला" देखील इतर कारणांसाठी ETH वापरत असतील, तर असे दिसणार नाही की बिलने ॲलिसला काही हस्तांतरित केले आहे, जरी ॲलिसने गुप्त पत्त्यावरून तिच्या ज्ञात मोहीम पत्त्यावर त्वरित पैसे काढले तरीही. + +## एक गुप्त-पत्ता ॲप्लिकेशन लिहिणे {#write-app} + +हा लेख [GitHub वर उपलब्ध](https://github.com/qbzzt/251022-stealth-addresses.git) असलेल्या गुप्त-पत्ता ॲप्लिकेशनबद्दल स्पष्ट करतो. + +### साधने {#tools} + +एक [टाइपस्क्रिप्ट गुप्त पत्ता लायब्ररी](https://github.com/ScopeLift/stealth-address-sdk) आहे जी आपण वापरू शकतो. तथापि, कूटलेखन ऑपरेशन्स CPU-केंद्रित असू शकतात. मी त्यांना [Rust](https://rust-lang.org/) सारख्या संकलित भाषेत कार्यान्वित करण्यास प्राधान्य देतो, आणि ब्राउझरमध्ये कोड चालवण्यासाठी [WASM](https://webassembly.org/) वापरतो. + +आम्ही [Vite](https://vite.dev/) आणि [React](https://react.dev/) वापरणार आहोत. ही उद्योग-मानक साधने आहेत; जर तुम्हाला त्यांच्याशी परिचय नसेल, तर तुम्ही [हे ट्यूटोरियल](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) वापरू शकता. Vite वापरण्यासाठी, आम्हाला Node ची आवश्यकता आहे. + +### गुप्त पत्ते प्रत्यक्षात पहा {#in-action} + +1. आवश्यक साधने स्थापित करा: [Rust](https://rust-lang.org/tools/install/) आणि [Node](https://nodejs.org/en/download). + +2. GitHub रिपॉझिटरी क्लोन करा. + + ```sh + git clone https://github.com/qbzzt/251022-stealth-addresses.git + cd 251022-stealth-addresses + ``` + +3. पूर्वापेक्षित गोष्टी स्थापित करा आणि Rust कोड संकलित करा. + + ```sh + cd src/rust-wasm + rustup target add wasm32-unknown-unknown + cargo install wasm-pack + wasm-pack build --target web + ``` + +4. वेब सर्व्हर सुरू करा. + + ```sh + cd ../.. + npm install + npm run dev + ``` + +5. [ॲप्लिकेशन](http://localhost:5173/) वर ब्राउझ करा. या ॲप्लिकेशन पृष्ठावर दोन फ्रेम आहेत: एक ॲलिसच्या वापरकर्ता इंटरफेससाठी आणि दुसरी बिलच्या. दोन फ्रेम संवाद साधत नाहीत; त्या फक्त सोयीसाठी एकाच पृष्ठावर आहेत. + +6. ॲलिस म्हणून, **एक गुप्त मेटा-पत्ता तयार करा** वर क्लिक करा. हे नवीन गुप्त पत्ता आणि संबंधित खाजगी की प्रदर्शित करेल. गुप्त मेटा-पत्ता क्लिपबोर्डवर कॉपी करा. + +7. बिल म्हणून, नवीन गुप्त मेटा-पत्ता पेस्ट करा आणि **एक पत्ता तयार करा** वर क्लिक करा. हे तुम्हाला ॲलिससाठी निधी देण्यासाठी पत्ता देते. + +8. पत्ता आणि बिलची सार्वजनिक की कॉपी करा आणि त्यांना ॲलिसच्या वापरकर्ता इंटरफेसच्या "बिलद्वारे तयार केलेल्या पत्त्यासाठी खाजगी की" क्षेत्रात पेस्ट करा. एकदा ती क्षेत्रे भरली की, तुम्हाला त्या पत्त्यावरील मालमत्तांमध्ये प्रवेश करण्यासाठी खाजगी की दिसेल. + +9. खाजगी की पत्त्याशी जुळते याची खात्री करण्यासाठी तुम्ही [एक ऑनलाइन कॅल्क्युलेटर](https://iancoleman.net/ethereum-private-key-to-address/) वापरू शकता. + +### प्रोग्राम कसा कार्य करतो {#how-the-program-works} + +#### WASM घटक {#wasm} + +WASM मध्ये संकलित होणारा स्त्रोत कोड [Rust](https://rust-lang.org/) मध्ये लिहिलेला आहे. तुम्ही ते [`src/rust_wasm/src/lib.rs`](https://github.com/qbzzt/251022-stealth-addresses/blob/main/src/rust-wasm/src/lib.rs) मध्ये पाहू शकता. हा कोड प्रामुख्याने JavaScript कोड आणि [`eth-stealth-addresses` लायब्ररी](https://github.com/kassandraoftroy/eth-stealth-addresses) यांच्यातील इंटरफेस आहे. + +**`Cargo.toml`** + +Rust मधील [`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html) हे JavaScript मधील [`package.json`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) प्रमाणेच आहे. यात पॅकेज माहिती, अवलंबित्व घोषणा इत्यादींचा समावेश आहे. + +```toml +[package] +name = "rust-wasm" +version = "0.1.0" +edition = "2024" + +[dependencies] +eth-stealth-addresses = "0.1.0" +hex = "0.4.3" +wasm-bindgen = "0.2.104" +getrandom = { version = "0.2", features = ["js"] } +``` + +[`getrandom`](https://docs.rs/getrandom/latest/getrandom/) पॅकेजला यादृच्छिक मूल्ये तयार करण्याची आवश्यकता आहे. हे केवळ अल्गोरिदमिक माध्यमांनी केले जाऊ शकत नाही; त्याला एंट्रॉपीचा स्त्रोत म्हणून भौतिक प्रक्रियेत प्रवेश आवश्यक आहे. ही व्याख्या निर्दिष्ट करते की आम्ही ज्या ब्राउझरमध्ये चालवत आहोत त्याला विचारून आम्ही ती एंट्रॉपी मिळवू. + +```toml +console_error_panic_hook = "0.1.7" +``` + +[ही लायब्ररी](https://docs.rs/console_error_panic_hook/latest/console_error_panic_hook/) आम्हाला अधिक अर्थपूर्ण त्रुटी संदेश देते जेव्हा WASM कोड पॅनिक होतो आणि पुढे चालू शकत नाही. + +```toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + +WASM कोड तयार करण्यासाठी आवश्यक असलेला आउटपुट प्रकार. + +**`lib.rs`** + +हा खरा Rust कोड आहे. + +```rust +use wasm_bindgen::prelude::*; +``` + +Rust मधून WASM पॅकेज तयार करण्याच्या व्याख्या. ते [येथे](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/index.html) दस्तऐवजीकरण केलेले आहेत. + +```rust +use eth_stealth_addresses::{ + generate_stealth_meta_address, + generate_stealth_address, + compute_stealth_key +}; +``` + +आम्हाला [`eth-stealth-addresses` लायब्ररी](https://github.com/kassandraoftroy/eth-stealth-addresses) मधून आवश्यक असलेली फंक्शन्स. + +```rust +use hex::{decode,encode}; +``` + +Rust सामान्यतः मूल्यांसाठी बाइट [अॅरे](https://doc.rust-lang.org/std/primitive.array.html) (`[u8; ]`) वापरते. परंतु JavaScript मध्ये, आम्ही सामान्यतः हेक्साडेसिमल स्ट्रिंग वापरतो. [`hex` लायब्ररी](https://docs.rs/hex/latest/hex/) आमच्यासाठी एका प्रतिनिधित्वातून दुसऱ्यामध्ये भाषांतर करते. + +```rust +#[wasm_bindgen] +``` + +JavaScript मधून हे फंक्शन कॉल करण्यासाठी WASM बाइंडिंग तयार करा. + +```rust +pub fn wasm_generate_stealth_meta_address() -> String { +``` + +अनेक फील्ड असलेले ऑब्जेक्ट परत करण्याचा सर्वात सोपा मार्ग म्हणजे JSON स्ट्रिंग परत करणे. + +```rust + let (address, spend_private_key, view_private_key) = + generate_stealth_meta_address(); +``` + +[`generate_stealth_meta_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_meta_address.html) तीन फील्ड परत करते: + +- मेटा-पत्ता (_Kpub_ आणि _Vpub_) +- पाहण्याची खाजगी की (_Vpriv_) +- खर्च करण्याची खाजगी की (_Kpriv_) + +[टपल](https://doc.rust-lang.org/std/primitive.tuple.html) सिंटॅक्स आम्हाला ती मूल्ये पुन्हा वेगळी करू देतो. + +```rust + format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}", + encode(address), + encode(view_private_key), + encode(spend_private_key) + ) +} +``` + +JSON-एनकोडेड स्ट्रिंग तयार करण्यासाठी [`format!`](https://doc.rust-lang.org/std/fmt/index.html) मॅक्रो वापरा. अॅरेला हेक्स स्ट्रिंगमध्ये बदलण्यासाठी [`hex::encode`](https://docs.rs/hex/latest/hex/fn.encode.html) वापरा. + +```rust +fn str_to_array(s: &str) -> Option<[u8; N]> { +``` + +हे फंक्शन हेक्स स्ट्रिंगला (JavaScript द्वारे प्रदान केलेले) बाइट अॅरेमध्ये बदलते. आम्ही JavaScript कोडद्वारे प्रदान केलेली मूल्ये पार्स करण्यासाठी याचा वापर करतो. Rust अॅरे आणि व्हेक्टर कसे हाताळते त्यामुळे हे फंक्शन क्लिष्ट आहे. + +`` अभिव्यक्तीला [जेनेरिक](https://doc.rust-lang.org/book/ch10-01-syntax.html) म्हणतात. `N` हे एक पॅरामीटर आहे जे परत केलेल्या अॅरेच्या लांबीवर नियंत्रण ठेवते. फंक्शनला प्रत्यक्षात `str_to_array::` असे म्हणतात, जिथे `n` ही अॅरेची लांबी आहे. + +परत केलेले मूल्य `Option<[u8; N]>` आहे, याचा अर्थ परत केलेला अॅरे [पर्यायी](https://doc.rust-lang.org/std/option/) आहे. Rust मध्ये अयशस्वी होऊ शकणाऱ्या फंक्शन्ससाठी हा एक सामान्य नमुना आहे. + +उदाहरणार्थ, जर आपण `str_to_array::10("bad060a7")` कॉल केले, तर फंक्शनने दहा-मूल्यांची अॅरे परत करणे अपेक्षित आहे, परंतु इनपुट फक्त चार बाइट्सचे आहे. फंक्शन अयशस्वी होणे आवश्यक आहे, आणि ते `None` परत करून तसे करते. `str_to_array::4("bad060a7")` साठी परत केलेले मूल्य `Some<[0xba, 0xd0, 0x60, 0xa7]>` असेल. + +```rust + // decode returns Result, _> + let vec = decode(s).ok()?; +``` + +[`hex::decode`](https://docs.rs/hex/latest/hex/fn.decode.html) फंक्शन `Result, FromHexError>` परत करते. [`Result`](https://doc.rust-lang.org/std/result/) प्रकारात एकतर यशस्वी परिणाम (`Ok(value)`) किंवा एक त्रुटी (`Err(error)`) असू शकते. + +`.ok()` पद्धत `Result` ला `Option` मध्ये रूपांतरित करते, ज्याचे मूल्य यशस्वी झाल्यास `Ok()` मूल्य किंवा अयशस्वी झाल्यास `None` असते. शेवटी, [प्रश्नचिन्ह ऑपरेटर](https://doc.rust-lang.org/std/option/#the-question-mark-operator-) `Option` रिक्त असल्यास वर्तमान फंक्शन रद्द करतो आणि `None` परत करतो. अन्यथा, ते मूल्य अनरॅप करते आणि ते परत करते (या प्रकरणात, `vec` ला मूल्य नियुक्त करण्यासाठी). + +त्रुटी हाताळण्याची ही एक विचित्र गुंतागुंतीची पद्धत वाटते, परंतु `Result` आणि `Option` हे सुनिश्चित करतात की सर्व त्रुटी, एका ना कोणत्या मार्गाने हाताळल्या जातात. + +```rust + if vec.len() != N { return None; } +``` + +जर बाइट्सची संख्या चुकीची असेल, तर ते अपयश आहे, आणि आम्ही `None` परत करतो. + +```rust + // try_into consumes vec and attempts to make [u8; N] + let array: [u8; N] = vec.try_into().ok()?; +``` + +Rust मध्ये दोन अॅरे प्रकार आहेत. [अॅरे](https://doc.rust-lang.org/std/primitive.array.html) चा आकार निश्चित असतो. [व्हेक्टर](https://doc.rust-lang.org/std/vec/index.html) वाढू आणि लहान होऊ शकतात. `hex::decode` एक व्हेक्टर परत करतो, परंतु `eth_stealth_addresses` लायब्ररीला अॅरे प्राप्त करायचे आहेत. [`.try_into()`](https://doc.rust-lang.org/std/convert/trait.TryInto.html#required-methods) एका मूल्याला दुसऱ्या प्रकारात रूपांतरित करते, उदाहरणार्थ, व्हेक्टरला अॅरेमध्ये. + +```rust + Some(array) +} +``` + +Rust तुम्हाला फंक्शनच्या शेवटी मूल्य परत करताना [`return`](https://doc.rust-lang.org/std/keyword.return.html) कीवर्ड वापरण्याची आवश्यकता नाही. + +```rust +#[wasm_bindgen] +pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option { +``` + +हे फंक्शन एक सार्वजनिक मेटा-पत्ता प्राप्त करते, ज्यात _Vpub_ आणि _Kpub_ दोन्ही समाविष्ट आहेत. ते गुप्त पत्ता, प्रकाशित करण्यासाठी सार्वजनिक की (_Rpub_), आणि एक-बाइट स्कॅन मूल्य परत करते जे ॲलिसच्या मालकीचे कोणते प्रकाशित पत्ते असू शकतात हे ओळखण्यास गती देते. + +स्कॅन मूल्य सामायिक गुप्त (_S = GRprivVpriv_) चा भाग आहे. हे मूल्य ॲलिससाठी उपलब्ध आहे, आणि ते तपासणे _f(Kpub+G\*hash(S))_ प्रकाशित पत्त्याच्या बरोबर आहे की नाही हे तपासण्यापेक्षा खूप वेगवान आहे. + +```rust + let (address, r_pub, scan) = + generate_stealth_address(&str_to_array::<66>(stealth_address)?); +``` + +आम्ही लायब्ररीचे [`generate_stealth_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_address.html) वापरतो. + +```rust + format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}", + encode(address), + encode(r_pub), + encode(&[scan]) + ).into() +} +``` + +JSON-एनकोडेड आउटपुट स्ट्रिंग तयार करा. + +```rust +#[wasm_bindgen] +pub fn wasm_compute_stealth_key( + address: &str, + bill_pub_key: &str, + view_private_key: &str, + spend_private_key: &str +) -> Option { + . + . + . +} +``` + +हे फंक्शन पत्त्यावरून (_Rpriv_) पैसे काढण्यासाठी खाजगी की मोजण्यासाठी लायब्ररीच्या [`compute_stealth_key`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.compute_stealth_key.html) चा वापर करते. या गणनेसाठी ही मूल्ये आवश्यक आहेत: + +- पत्ता (_पत्ता=f(Ppub)_) +- बिलद्वारे तयार केलेली सार्वजनिक की (_Rpub_) +- पाहण्याची खाजगी की (_Vpriv_) +- खर्च करण्याची खाजगी की (_Kpriv_) + +```rust +#[wasm_bindgen(start)] +``` + +[`#[wasm_bindgen(start)]`](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html) निर्दिष्ट करते की WASM कोड सुरू झाल्यावर फंक्शन कार्यान्वित केले जाते. + +```rust +pub fn main() { + console_error_panic_hook::set_once(); +} +``` + +हा कोड निर्दिष्ट करतो की पॅनिक आउटपुट JavaScript कन्सोलवर पाठवले जावे. ते प्रत्यक्षात पाहण्यासाठी, ॲप्लिकेशन वापरा आणि बिलला एक अवैध मेटा-पत्ता द्या (फक्त एक हेक्साडेसिमल अंक बदला). तुम्हाला JavaScript कन्सोलमध्ये ही त्रुटी दिसेल: + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9: +assertion `left == right` failed + left: 0 + right: 1 +``` + +त्यानंतर स्टॅक ट्रेस येईल. नंतर बिलला वैध मेटा-पत्ता द्या, आणि ॲलिसला एकतर अवैध पत्ता किंवा अवैध सार्वजनिक की द्या. तुम्हाला ही त्रुटी दिसेल: + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eth-stealth-addresses-0.1.0/src/lib.rs:78:9: +keys do not generate stealth address +``` + +पुन्हा, त्यानंतर स्टॅक ट्रेस येईल. + +#### वापरकर्ता इंटरफेस {#ui} + +वापरकर्ता इंटरफेस [React](https://react.dev/) वापरून लिहिलेला आहे आणि [Vite](https://vite.dev/) द्वारे सर्व्ह केला जातो. तुम्ही [या ट्यूटोरियल](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) चा वापर करून त्यांच्याबद्दल शिकू शकता. येथे [WAGMI](https://wagmi.sh/) ची गरज नाही कारण आम्ही थेट ब्लॉकचेन किंवा वॉलेटशी संवाद साधत नाही. + +वापरकर्ता इंटरफेसचा एकमेव अस्पष्ट भाग म्हणजे WASM कनेक्टिव्हिटी. हे कसे कार्य करते ते येथे आहे. + +**`vite.config.js`** + +या फाइलमध्ये [Vite कॉन्फिगरेशन](https://vite.dev/config/) आहे. + +```js +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import wasm from "vite-plugin-wasm"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), wasm()], +}) +``` + +आम्हाला दोन Vite प्लगइनची आवश्यकता आहे: [react](https://www.npmjs.com/package/@vitejs/plugin-react) आणि [wasm](https://github.com/Menci/vite-plugin-wasm#readme). + +**`App.jsx`** + +ही फाइल ॲप्लिकेशनचा मुख्य घटक आहे. हे एक कंटेनर आहे ज्यात दोन घटक आहेत: `Alice` आणि `Bill`, त्या वापरकर्त्यांसाठी वापरकर्ता इंटरफेस. WASM साठी संबंधित भाग म्हणजे इनिशियलायझेशन कोड. + +```jsx +import init from './rust-wasm/pkg/rust_wasm.js' +``` + +जेव्हा आपण [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) वापरतो, तेव्हा ते दोन फाइल्स तयार करते ज्या आपण येथे वापरतो: प्रत्यक्ष कोड असलेली एक wasm फाइल (येथे, `src/rust-wasm/pkg/rust_wasm_bg.wasm`) आणि ते वापरण्यासाठी व्याख्या असलेली एक JavaScript फाइल (येथे, `src/rust_wasm/pkg/rust_wasm.js`). त्या JavaScript फाइलचा डीफॉल्ट एक्सपोर्ट हा कोड आहे जो WASM सुरू करण्यासाठी चालवणे आवश्यक आहे. + +```jsx +function App() { + . + . + . + useEffect(() => { + const loadWasm = async () => { + try { + await init(); + setWasmReady(true) + } catch (err) { + console.error('Error loading wasm:', err) + alert("Wasm error: " + err) + } + } + + loadWasm() + }, [] + ) +``` + +[`useEffect` हुक](https://react.dev/reference/react/useEffect) तुम्हाला एक फंक्शन निर्दिष्ट करू देतो जे स्टेट व्हेरिएबल्स बदलल्यावर कार्यान्वित होते. येथे, स्टेट व्हेरिएबल्सची सूची रिकामी (`[]`) आहे, त्यामुळे हे फंक्शन पृष्ठ लोड झाल्यावर फक्त एकदाच कार्यान्वित होते. + +इफेक्ट फंक्शन त्वरित परत आले पाहिजे. असिंक्रोनस कोड वापरण्यासाठी, जसे की WASM `init` (ज्याला `.wasm` फाइल लोड करावी लागते आणि त्यामुळे वेळ लागतो) आम्ही एक अंतर्गत [`async`](https://en.wikipedia.org/wiki/Async/await) फंक्शन परिभाषित करतो आणि ते `await` शिवाय चालवतो. + +**`Bill.jsx`** + +हा बिलसाठी वापरकर्ता इंटरफेस आहे. त्यात एकच क्रिया आहे, ॲलिसने प्रदान केलेल्या गुप्त मेटा-पत्त्यावर आधारित पत्ता तयार करणे. + +```jsx +import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js' +``` + +डीफॉल्ट एक्सपोर्ट व्यतिरिक्त, `wasm-pack` द्वारे तयार केलेला JavaScript कोड WASM कोडमधील प्रत्येक फंक्शनसाठी एक फंक्शन एक्सपोर्ट करतो. + +```jsx +