Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Hyperledger Fabric enables CouchDB to be a state database

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)06/01 Report--

Hyperledger Fabric enables CouchDB as a state database

one。 Overview 1. Data request stream

The super ledger uses the endorsement / consensus model, and the simulation execution and block verification are performed separately in the nodes of different roles. Simulation execution is concurrent, which improves scalability and throughput:

Endorsement node: simulated execution chain code Peer node: verify the transaction and submit

two。 Super ledger storage element

The super ledger contains the following elements:

Account number: quickly query which account data exist: actual block data storage block index: quick query block / transaction status data: the latest world status data history data: tracking key history

Each Peer node maintains four DB, which are:

IdStore: store ChainID state database (StateDB): store world state history database (HistoryDB): store Key version change block index library (BlockIndex): store Block index

3. Status database

Optional types of state databases include LevelDB and CouchDB. LevelDB is a default key / value state database embedded in the peer process, and CouchDB is an optional external state database. Like the LevelDB key / value store, CouchDB can store any binary data modeled in chaincode (CouchDB attachment functions are used internally for non-json binary data). However, when chaincode values (for example, assets) are modeled as JSON data, CouchDB supports rich queries against chaincode data as a store of JSON documents.

Both LevelDB and CouchDB support core chaincode operations, such as getting and setting a key (asset) and querying based on the key. Keys can be queried through range, and key combinations can be modeled to support equivalent queries for multiple parameters. For example, as the owner's key combination, the asset id can be used to query all assets owned by an entity. These key-based queries can be used for read-only queries against the ledger and transactions for updating the general ledger.

If you model an asset as JSON and use CouchDB, you can use the CouchDB JSON query language in chaincode to perform complex rich queries on chaincode data values that are helpful in understanding what's on the ledger. For these types of queries, the transaction protocol response is usually useful to the client application, but is not usually committed to the sorting service as a transaction. In fact, there is no guarantee of the stability of the result set between chaincode execution and rich query submission time, so it is not appropriate to use the results of a rich query to perform the final transaction update operation, unless the stability of the result set between chaincode execution time and commit time can be guaranteed, or potential changes in subsequent transactions can be handled. For example, if a rich query is executed against all assets owned by Alice and transferred to Bob, then a new asset may be assigned to Alice by another transaction, which is another transaction between chaincode execution time and commit time, and this "virtual value" may be missed in the process.

CouchDB runs with peer as a separate database process, so there are additional considerations in terms of setup, management, and operation. We can consider starting with the default embedded LevelDB, and if we need additional complex rich queries, we can move to CouchDB. It is a good practice to model chaincode asset data as JSON so that we can execute the complex rich queries we need in the future.

two。 Enable CouchDB

This paper uses the relevant components and resources of fabric-samples in Hyperledger Fabric1.2 to start CouchDB services through Docker in the test environment (fabric-samples/chaincode-docker-devmode).

1. Configure CouchDB startup information

Reference: fabric-samples/first-network/docker-compose-couch.yaml

Couchdb0: container_name: couchdb0 image: hyperledger/fabric-couchdb # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. Environment:-COUCHDB_USER=-COUCHDB_PASSWORD= # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, # for example map it to utilize Fauxton User Interface in dev environments. Ports:-"5984" networks:-byfn

Modifying: adding and modifying at the end of fabric-samples/chaincode-docker-devmode/docker-compose-simple.yaml

Couchdb: container_name: couchdb image: hyperledger/fabric-couchdb # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. Environment:-COUCHDB_USER=-COUCHDB_PASSWORD= # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, # for example map it to utilize Fauxton User Interface in dev environments. Ports:-"5984" 2. Configure CouchDB connection information

Reference fabric-samples/first-network/docker-compose-couch.yaml

Peer0.org1.example.com: environment:-CORE_LEDGER_STATE_STATEDATABASE=CouchDB-CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984 # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD # provide the credentials for ledger to connect to CouchDB. The username and password must # match the username and password set for the associated CouchDB. -CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=-CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= depends_on:-couchdb0

Modify: peer module in fabric-samples/chaincode-docker-devmode/docker-compose-simple.yaml

Before modification

Peer: container_name: peer image: hyperledger/fabric-peer environment:-CORE_PEER_ID=peer-CORE_PEER_ADDRESS=peer:7051-CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer:7051-CORE_PEER_LOCALMSPID=DEFAULT-CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock-CORE_LOGGING_LEVEL=DEBUG-CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp volumes:-/ var/ Run/:/host/var/run/ -. / msp:/etc/hyperledger/msp working_dir: / opt/gopath/src/github.com/hyperledger/fabric/peer command: peer node start-- peer-chaincodedev=true-o orderer:7050 ports:-7051 peer node start-7053 depends_on:-orderer

After modification

