区块链学习笔记(一. 了解)

区块链是一种全新的信息记录模式,每一个参与者都可以是记录者,分布式账本。它不是一种单纯的技术,是多个老技术和新技术的结合应用,去中心化,如果是联盟链应该是多中心化了,类似于git,p2p下载,数据不可篡改,不可抵赖。

第一代是加密货币, 第二代是智能合约, 第三代是联盟链(私有链)。

共识算法

 

Merkle 树(简化支付验证),查询的话,区块头(版本号,区块高度,难度值,时间戳,随机数,前一区块哈希,后一区块哈希)

 

数据库, 任何一个数据库都可以, 中本聪使用 leveldb

   boltdb, couchDB

 

区块链中的联盟链(私有链) 的开源项目Hyperledger fabric,主要代码由IBM,Intel,R3,各大银行等贡献,链中的参与需要授权, 参与者都是经过预先选择的, 并且仅限于这些参与者访问网络。运行在许可模式下,因此可为记录提供更细粒度的访问控制,从而增强了隐私,只有参与交易的各方才必须要达成共识,因此在性能上有所提高。只能在交易层面达成共识, 不能在账本层面达成共识。

 

Fabric  将节点区分为客户节点(client)、对等节点(Peer)和订购节点(Orderer)。

  • 客户节点代表最终客户,创建并调用交易。他们与对等节点和订购节点沟通。
  • 对等节点维护账本,并接收订购节点订购的更新消息, 以向账本提交新的交易。
  • 背书节点(Endorser)是一类特殊的对等节点,任务是通过检查自身是否满足一些必要和充分的条件(例如提供所需的签名),对交易提供背书,在共识机制的投票环节里,背书意味着参与投票。
  • 订购节点在客户节点和对等节点间提供了通信通道,用于广播包含交易的消息。特别是对于共识,这些通道确保了所有已连接的对等节点按照安全相同的逻辑顺序传递完全相同的消息。

 

节点是区块链的通信主体,是逻辑概念。 节点之间通过gRPC 消息进行通信, 对等节点间通信使用 Gossip 协议。每个Peer 节点必定是一个记账节点,除记账节点外,它也开源担任其他一到多种角色,即某个节点可以同时是记账节点和背书节点,也可以同时是记账,背书,主节点,锚节点。

 

联盟链不允许节点任意加入,因此会对节点认证做出严格的限制,主要是用到了数字证书。

 

 

在Fabric 上运行的主要是智能合约, 因此Fabric 的交易定义比比特币要宽泛很多。在比特币上, 一笔交易指的就是转账,而在Fabric 上,任何对数据的增删改查都是交易。

 

交易流程

  1. 客户节点通过SDK 调用证书服务(CA)服务,进行注册和登记,并获取身份证书。
  2. 客户节点向已连接的背书节点发送交易,启动对账本的更新流程。
  3. 所有背书节点都必须就提出的交易达成一致,因此需要根据更新所建议的账本达成某种共识。
  4. 客户节点依次收集所有背书节点的批准,然后将经批准的交易发送给已连接的订购节点。
  5. 由这些订购节点再次达成共识,汇总各客户节点递交过来的交易,排序打包为区块。
  6. 随后,交易区块将被转发给持有分类账的对等节点, 以提交交易,各对等节点各自验证结果,最后将交易区块记录到自己的ledger 账本中,并修改世界状态。

智能合约,该术语有两种不同的常用方式,

  • 智能合约代码(smart contract code)。
  • 智能法律合约(smart legal contracts)。

智能合约代码就是用某种编程语言编写的软件。他作为一个软件代理, 或是代表其中某个一方,目的是履行某些义务,行使某些权限, 并以自动的方式控制分布式账本中的资产。因此,智能合约通过代码执行模拟,或模拟现实世界中合约逻辑,承担了分布式账本的任务和责任,尽管其合法性可能尚未明确。

