Fabric: Bereitstellung und Ausführung von Chaincode

Hyperledger Fabric:V2.5.4

schreibe zuerst

Referenz für die Verwendung von Fabric zum Aufbau eines benutzerdefinierten Netzwerks:https://blog.csdn.net/yeshang_lady/article/details/134113296
Verwenden von Fabric Reference zum Erstellen eines Anwendungskanals:https://blog.csdn.net/yeshang_lady/article/details/134668458
Als Nächstes stellen wir vor, wie So erstellen Sie einen Anwendungskanal in einem benutzerdefinierten Netzwerk. Stellen Sie Chaincode auf dem Kanal bereit und führen Sie ihn aus.

1 Chaincode-Bereitstellung

Die Bereitstellung von Kettencode in Fabric umfasst im Allgemeinen die folgenden Schritte: Kettencode schreiben – Kettencode verpacken – Kettencode installieren – Kettencode instanziieren – Kettencode bereitstellen usw. Die folgenden Schritte werden nacheinander eingeführt.

1.1 Kettencode schreiben

Gehen Sie nach dem Erstellen der Netzwerk- und Anwendungskanäle zurück zum Verzeichnis finance_network, um das Chaincode-Verzeichnis zu erstellenusersChaincode. Erstellen Sie dann eine Chaincode-Datei im Chaincode-VerzeichnisusersChaincode. Der Code lautet wie folgt (der Code in dieser Datei wird mit Konstruiert unter Verwendung des Chaincode-Beispiels in ):asset-transfer.gotest-network

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
type SmartContract struct {
    
    
	contractapi.Contract
}

type Asset struct {
    
    
	AppraisedValue int    `json:"AppraisedValue"`
	Color          string `json:"Color"`
	ID             string `json:"ID"`
	Owner          string `json:"Owner"`
	Size           int    `json:"Size"`
}
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
    
    
	assets := []Asset{
    
    
		{
    
    ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300},
		{
    
    ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400},
		{
    
    ID: "asset3", Color: "green", Size: 10, Owner: "Jin Soo", AppraisedValue: 500},
		{
    
    ID: "asset4", Color: "yellow", Size: 10, Owner: "Max", AppraisedValue: 600},
		{
    
    ID: "asset5", Color: "black", Size: 15, Owner: "Adriana", AppraisedValue: 700},
		{
    
    ID: "asset6", Color: "white", Size: 15, Owner: "Michel", AppraisedValue: 800},
	}
	for _, asset := range assets {
    
    
		assetJSON, err := json.Marshal(asset)
		if err != nil {
    
    
			return err
		}
		err = ctx.GetStub().PutState(asset.ID, assetJSON)
		if err != nil {
    
    
			return fmt.Errorf("failed to put to world state. %v", err)
		}
	}
	return nil
}
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    
    
	exists, err := s.AssetExists(ctx, id)
	if err != nil {
    
    
		return err
	}
	if exists {
    
    
		return fmt.Errorf("the asset %s already exists", id)
	}
	asset := Asset{
    
    
		ID:             id,
		Color:          color,
		Size:           size,
		Owner:          owner,
		AppraisedValue: appraisedValue,
	}
	assetJSON, err := json.Marshal(asset)
	if err != nil {
    
    
		return err
	}
	return ctx.GetStub().PutState(id, assetJSON)
}
func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) {
    
    
	assetJSON, err := ctx.GetStub().GetState(id)
	if err != nil {
    
    
		return nil, fmt.Errorf("failed to read from world state: %v", err)
	}
	if assetJSON == nil {
    
    
		return nil, fmt.Errorf("the asset %s does not exist", id)
	}
	var asset Asset
	err = json.Unmarshal(assetJSON, &asset)
	if err != nil {
    
    
		return nil, err
	}
	return &asset, nil
}

func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    
    
	exists, err := s.AssetExists(ctx, id)
	if err != nil {
    
    
		return err
	}
	if !exists {
    
    
		return fmt.Errorf("the asset %s does not exist", id)
	}
	asset := Asset{
    
    
		ID:             id,
		Color:          color,
		Size:           size,
		Owner:          owner,
		AppraisedValue: appraisedValue,
	}
	assetJSON, err := json.Marshal(asset)
	if err != nil {
    
    
		return err
	}
	return ctx.GetStub().PutState(id, assetJSON)
}
func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error {
    
    
	exists, err := s.AssetExists(ctx, id)
	if err != nil {
    
    
		return err
	}
	if !exists {
    
    
		return fmt.Errorf("the asset %s does not exist", id)
	}
	return ctx.GetStub().DelState(id)
}
func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    
    
	assetJSON, err := ctx.GetStub().GetState(id)
	if err != nil {
    
    
		return false, fmt.Errorf("failed to read from world state: %v", err)
	}
	return assetJSON != nil, nil
}
func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) (string, error) {
    
    
	asset, err := s.ReadAsset(ctx, id)
	if err != nil {
    
    
		return "", err
	}
	oldOwner := asset.Owner
	asset.Owner = newOwner
	assetJSON, err := json.Marshal(asset)
	if err != nil {
    
    
		return "", err
	}
	err = ctx.GetStub().PutState(id, assetJSON)
	if err != nil {
    
    
		return "", err
	}
	return oldOwner, nil
}
func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
    
    
	resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
	if err != nil {
    
    
		return nil, err
	}
	defer resultsIterator.Close()
	var assets []*Asset
	for resultsIterator.HasNext() {
    
    
		queryResponse, err := resultsIterator.Next()
		if err != nil {
    
    
			return nil, err
		}
		var asset Asset
		err = json.Unmarshal(queryResponse.Value, &asset)
		if err != nil {
    
    
			return nil, err
		}
		assets = append(assets, &asset)
	}
	return assets, nil
}
func main() {
    
    
	assetChaincode, err := contractapi.NewChaincode(&SmartContract{
    
    })
	if err != nil {
    
    
		log.Panicf("Error creating asset-transfer-basic chaincode: %v", err)
	}
	if err := assetChaincode.Start(); err != nil {
    
    
		log.Panicf("Error starting asset-transfer-basic chaincode: %v", err)
	}
}

