برای اینکه در نهایت به یک بلاک چین و نه فقط یک پایگاه داده ختم شود، باید 3 عنصر مهم را به پروژه خود اضافه کنیم:
- شرح ساختار داده بلوک و روش ها
- شرح ساختار داده ها و روش های تراکنش
- توابع بلاک چین که بلوک ها را در یک پایگاه داده ذخیره می کند و آنها را بر اساس هش یا ارتفاع (یا چیز دیگری) در آنجا پیدا می کند.
این دومین مقاله در مورد بلاک چین برای صنعت است، اولین مقاله
با یادآوری سوالاتی که خوانندگان در مورد مقاله قبلی این مجموعه از من پرسیدند، لازم به ذکر است: در این مورد، پایگاه داده LevelDB برای ذخیره داده های بلاک چین استفاده می شود، اما هیچ چیز مانع از استفاده شما از هیچ، مثلاً MySQL نمی شود. حال بیایید به ساختار این داده ها نگاه کنیم.
بیایید با معاملات شروع کنیم:
در اینجا ساختار داده آن است:
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(bytes []byte) در Build() و Check() استفاده می شود تا هش تراکنش تولید شده با هش تراکنش های تولید شده از برنامه های جاوا اسکریپت سازگار باشد.
متد Build() هش تراکنش را به صورت زیر تنظیم می کند: tx.TxHash = preByteHash(tx.ToBytes()).
متد رشته ToJSON() یک تراکنش را به یک رشته JSON تبدیل می کند.
روش خطای FromJSON(data []byte) یک تراکنش را از فرمت JSON که به عنوان یک تکه بایت ارسال شده بارگیری می کند.
متد Check()bool هش حاصل از فیلد هش تراکنش را با هش به دست آمده در نتیجه هش کردن این تراکنش (با نادیده گرفتن فیلد هش) مقایسه می کند.
تراکنش ها به بلوک اضافه می شوند:
ساختار داده بلوک حجیم تر است:
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 یک هش کلی از تراکنش ها است.
مرکل روت ریشه درخت مرکل است.
علاوه بر این در فیلدها کلید عمومی سازنده بلوک، امضای سازنده، نسخه بلوک، تعداد تراکنشهای بلوک و خود این تراکنشها وجود دارد.
بیایید به روش های آن نگاه کنیم:
برای ایجاد یک بلوک، از تابع ()block استفاده کنید. نوع بلوک نیز از ثابت بسته انواع تنظیم می شود:
b.DataType = types.BLOCK_TYPE.
روش AddTx(tx *transaction.TX) یک تراکنش را به یک بلوک اضافه می کند.
متد Build() مقادیر را در فیلدهای بلوک بارگذاری می کند و هش فعلی آن را تولید و تنظیم می کند.
متد ToBytesHeader() []byte هدر بلوک (بدون تراکنش) را به یک تکه بایت تبدیل می کند.
متد رشته ToJSON () بلوک را به فرمت JSON در یک نمایش رشته ای از داده ها تبدیل می کند.
روش خطای FromJSON(data []byte) داده ها را از JSON در یک ساختار بلوکی بارگیری می کند.
متد Check() bool یک هش بلوک تولید می کند و آن را با آنچه در فیلد هش بلوک مشخص شده مقایسه می کند.
متد رشته ()GetTxsHash کل هش تمام تراکنشهای بلوک را برمیگرداند.
متد GetMerkleRoot() ریشه درخت Merkle را برای تراکنش های یک بلوک مشخص می کند.
روش Sign (رشته privk) یک بلوک را با کلید خصوصی سازنده بلوک امضا می کند.
متد SetHeight(height int) ارتفاع بلوک را در قسمت ساختار بلوک می نویسد.
متد GetHeight() int ارتفاع بلوک را همانطور که در فیلد مربوطه ساختار بلوک مشخص شده است برمی گرداند.
متد ToGOBBytes() []byte یک بلوک را در قالب GOB رمزگذاری می کند و آن را به عنوان یک تکه بایت برمی گرداند.
روش خطای FromGOBBytes(data []byte) داده های بلوک را از برش بایت ارسال شده در قالب GOB به ساختار بلوک می نویسد.
متد رشته ()GetHash هش بلوک داده شده را برمی گرداند.
متد رشته ()GetPrevHash هش بلوک قبلی را برمی گرداند.
متد SetPublicKey (رشته pubk) کلید عمومی سازنده بلوک را در بلوک می نویسد.
بنابراین، با استفاده از متدهای شی Block، به راحتی میتوانیم آن را به قالبی برای انتقال از طریق شبکه و ذخیره در پایگاه داده LevelDB تبدیل کنیم.
توابع بسته بلاک چین مسئول ذخیره در بلاک چین هستند:
برای انجام این کار، بلوک باید رابط 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() یک wrapper برای db.Cloce() است - پس از کار با توابع بسته برای بستن اتصال به پایگاه داده فراخوانی می شود.
تابع خطای SetTargetBlockHash (رشته هش) هش بلوک فعلی را با کلید مشخص شده توسط ثابت BLOCK_HASH در پایگاه داده می نویسد.
تابع GetTargetBlockHash () (رشته، خطا) هش بلوک فعلی ذخیره شده در پایگاه داده را برمی گرداند.
تابع خطای SetTargetBlockHeight (height int) مقدار ارتفاع بلاک چین برای گره را با کلید مشخص شده توسط ثابت BLOCK_HEIGHT به پایگاه داده می نویسد.
تابع GetTargetBlockHeight () (int, error) ارتفاع بلاک چین را برای یک گره معین ذخیره شده در پایگاه داده برمی گرداند.
تابع Bool CheckBlock (block IBlock) قبل از افزودن این بلوک به بلاک چین، صحت یک بلوک را بررسی می کند.
تابع خطای AddBlock(block IBlock) یک بلوک به زنجیره بلوکی اضافه می کند.
توابع بازیابی و مشاهده بلوک ها در فایل explore.go بسته بلاک چین هستند:
تابع GetBlockByHash (رشته هش) (*block.Block، error) یک شیء بلوک خالی ایجاد می کند، یک بلوک را از پایگاه داده در آن بارگذاری می کند که هش آن به آن ارسال شده است، و یک اشاره گر به آن برمی گرداند.
ایجاد یک بلوک پیدایش توسط تابع خطای Genesis() از فایل genesis.go بسته بلاک چین انجام می شود.
مقاله بعدی در مورد اتصال کلاینت ها به یک گره با استفاده از مکانیسم WebSocket صحبت خواهد کرد.
منبع: www.habr.com