【Tecnología y aplicación de blockchain】(8)

https://blog.csdn.net/lakersssss24/article/details/125762826?spm=1001.2014.3001.5501
https://blog.csdn.net/lakersssss24/article/details/126434147
https://blog.csdn.net/ lakersssss24/article/details/126671408?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3-126671408-blog-126434147.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant. none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3-126671408-blog-126434147.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=4

Prepárate con anticipación

inserte la descripción de la imagen aquí

sudo apt-get update  更新源 
sudo apt-get install ssh 安装远程客户端
sudo apt-get install curl 安装命令行工具
sudo apt-get install git 安装git
sudo apt-get install gcc 安装gcc
sudo apt-get install vim 安装vim文件编辑器
sudo apt-get install make 安装make
sudo apt-get install net-tools 安装网络工具
sudo apt-get install net-tools  安装mousepad 类似于windows的记事本
./bootstrap.sh

https://teach.imcn.me/y2020/1146.html

instalación de couchDB https://blog.csdn.net/TU_Dresden/article/details/126864418

Por favor agregue una descripción de la imagen

experimentar uno

red

./network.sh up

Por favor agregue una descripción de la imagen
Por favor agregue una descripción de la imagen

./network.sh up createChannel -s couchdb

Por favor agregue una descripción de la imagen

./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP" 
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{
    
    "function":"InitLedger","Args":[""]}'

inserte la descripción de la imagen aquí
Reanudar

./network.sh up createChannel -ca -s couchdb


plantilla de ginebra

package main
 
import (
	"fmt"
	"github.com/gin-gonic/gin"
)
 
type Stu struct {
    
    
	Name string `form:"name"`
	Id   string `form:"id"`
	Age  string `form:"age"`
}
 
func main() {
    
    
	r := gin.Default()
	var stu Stu
	r1 := r.Group("/fabric2.4")
	r1.POST("/setstu", func(c *gin.Context) {
    
    
		//var stu Stu
		c.ShouldBind(&stu)
		c.JSON(200, stu)
		fmt.Println("stu:", stu)
	})
	r1.POST("/ok1", func(c *gin.Context) {
    
    
		c.JSON(200, "ok1")
	})
	r.Run(":8080") // 监听并在 0.0.0.0:8080 上启动服务
 
}

La única parte funcional del código de cadena:

package chaincode
 
import (
	"encoding/json"
	"fmt"
 
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
 
// SmartContract provides functions for managing an Asset
type SmartContract struct {
    
    
	contractapi.Contract
}
 
// Asset describes basic details of what makes up a simple asset
//Insert struct field in alphabetic order => to achieve determinism across languages
// golang keeps the order when marshal to json but doesn't order automatically
type Asset struct {
    
    
	AppraisedValue int    `json:"AppraisedValue"`
	Color          string `json:"Color"`
	ID             string `json:"ID"`
	Owner          string `json:"Owner"`
	Size           int    `json:"Size"`
}
 
// InitLedger adds a base set of assets to the ledger
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
}
 
// CreateAsset issues a new asset to the world state with given details.
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)
}
 
// ReadAsset returns the asset stored in the world state with given id.
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
}
 
// UpdateAsset updates an existing asset in the world state with provided parameters.
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)
	}
 
	// overwriting original asset with new asset
	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)
}
 
// DeleteAsset deletes an given asset from the world state.
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)
}
 
// AssetExists returns true when asset with given ID exists in world state
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
}
 
// TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
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
}
 
// GetAllAssets returns all assets found in world state
func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
    
    
	// range query with empty string for startKey and endKey does an
	// open-ended query of all assets in the chaincode namespace.
	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
}

Ver la IP y la dirección de la máquina virtual:

ifconfig

marco de ginebra

package main
 
import (
	"bytes"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/hyperledger/fabric-gateway/pkg/client"
	"github.com/hyperledger/fabric-gateway/pkg/identity"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"io/ioutil"
	"path"
	"time"
)
 
const (
	mspID         = "Org1MSP"
	cryptoPath    = "./peerOrganizations/org1.example.com"
	certPath      = cryptoPath + "/users/[email protected]/msp/signcerts/cert.pem"
	keyPath       = cryptoPath + "/users/[email protected]/msp/keystore/"
	tlsCertPath   = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
	peerEndpoint  = "192.168.136.130:7051"
	gatewayPeer   = "peer0.org1.example.com"
	channelName   = "mychannel"
	chaincodeName = "basic"
)
 
