在本文中,我将解释如何使用protobuf在hyperledger fabric中序列化和构造数据。Protobuf简化了hyperledger结构中的数据处理和格式化。它使用专门生成的源代码来生成数据,使得在同一个智能合约中轻松地编写和读取数据。
链码和智能合约
在超账本结构中,链码是一个特定的程序,用于处理区块链网络参与者同意的核心业务逻辑。Hyperledger fabric还使用称为artcontract的数据格式技术,该技术是为链码中的特定数据模集定义的。链代码可以有多组智能合约,这些合约控制不同数据模的事务逻辑。简而言之,artcontract管理事务,而链码管理artcontract的部署方式。
例如,如果我们需要在分类账中存储一些用户信息记录,我们需要一个artcontract,它可以定义单个记录所需的数据字段。
用户智能合约
type User struct {
ID string `on:"id"`
Email string `on:"email"`
Name string `on:"name"`
Mobile string `on:"mobile"`
Age string `on:"age"`
}
在artcontract中,有ID、email、name、mobile phone、age和其他与个人用户记录相关的数据字段。同样,如果我们需要存储每个用户的财务记录,我们需要另一个称为财务的智能合约。
金融智能合约
type Financial struct {
ID string `on:"id"`
BankName string `on:"bankName"`
IFSCCode string `on:"ifscCode"`
AccNumber string `on:"accNumber"`
CreatedDate string `on:"createdDate"`
}
这两个artcontract将部署到链码中,并处理两个分类账状态(WorldState和区块链)的交易逻辑。
artcontract主要在world状态下执行put、get、delete和gETHistory。
一。 ;putstate-为每个不同的键创建新对象,或覆盖现有对象。
2。 ;getstate–从分类帐状态中检索具有不同键的对象。
3 ;delstate-从分类帐的世界状态中删除对象。
四。 ;gETHistoryforkey-返回跨时间键的所有事务历史记录。
所有记录都作为世界记录存储在CouchDB中。对象以ON格式存储为键值对。CouchDB可以更快地从数据库查询ON集合。在区块链状态下,所有这些记录都以字节存储,并且是不可变的。
原
Protocol buffer(protobuf)是Google的序列化结构化数据,它独立于语言和平台,具有可扩展的机制。与传统的数据格式(如XML或ON)相比,序列化的结构化数据是以字节为单位编译的,因此它更小、更快、更简单。
为什么使用protobuf?
可见,用户和财务两个智能合约将信息存储在同一个用户账中,即用户存储用户的基本信息,财务存储用户银行账户的详细信息。
但是,如果我们从查询目的的角度来看待智能合约,那么这两个数据集之间就没有关系。我们不能为用户和财务数据模定义与密钥相同的ID,因为分类账数据存储在密钥-值对中,如果出现相同的密钥,则信息将被覆盖。
AMPL;
这两个记录将以两个不同的ID存储在分类帐状态中
为了解决这个问题,protobuf提供了一个更快、更灵活的解决方案。我们只需要编写一个.Proto文件来描述数据结构,在这种情况下,我们要存储的财务数据结构。
结果,protobuf消息格式中的字节结果被直接调用给用户artcontract,财务artcontract被完全删除。
protobuf是如何工作的?
接下来,我们将学习如何设置protobuf编译器并生成protobuf消息格式。
安装
首先,我们需要遵循一定的安装过程来使用protobuf编译器。
go get github.com/golang/protobuf
go get github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
export PATH=$PATH:$GOPATH/bin
现在,安装protobuf编译器
sudo apt install protobuf-compiler
然后,在命令行中键入protoc’应显示“缺少输入文件”,表示protobuf编译器已成功安装。
例子
首先,我们需要建立一个金融体系。原始文件。它由四个字段组成:银行名称、IFSC代码、帐号和创建日期。
financial.proto
syntax="proto3";
package main;
message Financial {
string bankName = 1;
string ifscCode = 2;
string accNumber = 3;
string createdDate = 4;
}
编译proto文件,生成财务信息格式的protobuf数据模文件。
protoc --go_out=. *.proto
您将看到protobuf文件已生成为financial.pb.go。该文件是与proto包兼容的数据模,将用于将proto消息格式转换为字节。
financial.pb.go
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: financial.proto
package main
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
ar _ = proto.Marshal
ar _ = fmt.Errorf
ar _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line like means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Financial struct {
BankName string `protobuf:"bytes,1,opt,name=bankName,proto3" on:"bankName,omitempty"`
IfscCode string `protobuf:"bytes,2,opt,name=ifscCode,proto3" on:"ifscCode,omitempty"`
AccNumber string `protobuf:"bytes,3,opt,name=accNumber,proto3" on:"accNumber,omitempty"`
CreatedDate string `protobuf:"bytes,4,opt,name=createdDate,proto3" on:"createdDate,omitempty"`
XXX_NoUnkeyedLiteral struct{} `on:"-"`
XXX_unrecognized []byte `on:"-"`
XXX_sizecache int32 `on:"-"`
}
func (m *Financial) Reset() { *m = Financial{} }
func (m *Financial) String() string { return proto.CompactTextString(m) }
func (*Financial) ProtoMessage() {
func (*Financial) Descriptor() ([]byte, []int) {
return fileDescriptor_a283ebe7677acfbc, []int{0}
}
func (m *Financial) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Financial.Unmarshal(m, b)
}
func (m *Financial) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Financial.Marshal(b, m, deterministic)
}
func (m *Financial) XXX_Merge(src proto.Message) {
xxx_messageInfo_Financial.Merge(m, src)
}
func (m *Financial) XXX_Size() int {
return xxx_messageInfo_Financial.Size(m)
}
func (m *Financial) XXX_DiscardUnknown() {
xxx_messageInfo_Financial.DiscardUnknown(m)
}
ar xxx_messageInfo_Financial proto.InternalMessageInfo
func (m *Financial) GetBankName() string {
if m != nil {
return m.BankName
}
return ""
}
func (m *Financial) GetIfscCode() string {
if m != nil {
return m.IfscCode
}
return ""
}
func (m *Financial) GetAccNumber() string {
if m != nil {
return m.AccNumber
}
return ""
}
func (m *Financial) GetCreatedDate() string {
if m != nil {
return m.CreatedDate
}
return ""
}
func init() {
proto.RegisterType((*Financial)(nil), "main.Financial")
}
func init() { proto.RegisterFile("financial.proto", fileDescriptor_a283ebe7677acfbc) }
ar fileDescriptor_a283ebe7677acfbc = []byte{
// 136 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0xcb, 0xcc, 0x4b,
0xcc, 0x4b, 0xce, 0x4c, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d, 0xcc,
0xcc, 0x53, 0x6a, 0x66, 0xe4, 0xe2, 0x74, 0x83, 0xc9, 0x08, 0x49, 0x71, 0x71, 0x24, 0x25, 0xe6,
0x65, 0xfb, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xf9, 0x20, 0xb9,
0xcc, 0xb4, 0xe2, 0x64, 0xe7, 0xfc, 0x94, 0x54, 0x09, 0x26, 0x88, 0x1c, 0x8c, 0x2f, 0x24, 0xc3,
0xc5, 0x99, 0x98, 0x9c, 0xec, 0x57, 0x9a, 0x9b, 0x94, 0x5a, 0x24, 0xc1, 0x0c, 0x96, 0x44, 0x08,
0x08, 0x29, 0x70, 0x71, 0x27, 0x17, 0xa5, 0x26, 0x96, 0xa4, 0xa6, 0xb8, 0x24, 0x96, 0xa4, 0x4a,
0xb0, 0x80, 0xe5, 0x91, 0x85, 0x92, 0xd8, 0xc0, 0x4e, 0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff,
0x44, 0x01, 0xf8, 0x14, 0xa5, 0x00, 0
现在,我们将在User artcontract中创建一个额外的数据字段financial。
type User struct {
ID string `on:"id"`
Email string `on:"email"`
Name string `on:"name"`
Mobile string `on:"mobile"`
Age string `on:"age"`
Financial string `on:"financial"`
}
财务信息格式见
financial := AMPLFinancial {
ID: "F1",
BankName: "Hellenic Bank",
IFSCCode: "1234",
AccNumber: "8765",
CreatedDate : "12/12/08,
}
将用户记录添加到分类账时,还可以将财务消息格式添加到同一用户智能合约。
package main
import (
"fmt"
"log"
"github.com/golang/protobuf/proto"
)
func main() {
financial := AMPLFinancial {
BankName: "Hellenic Bank",
IFSCCode: "1234",
AccNumber: "8765",
CreatedDate : "12/12/08,
}
financialdata, err := proto.Marshal(financial)
if err != nil {
log.Fatal("marshaling error: ", err)
}
userdata := AMPLUser {
ID: "1",
Email: "[email protected]",
Name: "James",
Mobile: "8765432",
Age: "34",
Financial: string(financialdata),
}
userDataONaytes, err := on.Marshal(userdata)
if err != nil {
return shim.Error(err.Error())
}
indexName := "id"
userNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{userdata.ID})
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(userNameIndexKey, userDataONaytes)
if err != nil {
return shim.Error(err.Error())
原机分析
解析protobuf数据非常简单,因为它以字节为单位存储记录,使用financial proto可以轻松解析这些记录。
financialByteData, err := proto.Marshal(financialData)
if err != nil {
log.Fatal("marshaling error: ", err)
}
//Parsing the financial byte data
financial := AMPLFinancial{}
err = proto.Unmarshal(financialByteData, financial)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
fmt.Println("BankName : "+financial.GetBankName())
fmt.Println("IFSCCode : "+financial.GetIfscCode())
fmt.Println("AccNumber : "+financial.GetAccNumber())
fmt.Println("CreatedDate : "+financial.GetCreatedDate()
总结
Protobuf简化了数据处理和格式化。它使用特殊生成的源代码来构造数据,这使得在同一个智能合约中轻松地编写和读取数据。
参考
1.https://deelopers.google.com/protocol-buffers
2.https://deelopers.google.com/protocol-buffers/docs/gotutorial
以上是在hyperledger fabric中使用protobu到artcontract的基本概述。
希望你能有所收获!
原始链接:https://hackernoon.com/what-is-protobuf-in-hyperledger-fabric-explained-gk7s32fz
这是CSDN的翻译。请注明转载来源。
文章标题:Hyperledger结构中的Protobuf是什么?
文章链接:https://www.btchangqing.cn/22355.html
更新时间:2020年05月19日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。