كيف صممت الكتل والمعاملات على My Go Blockchain

لكي نصل في نهاية المطاف إلى blockchain وليس مجرد قاعدة بيانات، نحتاج إلى إضافة 3 عناصر مهمة لمشروعنا:

  • وصف بنية بيانات الكتلة وطرقها
  • وصف هيكل البيانات وطرق المعاملات
  • وظائف Blockchain التي تحفظ الكتل في قاعدة بيانات وتجدها هناك من خلال التجزئة أو الارتفاع (أو أي شيء آخر).

كيف صممت الكتل والمعاملات على My Go Blockchain

هذه هي المقالة الثانية حول blockchain للصناعة، الأولى هنا.

تذكر الأسئلة التي طرحها علي القراء حول المقالة السابقة في هذه السلسلة، تجدر الإشارة إلى: في هذه الحالة، يتم استخدام قاعدة بيانات LevelDB لتخزين بيانات blockchain، ولكن لا شيء يمنعك من استخدام أي شيء آخر، على سبيل المثال، MySQL. الآن دعونا نلقي نظرة على هيكل هذه البيانات.

لنبدأ بالمعاملات: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

وهنا بنية البيانات الخاصة به:

type TX struct {
	DataType byte		
	TxHash string 
	TxType byte	
	Timestamp int64		
	INs []TxIn
	OUTs []TxOut
}

type TxIn struct {
	ThatTxHash string
	TxOutN int
	ByteCode string
}

type TxOut struct {
	Value int
	ByteCode string
}

يقوم TX بتخزين نوع البيانات (للمعاملة 2)، وتجزئة تلك المعاملة، ونوع المعاملة نفسها، والطابع الزمني، والمدخلات والمخرجات. تقوم مدخلات TxIn بتخزين تجزئة المعاملة التي تتم الإشارة إلى مخرجاتها، ورقم هذا الإخراج والرمز الثانوي، وتقوم مخرجات TxOut بتخزين بعض القيمة وكذلك الرمز الثانوي.

الآن دعونا نرى ما هي الإجراءات التي يمكن للمعاملة تنفيذها على بياناتها، أي. دعونا نلقي نظرة على الأساليب.

لإنشاء معاملة، استخدم الدالةTransaction.NewTransaction(txtype byte) *TX.

تضيف طريقة AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) مدخلاً إلى المعاملة.

تضيف طريقة AddTxOut(value int, data []byte) (*TxOut, error) مخرجات إلى المعاملة.

تقوم طريقة ToBytes() []byte بتحويل المعاملة إلى شريحة بايت.

يتم استخدام سلسلة preByteHash (بايت [] بايت) للوظيفة الداخلية في Build () وCheck () لجعل تجزئة المعاملة التي تم إنشاؤها متوافقة مع تجزئة المعاملة التي تم إنشاؤها من تطبيقات JavaScript.

تقوم طريقة Build() بتعيين تجزئة المعاملة كما يلي: tx.TxHash = preByteHash(tx.ToBytes()).

تقوم طريقة سلسلة ToJSON() بتحويل المعاملة إلى سلسلة JSON.

تقوم طريقة الخطأ FromJSON(data []byte) بتحميل معاملة من تنسيق JSON الذي تم تمريره كشريحة بايت.

تقارن الطريقة المنطقية Check() التجزئة الناتجة من حقل تجزئة المعاملة مع التجزئة التي تم الحصول عليها نتيجة تجزئة هذه المعاملة (تجاهل حقل التجزئة).

تتم إضافة المعاملات إلى الكتلة: github.com/Rusldv/bcstartup/blob/master/block/builder.go

بنية بيانات الكتلة أكثر ضخامة:

type Block struct {
	DataType byte				
	BlockHeight int					
        Timestamp int64				 
        HeaderSize int					
        PrevBlockHash string				 
        SelfBlockHash string			
	TxsHash string			
	MerkleRoot string
	CreatorPublicKey string			
	CreatorSig string
	Version int
	TxsN int
	Txs []transaction.TX
}

يقوم DataType بتخزين نوع البيانات، وتستخدمه العقدة وتميز الكتلة عن المعاملة أو البيانات الأخرى. بالنسبة للكتلة، هذه القيمة هي 1.

يقوم BlockHeight بتخزين ارتفاع الكتلة.
الطابع الزمني الطابع الزمني.
HeaderSize هو حجم الكتلة بالبايت.
PrevBlockHash هو تجزئة الكتلة السابقة، وSelfBlockHash هو تجزئة الكتلة الحالية.
TxsHash هو تجزئة عامة للمعاملات.
MerkleRoot هو جذر شجرة Merkle.

علاوة على ذلك، يوجد في الحقول المفتاح العام لمنشئ الكتلة، وتوقيع المنشئ، وإصدار الكتلة، وعدد المعاملات في الكتلة، وهذه المعاملات نفسها.

دعونا نلقي نظرة على أساليبه:
لإنشاء كتلة، استخدم وظيفة block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block، الذي يأخذ تجزئة الكتلة السابقة والارتفاع المحدد للكتلة التي تم إنشاؤها في blockchain. يتم أيضًا تعيين نوع الكتلة من ثابت حزمة الأنواع:

b.DataType = types.BLOCK_TYPE.

تضيف طريقة AddTx(tx *transaction.TX) معاملة إلى الكتلة.

تقوم طريقة Build () بتحميل القيم في حقول الكتلة وإنشاء التجزئة الحالية وتعيينها.

تقوم طريقة ToBytesHeader() []byte بتحويل رأس الكتلة (بدون معاملات) إلى شريحة بايت.

تقوم طريقة سلسلة ToJSON() بتحويل الكتلة إلى تنسيق JSON في تمثيل سلسلة للبيانات.

تقوم طريقة الخطأ FromJSON(data []byte) بتحميل البيانات من JSON إلى بنية الكتلة.

تقوم طريقة Check() bool بإنشاء تجزئة كتلة ومقارنتها مع تلك المحددة في حقل تجزئة الكتلة.

تقوم طريقة سلسلة GetTxsHash() بإرجاع إجمالي التجزئة لجميع المعاملات في الكتلة.

تحدد طريقة GetMerkleRoot() جذر شجرة Merkle للمعاملات في الكتلة.

تقوم طريقة Sign (سلسلة خاصة) بتوقيع الكتلة باستخدام المفتاح الخاص لمنشئ الكتلة.

تكتب طريقة SetHeight(height int) ارتفاع الكتلة في حقل بنية الكتلة.

تقوم طريقة GetHeight() int بإرجاع ارتفاع الكتلة كما هو محدد في الحقل المقابل لبنية الكتلة.

يقوم أسلوب ToGOBBytes() []byte بتشفير كتلة بتنسيق GOB وإرجاعها كشريحة بايت.

تقوم طريقة الخطأ FromGOBBytes(data []byte) بكتابة بيانات الكتلة إلى بنية الكتلة من شريحة البايت التي تم تمريرها بتنسيق GOB.

تقوم طريقة سلسلة GetHash () بإرجاع تجزئة الكتلة المحددة.

تقوم طريقة السلسلة GetPrevHash() بإرجاع تجزئة الكتلة السابقة.

تكتب طريقة SetPublicKey (سلسلة pubk) المفتاح العام لمنشئ الكتلة إلى الكتلة.

وبالتالي، باستخدام أساليب كائن Block، يمكننا بسهولة تحويله إلى تنسيق للإرسال عبر الشبكة وحفظه في قاعدة بيانات LevelDB.

وظائف حزمة blockchain مسؤولة عن الحفظ في blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

للقيام بذلك، يجب أن تقوم الكتلة بتنفيذ واجهة IBlock:

type IGOBBytes interface {
	ToGOBBytes() []byte
	FromGOBBytes(data []byte) error
}

type IBlock interface {
	IGOBBytes
	GetHash() string
	GetPrevHash() string
	GetHeight() int
	Check() bool

}

يتم إنشاء اتصال قاعدة البيانات مرة واحدة عند تهيئة الحزمة في الدالة init():

db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).

CloseDB() عبارة عن غلاف لـ db.Cloce() - يتم استدعاؤه بعد العمل مع وظائف الحزمة لإغلاق الاتصال بقاعدة البيانات.

تقوم وظيفة الخطأ SetTargetBlockHash (سلسلة التجزئة) بكتابة تجزئة الكتلة الحالية باستخدام المفتاح المحدد بواسطة ثابت BLOCK_HASH إلى قاعدة البيانات.

تقوم الدالة GetTargetBlockHash() (سلسلة، خطأ) بإرجاع تجزئة الكتلة الحالية المخزنة في قاعدة البيانات.

تكتب وظيفة الخطأ SetTargetBlockHeight(height int) إلى قاعدة البيانات قيمة ارتفاع blockchain للعقدة مع المفتاح المحدد بواسطة ثابت BLOCK_HEIGHT.

تقوم الدالة GetTargetBlockHeight() (int، error) بإرجاع ارتفاع blockchain لعقدة معينة، مخزنة في قاعدة البيانات.

تقوم وظيفة CheckBlock(block IBlock) المنطقية بالتحقق من صحة الكتلة قبل إضافة هذه الكتلة إلى blockchain.

تضيف وظيفة الخطأ AddBlock(block IBlock) كتلة إلى blockchain.

توجد وظائف استرداد الكتل وعرضها في ملف explore.go الخاص بحزمة blockchain:

تقوم وظيفة GetBlockByHash (سلسلة التجزئة) (*block.Block، خطأ) بإنشاء كائن كتلة فارغ، وتحميل كتلة إليه من قاعدة البيانات، وتم تمرير التجزئة إليه، وإرجاع مؤشر إليه.

يتم إنشاء كتلة التكوين بواسطة وظيفة الخطأ Genesis() من ملف Genesis.go الخاص بحزمة blockchain.

ستتحدث المقالة التالية عن توصيل العملاء بالعقدة باستخدام آلية WebSocket.

المصدر: www.habr.com

إضافة تعليق