type Asset struct {
    
    
	AppraisedValue int    `form:"appraisedValue" json:"appraisedValue" `
	Color          string `form:"color" json:"color"`
	ID             string `form:"id" json:"id"`
	Owner          string `form:"owner" json:"owner"`
	Size           int    `form:"size" json:"size"`
}
 
func main() {
    
    
	// The gRPC client connection should be shared by all Gateway connections to this endpoint
	clientConnection := newGrpcConnection()
	defer clientConnection.Close()
 
	id := newIdentity()
	sign := newSign()
 
	// Create a Gateway connection for a specific client identity
	gateway, err := client.Connect(
		id,
		client.WithSign(sign),
		client.WithClientConnection(clientConnection),
		// Default timeouts for different gRPC calls
		client.WithEvaluateTimeout(5*time.Second),
		client.WithEndorseTimeout(15*time.Second),
		client.WithSubmitTimeout(5*time.Second),
		client.WithCommitStatusTimeout(1*time.Minute),
	)
	if err != nil {
    
    
		panic(err)
	}
	defer gateway.Close()
	network := gateway.GetNetwork(channelName)
	contract := network.GetContract(chaincodeName)
 
	r := gin.Default()
	r1 := r.Group("/fabric2.4")
	r1.POST("/CreateAsset", func(c *gin.Context) {
    
    
		var asset Asset
		c.ShouldBind(&asset)
		c.JSON(200, asset)
		marshal, _ := json.Marshal(asset)
		fmt.Println(string(marshal))
		fmt.Println("asset:", asset)
	})
	r1.POST("/GetAllAssets", func(c *gin.Context) {
    
    
		result := getAllAssets(contract)
		c.JSON(200, result)
	})
	r.Run(":8080") // 监听并在 0.0.0.0:8080 上启动服务
 
}
 
// Evaluate a transaction to query ledger state.
func getAllAssets(contract *client.Contract) string {
    
    
	fmt.Println("Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger")
 
	evaluateResult, err := contract.EvaluateTransaction("GetAllAssets")
	if err != nil {
    
    
		panic(fmt.Errorf("failed to evaluate transaction: %w", err))
	}
	result := formatJSON(evaluateResult)
 
	fmt.Printf("*** Result:%s\n", result)
 
	return string(evaluateResult)
}
 
// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
    
    
	certificate, err := loadCertificate(tlsCertPath)
	if err != nil {
    
    
		panic(err)
	}
 
	certPool := x509.NewCertPool()
	certPool.AddCert(certificate)
	transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)
 
	connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
	if err != nil {
    
    
		panic(fmt.Errorf("failed to create gRPC connection: %w", err))
	}
 
	return connection
}
 
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity() *identity.X509Identity {
    
    
	certificate, err := loadCertificate(certPath)
	if err != nil {
    
    
		panic(err)
	}
 
	id, err := identity.NewX509Identity(mspID, certificate)
	if err != nil {
    
    
		panic(err)
	}
 
	return id
}
 
func loadCertificate(filename string) (*x509.Certificate, error) {
    
    
	certificatePEM, err := ioutil.ReadFile(filename)
	if err != nil {
    
    
		return nil, fmt.Errorf("failed to read certificate file: %w", err)
	}
	return identity.CertificateFromPEM(certificatePEM)
}
 
// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign() identity.Sign {
    
    
	files, err := ioutil.ReadDir(keyPath)
	if err != nil {
    
    
		panic(fmt.Errorf("failed to read private key directory: %w", err))
	}
	privateKeyPEM, err := ioutil.ReadFile(path.Join(keyPath, files[0].Name()))
 
	if err != nil {
    
    
		panic(fmt.Errorf("failed to read private key file: %w", err))
	}
 
	privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
	if err != nil {
    
    
		panic(err)
	}
 
	sign, err := identity.NewPrivateKeySign(privateKey)
	if err != nil {
    
    
		panic(err)
	}
 
	return sign
}
 
// Format JSON data
func formatJSON(data []byte) string {
    
    
	var prettyJSON bytes.Buffer
	if err := json.Indent(&prettyJSON, data, " ", ""); err != nil {
    
    
		panic(fmt.Errorf("failed to parse JSON: %w", err))
	}
	return prettyJSON.String()
}

inserte la descripción de la imagen aquí

código de cadena

package chaincode
 
