Simple serialize (Ssz)
பக்கத்தின் கடைசி புதுப்பிப்பு: 1 பிப்ரவரி, 2026
எளிய வரிசைப்படுத்தல் (SSZ) என்பது தீப்பந்த சங்கிலியில் பயன்படுத்தப்படும் வரிசைப்படுத்தல் முறையாகும். இது execution layer-இல் பயன்படுத்தப்படும் RLP serialization-ஐ மாற்றுகிறது, ஆனால் peer discovery protocol தவிர consensus layer முழுவதும் இதுவே பயன்படுத்தப்படுகிறது. RLP வரிசைப்படுத்தல் பற்றி மேலும் அறிய, சுழல்நிலை-நீள முன்னொட்டு (RLP) என்பதைப் பார்க்கவும். SSZ deterministic ஆக வடிவமைக்கப்பட்டுள்ளது, மேலும் Merkleize செய்யவும் திறமையாக உள்ளது. SSZ-ஐ இரண்டு பகுதிகளைக் கொண்டதாகக் கருதலாம்: ஒரு serialization scheme, ஒரு Merkleization scheme – இது serialized data structure-உடன் திறமையாக வேலை செய்ய வடிவமைக்கப்பட்டுள்ளது.
SSZ எப்படி செயல்படுகிறது?
வரிசைப்படுத்தல்
SSZ என்பது self-describing அல்லாத serialization scheme – அதாவது, முன்கூட்டியே schema தெரிந்திருக்க வேண்டும். SSZ serialization-ன் நோக்கம், எவ்வளவு சிக்கலான object ஆனாலும் அதை byte string ஆக மாற்றுவதாகும். இது "basic types" க்கு மிக எளிமையான செயல்முறை. Element எளிதாகவே hexadecimal bytes-ஆக மாற்றப்படுகிறது. Basic types:
- unsigned integers
- Booleans
சிக்கலான "composite types" க்கான serialization இன்னும் சிக்கலாகும். ஏனெனில் composite type-ல் பல elements இருக்கும், அவற்றின் type அல்லது size வேறுபட்டு இருக்கலாம். இந்த பொருள்கள் அனைத்தும் நிலையான நீளங்களைக் கொண்டிருக்கும் இடங்களில் (அதாவது, உறுப்புகளின் அளவு அவற்றின் உண்மையான மதிப்புகளைப் பொருட்படுத்தாமல் எப்போதும் மாறிலியாக இருக்கும்) வரிசைப்படுத்தல் என்பது கலப்பு வகையிலுள்ள ஒவ்வொரு உறுப்பையும் லிட்டில்-எண்டியன் பைட்ஸ்ட்ரிங்ஸ்களாக மாற்றுவதாகும். பிறகு, அந்த bytestring-கள் இணைக்கப்படும். Serialized object-ல், fixed-length elements-ன் bytelist representation, deserialized object-ல் அவை இருந்த அதே வரிசையில் இருக்கும்.
Variable length கொண்ட types-க்கு serialization வேறுபடும், அந்த element-ன் இடத்தில், actual data-க்கு பதிலாக ஒரு "offset value" வைக்கப்படும். அந்த actual data, serialized object-ன் முடிவில் இருக்கும் heap-ல் சேர்க்கப்படும். அந்த offset value, heap-ல் actual data ஆரம்பிக்கும் இடத்தின் index-ஐ குறிக்கும் (அதாவது, அந்த bytes-ஐச் சுட்டும் pointer ஆக செயல்படும்).
கீழே உள்ள உதாரணம், fixed மற்றும் variable-length elements இரண்டும் உள்ள ஒரு container-க்கு offset எவ்வாறு செயல்படுகிறது என்பதை விளக்குகிறது:
12 struct Dummy {34 number1: u64,5 number2: u64,6 vector: Vec<u8>,7 number3: u648 }910 dummy = Dummy{1112 number1: 37,13 number2: 55,14 vector: vec![1,2,3,4],15 number3: 22,16 }1718 serialized = ssz.serialize(dummy)19அனைத்தையும் காட்டுவரிசைப்படுத்தப்பட்ட தரவு பின்வரும் கட்டமைப்பைக் கொண்டிருக்கும் (இங்கே 4 பிட்டுகளுக்கு மட்டுமே திணிக்கப்பட்டுள்ளது, உண்மையில் 32 பிட்டுகளுக்கு திணிக்கப்படும், மேலும் தெளிவுக்காக int பிரதிநிதித்துவம் வைக்கப்பட்டுள்ளது):
1[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]2------------ ----------- ----------- ----------- ----------3 | | | | |4 எண்1 எண்2 திசையனுக்கான எண் 3 திசையனுக்கான5 ஆஃப்செட் மதிப்பு6விளக்கத்திற்காக பல வரிகளாகப் பிரிக்கப்பட்டது:
1[2 37, 0, 0, 0, # `number1`-இன் லிட்டில்-எண்டியன் குறியாக்கம்.3 55, 0, 0, 0, # `number2`-இன் லிட்டில்-எண்டியன் குறியாக்கம்.4 16, 0, 0, 0, # `vector`-இன் மதிப்பு எங்கு தொடங்குகிறது என்பதைக் குறிக்கும் "ஆஃப்செட்" (லிட்டில்-எண்டியன் 16).5 22, 0, 0, 0, # `number3`-இன் லிட்டில்-எண்டியன் குறியாக்கம்.6 1, 2, 3, 4, # `vector`-இல் உள்ள உண்மையான மதிப்புகள்.7]இது இன்னும் ஒரு simplification தான் – மேலே உள்ள schematic-ல் integers மற்றும் zeros உண்மையில் bytelists ஆகச் சேமிக்கப்படும், எடுத்துக்காட்டாக:
1[2 10100101000000000000000000000000 # `number1`-இன் லிட்டில்-எண்டியன் குறியாக்கம்3 10110111000000000000000000000000 # `number2`-இன் லிட்டில்-எண்டியன் குறியாக்கம்.4 10010000000000000000000000000000 # `vector`-இன் மதிப்பு எங்கு தொடங்குகிறது என்பதைக் குறிக்கும் "ஆஃப்செட்" (லிட்டில்-எண்டியன் 16).5 10010110000000000000000000000000 # `number3`-இன் லிட்டில்-எண்டியன் குறியாக்கம்.6 10000001100000101000001110000100 # `bytes` புலத்தின் உண்மையான மதிப்பு.7]இதனால், variable-length types-ன் actual values serialized object-ன் இறுதியில் உள்ள heap-ல் சேமிக்கப்படும், மற்றும் அவற்றின் offset values சரியான இடத்தில் (ordered list of fields-ல்) வைக்கப்படும்.
வரிசைப்படுத்தலின் போது நீள வரம்பைச் சேர்க்கவும், வரிசைநீக்கத்தின் போது அகற்றவும் தேவைப்படும் BitList வகை போன்ற குறிப்பிட்ட சிகிச்சை தேவைப்படும் சில சிறப்பு நிகழ்வுகளும் உள்ளன. முழு விவரங்களும் SSZ விவரக்குறிப்பில் (opens in a new tab) கிடைக்கின்றன.
வரிசைநீக்கம்
ஒரு object-ஐ deserialize செய்ய schema தேவைப்படுகிறது. Schema தான் serialized data-வின் சரியான அமைப்பை (precise layout) வரையறுக்கிறது. அதன் மூலம் ஒவ்வொரு element-மும் bytes blob-இலிருந்து மீண்டும் பொருத்தமான object-ஆக மாற்றப்படும், மேலும் அவை சரியான type, value, size, position உடன் மீள்பெறும். Schema தான் deserializer-க்கு எந்த values actual values, எந்த values offsets என்பதைச் சொல்கிறது. ஒரு object serialize ஆனபோது, அதன் field names அனைத்தும் மறைந்து விடும். ஆனால் deserialization போது schema அடிப்படையில் மீண்டும் field names உருவாக்கப்படும்.
இதற்கான ஒரு ஊடாடும் விளக்கத்திற்கு ssz.dev (opens in a new tab) ஐப் பார்க்கவும்.
மெர்க்கிலைசேஷன்
இந்த SSZ serialized object-ஐ Merkleize செய்யலாம் – அதாவது, அதே தரவின் Merkle-tree representation ஆக மாற்றலாம். முதலில், serialized object-இல் எத்தனை 32-byte chunks உள்ளன என்பதை தீர்மானிக்க வேண்டும். இவை தான் மரத்தின் "leaves". மொத்த leaves எண்ணிக்கை 2-ன் சக்தியாக (power of 2) இருக்க வேண்டும், அப்போதுதான் அவற்றை ஒன்றாக hash செய்யும் போது இறுதியில் ஒரு single hash-tree-root உருவாகும். இது இயல்பாக இல்லாவிட்டால், 32 bytes zeros கொண்ட கூடுதல் leaves சேர்க்கப்படும். Diagrammatically:
1 ஹாஷ் மரத்தின் மூலம்2 / \3 / \4 / \5 / \6 இலைகள் 1 மற்றும் 2-இன் ஹாஷ் இலைகள் 3 மற்றும் 4-இன் ஹாஷ்7 / \ / \8 / \ / \9 / \ / \10 இலை1 இலை2 இலை3 இலை4அனைத்தையும் காட்டுசில நேரங்களில், tree-ன் leaves மேலே காட்டிய மாதிரி சமமாகப் பகிரப்படாது. உதாரணமாக, leaf 4 ஒரு container ஆக இருந்து, அதில் பல elements இருக்கலாம். அப்படியானால், Merkle tree-க்கு கூடுதல் "depth" சேர்க்கப்பட வேண்டும், இதனால் tree uneven ஆகும்.
இந்த tree elements-ஐ leaf X, node X என்று குறிப்பிடுவதற்கு பதிலாக, அவற்றிற்கு generalized indices கொடுக்கலாம், root = 1 என்று தொடங்கி, ஒவ்வொரு level-இலும் இடமிருந்து வலமாக எண்ணலாம். இது மேலே விளக்கப்பட்ட generalized index ஆகும். வரிசைப்படுத்தப்பட்ட பட்டியலில் உள்ள ஒவ்வொரு உறுப்புக்கும் 2**depth + idx க்கு சமமான ஒரு பொதுவான குறியீடு உள்ளது, இங்கு idx என்பது வரிசைப்படுத்தப்பட்ட பொருளில் அதன் பூஜ்ஜிய-குறியீட்டு நிலையாகும், மேலும் டெப்த் என்பது மெர்க்கல் மரத்தில் உள்ள நிலைகளின் எண்ணிக்கையாகும், இது உறுப்புகளின் (இலைகள்) எண்ணிக்கையின் அடி-இரண்டு மடக்கையாக தீர்மானிக்கப்படலாம்.
பொதுவான குறியீடுகள்
ஒரு பொதுவான குறியீடு என்பது ஒரு முழு எண் ஆகும், இது ஒரு பைனரி மெர்க்கல் மரத்தில் ஒரு முனையை பிரதிபலிக்கிறது, அங்கு ஒவ்வொரு முனைக்கும் 2 ** depth + index in row என்ற பொதுவான குறியீடு உள்ளது.
1 1 --டெப்த் = 0 2**0 + 0 = 12 2 3 --டெப்த் = 1 2**1 + 0 = 2, 2**1+1 = 33 4 5 6 7 --டெப்த் = 2 2**2 + 0 = 4, 2**2 + 1 = 5...4இந்த representation, Merkle tree-இல் உள்ள ஒவ்வொரு data-க்கும் ஒரு node index-ஐ உருவாக்குகிறது.
பல்சான்றுகள்
ஒரு குறிப்பிட்ட element-ஐ குறிக்கும் generalized indices பட்டியல் வழங்கப்படும்போது, அதை hash-tree-root-க்கு எதிராக சரிபார்க்க முடியும். இந்த root தான் நாங்கள் ஏற்றுக்கொண்டுள்ள உண்மை (accepted version of reality). எந்த data கொடுக்கப்பட்டாலும், அதை அதன் generalized index தீர்மானிக்கும் சரியான இடத்தில் Merkle tree-இல் வைத்து, root மாறாமல் இருப்பதை கவனிப்பதன் மூலம் அந்த data-ஐ உண்மைக்கெதிராக சரிபார்க்க முடியும். இங்கே (opens in a new tab) உள்ள விவரக்குறிப்பில், ஒரு குறிப்பிட்ட பொதுவான குறியீடுகளின் தொகுப்பின் உள்ளடக்கங்களைச் சரிபார்க்கத் தேவையான குறைந்தபட்ச முனைகளின் தொகுப்பை எவ்வாறு கணக்கிடுவது என்பதைக் காட்டும் செயல்பாடுகள் உள்ளன.
உதாரணமாக, கீழே உள்ள tree-இல் index 9-இல் உள்ள data-ஐ verify செய்ய, indices 8, 9, 5, 3, 1-இல் உள்ள data-வின் hash தேவைப்படும். (8,9)-இன் hash, (4)-இன் hash-க்கு சமமாக இருக்க வேண்டும், அது 5-உடன் hash செய்யப்பட்டு 2 ஆகும், அது 3-உடன் hash செய்யப்பட்டு tree root 1 ஆகும். 9-க்கு தவறான data கொடுக்கப்பட்டால், root மாறிவிடும் – இதை நாம் கண்டறிந்து, அந்த branch verify ஆகாமல் போகும்.
1* = சான்றை உருவாக்க தேவையான தரவு23 1*4 2 3*5 4 5* 6 768* 9* 10 11 12 13 14 157