மெர்க்கல் பாட்ரிசியா ட்ரை
எத்திரியம் நிலை (அனைத்து கணக்குகள், நிலுவைகள் மற்றும் ஸ்மார்ட் ஒப்பந்தங்களின் ஒட்டுமொத்த தொகுப்பு), கணினி அறிவியலில் பொதுவாக மெர்க்கல் மரம் (Merkle Tree) என்று அழைக்கப்படும் தரவுக் கட்டமைப்பின் ஒரு சிறப்புப் பதிப்பாக குறியாக்கம் செய்யப்படுகிறது. இந்த கட்டமைப்பு குறியாக்கவியலில் உள்ள பல பயன்பாடுகளுக்கு பயனுள்ளதாக இருக்கும், ஏனெனில் இது மரத்தில் உள்ள அனைத்து தனிப்பட்ட தரவுத் துண்டுகளுக்கும் இடையே சரிபார்க்கக்கூடிய உறவை உருவாக்குகிறது, இதன் விளைவாக தரவைப் பற்றிய விஷயங்களை நிரூபிக்கப் பயன்படுத்தக்கூடிய ஒற்றை ரூட் (root) மதிப்பை உருவாக்குகிறது.
எத்திரியத்தின் தரவுக் கட்டமைப்பு ஒரு 'மாற்றியமைக்கப்பட்ட மெர்க்கல்-பாட்ரிசியா ட்ரை' (modified Merkle-Patricia Trie) ஆகும், இது PATRICIA (Practical Algorithm To Retrieve Information Coded in Alphanumeric) இன் சில அம்சங்களை கடன் வாங்குவதாலும், எத்திரியம் நிலையை உள்ளடக்கிய உருப்படிகளின் திறமையான தரவு மீட்டெடுப்பிற்காக (retrieval) வடிவமைக்கப்பட்டுள்ளதாலும் இவ்வாறு பெயரிடப்பட்டது.
ஒரு மெர்க்கல்-பாட்ரிசியா ட்ரை தீர்மானிக்கக்கூடியது மற்றும் குறியாக்கவியல் ரீதியாக சரிபார்க்கக்கூடியது: ஒரு நிலை ரூட்டை உருவாக்குவதற்கான ஒரே வழி, நிலையின் ஒவ்வொரு தனிப்பட்ட பகுதியிலிருந்தும் அதைக் கணக்கிடுவதாகும், மேலும் ஒரே மாதிரியான இரண்டு நிலைகளை ரூட் ஹாஷ் மற்றும் அதற்கு வழிவகுத்த ஹாஷ்களை ஒப்பிடுவதன் மூலம் எளிதாக நிரூபிக்க முடியும் (ஒரு மெர்க்கல் சான்று). மாறாக, ஒரே ரூட் ஹாஷுடன் இரண்டு வெவ்வேறு நிலைகளை உருவாக்க எந்த வழியும் இல்லை, மேலும் வெவ்வேறு மதிப்புகளுடன் நிலையை மாற்றியமைக்கும் எந்தவொரு முயற்சியும் வேறுபட்ட நிலை ரூட் ஹாஷை உருவாக்கும். கோட்பாட்டளவில், இந்த கட்டமைப்பு செருகல்கள், தேடல்கள் மற்றும் நீக்குதல்களுக்கு O(log(n)) செயல்திறனின் 'புனிதக் கோப்பையை' (holy grail) வழங்குகிறது.
எதிர்காலத்தில், எத்திரியம் ஒரு வெர்க்கல் மரக் (Verkle Tree) கட்டமைப்புக்கு மாற திட்டமிட்டுள்ளது, இது எதிர்கால நெறிமுறை மேம்பாடுகளுக்கு பல புதிய சாத்தியங்களைத் திறக்கும்.
முன்நிபந்தனைகள்
இந்தப் பக்கத்தை நன்கு புரிந்துகொள்ள, ஹாஷ்கள் (புதிய தாவலில் திறக்கப்படும்), மெர்க்கல் மரங்கள் (புதிய தாவலில் திறக்கப்படும்), ட்ரைஸ் (tries) (புதிய தாவலில் திறக்கப்படும்) மற்றும் வரிசைப்படுத்தல் (புதிய தாவலில் திறக்கப்படும்) பற்றிய அடிப்படை அறிவு இருப்பது உதவியாக இருக்கும். இந்தக் கட்டுரை ஒரு அடிப்படை ரேடிக்ஸ் மரத்தின் (radix tree) (புதிய தாவலில் திறக்கப்படும்) விளக்கத்துடன் தொடங்குகிறது, பின்னர் எத்திரியத்தின் மிகவும் உகந்த தரவுக் கட்டமைப்புக்குத் தேவையான மாற்றங்களை படிப்படியாக அறிமுகப்படுத்துகிறது.
அடிப்படை ரேடிக்ஸ் ட்ரைஸ்
ஒரு அடிப்படை ரேடிக்ஸ் ட்ரையில், ஒவ்வொரு கணுவும் பின்வருமாறு இருக்கும்:
[i_0, i_1 ... i_n, value]
இதில் i_0 ... i_n என்பது எழுத்துக்களின் குறியீடுகளைக் குறிக்கிறது (பெரும்பாலும் பைனரி அல்லது ஹெக்ஸ்), value என்பது கணுவில் உள்ள இறுதி மதிப்பு, மற்றும் i_0, i_1 ... i_n நேரப்பகுதிகளில் உள்ள மதிப்புகள் NULL ஆகவோ அல்லது பிற கணுக்களுக்கான சுட்டிகளாகவோ (நமது விஷயத்தில், ஹாஷ்கள்) இருக்கும். இது ஒரு அடிப்படை (key, value) சேமிப்பகத்தை உருவாக்குகிறது.
திறவுகோல் மதிப்பு ஜோடிகளின் தொகுப்பில் ஒரு வரிசையை நிலைநிறுத்த ரேடிக்ஸ் மரத் தரவுக் கட்டமைப்பைப் பயன்படுத்த விரும்புகிறீர்கள் என்று வைத்துக்கொள்வோம். ட்ரையில் தற்போது dog திறவுகோலுடன் வரைபடமாக்கப்பட்டுள்ள மதிப்பைக் கண்டறிய, நீங்கள் முதலில் dog என்பதை எழுத்துக்களாக மாற்ற வேண்டும் (64 6f 67 என கிடைக்கும்), பின்னர் மதிப்பைக் கண்டுபிடிக்கும் வரை அந்தப் பாதையைப் பின்பற்றி ட்ரையில் இறங்க வேண்டும். அதாவது, ட்ரையின் ரூட் கணுவைக் கண்டறிய ஒரு தட்டையான திறவுகோல்/மதிப்பு DB-யில் ரூட் ஹாஷைத் தேடுவதன் மூலம் தொடங்குகிறீர்கள். இது பிற கணுக்களைச் சுட்டிக்காட்டும் திறவுகோல்களின் வரிசையாகக் குறிக்கப்படுகிறது. குறியீடு 6 இல் உள்ள மதிப்பை ஒரு திறவுகோலாகப் பயன்படுத்தி, ஒரு நிலை கீழே உள்ள கணுவைப் பெற தட்டையான திறவுகோல்/மதிப்பு DB-யில் அதைத் தேடுவீர்கள். பின்னர் அடுத்த மதிப்பைக் கண்டறிய குறியீடு 4 ஐத் தேர்ந்தெடுக்கவும், பின்னர் குறியீடு 6 ஐத் தேர்ந்தெடுக்கவும், இதுபோலவே root -> 6 -> 4 -> 6 -> 15 -> 6 -> 7 என்ற பாதையைப் பின்பற்றியவுடன், கணுவின் மதிப்பைக் கண்டறிந்து முடிவை வழங்குவீர்கள்.
'ட்ரை' மற்றும் அடிப்படை தட்டையான திறவுகோல்/மதிப்பு 'DB' ஆகியவற்றில் ஒன்றைத் தேடுவதற்கும் இடையே வித்தியாசம் உள்ளது. அவை இரண்டும் திறவுகோல்/மதிப்பு ஏற்பாடுகளை வரையறுக்கின்றன, ஆனால் அடிப்படை DB ஒரு திறவுகோலின் பாரம்பரிய 1 படி தேடலைச் செய்ய முடியும். ட்ரையில் ஒரு திறவுகோலைத் தேடுவதற்கு, மேலே விவரிக்கப்பட்ட இறுதி மதிப்பைப் பெற பல அடிப்படை DB தேடல்கள் தேவைப்படுகின்றன. தெளிவின்மையைப் போக்க பிந்தையதை path என்று குறிப்பிடுவோம்.
ரேடிக்ஸ் ட்ரைஸ்களுக்கான புதுப்பித்தல் மற்றும் நீக்குதல் செயல்பாடுகளை பின்வருமாறு வரையறுக்கலாம்:
def update(node_hash, path, value):
curnode = db.get(node_hash) if node_hash else [NULL] * 17
newnode = curnode.copy()
if path == "":
newnode[-1] = value
else:
newindex = update(curnode[path[0]], path[1:], value)
newnode[path[0]] = newindex
db.put(hash(newnode), newnode)
return hash(newnode)
def delete(node_hash, path):
if node_hash is NULL:
return NULL
else:
curnode = db.get(node_hash)
newnode = curnode.copy()
if path == "":
newnode[-1] = NULL
else:
newindex = delete(curnode[path[0]], path[1:])
newnode[path[0]] = newindex
if all(x is NULL for x in newnode):
return NULL
else:
db.put(hash(newnode), newnode)
return hash(newnode)
ஒரு "மெர்க்கல்" ரேடிக்ஸ் மரம் தீர்மானிக்கக்கூடிய வகையில் உருவாக்கப்பட்ட குறியாக்கவியல் ஹாஷ் சுருக்கங்களைப் பயன்படுத்தி கணுக்களை இணைப்பதன் மூலம் கட்டப்பட்டுள்ளது. இந்த உள்ளடக்க-முகவரியிடல் (திறவுகோல்/மதிப்பு DB key == keccak256(rlp(value)) இல்) சேமிக்கப்பட்ட தரவின் குறியாக்கவியல் ஒருமைப்பாடு உத்தரவாதத்தை வழங்குகிறது. கொடுக்கப்பட்ட ட்ரையின் ரூட் ஹாஷ் பொதுவில் தெரிந்தால், அடிப்படை இலைத் தரவை அணுகக்கூடிய எவரும், ஒரு குறிப்பிட்ட மதிப்பை மரத்தின் ரூட்டுடன் இணைக்கும் ஒவ்வொரு கணுவின் ஹாஷ்களையும் வழங்குவதன் மூலம், ட்ரை ஒரு குறிப்பிட்ட பாதையில் கொடுக்கப்பட்ட மதிப்பை உள்ளடக்கியுள்ளது என்பதற்கான சான்றை உருவாக்க முடியும்.
ரூட் ஹாஷ் இறுதியில் அதன் கீழே உள்ள அனைத்து ஹாஷ்களையும் அடிப்படையாகக் கொண்டிருப்பதால், இல்லாத ஒரு (path, value) ஜோடியின் சான்றை தாக்குபவர் வழங்குவது சாத்தியமற்றது. எந்தவொரு அடிப்படை மாற்றமும் ரூட் ஹாஷை மாற்றிவிடும். ஹாஷ் செய்யும் செயல்பாட்டின் முன்-படப் பாதுகாப்பால் (pre-image protection) பாதுகாக்கப்பட்ட, தரவைப் பற்றிய கட்டமைப்புத் தகவலின் சுருக்கப்பட்ட பிரதிநிதித்துவமாக ஹாஷை நீங்கள் நினைக்கலாம்.
ரேடிக்ஸ் மரத்தின் அணு அலகு ஒன்றை (எ.கா., ஒற்றை ஹெக்ஸ் எழுத்து அல்லது 4 பிட் பைனரி எண்) "நிப்பிள்" (nibble) என்று குறிப்பிடுவோம். மேலே விவரிக்கப்பட்டுள்ளபடி, ஒரு நேரத்தில் ஒரு நிப்பிள் பாதையைக் கடக்கும்போது, கணுக்கள் அதிகபட்சமாக 16 குழந்தைகளைக் குறிக்கலாம் ஆனால் ஒரு value உறுப்பை உள்ளடக்கியிருக்கும். எனவே, அவற்றை 17 நீளமுள்ள வரிசையாகக் குறிக்கிறோம். இந்த 17-உறுப்பு வரிசைகளை "கிளைக் கணுக்கள்" (branch nodes) என்று அழைக்கிறோம்.
மெர்க்கல் பாட்ரிசியா ட்ரை
ரேடிக்ஸ் ட்ரைஸ் ஒரு முக்கிய வரம்பைக் கொண்டுள்ளன: அவை திறனற்றவை. எத்திரியத்தைப் போல பாதை 64 எழுத்துக்கள் நீளமாக ( bytes32 இல் உள்ள நிப்பிள்களின் எண்ணிக்கை) இருக்கும் ஒரு (path, value) பிணைப்பை நீங்கள் சேமிக்க விரும்பினால், ஒரு எழுத்துக்கு ஒரு நிலையைச் சேமிக்க ஒரு கிலோபைட்டுக்கும் அதிகமான கூடுதல் இடம் தேவைப்படும், மேலும் ஒவ்வொரு தேடலும் அல்லது நீக்குதலும் முழு 64 படிகளை எடுக்கும். பின்வருவனவற்றில் அறிமுகப்படுத்தப்பட்ட பாட்ரிசியா ட்ரை இந்த சிக்கலைத் தீர்க்கிறது.
உகப்பாக்கம்
மெர்க்கல் பாட்ரிசியா ட்ரையில் உள்ள ஒரு கணு பின்வருவனவற்றில் ஒன்றாகும்:
NULL(வெற்று சரமாகக் குறிக்கப்படுகிறது)branchஒரு 17-உருப்படி கணு[ v0 ... v15, vt ]leafஒரு 2-உருப்படி கணு[ encodedPath, value ]extensionஒரு 2-உருப்படி கணு[ encodedPath, key ]
64 எழுத்துப் பாதைகளுடன், ட்ரையின் முதல் சில அடுக்குகளைக் கடந்த பிறகு, குறைந்தபட்சம் பாதையின் ஒரு பகுதிக்காவது வேறுபட்ட பாதை இல்லாத ஒரு கணுவை நீங்கள் அடைவது தவிர்க்க முடியாதது. பாதையில் 15 சிதறிய NULL கணுக்கள் வரை உருவாக்குவதைத் தவிர்க்க, [ encodedPath, key ] வடிவத்தில் ஒரு extension கணுவை அமைப்பதன் மூலம் இறங்குதலைக் குறுக்குவழியாக்குகிறோம், இதில் encodedPath முன்னோக்கித் தவிர்ப்பதற்கான "பகுதிப் பாதையை" (கீழே விவரிக்கப்பட்டுள்ள சுருக்கமான குறியாக்கத்தைப் பயன்படுத்தி) கொண்டுள்ளது, மேலும் key அடுத்த DB தேடலுக்கானது.
ஒரு leaf கணுவிற்கு, encodedPath இன் முதல் நிப்பிளில் ஒரு கொடியால் குறிக்கப்படலாம், பாதை முந்தைய அனைத்து கணுக்களின் பாதை துண்டுகளையும் குறியாக்குகிறது மற்றும் நாம் நேரடியாக value ஐத் தேடலாம்.
இருப்பினும், மேலே உள்ள இந்த உகப்பாக்கம் தெளிவின்மையை அறிமுகப்படுத்துகிறது.
நிப்பிள்களில் பாதைகளைக் கடக்கும்போது, நாம் கடக்க ஒற்றைப்படை எண்ணிக்கையிலான நிப்பிள்களைப் பெறலாம், ஆனால் எல்லா தரவும் bytes வடிவத்தில் சேமிக்கப்படுவதால். எடுத்துக்காட்டாக, 1 நிப்பிள் மற்றும் 01 நிப்பிள்களுக்கு இடையே வேறுபாடு காண்பது சாத்தியமில்லை (இரண்டும் <01> ஆக சேமிக்கப்பட வேண்டும்). ஒற்றைப்படை நீளத்தைக் குறிப்பிட, பகுதிப் பாதை ஒரு கொடியுடன் முன்னொட்டப்பட்டுள்ளது.
விவரக்குறிப்பு: விருப்பமான டெர்மினேட்டருடன் ஹெக்ஸ் வரிசையின் சுருக்கமான குறியாக்கம்
மேலே விவரிக்கப்பட்டுள்ளபடி ஒற்றைப்படை மற்றும் இரட்டைப்படை மீதமுள்ள பகுதிப் பாதை நீளம் மற்றும் இலை மற்றும் நீட்டிப்புக் கணு ஆகிய இரண்டின் கொடியிடலும் எந்தவொரு 2-உருப்படி கணுவின் பகுதிப் பாதையின் முதல் நிப்பிளில் இருக்கும். அவை பின்வருவனவற்றை விளைவிக்கின்றன:
| ஹெக்ஸ் எழுத்து | பிட்கள் | கணு வகை பகுதி | பாதை நீளம் |
|---|---|---|---|
| 0 | 0000 | நீட்டிப்பு | இரட்டைப்படை |
| 1 | 0001 | நீட்டிப்பு | ஒற்றைப்படை |
| 2 | 0010 | முடிவடையும் (இலை) | இரட்டைப்படை |
| 3 | 0011 | முடிவடையும் (இலை) | ஒற்றைப்படை |
இரட்டைப்படை மீதமுள்ள பாதை நீளத்திற்கு (0 அல்லது 2), மற்றொரு 0 "பேடிங்" (padding) நிப்பிள் எப்போதும் தொடரும்.
def compact_encode(hexarray):
term = 1 if hexarray[-1] == 16 else 0
if term:
hexarray = hexarray[:-1]
oddlen = len(hexarray) % 2
flags = 2 * term + oddlen
if oddlen:
hexarray = [flags] + hexarray
else:
hexarray = [flags] + [0] + hexarray
# ஹெக்ஸ்அரே இப்போது இரட்டைப்படை நீளத்தைக் கொண்டுள்ளது, அதன் முதல் நிப்பிள் கொடிகளாகும்.
o = ""
for i in range(0, len(hexarray), 2):
o += chr(16 * hexarray[i] + hexarray[i + 1])
return o
எடுத்துக்காட்டுகள்:
> [1, 2, 3, 4, 5, ...]
'11 23 45'
> [0, 1, 2, 3, 4, 5, ...]
'00 01 23 45'
> [0, f, 1, c, b, 8, 10]
'20 0f 1c b8'
> [f, 1, c, b, 8, 10]
'3f 1c b8'
மெர்க்கல் பாட்ரிசியா ட்ரையில் ஒரு கணுவைப் பெறுவதற்கான நீட்டிக்கப்பட்ட குறியீடு இங்கே:
def get_helper(node_hash, path):
if path == []:
return node_hash
if node_hash == "":
return ""
curnode = rlp.decode(node_hash if len(node_hash) < 32 else db.get(node_hash))
if len(curnode) == 2:
(k2, v2) = curnode
k2 = compact_decode(k2)
if k2 == path[: len(k2)]:
return get(v2, path[len(k2) :])
else:
return ""
elif len(curnode) == 17:
return get_helper(curnode[path[0]], path[1:])
def get(node_hash, path):
path2 = []
for i in range(len(path)):
path2.push(int(ord(path[i]) / 16))
path2.push(ord(path[i]) % 16)
path2.push(16)
return get_helper(node_hash, path2)
எடுத்துக்காட்டு ட்ரை
('do', 'verb'), ('dog', 'puppy'), ('doge', 'coins'), ('horse', 'stallion') ஆகிய நான்கு பாதை/மதிப்பு ஜோடிகளைக் கொண்ட ஒரு ட்ரை நமக்கு வேண்டும் என்று வைத்துக்கொள்வோம்.
முதலில், பாதைகள் மற்றும் மதிப்புகள் இரண்டையும் bytes ஆக மாற்றுகிறோம். கீழே, பாதைகளுக்கான உண்மையான பைட் பிரதிநிதித்துவங்கள் <> ஆல் குறிக்கப்படுகின்றன, இருப்பினும் எளிதாகப் புரிந்துகொள்வதற்காக மதிப்புகள் இன்னும் சரங்களாகக் காட்டப்படுகின்றன, அவை '' ஆல் குறிக்கப்படுகின்றன (அவையும் உண்மையில் bytes ஆக இருக்கும்):
<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' ], <>, <>, <>, <>, <>, <>, <>, <> ]
hashB: [ <00 6f>, hashC ]
hashC: [ <>, <>, <>, <>, <>, <>, hashD, <>, <>, <>, <>, <>, <>, <>, <>, <>, 'verb' ]
hashD: [ <17>, [ <>, <>, <>, <>, <>, <>, [ <35>, 'coins' ], <>, <>, <>, <>, <>, <>, <>, <>, <>, 'puppy' ] ]
ஒரு கணு மற்றொரு கணுவிற்குள் குறிப்பிடப்படும்போது, சேர்க்கப்படுவது keccak256(rlp.encode(node)) ஆகும், len(rlp.encode(node)) >= 32 ஆக இருந்தால் இல்லையெனில் node ஆகும், இதில் rlp.encode என்பது RLP குறியாக்கச் செயல்பாடாகும்.
ஒரு ட்ரையைப் புதுப்பிக்கும்போது, புதிதாக உருவாக்கப்பட்ட கணுவின் நீளம் >= 32 ஆக இருந்தால், திறவுகோல்/மதிப்பு ஜோடியான (keccak256(x), x) ஐ ஒரு நிலையான தேடல் அட்டவணையில் சேமிக்க வேண்டும் என்பதை நினைவில் கொள்ளவும். இருப்பினும், கணு அதை விடக் குறைவாக இருந்தால், f(x) = x என்ற செயல்பாடு மீளக்கூடியது என்பதால், எதையும் சேமிக்க வேண்டியதில்லை.
எத்திரியத்தில் ட்ரைஸ்
எத்திரியத்தின் செயலாக்க அடுக்கில் உள்ள அனைத்து மெர்க்கல் ட்ரைஸ்களும் ஒரு மெர்க்கல் பாட்ரிசியா ட்ரையைப் பயன்படுத்துகின்றன.
ஒரு தொகுதித் தலைப்பிலிருந்து இந்த 3 ட்ரைஸ்களிலிருந்து 3 ரூட்கள் உள்ளன.
- stateRoot
- transactionsRoot
- receiptsRoot
நிலை ட்ரை
ஒரு உலகளாவிய நிலை ட்ரை உள்ளது, மேலும் ஒவ்வொரு முறையும் ஒரு கிளையண்ட் ஒரு தொகுதியைச் செயலாக்கும்போது அது புதுப்பிக்கப்படும். இதில், ஒரு path எப்போதும்: keccak256(ethereumAddress) ஆகவும், ஒரு value எப்போதும்: rlp(ethereumAccount) ஆகவும் இருக்கும். இன்னும் குறிப்பாக ஒரு எத்திரியம் account என்பது [nonce,balance,storageRoot,codeHash] இன் 4 உருப்படி வரிசையாகும். இந்த கட்டத்தில், இந்த storageRoot மற்றொரு பாட்ரிசியா ட்ரையின் ரூட் என்பதைக் கவனத்தில் கொள்ள வேண்டும்:
சேமிப்பக ட்ரை
சேமிப்பக ட்ரை என்பது அனைத்து ஒப்பந்தத் தரவுகளும் வசிக்கும் இடமாகும். ஒவ்வொரு கணக்கிற்கும் தனித்தனி சேமிப்பக ட்ரை உள்ளது. கொடுக்கப்பட்ட முகவரியில் குறிப்பிட்ட சேமிப்பக நிலைகளில் மதிப்புகளை மீட்டெடுக்க, சேமிப்பக முகவரி, சேமிப்பகத்தில் சேமிக்கப்பட்ட தரவின் முழு எண் நிலை மற்றும் தொகுதி ஐடி ஆகியவை தேவை. இவற்றை ஜேசன்-ஆர்பிசி API இல் வரையறுக்கப்பட்ட eth_getStorageAt க்கு வாதங்களாக அனுப்பலாம், எ.கா., 0x295a70b2de5e3953354a6a8344e616ed314d7251 முகவரிக்கான சேமிப்பக நேரப்பகுதி 0 இல் உள்ள தரவை மீட்டெடுக்க:
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 பைட்டுகள் நீளத்திற்கு பூஜ்ஜியங்களுடன் இடதுபுறம் நிரப்பப்பட்டிருக்கும். எடுத்துக்காட்டாக, 0x391694e7e0b0cce554cb130d723a9d27458f9298 முகவரிக்கான சேமிப்பக நேரப்பகுதி 1 இல் உள்ள தரவிற்கான நிலை:
keccak256(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"))
ஒரு கோ எத்திரியம் (கெத்) கன்சோலில், இதை பின்வருமாறு கணக்கிடலாம்:
> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"
undefined
> web3.sha3(key, {"encoding": "hex"})
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9"
எனவே path என்பது 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 அது ஒரு ஒப்பந்தக் கணக்காக இல்லாவிட்டால் இயல்பாகவே காலியாக இருக்கும்.
பரிவர்த்தனைகள் ட்ரை
ஒவ்வொரு தொகுதிக்கும் தனித்தனி பரிவர்த்தனைகள் ட்ரை உள்ளது, மீண்டும் (key, value) ஜோடிகளைச் சேமிக்கிறது. இங்குள்ள ஒரு பாதை: rlp(transactionIndex) இது பின்வருவனவற்றால் தீர்மானிக்கப்படும் மதிப்பிற்கு ஒத்த திறவுகோலைக் குறிக்கிறது:
if legacyTx:
value = rlp(tx)
else:
value = TxType | encode(tx)
இது பற்றிய கூடுதல் தகவல்களை EIP-2718 (புதிய தாவலில் திறக்கப்படும்) ஆவணத்தில் காணலாம்.
ரசீதுகள் ட்ரை
ஒவ்வொரு தொகுதியும் அதன் சொந்த ரசீதுகள் ட்ரையைக் கொண்டுள்ளது. இங்கு ஒரு path என்பது: rlp(transactionIndex) ஆகும். transactionIndex என்பது அது சேர்க்கப்பட்ட தொகுதிக்குள் அதன் குறியீடு ஆகும். ரசீதுகள் ட்ரை ஒருபோதும் புதுப்பிக்கப்படாது. பரிவர்த்தனைகள் ட்ரையைப் போலவே, தற்போதைய மற்றும் மரபு ரசீதுகள் உள்ளன. ரசீதுகள் ட்ரையில் ஒரு குறிப்பிட்ட ரசீதை வினவ, அதன் தொகுதியில் உள்ள பரிவர்த்தனையின் குறியீடு, ரசீது பேலோடு மற்றும் பரிவர்த்தனை வகை ஆகியவை தேவை. திரும்பப் பெறப்பட்ட ரசீது Receipt வகையாக இருக்கலாம், இது TransactionType மற்றும் ReceiptPayload ஆகியவற்றின் இணைப்பாக வரையறுக்கப்படுகிறது அல்லது இது rlp([status, cumulativeGasUsed, logsBloom, logs]) என வரையறுக்கப்பட்ட LegacyReceipt வகையாக இருக்கலாம்.
இது பற்றிய கூடுதல் தகவல்களை EIP-2718 (புதிய தாவலில் திறக்கப்படும்) ஆவணத்தில் காணலாம்.