所有的DLT 都支持以智能合约代码的形式履行智能合约。代码可以使用Go、Java for Fabric、Solidity for Ethereum,以及Java/Kotlin for Corda 编写。在Fabric 中使用了术语“链码”(chaincode),以此作为智能合约的同义词。

在Corda 中,智能合约不仅可以包含代码,还允许包含法律行文。智能法律合约是法律行文,其制定方式可以通过智能合同代码来表达和实施。   

智能合约中封装了信息处理的完整方案,以此来经量简化整个网络的信息交易。智能合约通过编写, 可以被升级,通过升级来丰富其功能并增强其对事务的处理能力。所有的参与者都可以按照智能合约中的约定自动执行相关事务处理操作。

简单理解,hyperledger fabric 的区块链通过智能合约进行更新, 并通过共识的协作过程保持一致。

 隐私

    联盟链(私有链),企业对企业(B2B)网络的参与者对他们所共享的信息非常敏感。HyperLedger Fabric 通过使用channel(频道)的方式,让一组参与者来共同维护一套账本,其他的参与者无法参与其中,在channel 内部的网络对参与者是开放的。


部署实例: 陶辉笔记《区块链开源实现FABRIC 快速部署及CLI 体验》

简书: 李孝伟 《Hyperledger Fabric 基于Kafka 的多机部署》

Java: tualala《基于Hyperledger Fabric 交易系统账户的钱包模型的java Chaincode 实例》

Csdn: Physicaloser 《Hyperledger fabric 在现有组织中增加节点》

 

调用api 写入,读取等,账本状态交互API,交易信息相关API,参数API

Stub sim.ChaincodeStubInterface

Stub.PutState(key, value)

Stub.GetState(key)

Stub.GetStateByRange(startKey, endKey)

Stub.GetHistroyForKey(key)

Stub.DelState(key)

//创建一个组合对象, 类似hash 对象, 这个用于高并发,官方例子high-throuhput。

//compositeIndexName := “varName~op~value~txID”

Stub.CreateCompositeKey(compositeIndexName, attributes)

Stub.GetStateByPartialCompositeKey(compositeIndexName, keys)

Stub.SplitCompositeKey()

//返回交易提案中指定交易的交易ID

Stub.GetTxID() 

 

chainCode 会执行完逻辑, 但是并不会在stub.PutState 的时候写数据库。

 

