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

提前准备

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

couchDB安装 https://blog.csdn.net/TU_Dresden/article/details/126864418

实验一

network

./network.sh up


./network.sh up createChannel -s couchdb

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


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":[""]}'


restart

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

gin模板

package mainimport ("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 Stur1 := r.Group("/fabric2.4")r1.POST("/setstu", func(c *gin.Context) {//var stu Stuc.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 上启动服务}

链码的只要功能部分:

package chaincodeimport ("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 Asseterr = 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 assetasset := 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.Ownerasset.Owner = newOwnerassetJSON, 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 []*Assetfor resultsIterator.HasNext() {queryResponse, err := resultsIterator.Next()if err != nil {return nil, err}var asset Asseterr = json.Unmarshal(queryResponse.Value, &asset)if err != nil {return nil, err}assets = append(assets, &asset)}return assets, nil
}

查看虚拟机的IP和地址:

ifconfig

gin框架

package mainimport ("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/User1@org1.example.com/msp/signcerts/cert.pem"keyPath       = cryptoPath + "/users/User1@org1.example.com/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 endpointclientConnection := newGrpcConnection()defer clientConnection.Close()id := newIdentity()sign := newSign()// Create a Gateway connection for a specific client identitygateway, err := client.Connect(id,client.WithSign(sign),client.WithClientConnection(clientConnection),// Default timeouts for different gRPC callsclient.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 Assetc.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.Bufferif err := json.Indent(&prettyJSON, data, " ", ""); err != nil {panic(fmt.Errorf("failed to parse JSON: %w", err))}return prettyJSON.String()
}

链码

package chaincodeimport ("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 Asseterr = 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 assetasset := 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.Ownerasset.Owner = newOwnerassetJSON, 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 []*Assetfor resultsIterator.HasNext() {queryResponse, err := resultsIterator.Next()if err != nil {return nil, err}var asset Asseterr = json.Unmarshal(queryResponse.Value, &asset)if err != nil {return nil, err}assets = append(assets, &asset)}return assets, nil
}

postman


测试自家网站:

本地查询:


自己的github:



实验二

gin

package mainimport ("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/User1@org1.example.com/msp/signcerts/cert.pem"keyPath       = cryptoPath + "/users/User1@org1.example.com/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 endpointclientConnection := newGrpcConnection()defer clientConnection.Close()id := newIdentity()sign := newSign()// Create a Gateway connection for a specific client identitygateway, err := client.Connect(id,client.WithSign(sign),client.WithClientConnection(clientConnection),// Default timeouts for different gRPC callsclient.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.Bufferif err := json.Indent(&prettyJSON, data, " ", ""); err != nil {panic(fmt.Errorf("failed to parse JSON: %w", err))}return prettyJSON.String()
}

New asset部分:
把下图代码:

改为这个:

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

函数:

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)
}


总结

本次实验内容内容不多,难度颇大。
其一在于作者默认搭好框架,所以需要按照前文做出适配。
其二是网络搭好之后的查询,如果看了前文,可以知道作者是修改了

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

部分的代码,也就是本文的gin框架部分。修改也很多,

然后就是代码,代码在我这里经常报错,然后为了解决一个bug往往会搞出更多的问题,尤其是网络接口的占用,就在写文档的现在,我的7051端口莫名被占用了,为了更好完成期末任务,决定找一个正确而清晰的文档从头开始配置。(很大的原因是这几次作业下来整个fabric文件夹臃肿不堪,fabric-samples就有好几个,隔着几周时间回去看,有能运行的,也有当初是坑,后来没删的,总之,归零重启更有效)

在做两个实验之前,我先按照作者的思路配置了环境,主要是启动网络。
其次是一种很新的工具,postman,现在还没有完全摸清这个软件的用途,目前仅做查询网址用途。

第二个查询部分没有把assets查出来,可能是某个方面出了bug,之后会重新启用虚拟机,然后从头开始做一遍。

