区块链教程Fabric1.0源代码分析链码 链码语言平台-兄弟连

简介:

Fabric 1.0源代码笔记 之 Chaincode(链码) #platforms(链码语言平台)

1、platforms概述

platforms代码集中在core/chaincode/platforms目录下。

  • core/chaincode/platforms目录,链码的编写语言平台实现,如golang或java。
        * platforms.go,Platform接口定义,及platforms相关工具函数。

    * util目录,Docker相关工具函数。
    * java目录,java语言平台实现。
    * golang目录,golang语言平台实现。
    

2、Platform接口定义

type Platform interface {
    //验证ChaincodeSpec
    ValidateSpec(spec *pb.ChaincodeSpec) error
    //验证ChaincodeDeploymentSpec
    ValidateDeploymentSpec(spec *pb.ChaincodeDeploymentSpec) error
    //获取部署Payload
    GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)
    //生成Dockerfile
    GenerateDockerfile(spec *pb.ChaincodeDeploymentSpec) (string, error)
    //生成DockerBuild
    GenerateDockerBuild(spec *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error
}
//代码在core/chaincode/platforms/platforms.go

3、platforms相关工具函数

3.1、platforms相关工具函数

//按链码类型构造Platform接口实例,如golang.Platform{}
func Find(chaincodeType pb.ChaincodeSpec_Type) (Platform, error)
//调取platform.GetDeploymentPayload(spec),获取部署Payload
func GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)
//优先获取tls根证书,如无则获取tls证书
func getPeerTLSCert() ([]byte, error)
//调取platform.GenerateDockerfile(cds),创建Dockerfile
func generateDockerfile(platform Platform, cds *pb.ChaincodeDeploymentSpec, tls bool) ([]byte, error)
//调取platform.GenerateDockerBuild(cds, tw),创建DockerBuild
func generateDockerBuild(platform Platform, cds *pb.ChaincodeDeploymentSpec, inputFiles InputFiles, tw *tar.Writer) error
//调取generateDockerfile(platform, cds, cert != nil)
func GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec) (io.Reader, error)
//代码在core/chaincode/platforms/platforms.go

3.2、Docker相关工具函数

//contents+hash合并后再哈希
func ComputeHash(contents []byte, hash []byte) []byte 
//哈希目录下文件并打包
func HashFilesInDir(rootDir string, dir string, hash []byte, tw *tar.Writer) ([]byte, error) 
//目录是否存在
func IsCodeExist(tmppath string) error 
//编译链码
func DockerBuild(opts DockerBuildOptions) error 
//代码在core/chaincode/platforms/util/utils.go

func DockerBuild(opts DockerBuildOptions) error代码如下:

type DockerBuildOptions struct {
    Image        string
    Env          []string
    Cmd          string
    InputStream  io.Reader
    OutputStream io.Writer
}

func DockerBuild(opts DockerBuildOptions) error {
    client, err := cutil.NewDockerClient()
    if err != nil {
        return fmt.Errorf("Error creating docker client: %s", err)
    }
    if opts.Image == "" {
        //通用的本地编译环境
        opts.Image = cutil.GetDockerfileFromConfig("chaincode.builder")
    }

    //确认镜像是否存在或从远程拉取
    _, err = client.InspectImage(opts.Image)
    if err != nil {
        err = client.PullImage(docker.PullImageOptions{Repository: opts.Image}, docker.AuthConfiguration{})
    }

    //创建一个暂时的容器
    container, err := client.CreateContainer(docker.CreateContainerOptions{
        Config: &docker.Config{
            Image:        opts.Image,
            Env:          opts.Env,
            Cmd:          []string{"/bin/sh", "-c", opts.Cmd},
            AttachStdout: true,
            AttachStderr: true,
        },
    })
    //删除容器
    defer client.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID})

    //上传输入
    err = client.UploadToContainer(container.ID, docker.UploadToContainerOptions{
        Path:        "/chaincode/input",
        InputStream: opts.InputStream,
    })

    stdout := bytes.NewBuffer(nil)
    _, err = client.AttachToContainerNonBlocking(docker.AttachToContainerOptions{
        Container:    container.ID,
        OutputStream: stdout,
        ErrorStream:  stdout,
        Logs:         true,
        Stdout:       true,
        Stderr:       true,
        Stream:       true,
    })

    //启动容器
    err = client.StartContainer(container.ID, nil)
    //等待容器返回
    retval, err := client.WaitContainer(container.ID)
    //获取容器输出
    err = client.DownloadFromContainer(container.ID, docker.DownloadFromContainerOptions{
        Path:         "/chaincode/output/.",
        OutputStream: opts.OutputStream,
    })
    return nil
}
//代码在core/chaincode/platforms/util/utils.go

