Skip to content

Commit

Permalink
fix: crowdin markdown syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
wackerow committed Oct 17, 2024
1 parent 4e968c7 commit 1f5dd2f
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ lang: fa

- [گیت‌هاب](https://github.com/paulrberg/create-eth-app)

**One Click Dapp _- ابزار FOSS برای تولید صفحات فرانت dapp از
‏ABI‏‏>.
**One Click Dapp _- ابزار FOSS برای تولید صفحات فرانت dapp از [ABI](/glossary/#abi)._**

- [oneclickdapp.com](https://oneclickdapp.com)
- [گیت هاب](https://github.com/oneclickdapp/oneclickdapp-v1)
Expand All @@ -81,8 +80,6 @@ lang: fa
- [اسناد](https://docs.crossmint.com)
- [دیسکورد](https://discord.com/invite/crossmint)



## بیشتر بخوانید {#further-reading}

- [کاوش در برنامه‌های غیرمتمرکز](/dapps)
Expand All @@ -93,8 +90,6 @@ lang: fa

_می‌خواهید در مورد منابع جامعه که به شما کمک کرده بدانید؟ این صفحه را ویرایش و اضافه کنید!_



## موضوعات مرتبط {#related-topics}

- [مقدمه ای بر پشته اتریوم](/developers/docs/ethereum-stack/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,16 @@ sidebarDepth: 2

## موارد مورد نیاز {#prerequisites}

برای درک بهتر این صفحه، داشتن دانش اولیه در مورد [هش](https://en.wikipedia.org/wiki/Hash_function)، [درخت مرکل](https://en.wikipedia.org/wiki/Merkle_tree)، [درخت ها](https://en.wikipedia.org/wiki/Trie) و
سریال سازی مفید خواهد بود. . این مقاله با توضیح یک [درخت ریشه](https://en.wikipedia.org/wiki/Radix_tree) اصلی آغاز می‌شود، سپس به تدریج تغییرات لازم برای ساختار داده بهینه‌تر اتریوم را معرفی می‌کند.


برای درک بهتر این صفحه، داشتن دانش اولیه در مورد [هش](https://en.wikipedia.org/wiki/Hash_function)، [درخت مرکل](https://en.wikipedia.org/wiki/Merkle_tree)، [درخت ها](https://en.wikipedia.org/wiki/Trie) و [سریال سازی](https://en.wikipedia.org/wiki/Serialization) مفید خواهد بود. این مقاله با توضیح یک [درخت ریشه](https://en.wikipedia.org/wiki/Radix_tree) اصلی آغاز می‌شود، سپس به تدریج تغییرات لازم برای ساختار داده بهینه‌تر اتریوم را معرفی می‌کند.

## درخت‌های پایه رادیکس {#basic-radix-tries}

در یک درخت پایه رادیکس، هر گره به صورت زیر به نظر می رسد:



```
[i_0, i_1 ... i_n, value]
```


در حالی که `i_0 ... i_n` نمادهای الفبا (اغلب باینری یا هگزا) را نشان می دهد، `مقدار` مقدار پایانی در گره است و مقادیر در ` i_0، i_1 ... i_n` اسلات‌ها یا `NULL` یا اشاره‌گر به (در مورد ما، هش‌های) گره‌های دیگر هستند. این یک ذخیره پایه `(کلید، مقدار)` را تشکیل می دهد.

فرض کنید می‌خواهید از یک ساختار داده درخت رادیکس برای تداوم سفارش روی مجموعه‌ای از جفت‌های مقدار کلیدی استفاده کنید. برای یافتن مقداری که در حال حاضر به کلید `dog` در درخت نگاشت شده است، ابتدا `dog` را به حروف الفبا تبدیل کنید (به `64 6f 67` بدهید) و سپس سعی کنید در درخت پایین بیایید تا مقدار را پیدا کنید. یعنی با جستجوی هش ریشه در یک DB کلید/مقدار مسطح برای یافتن گره ریشه درخت شروع می‌کنید. این امر، به صورت آرایه ای از کلیدها نشان داده می شود که به گره های دیگر اشاره می کنند. می‌توانید از مقدار شاخص `6` به عنوان کلید استفاده کنید و آن را در کلید/مقدار مسطح DB جستجو کنید تا گره را یک سطح پایین بیاورید. سپس index `4` را برای جستجوی مقدار بعدی انتخاب کنید، سپس شاخص `6` را انتخاب کنید و به همین ترتیب، تا زمانی که مسیر را دنبال کردید: `root -> 6 -> 4 -> 6 -> 15 -> 6 -> 7`، شما مقدار گره را جستجو می کنید و نتیجه را نشان می‌دهید.
Expand All @@ -39,8 +33,6 @@ sidebarDepth: 2

عملیات به روز رسانی و حذف برای درخت‌های radix را می توان به صورت زیر تعریف کرد:



```
def update(node,path,value):
curnode = db.get(node) if node else [ NULL ] * 17
Expand Down Expand Up @@ -72,21 +64,16 @@ sidebarDepth: 2
return hash(newnode)
```


درخت ریشه «مرکل» با پیوند دادن گره‌ها با استفاده از هش رمزنگاری ایجاد شده قطعی ساخته می‌شود. این آدرس دهی محتوا (در کلید/مقدار DB `key == keccak256(rlp(مقدار))`) تضمین یکپارچگی رمزنگاری داده های ذخیره شده را فراهم می کند. اگر هش ریشه یک درخت داده شده به طور عمومی شناخته شده باشد، هرکسی که به داده‌های برگ زیرین دسترسی داشته باشد، می‌تواند با ارائه هش‌های هر گره که مقدار خاصی را به ریشه درخت می‌پیوندد، اثبات کند که سعی می‌کند یک مقدار معین را در یک مسیر خاص اضافه می‌کند.

برای یک مهاجم غیرممکن است که اثباتی برای یک جفت `(مسیر، مقدار)` ارائه دهد که وجود ندارد، زیرا هش ریشه در نهایت بر اساس همه هش های زیر آن است. هر گونه تغییر اساسی، هش ریشه را تغییر می دهد. می‌توانید هش را به‌عنوان نمایش فشرده‌ای از اطلاعات ساختاری در مورد داده‌ها در نظر بگیرید، که با محافظت پیش‌تصویر تابع درهم‌سازی ایمن شده است.

ما به یک واحد اتمی یک درخت ریشه (مثلاً یک کاراکتر هگز یا عدد باینری 4 بیتی) به عنوان "نیبل" اشاره خواهیم کرد. همانطور که در بالا توضیح داده شد، در حین پیمودن یک مسیر یک نوبت، گره‌ها می‌توانند حداکثر به 16 فرزند اشاره داشته باشند اما یک عنصر `مقدار` را شامل می‌شوند. بنابراین ما آنها را به صورت آرایه ای به طول 17 نشان می دهیم. ما این آرایه های 17 عنصری را "گره های شاخه ای" می نامیم.



## درخت مرکل پاتریشیا {#merkle-patricia-trees}

درختهای رادیکس یک محدودیت عمده دارند: ناکارآمد هستند. اگر می خواهید یک پیوند `(مسیر، مقدار)` را در جایی که مسیر، مانند اتریوم، 64 کاراکتر طول دارد (تعداد nibble ها در `bytes32`) ذخیره کنید، به بیش از یک کیلوبایت فضای اضافی برای ذخیره یک سطح در هر کاراکتر نیاز خواهیم داشت، و هر جستجو یا حذف 64 مرحله کامل طول خواهد کشید. درخت پاتریشیا معرفی شده در ادامه این مشکل را حل می کند.



### بهينه سازی {#optimization}

یک گره در درخت مرکل پاتریشیا یکی از موارد زیر است:
Expand All @@ -104,8 +91,6 @@ sidebarDepth: 2

هنگام پیمایش مسیرها در نیبل، ممکن است در نهایت با تعداد فرد نیبل برای پیمایش مواجه شویم، اما به این دلیل که همه داده ها در قالب `بایت` ذخیره می شوند. نمی توان بین، به عنوان مثال، nibble `1` و nibbles `01` تفاوت قائل شد (هر دو باید به عنوان `<01>` ذخیره شوند). برای تعیین طول فرد، مسیر جزئی با یک پرچم پیشوند داده می شود.



### مشخصات: رمزگذاری فشرده دنباله هگزا با پایان دهنده اختیاری {#specification}

علامت گذاری _طول مسیر جزئی باقیمانده فرد در مقابل زوج_ و _گره برگ در مقابل پسوند_ همانطور که در بالا توضیح داده شد در اولین نوک مسیر جزئی هر گره 2 موردی قرار دارد. آنها به موارد زیر منجر می شوند:
Expand All @@ -116,12 +101,9 @@ sidebarDepth: 2
1 0001 | extension odd
2 0010 | terminating (leaf) even
3 0011 | terminating (leaf) odd


حتی برای طول مسیر باقی‌مانده (`0` یا `2`)، یک نوک `0` "padding" دیگر همیشه در پی می‌آید.



```
def compact_encode(hexarray):
term = 1 if hexarray[-1] == 16 else 0
Expand All @@ -139,11 +121,8 @@ sidebarDepth: 2
return o
```


مثال ها:



```
> [ 1, 2, 3, 4, 5, ...]
'11 23 45'
Expand All @@ -155,11 +134,8 @@ sidebarDepth: 2
'3f 1c b8'
```


در اینجا کد توسعه یافته برای گرفتن یک گره در درخت مرکل پاتریشیا آمده است:



```
def get_helper(node,path):
if path == []: return node
Expand All @@ -184,29 +160,21 @@ sidebarDepth: 2
return get_helper(node,path2)
```




### درخت نمونه {#example-trie}

فرض کنید ما درختی می خواهیم حاوی چهار جفت مسیر/مقدار `('do', 'verb')`, `('dog', 'puppy')`, `(' doge، «coins»)`، `(«horse»، «stallion»)`.

ابتدا، هم مسیرها و هم مقادیر را به `بایت` تبدیل می کنیم. در زیر، نمایش‌های واقعی بایت برای _مسیرها_ با &gt; نشان داده می‌شوند، اگرچه _مقادیر_ که برای درک آسان تر همچنان به صورت رشته‌ها`` نشان داده می‌شوند (آنها نیز در واقع `بایت` خواهند بود):



```
<64 6f> : 'verb'
<64 6f 67> : 'puppy'
<64 6f 67 65> : 'coins'
<68 6f 72 73 65> : 'stallion'
```


اکنون، ما چنین درختی را با جفت‌های کلید/مقدار زیر در DB زیرین می‌سازیم:



```
rootHash: [ <16>, hashA ]
hashA: [ <>, <>, <>, <>, hashB, <>, <>, <>, [ <20 6f 72 73 65>, 'stallion' ], <>, <>, <>, <>, <>, <>, <>, <> ]
Expand All @@ -215,13 +183,10 @@ sidebarDepth: 2
hashD: [ <17>, [ <>, <>, <>, <>, <>, <>, [ <35>, 'coins' ], <>, <>, <>, <>, <>, <>, <>, <>, <>, 'puppy' ] ]
```


هنگامی که یک گره در داخل گره دیگری ارجاع داده می شود، آنچه شامل می شود `H(rlp.encode(node))` است، که در آن `H(x) = keccak256(x) اگر len(x) > = 32 else x` و `rlp.encode` تابع رمزگذاری [RLP](/developers/docs/data-structures-and-encoding/rlp) است.

توجه داشته باشید که هنگام به‌روزرسانی یک درخت، باید جفت کلید/مقدار `(keccak256(x)، x)` را در یک جدول جستجوی دائمی ذخیره کنید _اگر_ گره تازه ایجاد شده دارای طول >= 32 باشد. با این حال، اگر گره کوتاه‌تر از آن باشد، نیازی به ذخیره چیزی نیست، زیرا تابع f(x) = x قابل برگشت است.



## درخت ها در اتریوم {#tries-in-ethereum}

تمام درخت های مرکل در لایه اجرایی اتریوم از درخت مرکل پاتریشیا استفاده می‌کنند.
Expand All @@ -232,90 +197,65 @@ sidebarDepth: 2
2. transactionsRoot
3. receiptsRoot



### درخت حالت {#state-trie}

یک درخت حالت جهانی وجود دارد و هر بار که کلاینت یک بلوک را پردازش می کند، به روز می شود. در آن، یک `مسیر` همیشه: `keccak256(ethereumAddress)` و یک `مقدار` همیشه: `rlp(ethereumAccount)` است. به طور خاص، `حساب` اتریوم یک آرایه 4 موردی از `[nonce,balance,storageRoot,codeHash]` است. در این مرحله، شایان ذکر است که این `storageRoot` ریشه یکی دیگر از درخت های پاتریشیا است:



### درخت حافظه {#storage-trie}

درخت Storage جایی است که _همه_ داده‌های قرارداد زندگی می‌کنند. برای هر حساب یک فضای ذخیره سازی جداگانه وجود دارد. برای بازیابی مقادیر در موقعیت‌های ذخیره‌سازی خاص در یک آدرس معین، آدرس ذخیره، موقعیت عدد صحیح داده‌های ذخیره‌شده در حافظه و شناسه بلوک مورد نیاز است. سپس می‌توان آن‌ها را به‌عنوان آرگومان به `eth_getStorageAt` تعریف‌شده در JSON-RPC API ارسال کرد، به‌عنوان مثال: برای بازیابی داده ها در اسلات ذخیره سازی 0 برای آدرس `0x295a70b2de5e3953354a6a8344e616ed314d7251`:



```
curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"}
```


بازیابی عناصر دیگر در ذخیره سازی کمی بیشتر دخیل است زیرا ابتدا باید موقعیت در درخت حافظه محاسبه شود. موقعیت به عنوان هش `keccak256` آدرس و موقعیت ذخیره سازی محاسبه می شود که هر دو در سمت چپ با صفر تا طول 32 بایت اضافه شده اند. به عنوان مثال، موقعیت داده در شکاف ذخیره سازی 1 برای آدرس `0x391694e7e0b0cce554cb130d723a9d27458f9298` است:



```
keccak256(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"))
```


در یک کنسول Geth، این می تواند به صورت زیر محاسبه شود:



```
> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"
undefined
> web3.sha3(key, {"encoding": "hex"})
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9"
```


بنابراین `مسیر` `keccak256(<6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9>)` است. اکنون می توان از آن برای بازیابی داده ها از درخت حافظه مانند قبل استفاده کرد:



```
curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"}
```


توجه: `storageRoot` برای یک حساب اتریوم اگر یک حساب قراردادی نباشد به طور پیش‌فرض خالی است.



### درخت تراکنش‌ها {#transaction-trie}

برای هر بلوک یک تراکنش جداگانه وجود دارد که دوباره جفت‌های `(کلید، مقدار)` را ذخیره می‌کند. یک مسیر در اینجا عبارت است از: `rlp(transactionIndex)` که نشان دهنده کلیدی است که با مقدار تعیین شده از سوی این مطابقت دارد:



```
if legacyTx:
value = rlp(tx)
else:
value = TxType | encode(tx)
```


اطلاعات بیشتر در این مورد را می توان در اسناد [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) یافت.



### درخت رسیدها {#receipts-trie}

هر بلوک درخت رسیدهای خود را دارد. یک `مسیر` در اینجا این است: `rlp(transactionIndex)`. `transactionIndex` شاخص آن در بلوکی است که در آن گنجانده شده است. درخت رسیدها هرگز به روز نمی شود. مشابه درخت تراکنش‌ها، رسیدهای جاری و قدیمی وجود دارد. برای استعلام یک رسید خاص در درخت رسیدها، شاخص تراکنش در بلوک آن، بار رسید و نوع تراکنش مورد نیاز است. رسید برگشتی می تواند از نوع `رسیدی` باشد که به عنوان الحاق `TransactionType` و `ReceiptPayload` تعریف می شود یا می تواند از نوع `LegacyReceipt< باشد /0> که به صورت <code>rlp([status, cumulativeGasUsed, logsBloom, logs])`. تعریف می‌شود.

اطلاعات بیشتر در این مورد را می توان در اسناد [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) یافت.



## اطلاعات بیشتر {#further-reading}

- [درخت مرکل پاتریشیا اصلاح شده – چگونه اتریوم یک حالت را ذخیره می کند](https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd)
Expand Down
Loading

0 comments on commit 1f5dd2f

Please sign in to comment.