Comment j'ai conçu des blocs et des transactions dans ma blockchain en Go

Pour qu'un véritable blockchain soit créé, et pas simplement une base de données, nous devons ajouter trois éléments importants à notre projet :

  • Description de la structure des donnĂ©es et des mĂ©thodes du bloc
  • Description de la structure des donnĂ©es et des mĂ©thodes de transaction
  • Fonctions de blockchain qui conservent les blocs dans la base de donnĂ©es et les trouvent par leur hachage ou leur hauteur (ou de toute autre maniĂšre).

Comment j'ai conçu des blocs et des transactions dans ma blockchain en Go

Ceci est le deuxiĂšme article sur la blockchain pour l'industrie, le premier ici.

En se remĂ©morant les questions que les lecteurs m'ont posĂ©es concernant l'article prĂ©cĂ©dent de cette sĂ©rie, il convient de noter : pour le stockage des donnĂ©es de blockchain, nous utilisons dans ce cas une base de donnĂ©es LevelDB, mais rien ne nous empĂȘche d'utiliser n'importe quelle autre, disons MySQL. Passons maintenant Ă  la structure de ces donnĂ©es.

Commençons par les transactions : github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Voici sa structure de données :

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
}

Dans TX, sont stockĂ©s le type de donnĂ©es (pour la transaction 2), le hachage de cette transaction, le type de la transaction elle-mĂȘme, l'horodatage, ainsi que les entrĂ©es et sorties. Les entrĂ©es TxIn stockent le hachage de la transaction Ă  laquelle elles font rĂ©fĂ©rence, le numĂ©ro de cette sortie et le bytecode, tandis que les sorties TxOut stockent une valeur et Ă©galement un bytecode.

Regardons maintenant quelles actions une transaction peut effectuer sur ses données, c'est-à-dire examinons les méthodes.

La fonction transaction.NewTransaction(txtype byte) *TX sert à créer une transaction.

La méthode AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) ajoute une entrée à la transaction.

La méthode AddTxOut(value int, data []byte) (*TxOut, error) ajoute une sortie à la transaction.

La méthode ToBytes() []byte transforme la transaction en un tableau de bytes.

La fonction interne preByteHash(bytes []byte) string est utilisée dans Build() et Check() pour garantir la compatibilité du hachage de la transaction créée avec les hachages des transactions générés par les applications en JavaScript.

La méthode Build() définit le hachage de la transaction comme suit : tx.TxHash = preByteHash(tx.ToBytes()).

La méthode ToJSON() string convertit la transaction en une chaßne JSON.

La méthode FromJSON(data []byte) error charge la transaction à partir du format JSON, transmis sous forme de tranche de bytes.

La méthode Check() bool compare le hachage obtenu du champ de hachage de la transaction avec le hachage obtenu suite au hachage de cette transaction (sans tenir compte du champ de hachage).

Les transactions sont ajoutées au bloc : github.com/Rusldv/bcstartup/blob/master/block/builder.go

La structure de données du bloc est plus complexe :

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 conserve le type de donnĂ©es, qui permet au nƓud de distinguer un bloc d'une transaction ou d'autres donnĂ©es. Pour un bloc, cette valeur est Ă©gale Ă  1.

BlockHeight conserve la hauteur du bloc.
Timestamp est le marqueur de temps.
HeaderSize est la taille du bloc en octets.
PrevBlockHash est le hachage du bloc précédent, tandis que SelfBlockHash est le hachage du bloc actuel.
TxsHash est le hachage global des transactions.
MerkleRoot est la racine de l'arbre de Merkle.

Ensuite, les champs contiennent la clĂ© publique du crĂ©ateur du bloc, la signature du crĂ©ateur, la version du bloc, le nombre de transactions dans le bloc et bien sĂ»r ces transactions elles-mĂȘmes.

Examinons ses méthodes :
Pour créer un bloc, on utilise la fonction block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, qui prend le hachage du bloc précédent et la hauteur définie pour le bloc créé dans la blockchain. On définit également le type de bloc depuis la constante du paquet types :

