兄弟连区块链技术培训Fabric 1.0源代码分析(47)ECDSA(椭圆曲线数字签名算法)
- 格式:docx
- 大小:37.97 KB
- 文档页数:6
兄弟连区块链技术培训Fabric 1.0源代码分析(4)Chain code(链码)#platforms(链码语言平台)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接口定义```gotype Platform interface {//验证ChaincodeSpecValidateSpec(spec *pb.ChaincodeSpec) error//验证ChaincodeDeploymentSpecValidateDeploymentSpec(spec *pb.ChaincodeDeploymentSpec) error//获取部署PayloadGetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)//生成DockerfileGenerateDockerfile(spec *pb.ChaincodeDeploymentSpec) (string, erro r)//生成DockerBuildGenerateDockerBuild(spec *pb.ChaincodeDeploymentSpec, tw *tar.Write r) error}//代码在core/chaincode/platforms/platforms.go```## 3、platforms相关工具函数### 3.1、platforms相关工具函数```go//按链码类型构造Platform接口实例,如golang.Platform{}func Find(chaincodeType pb.ChaincodeSpec_Type) (Platform, error)//调取platform.GetDeploymentPayload(spec),获取部署Payloadfunc GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)//优先获取tls根证书,如无则获取tls证书func getPeerTLSCert() ([]byte, error)//调取platform.GenerateDockerfile(cds),创建Dockerfilefunc generateDockerfile(platform Platform, cds *pb.ChaincodeDeploymentS pec, tls bool) ([]byte, error)//调取platform.GenerateDockerBuild(cds, tw),创建DockerBuildfunc generateDockerBuild(platform Platform, cds *pb.ChaincodeDeployment Spec, inputFiles InputFiles, tw *tar.Writer) error//调取generateDockerfile(platform, cds, cert != nil)func GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec) (io.Reader, e rror)//代码在core/chaincode/platforms/platforms.go```### 3.2、Docker相关工具函数```go//contents+hash合并后再哈希func ComputeHash(contents []byte, hash []byte) []byte//哈希目录下文件并打包func HashFilesInDir(rootDir string, dir string, hash []byte, tw *tar.Wr iter) ([]byte, error)//目录是否存在func IsCodeExist(tmppath string) error//编译链码func DockerBuild(opts DockerBuildOptions) error//代码在core/chaincode/platforms/util/utils.go```func DockerBuild(opts DockerBuildOptions) error代码如下:```gotype DockerBuildOptions struct {Image stringEnv []stringCmd stringInputStream io.ReaderOutputStream 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.CreateContainerOpti ons{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: cont ainer.ID})//上传输入err = client.UploadToContainer(container.ID, docker.UploadToContain erOptions{Path: "/chaincode/input",InputStream: opts.InputStream,})stdout := bytes.NewBuffer(nil)_, err = client.AttachToContainerNonBlocking(docker.AttachToContain erOptions{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.DownloadFro mContainerOptions{Path: "/chaincode/output/.",OutputStream: opts.OutputStream,})return nil}//代码在core/chaincode/platforms/util/utils.go```## 4、golang语言平台实现### 4.1、golang.Platform结构体定义及方法Platform接口golang语言平台实现,即golang.Platform结构体定义及方法。
兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二。
涉及方法如下:```go//构造blockIndexfunc newBlockIndex(indexConfig *blkstorage.IndexConfig, db*leveldbhelper.DBHandle) *blockIndex//获取最后一个块索引(或编号),取key为"indexCheckpointKey"的值,即为最新的区块编号func (index *blockIndex) getLastBlockIndexed() (uint64, error)func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error //索引区块//根据区块哈希,获取文件区块指针func (index *blockIndex) getBlockLocByHash(blockHash []byte)(*fileLocPointer, error)//根据区块编号,获取文件区块指针func (index *blockIndex) getBlockLocByBlockNum(blockNum uint64)(*fileLocPointer, error)//根据交易ID,获取文件交易指针func (index *blockIndex) getTxLoc(txID string) (*fileLocPointer, error) //根据交易ID,获取文件区块指针func (index *blockIndex) getBlockLocByTxID(txID string) (*fileLocPointer, error)//根据区块编号和交易编号,获取文件交易指针func (index *blockIndex) getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error)//根据交易ID,获取交易验证代码func (index *blockIndex) getTxValidationCodeByTxID(txID string)(peer.TxValidationCode, error)//代码在common/ledger/blkstorage/fsblkstorage/blockindex.go```补充blockIdxInfo结构体定义:块索引信息。
兄弟连区块链教程Fabric1.0源代码分析Proposal(提案)兄弟连区块链教程Fabric1.0源代码分析Proposal(提案),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric1.0源代码笔记之Proposal(提案)## 1、Proposal概述Proposal,即向Endorser发起的提案。
Proposal代码分布在protos/utils、protos/peer目录下,目录结构如下:protos/utils目录:proputils.go,Proposal工具函数。
txutils.go,Proposal工具函数。
protos/peer目录:proposal.pb.go,Proposal相关结构体定义。
## 2、Proposal相关结构体定义有个图3### 2.1、SignedProposal定义```gotype SignedProposal struct {ProposalBytes []byte //Proposal序列化,即type Proposal structSignature []byte //signer.Sign(ProposalBytes)}//代码在protos/peer/proposal.pb.go```### 2.2、Proposal定义```gotype Proposal struct {Header []byte //Header序列化,即type Header structPayload []byte //ChaincodeProposalPayload序列化,即type ChaincodeProposalPayload structExtension []byte //扩展}//代码在protos/peer/proposal.pb.go```Header更详细内容,参考:Fabric 1.0源代码笔记之 Tx(Transaction 交易)### 2.3、ChaincodeProposalPayload定义```gotype ChaincodeProposalPayload struct {Input []byte //ChaincodeInvocationSpec序列化,即type ChaincodeInvocationSpec structTransientMap map[string][]byte //瞬态映射}//代码在protos/peer/proposal.pb.go```ChaincodeInvocationSpec更详细内容,参考:Fabric 1.0源代码笔记之 Chaincode (链码)## 3、ProposalResponse结构体定义### 3.1、ProposalResponse定义```gotype ProposalResponse struct {Version int32Timestamp *google_protobuf1.TimestampResponse *Response //type Response struct,peer.Response{Status: 200, Message: "OK"}}Payload []byteEndorsement *Endorsement //type Endorsement struct}//代码在protos/peer/proposal_response.pb.go```### 3.2、Response定义```gotype Response struct { //peer.Response{Status: 200, Message: "OK"}}Status int32Message stringPayload []byte}//代码在protos/peer/proposal_response.pb.go```### 3.3、Endorsement定义```gotype Endorsement struct {Endorser []byte //bccspmsp.signerSignature []byte}//代码在protos/peer/proposal_response.pb.go ```感谢关注兄弟连区块链教程分享!。
兄弟连区块链教程Fabric1.0源代码分析Ledger idStore(ledgerID数据库)兄弟连区块链教程Fabric1.0源代码分析Ledger idStore(ledgerID数据库),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 Ledger #idStore(ledgerID数据库)## 1、idStore概述* Fabric支持创建多个Ledger,不同Ledger以ledgerID区分。
* 多个ledgerID及其创世区块存储在idStore数据库中,idStore数据库基于leveldb 实现。
* idStore默认使用路径:/var/hyperledger/production/ledgersData/ledgerProvider/。
* idStore库中特殊key "underConstructionLedgerKey",用于标志最新在建的ledgerID,ledgerID创建成功后或失败时该标志将清除,另外此标志也用于异常时按ledgerID恢复数据。
* idStore相关代码集中在core/ledger/kvledger/kv_ledger_provider.go。
## 2、idStore结构体定义leveldbhelper更详细内容,参考:[Fabric 1.0源代码笔记之 LevelDB(KV数据库)](../leveldb/README.md)```gotype idStore struct {db *leveldbhelper.DB}//代码在core/ledger/kvledger/kv_ledger_provider.go```## 3、idStore方法定义```gofunc openIDStore(path string) *idStore //按path创建并打开leveldb数据库func (s *idStore) setUnderConstructionFlag(ledgerID string) error //设置ledgerID在建标志,将key为"underConstructionLedgerKey",value为ledgerID写入库func (s *idStore) unsetUnderConstructionFlag() error //取消ledgerID在建标志(确认构建失败时),删除key"underConstructionLedgerKey"func (s *idStore) getUnderConstructionFlag() (string, error) //获取ledgerID 在建标志(按ledgerID恢复时),按key"underConstructionLedgerKey",取ledgerID func (s *idStore) createLedgerID(ledgerID string, gb *common.Block) error //创建LedgerID,即以ledgerID为key,将创世区块写入库func (s *idStore) ledgerIDExists(ledgerID string) (bool, error) //查找ledgerID是否存在,即查库中key为ledgerID是否存在func (s *idStore) getAllLedgerIds() ([]string, error) //获取ledgerID列表func (s *idStore) close() //关闭idStore leveldb数据库func (s *idStore) encodeLedgerKey(ledgerID string) []byte //为ledgerID添加前缀即"l"func (s *idStore) decodeLedgerID(key []byte) string //解除ledgerID前缀//代码在core/ledger/kvledger/kv_ledger_provider.go```func (s *idStore) createLedgerID(ledgerID string, gb *common.Block) error 代码如下:将ledgerID和Block入库,并清除ledgerID在建标志。
兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 Peer #peer node start命令实现有个图2## 1、peer node加载子命令start和statuspeer node加载子命令start和status,代码如下:```gofunc Cmd() *mand {nodeCmd.AddCommand(startCmd()) //加载子命令startnodeCmd.AddCommand(statusCmd()) //加载子命令statusreturn nodeCmd}var nodeCmd = &mand{Use: nodeFuncName,Short: fmt.Sprint(shortDes),Long: fmt.Sprint(longDes),}//代码在peer/node/node.go```startCmd()代码如下:其中serve(args)为peer node start的实现代码,比较复杂,本文将重点讲解。
另statusCmd()代码与startCmd()相近,暂略。
```gofunc startCmd() *mand {flags := nodeStartCmd.Flags()flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, "Whether peer in chaincode development mode")flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", false, "Whether to start peer with chain testchainid")flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint") //ordererreturn nodeStartCmd}var nodeStartCmd = &mand{Use: "start",Short: "Starts the node.",Long: `Starts a node that interacts with the network.`,RunE: func(cmd *mand, args []string) error {return serve(args) //serve(args)为peer node start的实现代码},}//代码在peer/node/start.go```**注:如下内容均为serve(args)的代码,即peer node start命令执行流程。
兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令一兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 Peer #peer根命令入口及加载子命令## 1、加载环境变量配置和配置文件Fabric支持通过环境变量对部分配置进行更新,如:CORE_LOGGING_LEVEL为输出的日志级别、CORE_PEER_ID为Peer的ID等。
此部分功能由第三方包viper来实现,viper除支持环境变量的配置方式外,还支持配置文件方式。
viper使用方法参考:https:///spf13/viper。
如下代码为加载环境变量配置,其中cmdRoot为"core",即CORE_开头的环境变量。
```goviper.SetEnvPrefix(cmdRoot)viper.AutomaticEnv()replacer := strings.NewReplacer(".", "_")viper.SetEnvKeyReplacer(replacer)//代码在peer/main.go```加载配置文件,同样由第三方包viper来实现,具体代码如下:其中cmdRoot为"core",即/etc/hyperledger/fabric/core.yaml。
```goerr := common.InitConfig(cmdRoot)//代码在peer/main.go```如下代码为common.InitConfig(cmdRoot)的具体实现:```goconfig.InitViper(nil, cmdRoot)err := viper.ReadInConfig()//代码在peer/common/common.go```另附config.InitViper(nil, cmdRoot)的代码实现:优先从环境变量FABRIC_CFG_PATH中获取配置文件路径,其次为当前目录、开发环境目录(即:src//hyperledger/fabric/sampleconfig)、和OfficialPath(即:/etc/hyperledger/fabric)。
兄弟连区块链教程Fabric1.0源代码分析consenter#filter兄弟连区块链教程Fabric1.0源代码分析consenter(共识插件)#filter(过滤器),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 consenter(共识插件) #filter(过滤器)## 1、filter概述filter代码分布在orderer/common/filter、orderer/common/configtxfilter、orderer/common/sizefilter、orderer/common/sigfilter、orderer/multichain目录下。
orderer/common/filter/filter.go,Rule接口定义及emptyRejectRule和acceptRule实现,Committer接口定义及noopCommitter实现,RuleSet结构体及方法。
orderer/common/configtxfilter目录,configFilter结构体(实现Rule接口)及configCommitter结构体(实现Committer接口)。
orderer/common/sizefilter目录,maxBytesRule结构体(实现Rule接口)。
orderer/multichain/chainsupport.go,filter工具函数。
orderer/multichain/systemchain.go,systemChainFilter结构体(实现Rule接口)及systemChainCommitter结构体(实现Committer接口)。
## 2、Rule接口定义及实现### 2.1、Rule接口定义```gotype Action intconst (Accept = iotaRejectForward)type Rule interface { //定义一个过滤器函数, 它接受、拒绝或转发 (到下一条规则) 一个信封Apply(message *ab.Envelope) (Action, Committer)}//代码在orderer/common/filter/filter.go```### 2.2、emptyRejectRule(校验是否为空过滤器)```gotype emptyRejectRule struct{}var EmptyRejectRule = Rule(emptyRejectRule{})func (a emptyRejectRule) Apply(message *ab.Envelope) (Action, Committer) {if message.Payload == nil {return Reject, nil}return Forward, nil}//代码在orderer/common/filter/filter.go```### 2.3、acceptRule(接受过滤器)```gotype acceptRule struct{}var AcceptRule = Rule(acceptRule{})func (a acceptRule) Apply(message *ab.Envelope) (Action, Committer) {return Accept, NoopCommitter}//代码在orderer/common/filter/filter.go```### 2.4、configFilter(配置交易合法性过滤器)```gotype configFilter struct {configManager api.Manager}func NewFilter(manager api.Manager) filter.Rule //构造configFilter//配置交易过滤器func (cf *configFilter) Apply(message *cb.Envelope) (filter.Action, mitter) {msgData, err := utils.UnmarshalPayload(message.Payload) //获取Payload chdr, err :=utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader) //获取ChannelHeaderif chdr.Type != int32(cb.HeaderType_CONFIG) { //配置交易return filter.Forward, nil}configEnvelope, err := configtx.UnmarshalConfigEnvelope(msgData.Data) //获取configEnvelopeerr = cf.configManager.Validate(configEnvelope) //校验configEnvelope return filter.Accept, &configCommitter{manager: cf.configManager,configEnvelope: configEnvelope,}}//代码在orderer/common/configtxfilter/filter.go```### 2.5、sizefilter(交易大小过滤器)```gotype maxBytesRule struct {support Support}func MaxBytesRule(support Support) filter.Rule //构造maxBytesRulefunc (r *maxBytesRule) Apply(message *cb.Envelope) (filter.Action, mitter) {maxBytes := r.support.BatchSize().AbsoluteMaxBytesif size := messageByteSize(message); size > maxBytes {return filter.Reject, nil}return filter.Forward, nil}//代码在orderer/common/sizefilter/sizefilter.go```### 2.6、sigFilter(签名数据校验过滤器)```gotype sigFilter struct {policySource stringpolicyManager policies.Manager}func New(policySource string, policyManager policies.Manager) filter.Rule //构造sigFilterfunc (sf *sigFilter) Apply(message *cb.Envelope) (filter.Action,mitter) {signedData, err := message.AsSignedData() //构造SignedDatapolicy, ok := sf.policyManager.GetPolicy(sf.policySource) //获取策略 err = policy.Evaluate(signedData) //校验策略if err == nil {return filter.Forward, nil}return filter.Reject, nil}//代码在orderer/common/sigfilter/sigfilter.go```### 2.7、systemChainFilter(系统链过滤器)```gotype systemChainFilter struct {cc chainCreatorsupport limitedSupport}func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule //构造systemChainFilterfunc (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, mitter) {msgData := &cb.Payload{}err := proto.Unmarshal(env.Payload, msgData) //获取Payloadchdr, err :=utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader)if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION){ //ORDERER_TRANSACTIONreturn filter.Forward, nil}maxChannels := scf.support.SharedConfig().MaxChannelsCount()if maxChannels > 0 {if uint64(.channelsCount()) > maxChannels {return filter.Reject, nil}}configTx := &cb.Envelope{}err = proto.Unmarshal(msgData.Data, configTx)err = scf.authorizeAndInspect(configTx)return filter.Accept, &systemChainCommitter{filter: scf,configTx: configTx,}}//代码在orderer/multichain/systemchain.go```## 3、Committer接口定义及实现### 3.1、Committer接口定义```gotype Committer interface {Commit() //提交Isolated() bool //判断交易是孤立的块,或与其他交易混合的块}//代码在orderer/common/filter/filter.go```### 3.2、noopCommitter```gotype noopCommitter struct{}var NoopCommitter = Committer(noopCommitter{})func (nc noopCommitter) Commit() {}func (nc noopCommitter) Isolated() bool { return false } //代码在orderer/common/filter/filter.go```### 3.3、configCommitter```gotype configCommitter struct {manager api.ManagerconfigEnvelope *cb.ConfigEnvelope}func (cc *configCommitter) Commit() {err := cc.manager.Apply(cc.configEnvelope)}func (cc *configCommitter) Isolated() bool {return true}//代码在orderer/common/configtxfilter/filter.go```### 3.4、systemChainCommitter```gotype systemChainCommitter struct {filter *systemChainFilterconfigTx *cb.Envelope}func (scc *systemChainCommitter) Isolated() bool {return true}func (scc *systemChainCommitter) Commit() {.newChain(scc.configTx)}//代码在orderer/multichain/systemchain.go```### 4、RuleSet结构体及方法```gotype RuleSet struct {rules []Rule}func NewRuleSet(rules []Rule) *RuleSet //构造RuleSetfunc (rs *RuleSet) Apply(message *ab.Envelope) (Committer, error) { for _, rule := range rs.rules {action, committer := rule.Apply(message)switch action {case Accept: //接受return committer, nilcase Reject: //拒绝return nil, fmt.Errorf("Rejected by rule: %T", rule)default:}}return nil, fmt.Errorf("No matching filter found")}//代码在orderer/common/filter/filter.go```### 5、filter工具函数```go//为普通 (非系统) 链创建过滤器集func createStandardFilters(ledgerResources *ledgerResources)*filter.RuleSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()),//sizefiltersigfilter.New(policies.ChannelWriters,ledgerResources.PolicyManager()), //sigfilterconfigtxfilter.NewFilter(ledgerResources), //configtxfilter filter.AcceptRule, //AcceptRule})}//为系统链创建过滤器集func createSystemChainFilters(ml *multiLedger, ledgerResources*ledgerResources) *filter.RuleSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()),//sizefiltersigfilter.New(policies.ChannelWriters,ledgerResources.PolicyManager()), //sigfilternewSystemChainFilter(ledgerResources, ml),configtxfilter.NewFilter(ledgerResources), //configtxfilter filter.AcceptRule, //AcceptRule})}//代码在orderer/multichain/chainsupport.go```。
兄弟连区块链教程Fabric1.0源代码分析policy(背书策略)兄弟连区块链教程Fabric1.0源代码分析policy(背书策略),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 policy(背书策略)## 1、policy概述policy代码分布在core/policy、core/policyprovider、common/policies目录下。
目录结构如下:* core/policy/policy.go,PolicyChecker接口定义及实现、PolicyCheckerFactory 接口定义。
* core/policyprovider/provider.go,PolicyChecker工厂默认实现。
* common/policies目录* policy.go,ChannelPolicyManagerGetter接口及实现。
* implicitmeta_util.go,通道策略工具函数。
## 2、PolicyChecker工厂### 2.1、PolicyCheckerFactory接口定义```gotype PolicyCheckerFactory interface {NewPolicyChecker() PolicyChecker //构造PolicyChecker实例}var pcFactory PolicyCheckerFactory //全局变量定义及赋值函数func RegisterPolicyCheckerFactory(f PolicyCheckerFactory) {pcFactory = f}//代码在core/policy/policy.go```### 2.2、PolicyCheckerFactory接口默认实现```gotype defaultFactory struct{}//构造policy.PolicyCheckerfunc (f *defaultFactory) NewPolicyChecker() policy.PolicyChecker {return policy.NewPolicyChecker(peer.NewChannelPolicyManagerGetter(),//&channelPolicyManagerGetter{}mgmt.GetLocalMSP(),mgmt.NewLocalMSPPrincipalGetter(),)}//获取policy.PolicyChecker,即调用policy.GetPolicyChecker()func GetPolicyChecker() policy.PolicyCheckerfunc init() { //初始化全局变量pcFactorypolicy.RegisterPolicyCheckerFactory(&defaultFactory{})}```## 3、PolicyChecker接口定义及实现### 3.1、PolicyChecker接口定义```gotype PolicyChecker interface {CheckPolicy(channelID, policyName string, signedProp*pb.SignedProposal) errorCheckPolicyBySignedData(channelID, policyName string, sd[]*common.SignedData) errorCheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error}//代码在core/policy/policy.go```### 3.2、PolicyChecker接口实现PolicyChecker接口实现,即policyChecker结构体及方法。
兄弟连区块链教程Fabric1.0源代码分析配置jiaoyi-生成通道配置兄弟连区块链教程Fabric1.0源代码分析配置jiaoyi-生成通道配置,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 configtx(配置jiaoyi) #configtxgen(生成通道配置)## 1、configtxgen概述configtxgen,用于生成通道配置,具体有如下三种用法:* 生成Orderer服务启动的初始区块(即系统通道的创世区块文件)* configtxgen -profile TwoOrgsOrdererGenesis-outputBlock ./channel-artifacts/genesis.block* 生成新建应用通道的配置jiaoyi(即用于创建应用通道的配置jiaoyi文件)* configtxgen -profile TwoOrgsChannel-outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel* 生成锚节点配置更新文件* configtxgen -profile TwoOrgsChannel-outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx-channelID mychannel -asOrg Org1MSPconfigtxgen代码分布在common/configtx/tool目录,目录结构如下:* localconfig/config.go,configtx.yaml配置文件相关的结构体及方法。
## 2、configtx.yaml配置文件示例```bashProfiles:TwoOrgsOrdererGenesis: #Orderer系统通道配置Orderer:<<: *OrdererDefaults #引用OrdererDefaults并合并到当前Organizations: #属于Orderer通道的组织- *OrdererOrgConsortiums: #Orderer所服务的联盟列表SampleConsortium:Organizations:- *Org1- *Org2TwoOrgsChannel: #应用通道配置Consortium: SampleConsortium #应用通道关联的联盟Application:<<: *ApplicationDefaults #引用ApplicationDefaults并合并到当前 Organizations: #初始加入应用通道的组织- *Org1- *Org2Organizations:- &OrdererOrgName: OrdererOrgID: OrdererMSP # MSP IDMSPDir: crypto-config/ordererOrganizations//msp #MSP 相关文件本地路径- &Org1Name: Org1MSPID: Org1MSPMSPDir: crypto-config/peerOrganizations//mspAnchorPeers: #锚节点地址,用于跨组织的Gossip通信- Host: Port: 7051- &Org2Name: Org2MSPID: Org2MSPMSPDir: crypto-config/peerOrganizations//mspAnchorPeers: #锚节点地址,用于跨组织的Gossip通信- Host: Port: 7051Orderer: &OrdererDefaultsOrdererType: solo # Orderer共识插件类型,分solo或kafkaAddresses:- :7050 #服务地址BatchTimeout: 2s #创建批量jiaoyi的zui大超时,一批jiaoyi构成一个块BatchSize: #写入区块内的jiaoyi个数MaxMessageCount: 10 #一批消息的zui大个数AbsoluteMaxBytes: 98 MB #一批jiaoyi的zui大字节数,任何时候均不能超过PreferredMaxBytes: 512 KB #批量jiaoyi的建议字节数Kafka:Brokers: #Kafka端口- 127.0.0.1:9092Organizations: #参与维护Orderer的组织,默认空Application: &ApplicationDefaultsOrganizations: #加入到通道的组织信息,此处为不包括任何组织```配置文件解读:* 每个Profile表示某种场景下的通道配置模板,包括Orderer系统通道模板和应用通道模板,其中TwoOrgsOrdererGenesis为系统通道模板,TwoOrgsChannel为应用通道模板。
兄弟连区块链教程Fabric1.0源代码分析putils(protos/utils工具包)兄弟连区块链教程Fabric1.0源代码分析putils(protos/utils工具包),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric1.0源代码笔记之putils(protos/utils工具包)## 1、putils概述putils,即protos/utils工具包,代码分布在:protos/utils目录下。
包括:txutils.go、proputils.go、commonutils.go、blockutils.go。
## 2、txutils```go//TransactionAction.Payload => ChaincodeActionPayload//ChaincodeActionPayload.Action.ProposalResponsePayload => ProposalResponsePayload//ProposalResponsePayload.Extension => ChaincodeAction//从TransactionAction中获取ChaincodeActionPayload和ChaincodeAction func GetPayloads(txActions *peer.TransactionAction)(*peer.ChaincodeActionPayload, *peer.ChaincodeAction, error)//[]byte反序列化为Envelopefunc GetEnvelopeFromBlock(data []byte) (*common.Envelope, error)func CreateSignedEnvelope(txType common.HeaderType, channelID string, signer crypto.LocalSigner, dataMsg proto.Message, msgVersion int32, epoch uint64) (*common.Envelope, error)//由Proposal创建签名交易Envelopefunc CreateSignedTx(proposal *peer.Proposal, signer msp.SigningIdentity, resps ...*peer.ProposalResponse) (*common.Envelope, error) {func CreateProposalResponse(hdrbytes []byte, payl []byte, response*peer.Response, results []byte, events []byte, ccid *peer.ChaincodeID, visibility []byte, signingEndorser msp.SigningIdentity)(*peer.ProposalResponse, error)func CreateProposalResponseFailure(hdrbytes []byte, payl []byte, response *peer.Response, results []byte, events []byte, ccid *peer.ChaincodeID, visibility []byte) (*peer.ProposalResponse, error)//签名Proposalfunc GetSignedProposal(prop *peer.Proposal, signer msp.SigningIdentity) (*peer.SignedProposal, error)func GetSignedEvent(evt *peer.Event, signer msp.SigningIdentity)(*peer.SignedEvent, error)func MockSignedEndorserProposalOrPanic(chainID string, cs*peer.ChaincodeSpec, creator, signature []byte) (*peer.SignedProposal,*peer.Proposal)func MockSignedEndorserProposal2OrPanic(chainID string, cs*peer.ChaincodeSpec, signer msp.SigningIdentity) (*peer.SignedProposal, *peer.Proposal)func GetBytesProposalPayloadForTx(payload *peer.ChaincodeProposalPayload, visibility []byte) ([]byte, error)func GetProposalHash2(header *common.Header, ccPropPayl []byte) ([]byte, error)func GetProposalHash1(header *common.Header, ccPropPayl []byte, visibility []byte) ([]byte, error)//代码在protos/utils/txutils.go```## 3、proputils```gofunc GetChaincodeInvocationSpec(prop *peer.Proposal)(*peer.ChaincodeInvocationSpec, error)func GetChaincodeProposalContext(prop *peer.Proposal) ([]byte,map[string][]byte, error)//反序列化为common.Headerfunc GetHeader(bytes []byte) (*common.Header, error)func GetNonce(prop *peer.Proposal) ([]byte, error)//Header.ChannelHeader反序列化为peer.ChaincodeHeaderExtensionfunc GetChaincodeHeaderExtension(hdr *common.Header)(*peer.ChaincodeHeaderExtension, error)func GetProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) func GetChaincodeDeploymentSpec(code []byte)(*peer.ChaincodeDeploymentSpec, error)func GetChaincodeAction(caBytes []byte) (*peer.ChaincodeAction, error) func GetResponse(resBytes []byte) (*peer.Response, error)func GetChaincodeEvents(eBytes []byte) (*peer.ChaincodeEvent, error)func GetProposalResponsePayload(prpBytes []byte)(*peer.ProposalResponsePayload, error)func GetProposal(propBytes []byte) (*peer.Proposal, error)//e.Payload反序列化为Payloadfunc GetPayload(e *common.Envelope) (*common.Payload, error)//[]byte反序列化为Transactionfunc GetTransaction(txBytes []byte) (*peer.Transaction, error)func GetChaincodeActionPayload(capBytes []byte)(*peer.ChaincodeActionPayload, error)//反序列化为peer.ChaincodeProposalPayloadfunc GetChaincodeProposalPayload(bytes []byte)(*peer.ChaincodeProposalPayload, error)//反序列化为common.SignatureHeaderfunc GetSignatureHeader(bytes []byte) (*common.SignatureHeader, error) func CreateChaincodeProposal(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error)func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error)func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error)func GetBytesProposalResponsePayload(hash []byte, response *peer.Response, result []byte, event []byte, ccid *peer.ChaincodeID) ([]byte, error)func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error)func GetBytesResponse(res *peer.Response) ([]byte, error)func GetBytesChaincodeEvent(event *peer.ChaincodeEvent) ([]byte, error) func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error)func GetBytesProposalResponse(pr *peer.ProposalResponse) ([]byte, error) func GetBytesProposal(prop *peer.Proposal) ([]byte, error)func GetBytesHeader(hdr *common.Header) ([]byte, error)func GetBytesSignatureHeader(hdr *common.SignatureHeader) ([]byte, error) func GetBytesTransaction(tx *peer.Transaction) ([]byte, error)func GetBytesPayload(payl *common.Payload) ([]byte, error)func GetBytesEnvelope(env *common.Envelope) ([]byte, error)//从envBytes []byte中获取ChaincodeActionfunc GetActionFromEnvelope(envBytes []byte) (*peer.ChaincodeAction, error)func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis*peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error)func CreateInstallProposalFromCDS(ccpack proto.Message, creator []byte) (*peer.Proposal, string, error)//按ChaincodeDeploymentSpec创建DeployProposalfunc CreateDeployProposalFromCDS(chainID string, cds*peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error)func CreateUpgradeProposalFromCDS(chainID string, cds*peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error)func createProposalFromCDS(chainID string, msg proto.Message, creator []byte, policy []byte, escc []byte, vscc []byte, propType string)(*peer.Proposal, string, error)func ComputeProposalTxID(nonce, creator []byte) (string, error)func CheckProposalTxID(txid string, nonce, creator []byte) errorfunc ComputeProposalBinding(proposal *peer.Proposal) ([]byte, error) func computeProposalBindingInternal(nonce, creator []byte, epoch uint64) ([]byte, error)//代码在protos/utils/proputils.go```## 4、commonutils```gofunc MarshalOrPanic(pb proto.Message) []bytefunc Marshal(pb proto.Message) ([]byte, error)func CreateNonceOrPanic() []bytefunc CreateNonce() ([]byte, error)func UnmarshalPayloadOrPanic(encoded []byte) *cb.Payloadfunc UnmarshalPayload(encoded []byte) (*cb.Payload, error)func UnmarshalEnvelopeOrPanic(encoded []byte) *cb.Envelopefunc UnmarshalEnvelope(encoded []byte) (*cb.Envelope, error)func UnmarshalEnvelopeOfType(envelope *cb.Envelope, headerTypecb.HeaderType, message proto.Message) (*cb.ChannelHeader, error)func ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) func ExtractPayloadOrPanic(envelope *cb.Envelope) *cb.Payloadfunc ExtractPayload(envelope *cb.Envelope) (*cb.Payload, error)func MakeChannelHeader(headerType cb.HeaderType, version int32, chainID string, epoch uint64) *cb.ChannelHeaderfunc MakeSignatureHeader(serializedCreatorCertChain []byte, nonce []byte) *cb.SignatureHeaderfunc SetTxID(channelHeader *cb.ChannelHeader, signatureHeader*cb.SignatureHeader) errorfunc MakePayloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader)*cb.Headerfunc NewSignatureHeaderOrPanic(signer crypto.LocalSigner)*cb.SignatureHeaderfunc SignOrPanic(signer crypto.LocalSigner, msg []byte) []byte//[]byte反序列化为ChannelHeaderfunc UnmarshalChannelHeader(bytes []byte) (*cb.ChannelHeader, error) func UnmarshalChaincodeID(bytes []byte) (*pb.ChaincodeID, error)func IsConfigBlock(block *cb.Block) bool//代码在protos/utils/commonutils.go```## 5、blockutils```go//[]byte转换为Block,从Block中获取ChainID(即ChannelId)func GetChainIDFromBlockBytes(bytes []byte) (string, error)//从Block中获取ChainID(即ChannelId)func GetChainIDFromBlock(block *cb.Block) (string, error)//从Block中按index获取Metadatafunc GetMetadataFromBlock(block *cb.Block, index cb.BlockMetadataIndex) (*cb.Metadata, error)//从Block中按index获取Metadata,如果失败则Panicfunc GetMetadataFromBlockOrPanic(block *cb.Block, indexcb.BlockMetadataIndex) *cb.Metadata//从Block.Metadata.Metadata中获取LastConfigfunc GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error)//从Block.Metadata.Metadata中获取LastConfig,如果失败则Panicfunc GetLastConfigIndexFromBlockOrPanic(block *cb.Block) uint64//[]byte转换为Blockfunc GetBlockFromBlockBytes(blockBytes []byte) (*cb.Block, error)//拷贝Block.Metadatafunc CopyBlockMetadata(src *cb.Block, dst *cb.Block)//初始化Block.Metadata.Metadatafunc InitBlockMetadata(block *cb.Block)//代码在protos/utils/blockutils.go```感谢关注兄弟连区块链教程分享!。
兄弟连区块链技术培训Fabric 1.0源代码分析(47)ECDSA (椭圆曲线数字签名算法)# Fabric 1.0源代码笔记之 ECDSA(椭圆曲线数字签名算法)## 1、椭圆曲线算法概述### 1.1、无穷远点、无穷远直线、射影平面* 平行线相交于无穷远点;* 直线上有且只有一个无穷远点;* 一组相互平行的直线有公共的无穷远点;* 平面上任何相交的两直线,有不同的无穷远点;* 全部无穷远点沟通一条无穷远直线;* 平面上全部无穷远点和全部普通点构成射影平面。
### 1.2、射影平面点定义对于普通平面上点(x, y),令x=X/Z,y=Y/Z,Z≠0,则投影为射影平面上的点为(X : Y : Z)。
如点(1,2)在射影平面的坐标为:(Z : 2Z : Z) Z≠0,即(1 : 2 : 1)或(2 : 4 : 2)均为(1, 2)在射影平面上的点。
Z=0时,(X : Y : 0)即为无穷远点,Z=0即为无穷远直线。
### 1.3、椭圆曲线方程椭圆曲线的定义:一条椭圆曲线是在射影平面上满足方程Y²Z+a1XYZ+a3YZ²=X³+a2X²Z+a4XZ²+a6Z³的所有点的集合,且曲线上的每个点都是非奇异(或光滑)的。
该方程为维尔斯特拉斯方程,是一个齐次方程。
所谓“非奇异”或“光滑”的,即满足方程的任意一点都存在切线。
椭圆曲线存在无穷远点(0, Y, 0),可以在平面坐标系中用椭圆曲线、加一个无穷远点来表示。
令x=X/Z,y=Y/Z,代入椭圆曲线方程,即椭圆曲线普通方程:y²+a1xy+a3y = x³+a2x²+a4x+a6。
### 1.4、椭圆曲线上的加法任意取椭圆曲线上两点P、Q (若P、Q两点重合,则做P点的切线)做直线交于椭圆曲线的另一点R’,过R’做y轴的平行线交于R。
我们规定P+Q=R。
根据这个法则,可以知道椭圆曲线无穷远点O∞与椭圆曲线上一点P的连线交于P’,过P’作y轴的平行线交于P,所以有无穷远点O∞+ P = P 。
这样,无穷远点O∞的作用与普通加法中零的作用相当(0+2=2),我们把无穷远点O∞ 称为零元。
同时我们把P’称为P的负元(简称,负P;记作,-P)。
根据这个法则,可以得到如下结论:如果椭圆曲线上的三个点A、B、C,处于同一条直线上,那么他们的和等于零元,即A+B+C= O∞ 。
k个相同的点P相加,我们记作kP。
如:P+P+P = 2P+P = 3P。
### 1.5、有限域椭圆曲线椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点,我们要把椭圆曲线定义在有限域上。
* 我们给出一个有限域Fp* Fp中有p(p为质数)个元素0,1,2,…, p-2,p-1* Fp的加法是a+b≡c(mod p)* Fp的乘法是a×b≡c(mod p)* Fp的除法是a÷b≡c(mod p),即 a×b^(-1)≡c (mod p),b^(-1)也是一个0到p-1之间的整数,但满足b×b^(-1)≡1 (mod p)* Fp的单位元是1,零元是0同时,并不是所有的椭圆曲线都适合加密。
y²=x³+ax+b是一类可以用来加密的椭圆曲线,也是最为简单的一类。
下面我们就把y²=x³+ax+b这条曲线定义在Fp上:选择两个满足下列条件的小于p(p为素数)的非负整数a、b,4a³+27b²≠0(mod p) 。
则满足下列方程的所有点(x,y),再加上无穷远点O∞ ,构成一条椭圆曲线。
y²=x³+ax+b (mod p) 其中 x,y属于0到p-1间的整数,并将这条椭圆曲线记为Ep(a,b)。
Fp上的椭圆曲线同样有加法,但已经不能给以几何意义的解释。
```无穷远点O∞是零元,有O∞+ O∞= O∞,O∞+P=PP(x,y)的负元是 (x,-y),有P+(-P)= O∞P(x1,y1),Q(x2,y2)的和R(x3,y3) 有如下关系:x3≡k2-x1-x2(mod p)y3≡k(x1-x3)-y1(mod p)其中若P=Q 则 k=(3x1²+a)/2y1 若P≠Q,则k=(y2-y1)/(x2-x1)```例已知E23(1,1)上两点P(3,10),Q(9,7),求1)-P,2)P+Q,3) 2P。
```1) –P的值为(3,-10)2) k=(7-10)/(9-3)=-1/2,2的乘法逆元为12 因为2*12≡1 (mod 23)k≡-1*12 (mod 23) 故 k=11。
x=112-3-9=109≡17 (mod 23);y=11[3-(-6)]-10=89≡20 (mod 23)故P+Q的坐标为(17,20)3) k=[3(3²)+1]/(2*10)=1/4≡6 (mod 23)x=62-3-3=30≡20 (mod 23)y=6(3-7)-10=-34≡12 (mod 23)故2P的坐标为(7,12)```如果椭圆曲线上一点P,存在最小的正整数n,使得数乘nP=O∞,则将n称为P的阶,若n 不存在,我们说P是无限阶的。
事实上,在有限域上定义的椭圆曲线上所有的点的阶n都是存在的。
### 1.6、椭圆曲线上简单的加密/解密考虑如下等式:K=kG [其中 K,G为Ep(a,b)上的点,k为小于n(n是点G的阶)的整数]。
不难发现,给定k和G,根据加法法则,计算K很容易;但给定K和G,求k就相对困难了。
这就是椭圆曲线加密算法采用的难题。
我们把点G称为基点(base point),k(k<n,n为基点G的阶)称为私有密钥(privt e key),K称为公开密钥(public key)。
补充:如上内容参考自* [【信息安全】ECC加密算法入门介绍](https:///articles/23897) * [ECC椭圆曲线详解(有具体实例)](https:///articles/23897)## 2、椭圆曲线接口及实现### 2.1、椭圆曲线接口定义```gotype Curve interface {Params() *CurveParams //返回曲线参数IsOnCurve(x, y *big.Int) bool //(x,y)是否在曲线上Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) //(x1,y1)和(x2,y2)求和Double(x1, y1 *big.Int) (x, y *big.Int) //2*(x,y)ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) //返回k*(Bx,B y)ScalarBaseMult(k []byte) (x, y *big.Int) //返回k*G,其中G为基点}//代码在crypto/elliptic/elliptic.go```### 2.2、CurveParams结构体定义及通用实现CurveParams包括椭圆曲线的参数,并提供了一个通用椭圆曲线实现。
代码如下:```gotype CurveParams struct {P *big.Int //% p中的pN *big.Int //基点的阶,如果椭圆曲线上一点P,存在最小的正整数n,使得数乘n P=O∞,则将n称为P的阶B *big.Int //曲线方程中常数b,如y² = x³ - 3x + bGx, Gy *big.Int //基点G(x,y)BitSize int //基础字段的大小Name string //椭圆曲线的名称}//代码在crypto/elliptic/elliptic.go```CurveParams涉及如下方法:```gofunc (curve *CurveParams) Params() *CurveParams //返回曲线参数,即curve func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool //(x,y)是否在曲线上func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big. Int) //(x1,y1)和(x2,y2)求和func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) //2*(x,y)func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.I nt, *big.Int) //返回k*(Bx,By)func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) //返回k*G,其中G为基点//代码在crypto/elliptic/elliptic.go```### 2.3、几种曲线```gofunc P224() Curve //实现了P-224的曲线func P256() Curve //实现了P-256的曲线func P384() Curve //实现了P-384的曲线func P521() Curve //实现了P-512的曲线//代码在crypto/elliptic/elliptic.go```## 3、椭圆曲线数字签名算法结构体定义:```gotype PublicKey struct { //公钥elliptic.CurveX, Y *big.Int}type PrivateKey struct { //私钥PublicKeyD *big.Int}type ecdsaSignature struct { //椭圆曲线签名R, S *big.Int}//代码在crypto/ecdsa/ecdsa.go```涉及如下方法:```gofunc (priv *PrivateKey) Public() crypto.PublicKey //获取公钥func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.Si gnerOpts) ([]byte, error) //使用私钥对任意长度的hash值进行签名func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) //生成一对公钥/私钥func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) //使用私钥对任意长度的hash值进行签名func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool //使用公钥验证hash值和两个大整数r、s构成的签名//代码在crypto/ecdsa/ecdsa.go```## 4、本文使用到的网络内容* [初学者如何理解射影平面](https:///view/3d245b608e9951e79 b892768.html)* [ECC椭圆曲线详解(有具体实例)](/Kalafinaian/p/7392 505.html)* [说说椭圆曲线](/s/blog_564e1db00102vq25.html) * [椭圆曲线密码学简介](/introduction)* [【信息安全】ECC加密算法入门介绍](https:///articles/23897) * [椭圆曲线算法:入门(1)](/p/2e6031ac3d50)。