import (
	"encoding/json"
	"fmt"
 
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
 
// SmartContract provides functions for managing an Asset
type SmartContract struct {
    
    
	contractapi.Contract
}
 
// Asset describes basic details of what makes up a simple asset
//Insert struct field in alphabetic order => to achieve determinism across languages
// golang keeps the order when marshal to json but doesn't order automatically
type Asset struct {
    
    
	AppraisedValue int    `json:"AppraisedValue"`
	Color          string `json:"Color"`
	ID             string `json:"ID"`
	Owner          string `json:"Owner"`
	Size           int    `json:"Size"`
}
 
// InitLedger adds a base set of assets to the ledger
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
}
 
// CreateAsset issues a new asset to the world state with given details.
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)
}
 
// ReadAsset returns the asset stored in the world state with given id.
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
}
 
// UpdateAsset updates an existing asset in the world state with provided parameters.
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)
	}
 
	// overwriting original asset with new asset
	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)
}
 
// DeleteAsset deletes an given asset from the world state.
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)
}
 
// AssetExists returns true when asset with given ID exists in world state
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
}
 
// TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
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
}
 
// GetAllAssets returns all assets found in world state
func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
    
    
	// range query with empty string for startKey and endKey does an
	// open-ended query of all assets in the chaincode namespace.
	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
}

cartero

inserte la descripción de la imagen aquí
Pruebe su propio sitio web:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Consulta local:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
propio github:
inserte la descripción de la imagen aquí

Por favor agregue una descripción de la imagen

Por favor agregue una descripción de la imagen
Por favor agregue una descripción de la imagen
Por favor agregue una descripción de la imagen

Experimento 2

Ginebra

package main
 
import (
	"bytes"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/hyperledger/fabric-gateway/pkg/client"
	"github.com/hyperledger/fabric-gateway/pkg/identity"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"io/ioutil"
	"path"
	"time"
)
 
const (
	mspID         = "Org1MSP"
	cryptoPath    = "./peerOrganizations/org1.example.com"
	certPath      = cryptoPath + "/users/[email protected]/msp/signcerts/cert.pem"
	keyPath       = cryptoPath + "/users/[email protected]/msp/keystore/"
	tlsCertPath   = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
	peerEndpoint  = "192.168.136.130:7051"
	gatewayPeer   = "peer0.org1.example.com"
	channelName   = "mychannel"
	chaincodeName = "basic"
)
 
type Asset struct {
    
    
	AppraisedValue int    `form:"appraisedValue" json:"appraisedValue" `
	Color          string `form:"color" json:"color"`
	ID             string `form:"id" json:"id"`
	Owner          string `form:"owner" json:"owner"`
	Size           int    `form:"size" json:"size"`
}
 
func main() {
    
    
	// The gRPC client connection should be shared by all Gateway connections to this endpoint
	clientConnection := newGrpcConnection()
	defer clientConnection.Close()
 
	id := newIdentity()
	sign := newSign()
 
	// Create a Gateway connection for a specific client identity
	gateway, err := client.Connect(
		id,
		client.WithSign(sign),
		client.WithClientConnection(clientConnection),
		// Default timeouts for different gRPC calls
		client.WithEvaluateTimeout(5*time.Second),
		client.WithEndorseTimeout(15*time.Second),
		client.WithSubmitTimeout(5*time.Second),
		client.WithCommitStatusTimeout(1*time.Minute),
	)
	if err != nil {
    
    
		panic(err)
	}
	defer gateway.Close()
	network := gateway.GetNetwork(channelName)
	contract := network.GetContract(chaincodeName)
 
	r := gin.Default()
	r1 := r.Group("/fabric2.4.2")
	r1.POST("/Init", func(c *gin.Context) {
    
    
		initLedger(contract)
		c.JSON(200, "init ok!")
	})
	r.Run(":8080") // 监听并在 0.0.0.0:8080 上启动服务
 
}
 
// Evaluate a transaction to query ledger state.
func getAllAssets(contract *client.Contract) string {
    
    
	fmt.Println("Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger")
 
	evaluateResult, err := contract.EvaluateTransaction("GetAllAssets")
	if err != nil {
    
    
		panic(fmt.Errorf("failed to evaluate transaction: %w", err))
	}
	result := formatJSON(evaluateResult)
 
	fmt.Printf("*** Result:%s\n", result)
 
	return string(evaluateResult)
}
 
// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
    
    
	certificate, err := loadCertificate(tlsCertPath)
	if err != nil {
    
    
		panic(err)
	}
 
	certPool := x509.NewCertPool()
	certPool.AddCert(certificate)
	transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)
 
	connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
	if err != nil {
    
    
		panic(fmt.Errorf("failed to create gRPC connection: %w", err))
	}
 
	return connection
}
 
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity() *identity.X509Identity {
    
    
	certificate, err := loadCertificate(certPath)
	if err != nil {
    
    
		panic(err)
	}
 
	id, err := identity.NewX509Identity(mspID, certificate)
	if err != nil {
    
    
		panic(err)
	}
 
	return id
}
 
func loadCertificate(filename string) (*x509.Certificate, error) {
    
    
	certificatePEM, err := ioutil.ReadFile(filename)
	if err != nil {
    
    
		return nil, fmt.Errorf("failed to read certificate file: %w", err)
	}
	return identity.CertificateFromPEM(certificatePEM)
}
 
// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign() identity.Sign {
    
    
	files, err := ioutil.ReadDir(keyPath)
	if err != nil {
    
    
		panic(fmt.Errorf("failed to read private key directory: %w", err))
	}
	privateKeyPEM, err := ioutil.ReadFile(path.Join(keyPath, files[0].Name()))
 
	if err != nil {
    
    
		panic(fmt.Errorf("failed to read private key file: %w", err))
	}
 
	privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
	if err != nil {
    
    
		panic(err)
	}
 
	sign, err := identity.NewPrivateKeySign(privateKey)
	if err != nil {
    
    
		panic(err)
	}
 
	return sign
}
 
// Format JSON data
func formatJSON(data []byte) string {
    
    
	var prettyJSON bytes.Buffer
	if err := json.Indent(&prettyJSON, data, " ", ""); err != nil {
    
    
		panic(fmt.Errorf("failed to parse JSON: %w", err))
	}
	return prettyJSON.String()
}

Nueva parte de activos:
cambie el código a continuación:
inserte la descripción de la imagen aquí
a esto:

r1.POST("/CreateAsset", func(c *gin.Context) {
    
    
		var asset Asset
		c.ShouldBind(&asset)
		c.JSON(200, asset)
		marshal, _ := json.Marshal(asset)
		CreateAsset(contract, asset)
		fmt.Println("存入成功!存入的数据是:", string(marshal))
		//fmt.Println("asset:", asset)
	})

función:

func CreateAsset(contract *client.Contract, asset Asset) string {
    
    
	evaluateResult, err := contract.SubmitTransaction("CreateAsset", asset.ID, asset.Color, strconv.Itoa(asset.Size), asset.Owner, strconv.Itoa(asset.AppraisedValue))
	if err != nil {
    
    
		panic(fmt.Errorf("failed to evaluate transaction: %w", err))
	}
	result := formatJSON(evaluateResult)
 
	fmt.Printf("*** Result:%s\n", result)
 
	return string(evaluateResult)
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Resumir

El contenido de este experimento no es mucho, y es bastante difícil.
Una es que el autor ha configurado el marco de forma predeterminada, por lo que debe adaptarse de acuerdo con el artículo anterior.
La segunda es la consulta después de configurar la Red. Si lees el artículo anterior, puedes saber que el autor ha modificado el

https://github.com/hyperledger/fabric-samples/tree/main/asset-transfer-basic

Parte del código, que es la parte del marco de gin de este artículo. También hay muchas modificaciones,
inserte la descripción de la imagen aquí
y luego está el código. El código a menudo informa un error aquí, y luego, para resolver un error, a menudo surgirán más problemas, especialmente la ocupación de la interfaz de red. Justo ahora cuando escribo el documento, mi puerto 7051 está inexplicablemente ocupado Sí, para completar mejor la tarea final, decidí encontrar un documento correcto y claro y configurarlo desde cero. (La gran razón es que toda la carpeta de telas está hinchada después de estas pocas operaciones, y hay varias muestras de telas. Vuelva atrás y mírela después de algunas semanas. Restablecer a cero es más efectivo)

Antes de hacer dos experimentos, primero configuré el entorno de acuerdo con las ideas del autor, principalmente para iniciar la red.
El segundo es una herramienta muy nueva, cartero, y el propósito de este software aún no se ha entendido completamente.Actualmente, solo se usa para consultar URL.

La segunda parte de la consulta no encontró los activos, puede ser que haya un error en algún aspecto, después de eso, se volverá a habilitar la máquina virtual y luego se hará desde cero.

Por favor agregue una descripción de la imagen

Supongo que te gusta

Origin blog.csdn.net/Algernon98/article/details/128009665
Recomendado
Clasificación