《HyperLedger Fabric 实战》—— 十、项目演练 -- 反欺诈系统

《HyperLedger Fabric 实战》—— 十、项目演练 – 反欺诈系统

注意点

1、用户唯一ID应该是姓名与身份证号组合后的MD5,这样可以防止加盟用户仅通过机器生成的大量身份证号来恶意刷区块链平台;

  2、合约不应以用户为核心,而应以用户及小贷公司的合同作为合约核心,以防止加盟方自身的Bug等问题,向联盟平台写入大量无法溯源的用户数据,而导致错误;

编写贷款合约

finance/bean/compact.go

package bean

import (
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"fmt"
	"time"
	"encoding/json"
)

// 合同全集详情
// 本条记录主键key由成员ID和合同ID联合组成,且备唯一性
type Compact struct {
	Timestamp        int64  `json:"timestamp"`        // 本条记录创建时间戳
	Uid              string `json:"uid"`              // 用户唯一ID(32位MD5值)
	LoanAmount       string `json:"loanAmount"`       // 用户贷款金额
	ApplyDate        string `json:"applyDate"`        // 申请日期
	CompactStartDate string `json:"compactStartDate"` // 贷款开始日期
	CompactEndDate   string `json:"compactEndDate"`   // 贷款计划终止日期
	RealEndDate      string `json:"realEndDate"`      // 贷款实际终止日期
}

// 贷款操作
// args: UID、贷款金额、申请日期、贷款开始日期、贷款计划终止日期、合同ID
// name: 成员名称
func Loan(stub shim.ChaincodeStubInterface, args []string, name string) error {
	if len(args) != 6 {
		return fmt.Errorf("Parameter count error while Loan, count must 5")
	}
	if len(args[0]) != 32 {
		return fmt.Errorf("Parameter uid length error while Loan, 32 is right")
	}
	if len(args[2]) != 14 {
		return fmt.Errorf("Parameter ApplyDate length error while Loan, 14 is right")
	}
	if len(args[3]) != 14 {
		return fmt.Errorf("Parameter CompactStartDate lengh error while Loan, 14 is right")
	}
	if len(args[4]) != 24 {
		return fmt.Errorf("Parameter CompactEndDate length error while Loan, 14 is right")
	}
	var compact Compact
	compact.Uid = args[0]
	compact.LoanAmount = args[1]
	compact.ApplyDate = args[2]
	compact.CompactStartDate = args[3]
	compact.CompactEndDate = args[4]
	compact.Timestamp = time.Now().Unix()

	compactJsonBytes, err := json.Marshal(&compact) // Json序列化
	if err != nil {
		return fmt.Errorf("Json serialize Compact fail while Loan, compact id = " + args[5])
	}

	// 生成合同联合主键
	key, err := stub.CreateCompositeKey("Compact", []string{name, args[5]})
	if err != nil {
		return fmt.Errorf("Failed to CreateCompositeKey while Loan")
	}
	// 保存合同信息
	err = stub.PutState(key, compactJsonBytes)
	if err != nil {
		return fmt.Errorf("Failed to PutState while Loan, compact id = " + args[5])
	}
	return nil
}

finance/utils/utils.go

package utils

import (
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"strings"
	"bytes"
	"fmt"
	"encoding/pem"
	"crypto/x509"
)

// 获取当前操作智能合约成员具体名称,如a1aw28
func GetCreatorName(stub shim.ChaincodeStubInterface) (string, error) {
	name, err := GetCreator(stub) // 获取当前智能合约操作成员名称
	if err != nil {
		return "", err
	}
	// 格式化当前智能合约操作成员名称
	memberName := name[(strings.Index(name, "@") + 1):strings.LastIndex(name, ".example.com")]
	return memberName, nil;
}

// 获取操作成员
func GetCreator(stub shim.ChaincodeStubInterface) (string, error) {
	creatorByte, _ := stub.GetCreator()
	certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
	if certStart == -1 {
		fmt.Errorf("No certificate found")
	}
	certText := creatorByte[certStart:]
	bl, _ := pem.Decode(certText)
	if bl == nil {
		fmt.Errorf("Could not decode the PEM structure")
	}

	cert, err := x509.ParseCertificate(bl.Bytes)
	if err != nil {
		fmt.Errorf("ParseCertificate failed")
	}
	uname := cert.Subject.CommonName
	return uname, nil
}

finance/finance.go

package main

import (
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/protos/peer"
	"fmt"

	"github.com/hyperledger/fabric/examples/chaincode/go/finance/bean"
	"github.com/hyperledger/fabric/examples/chaincode/go/finance/utils"
)

type Finance struct {
}

func (t *Finance) Init(stub shim.ChaincodeStubInterface) peer.Response {
	args := stub.GetStringArgs()
	if len(args) != 0 {
		return shim.Error("Parameter error while Init")
	}
	return shim.Success(nil)
}

