为了最终产生区块链,而不仅仅是数据库,我们需要在项目中添加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字节)* TX函数。AddTxIn方法(thattxhash []字节,txoutn int,代码[]字节)(* TxIn,错误)将输入添加到事务中。AddTxOut(值int,数据[]字节)(* TxOut,错误)方法将输出添加到事务中。ToBytes()[] byte方法将事务转换为字节片。内部函数preByteHash(字节[]字节)字符串用于Build()和Check()中,以确保创建的事务哈希与JavaScript应用程序生成的事务哈希兼容。Build()方法将事务哈希设置如下:tx.TxHash = preByteHash(tx.ToBytes())。字符串的ToJSON()方法将事务转换为JSON字符串。FromJSON(数据[]字节)错误方法从作为字节片传输的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存储块的高度。时间戳记时间戳记。HeaderSize块大小(以字节为单位)。上一个块的PrevBlockHash哈希,而SelfBlockHash-当前。TxsHash是常见的事务哈希。MerkleRoot-Merkle树的根。字段中的下一个是块的创建者的公钥,创建者的签名,块的版本,块中的事务数量以及这些事务本身。考虑其方法:block.NewBlock()函数用于创建一个块:NewBlock(prevBlockHash字符串,height int)* Block,它获取前一个块的哈希值以及在区块链中为所创建的块设置的高度。还设置了来自types包常量的块类型:b.DataType = types.BLOCK_TYPE.
AddTx方法(tx * transaction.TX)将事务添加到块中。Build()方法将值加载到块的字段中并生成并设置其当前哈希值。ToBytesHeader()[] byte方法将块头(无事务)转换为字节片。字符串的ToJSON()方法以数据的字符串表示形式将块转换为JSON格式。FromJSON(数据[]字节)错误方法将数据从JSON加载到块结构中。Check()bool方法生成一个块哈希并将其与在块哈希字段中指定的哈希进行比较。GetTxsHash()字符串方法返回该块中所有事务的公共哈希。GetMerkleRoot()方法设置块中事务的Merkle树的根。Sign(私有字符串)方法使用块创建者的私钥对块进行签名。SetHeight(高度整数)方法将块高度写入块结构字段。GetHeight()int方法返回块的高度,如块结构的相应字段中所示。ToGOBBytes()[]字节方法以GOB格式编码该块,并将其作为字节片返回。FromGOBBytes(数据[]字节)错误方法将块数据从发送的字节片中以GOB格式写入块结构。GetHash()方法字符串返回此块的哈希。GetPrevHash()方法字符串返回上一个块的哈希。SetPublicKey(公共字符串)方法将块创建者的公钥写入该块。因此,使用Block对象的方法,我们可以轻松地将其转换为通过网络传输的格式,并将其保存到LevelDB数据库。区块
链软件包功能负责保存到区块链: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(高度整数)错误函数将使用BLOCK_HEIGHT常量指定的键将节点的区块链高度值写入数据库。GetTargetBlockHeight()(int,error)函数返回存储在数据库中给定节点的区块链高度。CheckBlock(块IBlock)布尔函数在将该块添加到区块链之前检查该块的正确性。AddBlock(块IBlock)错误函数将一个块添加到区块链。接收和查看块的功能位于区块链程序包的explorer.go文件中:GetBlockByHash(哈希字符串)(*块。块,错误)函数创建一个空块对象,从数据库中加载一个块,并将其哈希值传递给该块并返回指向该块的指针。创世块是由来自区块链软件包genesis.go文件的Genesis()错误函数创建的。在下一篇文章中,我们将讨论使用WebSocket机制连接到客户端节点。