मी माझ्या गो ब्लॉकचेनमध्ये ब्लॉक्स आणि व्यवहार कसे डिझाइन केले

Для того, чтобы в конечном счете получиляся блокчейн, а не просто база данных, нам нужно добавить в свой проект 3 важных элемента:

  • Описание структуры данных и методов блока
  • Описание структуры данных и методов транзакции
  • Функции блокчейна, которые сохраняют блоки в БД и находят их там по их хешу или высоте (или еще как нибудь).

मी माझ्या गो ब्लॉकचेनमध्ये ब्लॉक्स आणि व्यवहार कसे डिझाइन केले

Это вторая статья про блокчейн для промышленности, первая येथे.

Вспоминая вопросы, которые мне задавали читатели к предыдущей статье этого цикла, следует отметить: для хранения данных блокчейна в данном случае используется база данных LevelDB, но ни чего не мешает использовать любую другую, скажем ту же 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(bytes []byte) string применяется в Build() и Check() для совместимости создаваемого хеша транзакций с хешами транзакций генерируемыми из приложений на JavaScript.

Метод Build() задает хеш транзакции следующим образом: tx.TxHash = preByteHash(tx.ToBytes()).

Метод ToJSON() string преобразует транзакцию в JSON строку.

Метод FromJSON(data []byte) error загружает транзакцию из формата JSON, переданного в виде байтового слайса.

Метод Check() bool сравнивает полученных хеш из поля хеша транзакции с хешем, полученным в результате хеширования этой транзакции (без учета поля хеша).

Транзакции добавляются в блок: 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 хранит высоту блока.
Timestamp временную метку.
HeaderSize размер блока в байтах.
PrevBlockHash хеш предыдущего блока, а SelfBlockHash — текущего.
TxsHash — это общий хеш транзакций.
MerkleRoot — корень дерева Меркла.

Далее в полях находится публичный ключ создателя блока, подпись создателя, версия блока, количество транзакций в блоке и собственно сами эти транзакции.

Рассмотрим его методы:
Для создания блока применяется функция block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, которая принимает хеш предыдущего блока и высоту установленную для созданного блока в блокчейне. Также задается тип блока из константы пакета types:

b.DataType = types.BLOCK_TYPE.

Метод AddTx(tx *transaction.TX) добавляет транзакцию в блок.

Метод Build() загружает значения в поля блока и генерирует и устанавливает его текущий хеш.

Метод ToBytesHeader() []byte переводит заголовок блока (без транзакций) в байтовый слайс.

Метод ToJSON() string переводит блок в формат JSON в строковом представлении данных.

Метод FromJSON(data []byte) error загружает данные из JSON в структуру блока.

Метод Check() bool генерирует хеш блока и сравнивает с заданным в поле хеша блока.

Метод GetTxsHash() string возвращает общий хеш всех транзакций в блоке.

Метод GetMerkleRoot() задает корень дерева Меркла для транзакций в блоке.

Метод Sign(privk string) подписывает блок приватным клюем создателя блока.

Метод SetHeight(height int) записывает высоту блока в поле структуры блока.

Метод GetHeight() int возвращает высоту блока так как указано в соответствующем поле структуры блока.

Метод ToGOBBytes() []byte кодирует блок в GOB формат и возвращает его в виде байтового слайса.

Метод FromGOBBytes(data []byte) error записывает данные блока в структуру блока из переданного байтового слайса в формате GOB.

Метод GetHash() string возвращает хеш данного блока.

Метод GetPrevHash() string возвращает хеш предыдущего блока.

Метод SetPublicKey(pubk string) записывает в блок публичный ключ создателя блока.

Таким образом, с помощью методов объекта Block мы можем легко конвертировать его в формат для передачи по сети и сохранения в базу данных LevelDB.

За сохранения в блокчейн отвечают функции пакета 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(hash string) error записывает в БД хеш текущего блока с ключем заданным константой BLOCK_HASH.

Функция GetTargetBlockHash() (string, error) возвращает хеш текущего блока, хранящийся в БД.

Функция SetTargetBlockHeight(height int) error записывает в БД значение высоты блокчейна для ноды с ключем заданным константой BLOCK_HEIGHT.

Функция GetTargetBlockHeight() (int, error) возвращает высоту блокчейна для данной ноды, хранимую в БД.

Функция CheckBlock(block IBlock) bool выполняет проверку блока на корректность перед добавлением этого блока в блокчейн.

Функция AddBlock(block IBlock) error добавляет блок в блокчейн.

Функции для получения и просмотра блоков находятся в файле explore.go пакета blockchain:

Функция GetBlockByHash(hash string) (*block.Block, error) создает пустой объект блока, загружает туда блок из БД хеш которого ей передан и возвращает на него указатель.

Создание блока генезиса осуществляется функцией Genesis() error из файла genesis.go пакета blockchain.

В следующей статье речь пойдет о подключению к ноде клиентов с помощью механизма WebSocket.

स्त्रोत: www.habr.com

एक टिप्पणी जोडा