Peer: container_name: peer image: hyperledger/fabric-peer environment:-CORE_PEER_ID=peer-CORE_PEER_ADDRESS=peer:7051-CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer:7051-CORE_PEER_LOCALMSPID=DEFAULT-CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock-CORE_LOGGING_LEVEL=DEBUG-CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp-CORE_LEDGER_STATE_STATEDATABASE=CouchDB -CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984-CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=-CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= volumes:-/ var/run/:/host/var/run/ -. / msp:/etc/hyperledger/msp working_dir: / opt/gopath/src/github.com/hyperledger/fabric/peer command: peer node start-- peer-chaincodedev=true-o orderer:7050 ports: -7051-7053 depends_on:-orderer-couchdb

Pay attention to the format of the JSON file and the consistency of configuration information, such as couchdb name, etc.

3. Launch the test environment # docker-compose- f docker-compose-simple.yaml up-d # docker container ls

three。 Write chain code 1. Code structure

Code package: testdb

Code file

Domain.go / / data structure code main.go / / business test code 2. Data structure package maintype BillStruct struct {ObjectType string `json: "DocType" `/ object type definition BillInfoID string `json: "BillInfoID"` / / ticket ID BillInfoAmt string `json: "BillInfoAmt" `/ / ticket amount BillInfoType string `json: "BillInfoType"` / / ticket type BillIsseData string `json: "BillIsseData" `/ / issue date BillDueDate string `json: "BillDueDate"` / / maturity date HoldrAcct string `json: "HoldrAcct" `/ / ticket holder name HoldrCmID string `json: "HoldrCmID"` / / ticket holder ID WaitEndroseAcct string `json: "WaitEndroseAcct" `/ / endorser name WaitEndorseCmID string `json: "WaitEndorseCmID"` / / endorser ID} 3. Test code

Please read the comments carefully. There is no description of code segmentation here.