更新智能合约代码放在: /opt/gopath/src/,   /github.com/hyperledger/fabric/examples/chiancode/go/***

根目录/opt/gopath/src/ 可以换,  目录 /github.com/hyperledger/fabric/ 保持这样的结构

 

Fabric

  • 证书生成工具 cryptogen (配置文件crypto-config.yaml)
  • 每个通道的创世区块生成工具configtxgen(configtx.yaml)

帮助脚本类文件(IBM 写的)

       download-dockerimages.sh

         generateArtifacts-3o4p.sh yourchannel  生成通道根证书,msp证书,orderer证书,peer证书,tls 证书等等和区块相关文件

        e2e_cli/scripts/script.sh

 

 

证书:

  • 每个组织都有子的TLS Root CA 证书, 与其数据层的组织Root CA 证书独立开来
  • 每个节点(Orderer和Peer)都有自己的Server TLS 证书, 是由它所在组织的TLS Root CA 签发出来的。

 

共识排序服务

  • 1.1 版本开始支持kafka 共识(生产环境部署需要至少4个kafka和3个Zookeeper)
  • 1.4.1 版本开始支持 Raft 共识和排序。
  • 单机环境默认使用Solo

 

 

Fabric 的区块链, 本身是文件系统,不是数据库, 所以会把区块中的数据在LevelDB 中建立索引。

状态快照, 不支持并行验证

数据存储结构

  • 文件系统,保存区块链数据。
  • 状态数据,最新的世界状态数据
  • 区块索引,快速查询区块/交易

 

智能合约代码

  • 默认go 语言
  • 也支持node.js
  • 也支持java
发布了189 篇原创文章 · 获赞 19 · 访问量 54万+
展开阅读全文

Fabric第一个应用中,如何改写fabcar的智能合约,对数据的某一个属性进行查询获取所有满足条件的数据。

05-24

Hyperledger Fabric第一个应用中,如何改写fabcar的智能合约,对数据的某一个属性进行查询获取所有满足条件的数据,例如所有颜色为红色的汽车信息。 智能合约源码如下。 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * The sample smart contract for documentation topic: * Writing Your First Blockchain Application */ package main /* Imports * 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation * 2 specific Hyperledger Fabric specific libraries for Smart Contracts */ import ( "bytes" "encoding/json" "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer" ) // Define the Smart Contract structure type SmartContract struct { } // Define the car structure, with 4 properties. Structure tags are used by encoding/json library type Car struct { Make string `json:"make"` Model string `json:"model"` Colour string `json:"colour"` Owner string `json:"owner"` } /* * The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network * Best practice is to have any Ledger initialization in separate function -- see initLedger() */ func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response { return shim.Success(nil) } /* * The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" * The calling application program has also specified the particular smart contract function to be called, with arguments */ func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { // Retrieve the requested Smart Contract function and arguments function, args := APIstub.GetFunctionAndParameters() // Route to the appropriate handler function to interact with the ledger appropriately if function == "queryCar" { return s.queryCar(APIstub, args) } else if function == "initLedger" { return s.initLedger(APIstub) } else if function == "createCar" { return s.createCar(APIstub, args) } else if function == "queryAllCars" { return s.queryAllCars(APIstub) } else if function == "changeCarOwner" { return s.changeCarOwner(APIstub, args) } return shim.Error("Invalid Smart Contract function name.") } func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } carAsBytes, _ := APIstub.GetState(args[0]) return shim.Success(carAsBytes) } func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response { cars := []Car{ Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"}, Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"}, Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"}, Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"}, Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"}, Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"}, Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"}, Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"}, Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"}, Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"}, } i := 0 for i < len(cars) { fmt.Println("i is ", i) carAsBytes, _ := json.Marshal(cars[i]) APIstub.PutState("CAR"+strconv.Itoa(i), carAsBytes) fmt.Println("Added", cars[i]) i = i + 1 } return shim.Success(nil) } func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 5 { return shim.Error("Incorrect number of arguments. Expecting 5") } var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]} carAsBytes, _ := json.Marshal(car) APIstub.PutState(args[0], carAsBytes) return shim.Success(nil) } func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { startKey := "CAR0" endKey := "CAR999" resultsIterator, err := APIstub.GetStateByRange(startKey, endKey) if err != nil { return shim.Error(err.Error()) } defer resultsIterator.Close() // buffer is a JSON array containing QueryResults var buffer bytes.Buffer buffer.WriteString("[") bArrayMemberAlreadyWritten := false for resultsIterator.HasNext() { queryResponse, err := resultsIterator.Next() if err != nil { return shim.Error(err.Error()) } // Add a comma before array members, suppress it for the first array member if bArrayMemberAlreadyWritten == true { buffer.WriteString(",") } buffer.WriteString("{\"Key\":") buffer.WriteString("\"") buffer.WriteString(queryResponse.Key) buffer.WriteString("\"") buffer.WriteString(", \"Record\":") // Record is a JSON object, so we write as-is buffer.WriteString(string(queryResponse.Value)) buffer.WriteString("}") bArrayMemberAlreadyWritten = true } buffer.WriteString("]") fmt.Printf("- queryAllCars:\n%s\n", buffer.String()) return shim.Success(buffer.Bytes()) } func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } carAsBytes, _ := APIstub.GetState(args[0]) car := Car{} json.Unmarshal(carAsBytes, &car) car.Owner = args[1] carAsBytes, _ = json.Marshal(car) APIstub.PutState(args[0], carAsBytes) return shim.Success(nil) } // The main function is only relevant in unit test mode. Only included here for completeness. func main() { // Create a new Smart Contract err := shim.Start(new(SmartContract)) if err != nil { fmt.Printf("Error creating new Smart Contract: %s", err) } } 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览