b.DataType = types.BLOCK_TYPE.

La méthode AddTx(tx *transaction.TX) ajoute une transaction au bloc.

La méthode Build() charge les valeurs dans les champs du bloc et génÚre et établit son hachage actuel.

La mĂ©thode ToBytesHeader() []byte convertit l'en-tĂȘte du bloc (sans transactions) en un tableau d'octets.

La méthode ToJSON() string convertit le bloc en format JSON en représentation textuelle des données.

La méthode FromJSON(data []byte) error charge des données JSON dans la structure du bloc.

La méthode Check() bool génÚre le hachage du bloc et le compare avec celui spécifié dans le champ du hachage du bloc.

La méthode GetTxsHash() string retourne le hachage global de toutes les transactions dans le bloc.

La méthode GetMerkleRoot() définit la racine de l'arbre de Merkle pour les transactions dans le bloc.

La méthode Sign(privk string) signe le bloc avec la clé privée du créateur du bloc.

La méthode SetHeight(height int) enregistre la hauteur du bloc dans le champ de la structure du bloc.

La méthode GetHeight() int retourne la hauteur du bloc telle qu'indiquée dans le champ correspondant de la structure du bloc.

La méthode ToGOBBytes() []byte encode le bloc au format GOB et le retourne sous forme de tableau d'octets.

La méthode FromGOBBytes(data []byte) error enregistre les données du bloc dans la structure du bloc à partir du tableau d'octets fourni au format GOB.

La méthode GetHash() string retourne le hachage de ce bloc.

La méthode GetPrevHash() string retourne le hachage du bloc précédent.

La méthode SetPublicKey(pubk string) enregistre dans le bloc la clé publique du créateur du bloc.

Ainsi, grùce aux méthodes de l'objet Block, nous pouvons facilement le convertir au format pour le transmettre sur le réseau et le stocker dans une base de données LevelDB.

Les fonctions du paquet blockchain sont responsables de la sauvegarde dans la blockchain : github.com/Rusldv/bcstartup/tree/master/blockchain

Pour cela, le bloc doit implémenter l'interface IBlock :

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

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

}

La connexion à la base de données est créée une fois lors de l'initialisation du paquet dans la fonction init() :

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

CloseDB() est une enveloppe pour db.Close() — elle est appelĂ©e aprĂšs avoir travaillĂ© avec les fonctions du paquet pour fermer la connexion Ă  la base de donnĂ©es.

La fonction SetTargetBlockHash(hash string) error enregistre dans la base de données le hachage du bloc actuel avec la clé définie par la constante BLOCK_HASH.

La fonction GetTargetBlockHash() (string, error) retourne le hachage du bloc actuel, stocké dans la base de données.

La fonction SetTargetBlockHeight(height int) error enregistre dans la base de donnĂ©es la valeur de la hauteur de la blockchain pour le nƓud avec la clĂ© dĂ©finie par la constante BLOCK_HEIGHT.

La fonction GetTargetBlockHeight() (int, error) retourne la hauteur de la blockchain pour le nƓud donnĂ©, stockĂ©e dans la base de donnĂ©es.

La fonction CheckBlock(block IBlock) bool effectue une vérification du bloc pour en assurer la validité avant de l'ajouter à la blockchain.

La fonction AddBlock(block IBlock) error ajoute le bloc Ă  la blockchain.

Les fonctions pour obtenir et visualiser les blocs se trouvent dans le fichier explore.go du paquet blockchain :

La fonction GetBlockByHash(hash string) (*block.Block, error) crée un objet de bloc vide, charge le bloc correspondant de la base de données dont le hachage lui a été transmis et retourne un pointeur vers celui-ci.

La création d'un bloc génésis est effectuée par la fonction Genesis() error du fichier genesis.go du paquet blockchain.

Dans l'article suivant, nous aborderons la connexion des nƓuds clients via le mĂ©canisme WebSocket.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster