You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: public/content/translations/fa/developers/docs/data-structures-and-encoding/patricia-merkle-trie/index.md
+1-61Lines changed: 1 addition & 61 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,22 +15,16 @@ sidebarDepth: 2
15
15
16
16
## موارد مورد نیاز {#prerequisites}
17
17
18
-
برای درک بهتر این صفحه، داشتن دانش اولیه در مورد [هش](https://en.wikipedia.org/wiki/Hash_function)، [درخت مرکل](https://en.wikipedia.org/wiki/Merkle_tree)، [درخت ها](https://en.wikipedia.org/wiki/Trie) و
19
-
سریال سازی مفید خواهد بود. . این مقاله با توضیح یک [درخت ریشه](https://en.wikipedia.org/wiki/Radix_tree) اصلی آغاز میشود، سپس به تدریج تغییرات لازم برای ساختار داده بهینهتر اتریوم را معرفی میکند.
20
-
21
-
18
+
برای درک بهتر این صفحه، داشتن دانش اولیه در مورد [هش](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) اصلی آغاز میشود، سپس به تدریج تغییرات لازم برای ساختار داده بهینهتر اتریوم را معرفی میکند.
22
19
23
20
## درختهای پایه رادیکس {#basic-radix-tries}
24
21
25
22
در یک درخت پایه رادیکس، هر گره به صورت زیر به نظر می رسد:
26
23
27
-
28
-
29
24
```
30
25
[i_0, i_1 ... i_n, value]
31
26
```
32
27
33
-
34
28
در حالی که `i_0 ... i_n` نمادهای الفبا (اغلب باینری یا هگزا) را نشان می دهد، `مقدار` مقدار پایانی در گره است و مقادیر در ` i_0، i_1 ... i_n` اسلاتها یا `NULL` یا اشارهگر به (در مورد ما، هشهای) گرههای دیگر هستند. این یک ذخیره پایه `(کلید، مقدار)` را تشکیل می دهد.
35
29
36
30
فرض کنید میخواهید از یک ساختار داده درخت رادیکس برای تداوم سفارش روی مجموعهای از جفتهای مقدار کلیدی استفاده کنید. برای یافتن مقداری که در حال حاضر به کلید `dog` در درخت نگاشت شده است، ابتدا `dog` را به حروف الفبا تبدیل کنید (به `64 6f 67` بدهید) و سپس سعی کنید در درخت پایین بیایید تا مقدار را پیدا کنید. یعنی با جستجوی هش ریشه در یک DB کلید/مقدار مسطح برای یافتن گره ریشه درخت شروع میکنید. این امر، به صورت آرایه ای از کلیدها نشان داده می شود که به گره های دیگر اشاره می کنند. میتوانید از مقدار شاخص `6` به عنوان کلید استفاده کنید و آن را در کلید/مقدار مسطح DB جستجو کنید تا گره را یک سطح پایین بیاورید. سپس index `4` را برای جستجوی مقدار بعدی انتخاب کنید، سپس شاخص `6` را انتخاب کنید و به همین ترتیب، تا زمانی که مسیر را دنبال کردید: `root -> 6 -> 4 -> 6 -> 15 -> 6 -> 7`، شما مقدار گره را جستجو می کنید و نتیجه را نشان میدهید.
@@ -39,8 +33,6 @@ sidebarDepth: 2
39
33
40
34
عملیات به روز رسانی و حذف برای درختهای radix را می توان به صورت زیر تعریف کرد:
41
35
42
-
43
-
44
36
```
45
37
def update(node,path,value):
46
38
curnode = db.get(node) if node else [ NULL ] * 17
@@ -72,21 +64,16 @@ sidebarDepth: 2
72
64
return hash(newnode)
73
65
```
74
66
75
-
76
67
درخت ریشه «مرکل» با پیوند دادن گرهها با استفاده از هش رمزنگاری ایجاد شده قطعی ساخته میشود. این آدرس دهی محتوا (در کلید/مقدار DB `key == keccak256(rlp(مقدار))`) تضمین یکپارچگی رمزنگاری داده های ذخیره شده را فراهم می کند. اگر هش ریشه یک درخت داده شده به طور عمومی شناخته شده باشد، هرکسی که به دادههای برگ زیرین دسترسی داشته باشد، میتواند با ارائه هشهای هر گره که مقدار خاصی را به ریشه درخت میپیوندد، اثبات کند که سعی میکند یک مقدار معین را در یک مسیر خاص اضافه میکند.
77
68
78
69
برای یک مهاجم غیرممکن است که اثباتی برای یک جفت `(مسیر، مقدار)` ارائه دهد که وجود ندارد، زیرا هش ریشه در نهایت بر اساس همه هش های زیر آن است. هر گونه تغییر اساسی، هش ریشه را تغییر می دهد. میتوانید هش را بهعنوان نمایش فشردهای از اطلاعات ساختاری در مورد دادهها در نظر بگیرید، که با محافظت پیشتصویر تابع درهمسازی ایمن شده است.
79
70
80
71
ما به یک واحد اتمی یک درخت ریشه (مثلاً یک کاراکتر هگز یا عدد باینری 4 بیتی) به عنوان "نیبل" اشاره خواهیم کرد. همانطور که در بالا توضیح داده شد، در حین پیمودن یک مسیر یک نوبت، گرهها میتوانند حداکثر به 16 فرزند اشاره داشته باشند اما یک عنصر `مقدار` را شامل میشوند. بنابراین ما آنها را به صورت آرایه ای به طول 17 نشان می دهیم. ما این آرایه های 17 عنصری را "گره های شاخه ای" می نامیم.
81
72
82
-
83
-
84
73
## درخت مرکل پاتریشیا {#merkle-patricia-trees}
85
74
86
75
درختهای رادیکس یک محدودیت عمده دارند: ناکارآمد هستند. اگر می خواهید یک پیوند `(مسیر، مقدار)` را در جایی که مسیر، مانند اتریوم، 64 کاراکتر طول دارد (تعداد nibble ها در `bytes32`) ذخیره کنید، به بیش از یک کیلوبایت فضای اضافی برای ذخیره یک سطح در هر کاراکتر نیاز خواهیم داشت، و هر جستجو یا حذف 64 مرحله کامل طول خواهد کشید. درخت پاتریشیا معرفی شده در ادامه این مشکل را حل می کند.
87
76
88
-
89
-
90
77
### بهينه سازی {#optimization}
91
78
92
79
یک گره در درخت مرکل پاتریشیا یکی از موارد زیر است:
@@ -104,8 +91,6 @@ sidebarDepth: 2
104
91
105
92
هنگام پیمایش مسیرها در نیبل، ممکن است در نهایت با تعداد فرد نیبل برای پیمایش مواجه شویم، اما به این دلیل که همه داده ها در قالب `بایت` ذخیره می شوند. نمی توان بین، به عنوان مثال، nibble `1` و nibbles `01` تفاوت قائل شد (هر دو باید به عنوان `<01>` ذخیره شوند). برای تعیین طول فرد، مسیر جزئی با یک پرچم پیشوند داده می شود.
106
93
107
-
108
-
109
94
### مشخصات: رمزگذاری فشرده دنباله هگزا با پایان دهنده اختیاری {#specification}
110
95
111
96
علامت گذاری _طول مسیر جزئی باقیمانده فرد در مقابل زوج_ و _گره برگ در مقابل پسوند_ همانطور که در بالا توضیح داده شد در اولین نوک مسیر جزئی هر گره 2 موردی قرار دارد. آنها به موارد زیر منجر می شوند:
@@ -116,12 +101,9 @@ sidebarDepth: 2
116
101
1 0001 | extension odd
117
102
2 0010 | terminating (leaf) even
118
103
3 0011 | terminating (leaf) odd
119
-
120
104
121
105
حتی برای طول مسیر باقیمانده (`0` یا `2`)، یک نوک `0` "padding" دیگر همیشه در پی میآید.
122
106
123
-
124
-
125
107
```
126
108
def compact_encode(hexarray):
127
109
term = 1 if hexarray[-1] == 16 else 0
@@ -139,11 +121,8 @@ sidebarDepth: 2
139
121
return o
140
122
```
141
123
142
-
143
124
مثال ها:
144
125
145
-
146
-
147
126
```
148
127
> [ 1, 2, 3, 4, 5, ...]
149
128
'11 23 45'
@@ -155,11 +134,8 @@ sidebarDepth: 2
155
134
'3f 1c b8'
156
135
```
157
136
158
-
159
137
در اینجا کد توسعه یافته برای گرفتن یک گره در درخت مرکل پاتریشیا آمده است:
160
138
161
-
162
-
163
139
```
164
140
def get_helper(node,path):
165
141
if path == []: return node
@@ -184,29 +160,21 @@ sidebarDepth: 2
184
160
return get_helper(node,path2)
185
161
```
186
162
187
-
188
-
189
-
190
163
### درخت نمونه {#example-trie}
191
164
192
165
فرض کنید ما درختی می خواهیم حاوی چهار جفت مسیر/مقدار `('do', 'verb')`, `('dog', 'puppy')`, `(' doge، «coins»)`، `(«horse»، «stallion»)`.
193
166
194
167
ابتدا، هم مسیرها و هم مقادیر را به `بایت` تبدیل می کنیم. در زیر، نمایشهای واقعی بایت برای _مسیرها_ با > نشان داده میشوند، اگرچه _مقادیر_ که برای درک آسان تر همچنان به صورت رشتهها`` نشان داده میشوند (آنها نیز در واقع `بایت` خواهند بود):
195
168
196
-
197
-
198
169
```
199
170
<64 6f> : 'verb'
200
171
<64 6f 67> : 'puppy'
201
172
<64 6f 67 65> : 'coins'
202
173
<68 6f 72 73 65> : 'stallion'
203
174
```
204
175
205
-
206
176
اکنون، ما چنین درختی را با جفتهای کلید/مقدار زیر در DB زیرین میسازیم:
هنگامی که یک گره در داخل گره دیگری ارجاع داده می شود، آنچه شامل می شود `H(rlp.encode(node))` است، که در آن `H(x) = keccak256(x) اگر len(x) > = 32 else x` و `rlp.encode` تابع رمزگذاری [RLP](/developers/docs/data-structures-and-encoding/rlp) است.
220
187
221
188
توجه داشته باشید که هنگام بهروزرسانی یک درخت، باید جفت کلید/مقدار `(keccak256(x)، x)` را در یک جدول جستجوی دائمی ذخیره کنید _اگر_ گره تازه ایجاد شده دارای طول >= 32 باشد. با این حال، اگر گره کوتاهتر از آن باشد، نیازی به ذخیره چیزی نیست، زیرا تابع f(x) = x قابل برگشت است.
222
189
223
-
224
-
225
190
## درخت ها در اتریوم {#tries-in-ethereum}
226
191
227
192
تمام درخت های مرکل در لایه اجرایی اتریوم از درخت مرکل پاتریشیا استفاده میکنند.
@@ -232,90 +197,65 @@ sidebarDepth: 2
232
197
2. transactionsRoot
233
198
3. receiptsRoot
234
199
235
-
236
-
237
200
### درخت حالت {#state-trie}
238
201
239
202
یک درخت حالت جهانی وجود دارد و هر بار که کلاینت یک بلوک را پردازش می کند، به روز می شود. در آن، یک `مسیر` همیشه: `keccak256(ethereumAddress)` و یک `مقدار` همیشه: `rlp(ethereumAccount)` است. به طور خاص، `حساب` اتریوم یک آرایه 4 موردی از `[nonce,balance,storageRoot,codeHash]` است. در این مرحله، شایان ذکر است که این `storageRoot` ریشه یکی دیگر از درخت های پاتریشیا است:
240
203
241
-
242
-
243
204
### درخت حافظه {#storage-trie}
244
205
245
206
درخت Storage جایی است که _همه_ دادههای قرارداد زندگی میکنند. برای هر حساب یک فضای ذخیره سازی جداگانه وجود دارد. برای بازیابی مقادیر در موقعیتهای ذخیرهسازی خاص در یک آدرس معین، آدرس ذخیره، موقعیت عدد صحیح دادههای ذخیرهشده در حافظه و شناسه بلوک مورد نیاز است. سپس میتوان آنها را بهعنوان آرگومان به `eth_getStorageAt` تعریفشده در JSON-RPC API ارسال کرد، بهعنوان مثال: برای بازیابی داده ها در اسلات ذخیره سازی 0 برای آدرس `0x295a70b2de5e3953354a6a8344e616ed314d7251`:
بازیابی عناصر دیگر در ذخیره سازی کمی بیشتر دخیل است زیرا ابتدا باید موقعیت در درخت حافظه محاسبه شود. موقعیت به عنوان هش `keccak256` آدرس و موقعیت ذخیره سازی محاسبه می شود که هر دو در سمت چپ با صفر تا طول 32 بایت اضافه شده اند. به عنوان مثال، موقعیت داده در شکاف ذخیره سازی 1 برای آدرس `0x391694e7e0b0cce554cb130d723a9d27458f9298` است:
بنابراین `مسیر``keccak256(<6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9>)` است. اکنون می توان از آن برای بازیابی داده ها از درخت حافظه مانند قبل استفاده کرد:
توجه: `storageRoot` برای یک حساب اتریوم اگر یک حساب قراردادی نباشد به طور پیشفرض خالی است.
290
239
291
-
292
-
293
240
### درخت تراکنشها {#transaction-trie}
294
241
295
242
برای هر بلوک یک تراکنش جداگانه وجود دارد که دوباره جفتهای `(کلید، مقدار)` را ذخیره میکند. یک مسیر در اینجا عبارت است از: `rlp(transactionIndex)` که نشان دهنده کلیدی است که با مقدار تعیین شده از سوی این مطابقت دارد:
296
243
297
-
298
-
299
244
```
300
245
if legacyTx:
301
246
value = rlp(tx)
302
247
else:
303
248
value = TxType | encode(tx)
304
249
```
305
250
306
-
307
251
اطلاعات بیشتر در این مورد را می توان در اسناد [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) یافت.
308
252
309
-
310
-
311
253
### درخت رسیدها {#receipts-trie}
312
254
313
255
هر بلوک درخت رسیدهای خود را دارد. یک `مسیر` در اینجا این است: `rlp(transactionIndex)`. `transactionIndex` شاخص آن در بلوکی است که در آن گنجانده شده است. درخت رسیدها هرگز به روز نمی شود. مشابه درخت تراکنشها، رسیدهای جاری و قدیمی وجود دارد. برای استعلام یک رسید خاص در درخت رسیدها، شاخص تراکنش در بلوک آن، بار رسید و نوع تراکنش مورد نیاز است. رسید برگشتی می تواند از نوع `رسیدی` باشد که به عنوان الحاق `TransactionType` و `ReceiptPayload` تعریف می شود یا می تواند از نوع `LegacyReceipt< باشد /0> که به صورت <code>rlp([status, cumulativeGasUsed, logsBloom, logs])`. تعریف میشود.
314
256
315
257
اطلاعات بیشتر در این مورد را می توان در اسناد [EIP 2718](https://eips.ethereum.org/EIPS/eip-2718) یافت.
316
258
317
-
318
-
319
259
## اطلاعات بیشتر {#further-reading}
320
260
321
261
-[درخت مرکل پاتریشیا اصلاح شده – چگونه اتریوم یک حالت را ذخیره می کند](https://medium.com/codechain/modified-merkle-patricia-trie-how-ethereum-saves-a-state-e6d7555078dd)
0 commit comments