4、golang语言平台实现

4.1、golang.Platform结构体定义及方法

Platform接口golang语言平台实现,即golang.Platform结构体定义及方法。

type Platform struct {
}

//验证ChaincodeSpec,即检查spec.ChaincodeId.Path是否存在
func (goPlatform *Platform) ValidateSpec(spec *pb.ChaincodeSpec) error
//验证ChaincodeDeploymentSpec,即检查cds.CodePackage(tar.gz文件)解压后文件合法性
func (goPlatform *Platform) ValidateDeploymentSpec(cds *pb.ChaincodeDeploymentSpec) error
//获取部署Payload,即将链码目录下文件及导入包所依赖的外部包目录下文件达成tar.gz包
func (goPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)
func (goPlatform *Platform) GenerateDockerfile(cds *pb.ChaincodeDeploymentSpec) (string, error)
func (goPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error

func pathExists(path string) (bool, error) //路径是否存在
func decodeUrl(spec *pb.ChaincodeSpec) (string, error) //spec.ChaincodeId.Path去掉http://或https://
func getGopath() (string, error) //获取GOPATH
func filter(vs []string, f func(string) bool) []string //按func(string) bool过滤[]string
func vendorDependencies(pkg string, files Sources) //重新映射依赖关系
//代码在core/chaincode/platforms/golang/platform.go

4.1.1 func (goPlatform Platform) GetDeploymentPayload(spec pb.ChaincodeSpec) ([]byte, error)

func (goPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error) {
    var err error
    code, err := getCode(spec) //获取代码,即构造CodeDescriptor,Gopath为代码真实路径,Pkg为代码相对路径
    env, err := getGoEnv()
    gopaths := splitEnvPaths(env["GOPATH"]) //GOPATH
    goroots := splitEnvPaths(env["GOROOT"]) //GOROOT,go安装路径
    gopaths[code.Gopath] = true //链码真实路径
    env["GOPATH"] = flattenEnvPaths(gopaths) //GOPATH、GOROOT、链码真实路径重新拼合为新GOPATH
    
    imports, err := listImports(env, code.Pkg) //获取导入包列表
    var provided = map[string]bool{ //如下两个包为ccenv已自带,可删除
        "github.com/hyperledger/fabric/core/chaincode/shim": true,
        "github.com/hyperledger/fabric/protos/peer":         true,
    }
    
    imports = filter(imports, func(pkg string) bool {
        if _, ok := provided[pkg]; ok == true { //从导入包中删除ccenv已自带的包
            return false
        }
        for goroot := range goroots { //删除goroot中自带的包
            fqp := filepath.Join(goroot, "src", pkg)
            exists, err := pathExists(fqp)
            if err == nil && exists {
                return false
            }
        }   
        return true
    })
    
    deps := make(map[string]bool)
    for _, pkg := range imports {
        transitives, err := listDeps(env, pkg) //列出所有导入包的依赖包
        deps[pkg] = true
        for _, dep := range transitives {
            deps[dep] = true
        }
    }
    delete(deps, "") //删除空
    
    fileMap, err := findSource(code.Gopath, code.Pkg) //遍历链码路径下文件
    for dep := range deps {
        for gopath := range gopaths {
            fqp := filepath.Join(gopath, "src", dep)
            exists, err := pathExists(fqp)
            if err == nil && exists {
                files, err := findSource(gopath, dep) //遍历依赖包下文件
                for _, file := range files {
                    fileMap[file.Name] = file
                }
                
            }
        }
    }
    
    files := make(Sources, 0) //数组
    for _, file := range fileMap {
        files = append(files, file)
    }
    vendorDependencies(code.Pkg, files) //重新映射依赖关系
    sort.Sort(files)
    
    payload := bytes.NewBuffer(nil)
    gw := gzip.NewWriter(payload)
    tw := tar.NewWriter(gw)
    for _, file := range files {
        err = cutil.WriteFileToPackage(file.Path, file.Name, tw) //将文件写入压缩包中
    }
    tw.Close()
    gw.Close()
    return payload.Bytes(), nil
}
//代码在core/chaincode/platforms/golang/platform.go

4.1.2、func (goPlatform Platform) GenerateDockerfile(cds pb.ChaincodeDeploymentSpec) (string, error)

func (goPlatform *Platform) GenerateDockerfile(cds *pb.ChaincodeDeploymentSpec) (string, error) {
    var buf []string
    //go语言链码部署依赖的基础镜像
    buf = append(buf, "FROM "+cutil.GetDockerfileFromConfig("chaincode.golang.runtime"))
    //binpackage.tar添加到/usr/local/bin目录下
    buf = append(buf, "ADD binpackage.tar /usr/local/bin")
    dockerFileContents := strings.Join(buf, "\n")
    return dockerFileContents, nil
}
//代码在core/chaincode/platforms/golang/platform.go

4.1.3、func (goPlatform Platform) GenerateDockerBuild(cds pb.ChaincodeDeploymentSpec, tw *tar.Writer) error

func (goPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error {
    spec := cds.ChaincodeSpec
    pkgname, err := decodeUrl(spec)
    const ldflags = "-linkmode external -extldflags '-static'"

    codepackage := bytes.NewReader(cds.CodePackage)
    binpackage := bytes.NewBuffer(nil)
    //编译链码
    err = util.DockerBuild(util.DockerBuildOptions{
        Cmd:          fmt.Sprintf("GOPATH=/chaincode/input:$GOPATH go build -ldflags \"%s\" -o /chaincode/output/chaincode %s", ldflags, pkgname),
        InputStream:  codepackage,
        OutputStream: binpackage,
    })
    return cutil.WriteBytesToPackage("binpackage.tar", binpackage.Bytes(), tw)
}
//代码在core/chaincode/platforms/golang/platform.go

4.2、env相关函数

type Env map[string]string
type Paths map[string]bool

func getEnv() Env //获取环境变量,写入map[string]string
func getGoEnv() (Env, error) //执行go env获取go环境变量,写入map[string]string
func flattenEnv(env Env) []string //拼合env,形式k=v,写入[]string
func splitEnvPaths(value string) Paths //分割多个路径字符串,linux下按:分割
func flattenEnvPaths(paths Paths) string //拼合多个路径字符串,以:分隔
//代码在core/chaincode/platforms/golang/env.go

4.3、list相关函数

//执行命令pgm,支持设置timeout,timeout后将kill进程
func runProgram(env Env, timeout time.Duration, pgm string, args ...string) ([]byte, error) 
//执行go list -f 规则 链码路径,获取导入包列表或依赖包列表
func list(env Env, template, pkg string) ([]string, error) 
//执行go list -f "{{ join .Deps \"\\n\"}}" 链码路径,获取依赖包列表
func listDeps(env Env, pkg string) ([]string, error) 
//执行go list -f "{{ join .Imports \"\\n\"}}" 链码路径,获取导入包列表
func listImports(env Env, pkg string) ([]string, error) 
//代码在core/chaincode/platforms/golang/list.go

4.4、Sources类型及方法

type Sources []SourceDescriptor
type SourceMap map[string]SourceDescriptor

type SourceDescriptor struct {
    Name, Path string
    Info       os.FileInfo
}

type CodeDescriptor struct {
    Gopath, Pkg string
    Cleanup     func()
}
//代码在core/chaincode/platforms/golang/package.go

涉及方法如下:

//获取代码真实路径
func getCodeFromFS(path string) (codegopath string, err error) 
//获取代码,即构造CodeDescriptor,Gopath为代码真实路径,Pkg为代码相对路径
func getCode(spec *pb.ChaincodeSpec) (*CodeDescriptor, error)
//数组长度 
func (s Sources) Len() int
//交换数组i,j内容
func (s Sources) Swap(i, j int) 
//比较i,j的名称
func (s Sources) Less(i, j int) bool 
//遍历目录下文件,填充type SourceMap map[string]SourceDescriptor
func findSource(gopath, pkg string) (SourceMap, error) 
//代码在core/chaincode/platforms/golang/package.go

欢迎继续关注兄弟连区块链教程分享!

相关文章
|
6月前
|
存储 供应链 监控
区块链技术在供应链管理中的应用与前景分析
随着信息化时代的到来,供应链管理面临着越来越多的挑战和机遇。本文主要探讨了区块链技术在供应链管理中的应用,以及未来的发展前景。通过对区块链技术的特点和优势进行分析,结合实际案例和趋势展望,展示了区块链技术在提升供应链透明度、效率和安全性方面的潜力,以及未来发展的可能方向。
|
6月前
|
安全 区块链
区块链积分商城系统开发详细指南//需求功能/指南教程/源码流程
Developing a blockchain points mall system involves multiple aspects such as blockchain technology, smart contracts, front-end development, and business logic design. The following is the general process for developing a blockchain points mall system
|
6月前
|
存储 算法 API
面向企业的区块链教程(一)(2)
面向企业的区块链教程(一)
107 6
|
1月前
|
传感器 安全 物联网
新技术趋势与应用随着科技的不断进步,新兴技术如区块链、物联网和虚拟现实等正迅速改变我们的世界。这些技术不仅在各自领域内展现出强大的潜力,还在相互融合中催生出更多创新应用场景。本文将探讨这些新兴技术的发展趋势及其在各行业中的应用前景,通过通俗易懂的语言和清晰的条理,带领读者了解其内涵和意义。
本文旨在探讨区块链技术、物联网和虚拟现实等新兴技术的发展趋势及其在各个行业的应用场景。通过分析这些技术的独特优势和潜在缺陷,揭示它们对未来社会和经济可能带来的深远影响。同时,结合实际案例,展示这些技术如何解决现实问题,为各行各业提供新的发展机遇。
67 4
|
3月前
|
安全 区块链
Massa Layer 1区块链 POS 安全性分析
Massa Labs 回应 Certik 的挑战,通过严格的数学分析证明了其权益证明系统的安全性,抵抗了潜在攻击者试图操纵随机抽签的企图。
60 0
Massa Layer 1区块链 POS 安全性分析
|
5月前
|
安全 算法 定位技术
[Solidity][区块链安全入门]Solidity语言关于密码学知识的运用以及存在漏洞
密码学在区块链中扮演关键角色,确保机密性、完整性、身份认证和不可否认性。对称密钥加密用于快速加密,但不支持不可否认性。非对称加密(如RSA)解决了这一问题,每个用户拥有公钥和私钥。散列函数(如SHA-1、SHA-2)用于数字签名,保证信息来源和完整性。同态加密允许在不解密情况下处理加密数据,增强隐私保护。零知识证明则能验证信息正确性而不泄露额外信息,如ZCash使用该技术隐藏交易详情。环签名技术(如在门罗币中)隐藏签名者身份。区块链隐私保护措施包括混币技术,旨在混淆交易路径。网络和应用层面上也存在隐私挑战,需要综合策略来防御。
|
6月前
|
存储 供应链 安全
基于区块链技术的智能合约安全性分析
【5月更文挑战第31天】本文深入探讨了区块链技术中智能合约的安全性问题,通过分析现有智能合约的安全漏洞和攻击手段,提出了一系列增强智能合约安全性的策略。文章首先介绍了区块链和智能合约的基本概念,随后详细讨论了智能合约面临的安全挑战,包括代码漏洞、重入攻击等问题,并对比分析了不同平台下智能合约的安全性差异。最后,文章提出了一系列提高智能合约安全性的建议,旨在为区块链应用的健康发展提供参考。
|
5月前
|
存储 安全 区块链
元宇宙与区块链技术的关系可以从多个角度进行阐述。以下是对这两者之间关系的详细分析
**元宇宙:虚拟世界融合现实元素,强调交互与沉浸;区块链:去中心化、安全的分布式账本。两者结合,区块链确保元宇宙中虚拟资产安全、支付高效、身份验证私密、治理透明,支撑其经济体系与用户信任,驱动未来发展。**
|
6月前
|
存储 算法 安全
区块链系统开发技术规则分析
区块链核心技术包括:1) 哈希算法,利用单向函数将任意数据转化为固定长度代码,确保安全验证;2) 非对称加密,使用公钥和私钥一对进行加密解密,保证信息安全;3) 共识机制,如PoW、PoS、DPoS等,实现快速交易验证和确认;4) 智能合约,自动执行的可信代码,一旦编写即不可更改,用于自动化交易;5) 分布式存储,将数据分散存储在网络各处,涵盖结构化、非结构化和半结构化数据。
|
5月前
|
区块链
近期区块链市场趋势分析
**区块链市场趋势摘要:** - 跨链技术成熟,提升互操作性,助力区块链网络融合。 - DeFi持续繁荣,智能合约与AMM创新活跃,市场竞争驱动市场壮大。 - NFT市场多样化,拓展至游戏、音乐等领域,实用性增强。 - 区块链寻求绿色转型,通过PoS共识与绿色能源减少能耗。 - 技术模块化、可组合性提升,降低成本,增强系统灵活性。 这些趋势展现区块链潜力,带来机遇与挑战,促进行业创新。
下一篇
无影云桌面