【区块链技术与应用】(八)相关推荐

  1. 八分量基于区块链技术赋能我国工业互联网建设

    id:BSN_2021 公众号:BSN研习社 经区块链服务网络发展联盟官方审核批准,北京八分量信息科技有限公司正式成为区块链服务网络(Blockchain-based Service Network, ...

  2. Bitcoin比特币与BlockChain区块链技术

    一.比特币的历史 比特币现在大火,一枚7000多人民币,遥想当年1万枚才买一张价值25美元的披萨优惠券,如果上天能给我回到当年的机会的话,我一定买买买!!! 比特币有很高的开采及投资价值,被我们中国人 ...

  3. 区块链监管的一年,剥离“币”的区块链技术该何去何从?

    不知不觉已经步入九月中旬,距离九四监管已经有一年多时间.这一年币圈价格升到制高点又急速下降!犹如过山车,高低起伏!但是丝毫没有挡住区块链创业者涌入区块链领域. 目前实际场景落地的产品虽然不多,但不是没 ...

  4. 中国的区块链技术,究竟发展到哪里了?

    作者 | 刘为怀 责编 | 胡巍巍  背景 区块链在本质上,是一个共享.可信的公共总账,任何人都可以对它进行核查,但不存在一个单一的用户可以对它进行控制.在区块链系统中的参与者们,会共同维持总账的更新 ...

  5. 2018 区块链技术及应用峰会(BTA)·中国在北京盛大召开

    2018 年 3 月 30-31 日,由 CSDN.火星财经主办,中关村区块链产业联盟.柏链教育.区块链大本营.TokenSky 联合主办的 2018 区块链技术及应用峰会(BTA)在北京盛大召开.本 ...

  6. 区块链技术人才严重不足,平均薪资 2.58 万

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 去年12月,我们报道了一篇文章<AI专业人才缺口上百万,年薪80万远超同行>引起 ...

  7. 【区块链之技术进阶】Attention please!区块链技术的风险!

    不知不觉咱们在[区块链之技术进阶]部分已经分享了七篇文章了,通过之前的七篇文章大家对于区块链技术的理解是不是上升了一个高度呢?这七篇文章,告诉我们区块链是互联网时代的通往第二纪元--信任纪元的革命,这 ...

  8. 链塔智库联合清华发布《2018区块链技术应用白皮书》

    近日,链塔智库BlockData联合清华大学互联网产业研究院共同发布了<2018区块链技术应用白皮书>,从区块链行业发展现状.区块链产业发展.区块链技术产业应用三个方面对行业进行了分析,并 ...

  9. 区块链技术应用将迎来多场景布局

    6月9日讯,人民论坛今日刊文<区块链技术是高新技术发展的突破口>,文章提到,区块链技术作为一种新兴技术,具有广阔发展前景.将区块链技术作为自主创新和高新技术发展的重要突破口,是当前产业创新 ...

  10. 本田及通用公司利用区块链技术探索智能电网与电动汽车的互操作性

    点击上方 "蓝色字" 可关注我们! 暴走时评: 据日本新闻媒体Nikkei 5月20日报道,主要汽车制造商本田和通用汽车正在合作利用区块链技术研究电动汽车和智能电网的互操作性.作为 ...

最新文章

  1. 一次HP 阵列卡排障
  2. Python中的内存管理机制
  3. 马云:我不懂技术但欣赏技术 达摩院必须超越微软 - 20171011
  4. 1017 Queueing at Bank (25 分)_27行代码AC
  5. jQuery.extend与jQuery.fn.extend的区别分析与实例
  6. attiny13a程序实例_ATtiny13A图文构成
  7. python字符串的表示_Python字符串方法总结
  8. php全选按钮怎么写,PHP中的“全选”复选框,其中包含header.php
  9. Problem A: 判断操作是否合法(栈和队列)
  10. android 事件分发
  11. 团队-象棋游戏-代码设计规范
  12. django路由层 虚拟环境 视图层
  13. WebAPI HelpPage出现Failed to generate the sample for media type 'application/x-www-form-urlencoded'. 错
  14. java p2p编程_JXTA-JAVA P2P网络编程技术(入门篇)
  15. 怎么撤销工作表保护,没有密码?
  16. 全面的SWOT分析的技巧和策略
  17. 二级计算机excel以宏保存,excel宏保存 设置宏保存位置的操作方法
  18. 使用ACCESS数据库时出现“操作必须使用一个可更新的查询”的解决办法
  19. 【ESP32-IDF】02-2 外设-触摸传感器
  20. 辽宁师范大学计算机科学与技术在哪个校区,2021年辽宁师范大学有几个校区,大一新生在哪个校区...

热门文章

  1. 狂神JUC——7大参数及自定义线程池
  2. 【职场】反思如何做好技术分分享
  3. 私有云:何去何从?解决方案有哪些
  4. 中山大学 学医还是学计算机,理科生学医:打算在北京工作,选中山大学医学院还是首医大?...
  5. 如何禁止Chrome弹出无法更新的提示窗?
  6. 虚拟机nat方式联网
  7. 计算机冷知识科普,【科普冷知识】有趣的8个科学冷知识,让你大吃一惊
  8. php函数echo,PHP echo()函数讲解
  9. c语言消隐的作用是什么,【C语言程序设计最终版材料】
  10. 从零开始的Java笔记01