func (t *Finance) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	fn, args := stub.GetFunctionAndParameters()
	switch fn {
		case "loan": // 记录贷款数据
			return loan(stub, args)
		default:
			return shim.Error("Unknown func type while Invoke, please check")
	}
}

// 记录贷款数据
func loan(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	name, err := utils.GetCreatorName(stub)
	if err != nil {
		return shim.Error(err.Error())
	}

	err = bean.Loan(stub, args, name)
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success([]byte("记录贷款数据成功"))
}

func main() {
	if err := shim.Start(new(Finance)); err != nil {
		fmt.Printf("Chaincode startup error: %s", err)
	}
}

上传合约

上传整个 finance 包到 peer 节点服务器的 aberic/chaincode/go 目录下。

安装 & 实例化

peer chaincode install -n finance -p github.com/hyperledger/fabric/aberic/chaincode/go/finance -v 1.0
peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n finance -c '{"Args":[]}' -P "OR ('Org1MSP.member', 'Org2MSP.member')" -v 1.0

升级合约

这一步非必须,笔者是因为第一版合约开发有问题,因此需要升级。

升级需先安装

peer chaincode install -n finance -p github.com/hyperledger/fabric/aberic/chaincode/go/finance -v 1.1
peer chaincode upgrade -C mychannel -n finance -p github.com/hyperledger/fabric/aberic/chaincode/go/finance -v 1.1 -c '{"Args":[]}'

执行贷款操作

peer chaincode invoke -C mychannel -n finance -v 1.0 -c '{"Args":["loan", "4e4d6c332b6fe62a63afe56171fd3725", "200000", "20180420080812", "20180421080812", "20190421080812", "000001"]}'
peer chaincode invoke -C mychannel -n finance -v 1.0 -c '{"Args":["loan", "4e4d6c332b6fe62a63afe56171fd3725", "200000", "20180420080812", "20180421080812", "20190421080812", "000002"]}'
peer chaincode invoke -C mychannel -n finance -v 1.0 -c '{"Args":["loan", "4e4d6c332b6fe62a63afe56171fd3725", "200000", "20180420080812", "20180421080812", "20190421080812", "000003"]}'

CouchDB 索引 & 查询

浏览器打开地址:http://192.168.24.251:5984/_utils/#/database/mychannel_finance/_index

{
	"index": {
		"fields": [
			"uid"
		]
	},
	"name": "indexUid",
	"ddoc": "indexUidDoc",
	"type": "json"
}

CouchDB -> Run A Query with Mango ->

{
	"selector": {
		"uid": "4e4d6c332b6fe62a63afe56171fd3725"
	}
}

Post 方式查询

Postman 发送上面查询 json 到 http://192.168.24.251:5984/mychannel_finance/_find

案例强调

本案例只是演练需求落地,但检索方面不能以这样的方式上生产环境,必须为所有加盟方提供开源可见的查询方法,并在智能合约中体现。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Hyperledger Fabric 1.0 从零开始系列的第二篇文章中,我们将介绍如何使用 fabric-sdk-java 应用程序来与 Hyperledger Fabric 交互。 fabric-sdk-java 是一个 Java 版本的 Hyperledger Fabric SDK,它提供了一种方便的方式来与 Hyperledger Fabric 网络进行交互。它使用 Fabric 的 Java 操作系统链码(Java Chaincode)来运行链码,同时也支持 Go 语言链码。 以下是使用 fabric-sdk-java 的步骤: 1. 下载 fabric-sdk-java,并将其添加到您的 Java 项目中。 2. 创建一个 ConnectionProfile 对象,该对象定义了与 Fabric 网络的连接参数。 3. 创建一个 HFClient 对象,该对象表示一个 Fabric 用户的身份。 4. 通过调用 HFClient 对象的 setUserContext() 方法来设置用户身份。 5. 创建一个 Channel 对象,该对象表示与一个 Fabric 通道的连接。 6. 调用 Channel 对象的 initialize() 方法来初始化通道对象。 7. 创建一个 QueryByChaincodeRequest 对象,该对象用于查询链码。 8.调用 Channel 对象的 queryByChaincode() 方法,并传递 QueryByChaincodeRequest 对象作为参数,以执行查询。 9. 创建一个 TransactionProposalRequest 对象,它用于提交一个事务提议。 10. 调用 Channel 对象的 sendTransactionProposal() 方法,并传递 TransactionProposalRequest 对象作为参数,以向 Fabric 提交事务提议。 11. 创建一个 TransactionRequest 对象,该对象包含有关要提交的事务的详细信息。 12. 调用 Channel 对象的 sendTransaction() 方法,并传递 TransactionRequest 对象作为参数,以提交事务。 通过使用 fabric-sdk-java,您可以轻松地与 Hyperledger Fabric 网络进行交互,并执行各种操作,例如查询链码和提交事务。 希望这篇文章对您有所帮助!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值