సాధారణ శ్రేణీకరణ
సాధారణ శ్రేణీకరణ (SSZ) అనేది బీకన్ చైన్ పై ఉపయోగించే శ్రేణీకరణ పద్ధతి. ఇది పీర్ అన్వేషణ ప్రోటోకాల్ మినహా ఏకాభిప్రాయ పొర అంతటా అమలు పొరలో ఉపయోగించే RLP శ్రేణీకరణను భర్తీ చేస్తుంది. RLP శ్రేణీకరణ గురించి మరింత తెలుసుకోవడానికి, రికార్సివ్-లెంగ్త్ ప్రిఫిక్స్ (RLP) చూడండి. SSZ నిర్ణయాత్మకంగా ఉండటానికి మరియు సమర్థవంతంగా మెర్కిలైజ్ చేయడానికి రూపొందించబడింది. SSZ రెండు భాగాలను కలిగి ఉన్నట్లుగా భావించవచ్చు: ఒక శ్రేణీకరణ స్కీమ్ మరియు శ్రేణీకరించబడిన డేటా నిర్మాణంతో సమర్థవంతంగా పనిచేయడానికి రూపొందించబడిన మెర్కిలైజేషన్ స్కీమ్.
SSZ ఎలా పనిచేస్తుంది?
శ్రేణీకరణ
SSZ అనేది స్వీయ-వివరణాత్మకమైన శ్రేణీకరణ స్కీమ్ కాదు - బదులుగా ఇది ముందుగానే తెలుసుకోవలసిన స్కీమాపై ఆధారపడి ఉంటుంది. SSZ శ్రేణీకరణ యొక్క లక్ష్యం ఏకపక్ష సంక్లిష్టత కలిగిన వస్తువులను బైట్ల స్ట్రింగ్లుగా సూచించడం. "ప్రాథమిక రకాల" కోసం ఇది చాలా సులభమైన ప్రక్రియ. మూలకం కేవలం హెక్సాడెసిమల్ బైట్లుగా మార్చబడుతుంది. ప్రాథమిక రకాలు ఇవి:
- అన్సైన్డ్ పూర్ణాంకాలు (unsigned integers)
- బూలియన్స్ (Booleans)
సంక్లిష్టమైన "మిశ్రమ (composite)" రకాల కోసం, శ్రేణీకరణ మరింత క్లిష్టంగా ఉంటుంది ఎందుకంటే మిశ్రమ రకం వేర్వేరు రకాలు లేదా వేర్వేరు పరిమాణాలు లేదా రెండింటినీ కలిగి ఉండే బహుళ మూలకాలను కలిగి ఉంటుంది. ఈ వస్తువులన్నీ స్థిరమైన పొడవులను కలిగి ఉన్న చోట (అంటే, మూలకాల పరిమాణం వాటి వాస్తవ విలువల ప్రమేయం లేకుండా ఎల్లప్పుడూ స్థిరంగా ఉంటుంది) శ్రేణీకరణ అనేది మిశ్రమ రకంలోని ప్రతి మూలకాన్ని లిటిల్-ఎండియన్ (little-endian) బైట్స్ట్రింగ్లుగా మార్చడం. ఈ బైట్స్ట్రింగ్లు ఒకదానితో ఒకటి కలపబడతాయి. శ్రేణీకరించబడిన వస్తువు డీసీరియలైజ్ చేయబడిన వస్తువులో కనిపించే క్రమంలోనే స్థిర-పొడవు మూలకాల బైట్లిస్ట్ ప్రాతినిధ్యాన్ని కలిగి ఉంటుంది.
వేరియబుల్ పొడవు ఉన్న రకాల కోసం, వాస్తవ డేటా శ్రేణీకరించబడిన వస్తువులోని ఆ మూలకం స్థానంలో "ఆఫ్సెట్ (offset)" విలువతో భర్తీ చేయబడుతుంది. వాస్తవ డేటా శ్రేణీకరించబడిన వస్తువు చివర ఉన్న కుప్ప (heap)కు జోడించబడుతుంది. ఆఫ్సెట్ విలువ అనేది కుప్పలోని వాస్తవ డేటా ప్రారంభానికి సూచిక, ఇది సంబంధిత బైట్లకు పాయింటర్గా పనిచేస్తుంది.
స్థిర మరియు వేరియబుల్-పొడవు మూలకాలు రెండింటినీ కలిగి ఉన్న కంటైనర్ కోసం ఆఫ్సెట్టింగ్ ఎలా పనిచేస్తుందో దిగువ ఉదాహరణ వివరిస్తుంది:
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]
------------ ----------- ----------- ----------- ----------
| | | | |
number1 number2 వెక్టర్ కోసం number 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` ఫీల్డ్ యొక్క వాస్తవ విలువ.
]
కాబట్టి వేరియబుల్-పొడవు రకాల వాస్తవ విలువలు శ్రేణీకరించబడిన వస్తువు చివర ఉన్న కుప్పలో నిల్వ చేయబడతాయి, వాటి ఆఫ్సెట్లు ఫీల్డ్ల క్రమబద్ధీకరించబడిన జాబితాలో వాటి సరైన స్థానాల్లో నిల్వ చేయబడతాయి.
శ్రేణీకరణ సమయంలో పొడవు పరిమితిని (length cap) జోడించడం మరియు డీసీరియలైజేషన్ సమయంలో తీసివేయడం అవసరం అయ్యే BitList రకం వంటి నిర్దిష్ట చికిత్స అవసరమయ్యే కొన్ని ప్రత్యేక సందర్భాలు కూడా ఉన్నాయి. పూర్తి వివరాలు SSZ స్పెక్ (opens in a new tab)లో అందుబాటులో ఉన్నాయి.
డీసీరియలైజేషన్
ఈ వస్తువును డీసీరియలైజ్ చేయడానికి స్కీమా (schema) అవసరం. స్కీమా శ్రేణీకరించబడిన డేటా యొక్క ఖచ్చితమైన లేఅవుట్ను నిర్వచిస్తుంది, తద్వారా ప్రతి నిర్దిష్ట మూలకం బైట్ల బ్లాబ్ నుండి సరైన రకం, విలువ, పరిమాణం మరియు స్థానాన్ని కలిగి ఉన్న అర్థవంతమైన వస్తువుగా డీసీరియలైజ్ చేయబడుతుంది. ఏ విలువలు వాస్తవ విలువలు మరియు ఏవి ఆఫ్సెట్లు అని డీసీరియలైజర్కు చెప్పేది స్కీమానే. ఒక వస్తువు శ్రేణీకరించబడినప్పుడు అన్ని ఫీల్డ్ పేర్లు అదృశ్యమవుతాయి, కానీ స్కీమా ప్రకారం డీసీరియలైజేషన్ సమయంలో తిరిగి సృష్టించబడతాయి.
మెర్కిలైజేషన్
ఈ SSZ శ్రేణీకరించబడిన వస్తువును ఆ తర్వాత మెర్కిలైజ్ చేయవచ్చు - అంటే అదే డేటా యొక్క మెర్కిల్ వృక్షం ప్రాతినిధ్యంగా మార్చబడుతుంది. ముందుగా, శ్రేణీకరించబడిన వస్తువులోని 32-బైట్ ముక్కల సంఖ్య నిర్ణయించబడుతుంది. ఇవి వృక్షం యొక్క "ఆకులు (leaves)". ఆకుల మొత్తం సంఖ్య 2 యొక్క ఘాతంగా ఉండాలి, తద్వారా ఆకులను కలిపి హాషింగ్ చేయడం ద్వారా చివరకు ఒకే హాష్-ట్రీ-రూట్ (hash-tree-root) ఉత్పత్తి అవుతుంది. సహజంగా ఇలా లేకపోతే, 32 బైట్ల సున్నాలను కలిగి ఉన్న అదనపు ఆకులు జోడించబడతాయి. రేఖాచిత్రంగా:
హాష్ ట్రీ రూట్
/ \
/ \
/ \
/ \
1 మరియు 2 ఆకుల హాష్ 3 మరియు 4 ఆకుల హాష్
/ \ / \
/ \ / \
/ \ / \
ఆకు1 ఆకు2 ఆకు3 ఆకు4
పై ఉదాహరణలో ఉన్నట్లుగా వృక్షం యొక్క ఆకులు సహజంగా సమానంగా పంపిణీ చేయబడని సందర్భాలు కూడా ఉన్నాయి. ఉదాహరణకు, ఆకు 4 అనేది మెర్కిల్ వృక్షానికి అదనపు "లోతు (depth)" జోడించాల్సిన బహుళ మూలకాలను కలిగి ఉన్న కంటైనర్ కావచ్చు, ఇది అసమాన వృక్షాన్ని సృష్టిస్తుంది.
ఈ వృక్ష మూలకాలను ఆకు X, నోడ్ X మొదలైనవిగా సూచించడానికి బదులుగా, మనం వాటికి సాధారణీకరించిన సూచికలను ఇవ్వవచ్చు, రూట్ = 1 తో ప్రారంభించి ప్రతి స్థాయిలో ఎడమ నుండి కుడికి లెక్కించవచ్చు. పైన వివరించిన సాధారణీకరించిన సూచిక ఇదే. శ్రేణీకరించబడిన జాబితాలోని ప్రతి మూలకం 2**depth + idx కు సమానమైన సాధారణీకరించిన సూచికను కలిగి ఉంటుంది, ఇక్కడ idx అనేది శ్రేణీకరించబడిన వస్తువులో దాని సున్నా-సూచిక స్థానం మరియు లోతు అనేది మెర్కిల్ వృక్షంలోని స్థాయిల సంఖ్య, దీనిని మూలకాల (ఆకుల) సంఖ్య యొక్క బేస్-టూ లాగరిథమ్గా నిర్ణయించవచ్చు.
సాధారణీకరించిన సూచికలు
సాధారణీకరించిన సూచిక అనేది బైనరీ మెర్కిల్ వృక్షంలోని నోడ్ను సూచించే పూర్ణాంకం, ఇక్కడ ప్రతి నోడ్ 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...
ఈ ప్రాతినిధ్యం మెర్కిల్ వృక్షంలోని ప్రతి డేటా ముక్కకు నోడ్ సూచికను ఇస్తుంది.
మల్టీప్రూఫ్లు
ఒక నిర్దిష్ట మూలకాన్ని సూచించే సాధారణీకరించిన సూచికల జాబితాను అందించడం ద్వారా దానిని హాష్-ట్రీ-రూట్కు వ్యతిరేకంగా ధృవీకరించడానికి అనుమతిస్తుంది. ఈ రూట్ అనేది మనం అంగీకరించిన వాస్తవికత యొక్క వెర్షన్. మనకు అందించబడిన ఏదైనా డేటాను మెర్కిల్ వృక్షంలో సరైన స్థానంలో (దాని సాధారణీకరించిన సూచిక ద్వారా నిర్ణయించబడుతుంది) చొప్పించడం ద్వారా మరియు రూట్ స్థిరంగా ఉంటుందని గమనించడం ద్వారా ఆ వాస్తవికతకు వ్యతిరేకంగా ధృవీకరించవచ్చు. ఒక నిర్దిష్ట సాధారణీకరించిన సూచికల సెట్ యొక్క కంటెంట్లను ధృవీకరించడానికి అవసరమైన కనీస నోడ్ల సెట్ను ఎలా లెక్కించాలో చూపే ఫంక్షన్లు స్పెక్ ఇక్కడ (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