Package mainimport ("github.com/hyperledger/fabric/core/chaincode/shim", "fmt", "github.com/hyperledger/fabric/protos/peer", "encoding/json", "bytes") / / define the structure CouchDBChaincode Init method func (t * CouchDBChaincode) Init (stub shim.ChaincodeStubInterface) peer.Response {return shim.Success (nil)} / / override shim.ChaincodeStubInterface interface Invoke method func (t * CouchDBChaincode) Invoke (stub shim.ChaincodeStubInterface) peer.Response {/ / get user intention and parameter fun as shim.ChaincodeStubInterface implementation class object type CouchDBChaincode struct {} / rewrite Init interface Args: = stub.GetFunctionAndParameters () / / determine which implementation function to use according to the user's intention if fun = = "billInit" {return billInit (stub)} else if fun = = "queryBills" {return queryBills (stub, args)} else if fun = = "queryWaitBills" {return queryWaitBills (stub, args)} / / if the user's intention does not conform to the above Make an error prompt return shim.Error ("illegal operation The specified function name is invalid ")} / / billInit function: initialize ticket data func billInit (stub shim.ChaincodeStubInterface) peer.Response {/ * define the first ticket: holder name: AAA bearer ID:AID endorser name: no endorser ID: no * / billA: = BillStruct {ObjectType:" billObj ", BillInfoID:" POC001 ", BillInfoAmt:" 1000 " BillInfoType: "111l", BillIsseData: "20180501", BillDueDate: "20180508", HoldrAcct: "AAA", HoldrCmID: "AID", WaitEndroseAcct: ", WaitEndorseCmID:",} / / serialize the bill through the json.Marshal method billAByte _: = json.Marshal (billA) / / Storage serialized byte array err: = stub.PutState (billA.BillInfoID, billAByte) if err! = nil {return shim.Error ("failed to initialize the first ticket:" + err.Error ())} billB: = BillStruct {ObjectType: "billObj", BillInfoID: "POC002" via the stub.PutState method BillInfoAmt: "1000", BillInfoType: "111l", BillIsseData: "20180501", BillDueDate: "20180508", HoldrAcct: "AAA", HoldrCmID: "AID", WaitEndroseAcct: "BBB", WaitEndorseCmID: "BID",} billBByte, _: = json.Marshal (billB) err = stub.PutState (billB.BillInfoID BillBByte) if err! = nil {return shim.Error ("failed to initialize the second ticket:" + err.Error ())} billC: = BillStruct {ObjectType: "billObj", BillInfoID: "POC003", BillInfoAmt: "1000", BillInfoType: "1000", BillIsseData: "20180501", BillDueDate: "20180508" HoldrAcct: "BBB", HoldrCmID: "BID", WaitEndroseAcct: "CCC", WaitEndorseCmID: "CID",} billCByte, _: = json.Marshal (billC) err = stub.PutState (billC.BillInfoID) BillCByte) if err! = nil {return shim.Error ("failed to initialize the third ticket:" + err.Error ())} billD: = BillStruct {ObjectType: "billObj", BillInfoID: "POC004", BillInfoAmt: "1000", BillInfoType: "1000", BillIsseData: "20180501", BillDueDate: "20180508" HoldrAcct: "CCC", HoldrCmID: "CID", WaitEndroseAcct: "BBB", WaitEndorseCmID: "BID",} billDByte, _: = json.Marshal (billD) err = stub.PutState (billD.BillInfoID) BillDByte) if err! = nil {return shim.Error ("failed to initialize the fourth ticket:" + err.Error ())} return shim.Success ([] byte ("all tickets initialized successfully")} / / queryBills function: batch query the ticket holding list of the specified user func queryBills (stub shim.ChaincodeStubInterface) Args [] string) peer.Response {/ / determine whether a parameter is passed in if len (args)! = 1 {return shim.Error ("the ticket holder's certificate number must be specified")} / / take the first parameter as the user ID holdrCmID: = args [0] / * concatenate the CouchDB query string into a JSON string The format is as follows: {"selector": {"docType": "billObj", "HoldrCmID": "% s"} * / queryString: = fmt.Sprintf ("{\" selector\ ": {\" DocType\ ":\" billObj\ ",\" HoldrCmID\ ":\"% s\ "}}" HoldrCmID) / / perform data query operation through custom getBillByQueryString function result, err: = getBillByQueryString (stub QueryString) if err! = nil {return shim.Error ("error occurred when querying the ticket holder's ticket list in batches based on the holder's certificate number" + err.Error ()} return shim.Success (result)} / / queryWaitBills function: batch query the list of bills to be endorsed by the specified user func queryWaitBills (stub shim.ChaincodeStubInterface) Error) {/ / get the iterator through the stub.GetQueryResult method, err: = stub.GetQueryResult (queryString) if err! = nil {return nil Err: = iterator.Next () if err! = nil {return nil, err} if isSplit {buffer.WriteString (" ")} / / define format / / key:result.key result.Value buffer.WriteString (" key: ") buffer.WriteString (result.Key) buffer.WriteString (", value: ") buffer.WriteString (string (result.Value)) / / after getting the first value, set isSplit to true Used to split isSplit = true} / / return the byte type return buffer.Bytes () of the buffer object with the second value, nil} func main () {/ / startup chain code CouchDBChaincode err: = shim.Start (new (CouchDBChaincode)) / / if an error is reported, the error message if err! = nil {fmt.Errorf (err.Error ())} four. Install chain code 1. Upload chain code

Upload chain code package testdb to: fabric-samples/chaincode

# ls / home/bruce/hyfa/fabric-samples/chaincode/testdb/ domain.go main.go2. Compile chain code # cd / home/bruce/hyfa/fabric-samples/chaincode/testdb/# go build # ls domain.go main.go testdb3. Start chain code

Enter the chaincode container to operate

# docker container exec-it chaincode bash # enter the chaincode container to operate # cd testdb/# CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=testCouchDB:1.0. / testdb2018-08-05 10 UTC 337. [shim] SetupChaincodeLogging-> INFO 001 Chaincode log level not provided; defaulting to: INFO2018-08-05 10 INFO2018 33 UTC [shim] SetupChaincodeLogging-> INFO 002 Chaincode (build level:) starting up. 4. Installation and instantiation of chain codes

Enter the cli container to operate

# docker container exec-it cli bash# peer chaincode install-n testCouchDB-v 1.0-p chaincodedev/chaincode/testdb# peer chaincode instantiate-n testCouchDB-v 1.0-C myc-c'{"Args": ["init"]}'if there is an update, please use the following command # peer chaincode install-n testCouchDB-v 1.1-p chaincodedev/chaincode/testdb# peer chaincode upgrade-n testCouchDB-v 1.1-C myc-c'{"Args": ["init"]}'V. Test chain code 1.

Key: POC001, value: {"BillDueDate": "20180508", "BillInfoAmt": "1000", "BillInfoID": "POC001", "BillInfoType": "111l", "BillIsseData": "20180501", "HoldrAcct": "AAA", "HoldrCmID": "AID", "WaitEndorseCmID": "", "WaitEndroseAcct": "," docType ":" billObj "} Key: POC002, value: {"BillDueDate": "20180508", "BillInfoAmt": "1000", "BillInfoID": "POC002", "BillInfoType": "20180501", "HoldrAcct": "AAA", "HoldrCmID": "AID", "WaitEndorseCmID": "BID", "WaitEndroseAcct": "BBB", "docType": "billObj"}

In the query results, you can see the delimiters we defined.

3. Query specified user pending endorsement ticket # peer chaincode query-n testCouchDB-C myc-c'{"Args": ["queryWaitBills", "BID"]}'

Key: POC002, value: {"BillDueDate": "20180508", "BillInfoAmt": "1000", "BillInfoID": "POC002", "BillInfoType": "20180501", "HoldrAcct": "AAA", "HoldrCmID": "AID", "WaitEndorseCmID": "BID", "WaitEndroseAcct": "BBB", "docType": "billObj"} Key: POC004, value: {"BillDueDate": "20180508", "BillInfoAmt": "1000", "BillInfoID": "POC004", "BillInfoType": "20180501", "HoldrAcct": "CCC", "HoldrCmID": "CID", "WaitEndorseCmID": "BID", "WaitEndroseAcct": "BBB", "docType": "billObj"}

In addition, with regard to LevelDB,CouchDB or MongoDB, we may adopt different database types according to the version of Hyperledger Fabric in the future. We will wait and see. The only thing we can do now is to use Hyperledger Fabric under the existing resources to create maximum business value for business scenarios.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report