ブロックチェーン教程Fabric 1.0ソースコード分析チェーンコード言語プラットフォーム
11430 ワード
Fabric 1.0ソースコードノートのChincode(鎖コード)
1、plotforms概要
plotformsコードはcore/chaincode/plotformsディレクトリに集中しています。 core/chaincode/plotformsディレクトリ、チェーンコードの作成言語プラットフォーム、例えばgolangまたはjava。 plotforms.go、Platformインターフェース定義、およびplotforms関連ツール関数。 utilディレクトリ、Docker関連ツール関数。 javaディレクトリ、java言語プラットフォームが実現されます。 golangディレクトリ、golang言語プラットフォームが実現します。 2、Platformインターフェース定義
3.1、plotforms関連ツール関数
4.1、golang.Platform構造体の定義と方法
Platformインターフェースgolang言語プラットフォームの実現、すなわちgolang.Platform構造体の定義と方法です。
1、plotforms概要
plotformsコードはcore/chaincode/plotformsディレクトリに集中しています。
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、plotforms関連ツール関数3.1、plotforms関連ツール関数
// 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 DocerBuild 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)Get Deployment Payload(spec pb.C haincodeSpec)([]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)Generate Docerfile(cds pb.ChiincodeDeployments Spec)(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, "
")
return dockerFileContents, nil
}
// core/chaincode/platforms/golang/platform.go
4.1.3、func(goplatform Platform)Generate DocerBuild(cds pb.C haincodeDeployment Spec、tw*tar.Writer)errorfunc (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 \"\
\"}}" ,
func listDeps(env Env, pkg string) ([]string, error)
// go list -f "{{ join .Imports \"\
\"}}" ,
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