எளிய வரிசைப்படுத்தல் (Simple serialize)
எளிய வரிசைப்படுத்தல் (Simple serialize - SSZ) என்பது பீக்கன் சங்கிலியில் (beacon chain) பயன்படுத்தப்படும் வரிசைப்படுத்தல் (serialization) முறையாகும். இது சகக்கணு கண்டறிதல் நெறிமுறையைத் (peer discovery protocol) தவிர, கருத்தொருமிப்பு அடுக்கு (consensus layer) முழுவதும் செயலாக்க அடுக்கில் (execution layer) பயன்படுத்தப்படும் RLP வரிசைப்படுத்தலை மாற்றுகிறது. RLP வரிசைப்படுத்தல் பற்றி மேலும் அறிய, சுழல்-நீள முன்னொட்டு (Recursive-length prefix - RLP) என்பதைப் பார்க்கவும். SSZ ஆனது தீர்மானிக்கக்கூடியதாகவும், திறமையாக மெர்க்கல் (Merkleize) செய்யவும் வடிவமைக்கப்பட்டுள்ளது. SSZ இரண்டு கூறுகளைக் கொண்டிருப்பதாகக் கருதலாம்: ஒரு வரிசைப்படுத்தல் திட்டம் மற்றும் வரிசைப்படுத்தப்பட்ட தரவு கட்டமைப்புடன் திறமையாக செயல்பட வடிவமைக்கப்பட்ட ஒரு மெர்க்கல் திட்டம்.
SSZ எவ்வாறு செயல்படுகிறது?
வரிசைப்படுத்தல்
SSZ என்பது தன்னைத்தானே விவரித்துக்கொள்ளாத ஒரு வரிசைப்படுத்தல் திட்டமாகும் - மாறாக இது முன்கூட்டியே தெரிந்திருக்க வேண்டிய ஒரு திட்டவடிவத்தை (schema) நம்பியுள்ளது. SSZ வரிசைப்படுத்தலின் குறிக்கோள், தன்னிச்சையான சிக்கலான பொருள்களை பைட் சரங்களாக (strings of bytes) குறிப்பதாகும். "அடிப்படை வகைகளுக்கு" (basic types) இது மிகவும் எளிமையான செயல்முறையாகும். உறுப்பு வெறுமனே ஹெக்ஸாடெசிமல் பைட்டுகளாக மாற்றப்படுகிறது. அடிப்படை வகைகளில் பின்வருவன அடங்கும்:
- குறியிடப்படாத முழு எண்கள் (unsigned integers)
- பூலியன்கள் (Booleans)
சிக்கலான "கலப்பு" (composite) வகைகளுக்கு, வரிசைப்படுத்தல் மிகவும் சிக்கலானது, ஏனெனில் கலப்பு வகையானது வெவ்வேறு வகைகள் அல்லது வெவ்வேறு அளவுகள் அல்லது இரண்டையும் கொண்ட பல உறுப்புகளைக் கொண்டுள்ளது. இந்த பொருள்கள் அனைத்தும் நிலையான நீளங்களைக் கொண்டிருக்கும் போது (அதாவது, உறுப்புகளின் அளவு அவற்றின் உண்மையான மதிப்புகளைப் பொருட்படுத்தாமல் எப்போதும் மாறிலியாக இருக்கும்), வரிசைப்படுத்தல் என்பது கலப்பு வகையில் உள்ள ஒவ்வொரு உறுப்பையும் லிட்டில்-எண்டியன் (little-endian) பைட் சரங்களாக வரிசைப்படுத்தி மாற்றுவதாகும். இந்த பைட் சரங்கள் ஒன்றாக இணைக்கப்படுகின்றன. வரிசைப்படுத்தப்பட்ட பொருளானது, வரிசைப்படுத்தப்படாத பொருளில் தோன்றும் அதே வரிசையில் நிலையான-நீள உறுப்புகளின் பைட் பட்டியல் பிரதிநிதித்துவத்தைக் கொண்டுள்ளது.
மாறும் நீளங்களைக் கொண்ட வகைகளுக்கு, வரிசைப்படுத்தப்பட்ட பொருளில் அந்த உறுப்பின் நிலையில் உள்ள உண்மையான தரவு ஒரு "ஆஃப்செட்" (offset) மதிப்பால் மாற்றப்படுகிறது. உண்மையான தரவு வரிசைப்படுத்தப்பட்ட பொருளின் முடிவில் உள்ள ஒரு குவியலில் (heap) சேர்க்கப்படுகிறது. ஆஃப்செட் மதிப்பு என்பது குவியலில் உள்ள உண்மையான தரவின் தொடக்கத்திற்கான குறியீடு (index) ஆகும், இது தொடர்புடைய பைட்டுகளுக்கான சுட்டியாக (pointer) செயல்படுகிறது.
நிலையான மற்றும் மாறும்-நீள உறுப்புகள் இரண்டையும் கொண்ட ஒரு கொள்கலனுக்கு ஆஃப்செட்டிங் எவ்வாறு செயல்படுகிறது என்பதை கீழேயுள்ள எடுத்துக்காட்டு விளக்குகிறது:
struct Dummy {
number1: u64,
number2: u64,
vector: Vec<u8>,
number3: u64
}
dummy = Dummy{
number1: 37,
number2: 55,
vector: vec![1,2,3,4],
number3: 22,
}
serialized = ssz.serialize(dummy)
serialized பின்வரும் கட்டமைப்பைக் கொண்டிருக்கும் (இங்கு 4 பிட்டுகளுக்கு மட்டுமே பேட் செய்யப்பட்டுள்ளது, உண்மையில் 32 பிட்டுகளுக்கு பேட் செய்யப்படும், மேலும் தெளிவுக்காக int பிரதிநிதித்துவம் வைக்கப்பட்டுள்ளது):
[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]
------------ ----------- ----------- ----------- ----------
| | | | |
எண்1 எண்2 வெக்டருக்கான எண் 3 வெக்டருக்கான
ஆஃப்செட் மதிப்பு
தெளிவுக்காக வரிகளாகப் பிரிக்கப்பட்டுள்ளது:
[
37, 0, 0, 0, # `number1` இன் லிட்டில்-எண்டியன் குறியாக்கம்.
55, 0, 0, 0, # `number2` இன் லிட்டில்-எண்டியன் குறியாக்கம்.
16, 0, 0, 0, # `vector` இன் மதிப்பு எங்கு தொடங்குகிறது என்பதைக் குறிக்கும் "ஆஃப்செட்" (லிட்டில்-எண்டியன் 16).
22, 0, 0, 0, # `number3` இன் லிட்டில்-எண்டியன் குறியாக்கம்.
1, 2, 3, 4, # `vector` இல் உள்ள உண்மையான மதிப்புகள்.
]
இது இன்னும் ஒரு எளிமைப்படுத்தலாகும் - மேலே உள்ள வரைபடங்களில் உள்ள முழு எண்கள் மற்றும் பூஜ்ஜியங்கள் உண்மையில் இதுபோன்று பைட் பட்டியல்களாக சேமிக்கப்படும்:
[
10100101000000000000000000000000 # `number1` இன் லிட்டில்-எண்டியன் குறியாக்கம்
10110111000000000000000000000000 # `number2` இன் லிட்டில்-எண்டியன் குறியாக்கம்.
10010000000000000000000000000000 # `vector` இன் மதிப்பு எங்கு தொடங்குகிறது என்பதைக் குறிக்கும் "ஆஃப்செட்" (லிட்டில்-எண்டியன் 16).
10010110000000000000000000000000 # `number3` இன் லிட்டில்-எண்டியன் குறியாக்கம்.
10000001100000101000001110000100 # `bytes` புலத்தின் உண்மையான மதிப்பு.
]
எனவே மாறும்-நீள வகைகளுக்கான உண்மையான மதிப்புகள் வரிசைப்படுத்தப்பட்ட பொருளின் முடிவில் ஒரு குவியலில் சேமிக்கப்படுகின்றன, அவற்றின் ஆஃப்செட்டுகள் புலங்களின் வரிசைப்படுத்தப்பட்ட பட்டியலில் அவற்றின் சரியான நிலைகளில் சேமிக்கப்படுகின்றன.
வரிசைப்படுத்தலின் போது நீள வரம்பு சேர்க்கப்பட வேண்டிய மற்றும் வரிசைப்படுத்தலை நீக்கும் போது அகற்றப்பட வேண்டிய BitList வகை போன்ற குறிப்பிட்ட கையாளுதல் தேவைப்படும் சில சிறப்பு நிகழ்வுகளும் உள்ளன. முழு விவரங்களும் SSZ விவரக்குறிப்பில் (opens in a new tab) கிடைக்கின்றன.
வரிசைப்படுத்தலை நீக்குதல் (Deserialization)
இந்த பொருளின் வரிசைப்படுத்தலை நீக்க திட்டவடிவம் (schema) தேவை. திட்டவடிவமானது வரிசைப்படுத்தப்பட்ட தரவின் துல்லியமான அமைப்பை வரையறுக்கிறது, இதனால் ஒவ்வொரு குறிப்பிட்ட உறுப்பும் பைட்டுகளின் தரவுத் திரளையிலிருந்து (blob) சரியான வகை, மதிப்பு, அளவு மற்றும் நிலையைக் கொண்ட உறுப்புகளுடன் சில அர்த்தமுள்ள பொருளாக வரிசைப்படுத்தலை நீக்க முடியும். எந்த மதிப்புகள் உண்மையான மதிப்புகள் மற்றும் எவை ஆஃப்செட்டுகள் என்பதை வரிசைப்படுத்தலை நீக்குபவருக்கு (deserializer) திட்டவடிவமே கூறுகிறது. ஒரு பொருள் வரிசைப்படுத்தப்படும்போது அனைத்து புலப் பெயர்களும் மறைந்துவிடும், ஆனால் திட்டவடிவத்தின்படி வரிசைப்படுத்தலை நீக்கும்போது மீண்டும் உருவாக்கப்படும்.
இது குறித்த ஊடாடும் விளக்கத்திற்கு ssz.dev (opens in a new tab) என்பதைப் பார்க்கவும்.
மெர்க்கலைசேஷன் (Merkleization)
இந்த SSZ வரிசைப்படுத்தப்பட்ட பொருளை பின்னர் மெர்க்கலைஸ் செய்யலாம் - அதாவது அதே தரவின் மெர்க்கல் மரம் (Merkle tree) பிரதிநிதித்துவமாக மாற்றலாம். முதலில், வரிசைப்படுத்தப்பட்ட பொருளில் உள்ள 32-பைட் துண்டுகளின் எண்ணிக்கை தீர்மானிக்கப்படுகிறது. இவை மரத்தின் "இலைகள்" (leaves) ஆகும். இலைகளின் மொத்த எண்ணிக்கை 2 இன் அடுக்காக இருக்க வேண்டும், இதனால் இலைகளை ஒன்றாக ஹாஷ் செய்தல் (hashing) இறுதியில் ஒரு ஒற்றை ஹாஷ்-மர-வேரை (hash-tree-root) உருவாக்குகிறது. இது இயற்கையாகவே இல்லையென்றால், 32 பைட்டுகள் பூஜ்ஜியங்களைக் கொண்ட கூடுதல் இலைகள் சேர்க்கப்படுகின்றன. வரைபடமாக:
ஹாஷ் மர வேர்
/ \
/ \
/ \
/ \
இலைகள் 1 மற்றும் இலைகள் 3 மற்றும்
2 இன் ஹாஷ் 4 இன் ஹாஷ்
/ \ / \
/ \ / \
/ \ / \
இலை1 இலை2 இலை3 இலை4
மேலே உள்ள எடுத்துக்காட்டில் உள்ளதைப் போல மரத்தின் இலைகள் இயற்கையாகவே சமமாக விநியோகிக்கப்படாத நிகழ்வுகளும் உள்ளன. எடுத்துக்காட்டாக, இலை 4 என்பது மெர்க்கல் மரத்தில் கூடுதல் "ஆழம்" (depth) சேர்க்கப்பட வேண்டிய பல உறுப்புகளைக் கொண்ட ஒரு கொள்கலனாக இருக்கலாம், இது சீரற்ற மரத்தை உருவாக்குகிறது.
இந்த மர உறுப்புகளை இலை X, கணு (node) X என்று குறிப்பிடுவதற்குப் பதிலாக, வேர் = 1 என்று தொடங்கி ஒவ்வொரு மட்டத்திலும் இடமிருந்து வலமாக எண்ணி, அவற்றுக்கு பொதுவான குறியீடுகளை (generalized indices) வழங்கலாம். இது மேலே விளக்கப்பட்ட பொதுவான குறியீடு ஆகும். வரிசைப்படுத்தப்பட்ட பட்டியலில் உள்ள ஒவ்வொரு உறுப்பும் 2**depth + idx க்கு சமமான பொதுவான குறியீட்டைக் கொண்டுள்ளது, இதில் idx என்பது வரிசைப்படுத்தப்பட்ட பொருளில் அதன் பூஜ்ஜிய-குறியீட்டு நிலை மற்றும் ஆழம் என்பது மெர்க்கல் மரத்தில் உள்ள நிலைகளின் எண்ணிக்கையாகும், இது உறுப்புகளின் (இலைகள்) எண்ணிக்கையின் அடிமானம்-இரண்டு மடக்கையாக (base-two logarithm) தீர்மானிக்கப்படலாம்.
பொதுவான குறியீடுகள் (Generalized indices)
பொதுவான குறியீடு என்பது பைனரி மெர்க்கல் மரத்தில் உள்ள ஒரு கணுவைக் குறிக்கும் முழு எண்ணாகும், இதில் ஒவ்வொரு கணுவும் 2 ** depth + index in row என்ற பொதுவான குறியீட்டைக் கொண்டுள்ளது.
1 --ஆழம் = 0 2**0 + 0 = 1
2 3 --ஆழம் = 1 2**1 + 0 = 2, 2**1+1 = 3
4 5 6 7 --ஆழம் = 2 2**2 + 0 = 4, 2**2 + 1 = 5...
இந்த பிரதிநிதித்துவம் மெர்க்கல் மரத்தில் உள்ள ஒவ்வொரு தரவுத் துண்டுக்கும் ஒரு கணு குறியீட்டை (node index) அளிக்கிறது.
மல்டிப்ரூஃப்கள் (Multiproofs)
ஒரு குறிப்பிட்ட உறுப்பைக் குறிக்கும் பொதுவான குறியீடுகளின் பட்டியலை வழங்குவது, ஹாஷ்-மர-வேருக்கு எதிராக அதைச் சரிபார்க்க அனுமதிக்கிறது. இந்த வேர் என்பது நாம் ஏற்றுக்கொண்ட யதார்த்தத்தின் பதிப்பாகும். நமக்கு வழங்கப்படும் எந்தவொரு தரவையும் மெர்க்கல் மரத்தில் சரியான இடத்தில் செருகுவதன் மூலம் (அதன் பொதுவான குறியீட்டால் தீர்மானிக்கப்படுகிறது) மற்றும் வேர் மாறிலியாக இருப்பதைக் கவனிப்பதன் மூலம் அந்த யதார்த்தத்திற்கு எதிராக சரிபார்க்க முடியும். ஒரு குறிப்பிட்ட பொதுவான குறியீடுகளின் தொகுப்பின் உள்ளடக்கங்களைச் சரிபார்க்கத் தேவையான குறைந்தபட்ச கணுக்களின் தொகுப்பை எவ்வாறு கணக்கிடுவது என்பதைக் காட்டும் செயல்பாடுகள் இங்கே (opens in a new tab) விவரக்குறிப்பில் உள்ளன.
எடுத்துக்காட்டாக, கீழே உள்ள மரத்தில் குறியீடு 9 இல் உள்ள தரவைச் சரிபார்க்க, குறியீடுகள் 8, 9, 5, 3, 1 இல் உள்ள தரவின் ஹாஷ் நமக்குத் தேவை. (8,9) இன் ஹாஷ் ஹாஷ் (4) க்கு சமமாக இருக்க வேண்டும், இது 5 உடன் ஹாஷ் செய்து 2 ஐ உருவாக்குகிறது, இது 3 உடன் ஹாஷ் செய்து மரத்தின் வேர் 1 ஐ உருவாக்குகிறது. 9 க்கு தவறான தரவு வழங்கப்பட்டால், வேர் மாறும் - இதை நாங்கள் கண்டறிந்து கிளையைச் சரிபார்க்கத் தவறிவிடுவோம்.
* = சான்றை உருவாக்கத் தேவையான தரவு
1*
2 3*
4 5* 6 7
8* 9* 10 11 12 13 14 15