Verwenden Sie dann Befehle wiego mod im Chaincode-Verzeichnis, um das Modul zu initialisieren. Fügen Sie insbesondere Folgendes hinzu:

#先进入usersChaincode目录下
go mod init
sudo chmod -R 777 go.mod
#下载链码中的需要的模块信息
go get github.com/hyperledger/fabric-contract-api-go/contractapi
sudo chmod -R 777 go.sum
#将项目的依赖库复制都vendor目录中去
GO111MODULE=on go mod vendor

Tipps: Folgende Punkte sind zu beachten

  • Zunächst wird beim Generieren der go.mod-Datei die Go-Sprachversion automatisch als die in der aktuellen Umgebung installierte Go-Sprachversionsnummer angegeben. Zum Beispielgo 1.21.3. Die Versionsnummer der Go-Sprache in go.mod sollte jedoch aus zwei durch Punkte getrennten Zahlen bestehen, z. B. 1.13, 1.14 usw.
  • Zweitensgo.modDie Go-Sprachversion in der Datei muss hier auch die kompatible Version des aktuellen Drittanbieterpakets berücksichtigen.
  • Erneutgo.mod muss die Datei geändert werden und der Befehl go mod tidy muss ausgeführt werden, um die Datei neu zu generierengo.sum.
  • Wenn bei der Installation des Kettencodes schließlich die folgenden Probleme auftreten, müssen Sie fortfahren zurück und ändern Sie die Datei. Hier müssen Sie die Go-Sprachversion in der Datei in ändern (siehe ) und dann muss auch den Kettencode neu packen. Der Einfachheit halber ist es am besten, dieDatei im Voraus zu ändern. invalid go version 1.21.3: must match format 1.23go.modgo.modgo 1.17fabric-samplesgo.sumgo.modFügen Sie hier eine Bildbeschreibung ein
  • Wenn Sie außerdem den Befehl GO111MODULE=on go mod vendor nicht ausführen, tritt bei der nachfolgenden Installation des KettencodesError: chaincode install failed with status: 500 ... error sending: timeout expired while executing transaction. :
    Fügen Sie hier eine Bildbeschreibung ein

1.2 Verpackungskettencode

Das Packen von Chaincode bezieht sich auf das Packen der Chaincode-Datei in eine Datei im TAR-Format. Sie können den Befehl peer lifecycle chaincode package verwenden. Der spezifische Ausführungsbefehl lautet wie folgt:

#先使用cd命令跳转到finance_network目录下
export FABRIC_CFG_PATH=$PWD/config
#basic即为链码的名字
peer lifecycle chaincode package basic.tar.gz --path usersChaincode --lang "golang" --label basic_1.0.1

wobeibasic der Kettencodename ist. Nachdem der Code ausgeführt wurde, sehen Sie die Datei im Verzeichnis finance_network. Tipps: Der Befehl „peer lifecycle chaincode package“ packt den Chaincode nur in eine TAR-Formatdatei. Dieser Prozess erfordert keine Interaktion mit bestimmten Peer-Knoten, sodass die Ausführung dieses Befehls keine Bindung des Knotens erfordert im Voraus. . basic.tar.gz

1.3 Chaincode installieren

Die Installation des Kettencodes ist hauptsächlich für die Bereitstellung des Kettencodes auf jedem Peer-Knoten verantwortlich, der den Kettencode ausführen muss. Installieren Sie den Kettencode im lokalen Dateisystem des Peer-Knotens, indem Sie den Befehl peer lifecycle chaincode install des Peer-Knotens aufrufen. Im Folgenden wird nur der Kettencode-Installationsprozess unter Verwendung des peer0.org1.finance.com-Knotens beschrieben. Die Details lauten wie folgt:

#先设置环境变量将peer CLI绑定到peer0.org1.finance.com节点上
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PWD/organizations/peerOrganizations/org1.finance.com/peers/peer0.org1.finance.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org1.finance.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051
export FABRIC_CFG_PATH=$PWD/config
# 安装链码
peer lifecycle chaincode install basic.tar.gz

Die Ergebnisse lauten wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Sie können peer lifecycle chaincode queryinstalled verwenden, um den Kettencode anzuzeigen, der auf dem Peer-Knoten installiert wurde. Die Details lauten wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Darüber hinaus wird der Kettencode auch auf peer0.org2.finance.com installiert, und die Installationsschritte werden hier weggelassen. Tipps: Obwohl im fabric_test-Netzwerk 3 Peer-Knoten erstellt werden, muss der Kettencode nicht unbedingt auf allen Peer-Knoten installiert werden.

1.4 Kettencode instanziieren

  • Verwenden Sie den Befehl peer lifecycle chaincode approveformyorg, um die Genehmigung der Chaincode-Bereitstellung durch die Organisation abzuschließen. Gehen Sie davon aus, dass beide Organisationen sich auf die Bereitstellung von Chaincode einigen müssen. Hier nehmen wir Org1 als Beispiel. Der spezifische Code lautet wie folgt:
export ORDERER_CA=$PWD/organizations/ordererOrganizations/finance.com/orderers/orderer.finance.com/msp/tlscacerts/tlsca.finance.com-cert.pem
export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid basic.tar.gz)
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.finance.com --tls --cafile "$ORDERER_CA" --channelID channel1 --name basic --version 1.0 --sequence 1 --package-id ${PACKAGE_ID} 

Das Ergebnis ist wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

  • Verwenden Sie den Befehl peer lifecycle chaincode checkcommitreadiness, um die Commit-Bereitschaft der Chaincode-Definition zu überprüfen. Die spezifischen Befehle lauten wie folgt:
peer lifecycle chaincode checkcommitreadiness --channelID channel1 --name basic --version 1.0 --sequence 1 

Die Ausführungsergebnisse sind wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

  • Verwenden Sie den Befehl peer lifecycle chaincode commit, um die durch den Kettencode definierte Transaktion zu übermitteln. Der Befehl lautet wie folgt:
peer lifecycle chaincode commit -o localhost:7050 --orderdeTLSHostnameOverride orderer.finance.com --tls --cafile "$ORDERER_CA" --channelID channel1 --name basic --version 1.0 --sequence 1  --peerAddresses localhost:7051 --tlsRootCertFiles "${
     
     PWD}/organizations/peerOrganizations/org1.finance.com/peers/peer0.org1.finance.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${
     
     PWD}/organizations/peerOrganizations/org2.finance.com/peers/peer0.org2.finance.com/tls/ca.crt"

Das Ergebnis der Codeausführung lautet wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Mit dem folgenden Code können Sie feststellen, ob die Übermittlung erfolgreich war. Die Details lauten wie folgt:

peer lifecycly chaincode querycommitted -C channel1 -n basic

Das Ausführungsergebnis ist wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Zu diesem Zeitpunkt ist die Instanziierung des Kettencodes abgeschlossen. Mitdocker ps -a können Sie die Containerinformationen des Chaincodes anzeigen. Die Details lauten wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

2 Chaincode-Ausführung

Bezüglich der Ausführung von Kettencode werden hier nur zwei Befehle vorgestellt.

  • peer chaincode invoke: Der Kettencode kann so gestaltet werden, dass er eine benutzerdefinierte Geschäftslogik ausführt und den Status im Blockchain-Ledger ändert. Beispiele sind wie folgt:
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.finance.com --tls --cafile "${
     
     PWD}/organizations/ordererOrganizations/finance.com/orderers/orderer.finance.com/msp/tlscacerts/tlsca.finance.com-cert.pem" -C channel1 -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${
     
     PWD}/organizations/peerOrganizations/org1.finance.com/peers/peer0.org1.finance.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${
     
     PWD}/organizations/peerOrganizations/org2.finance.com/peers/peer0.org2.finance.com/tls/ca.crt" -c '{"Args":["InitLedger"]}'

Die Ausführungsergebnisse sind wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

  • peer chaincode query: Daten können aus dem Blockchain-Ledger abgerufen werden, ohne dass Statusaktualisierungen des Ledgers erforderlich sind.
peer chaincode query -C channel -n basic -c '{
    
    "Args":["GetAllAssets

Die Ausführungsergebnisse lauten wie folgt:
Fügen Sie hier eine Bildbeschreibung ein
Um zu veranschaulichen, dasspeer chaincode query das Hauptbuch nicht geändert hat, führen Sie die folgenden zwei Befehle wie folgt aus:

#删除id为asset6的记录
peer chaincode query -C channel1 -n basic -c '{"Args":["DeleteAsset","asset6"]}'
#读取id为asset6的记录
peer chaincode query -C channel1 -n basic -c '{"Args":["ReadAsset","asset6"]}'

Das Ergebnis ist wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

Supongo que te gusta

Origin blog.csdn.net/yeshang_lady/article/details/134801201
Recomendado
Clasificación