区块链银行应用探索(Hyperledger fabric)


声明:本文转载自https://my.oschina.net/neochen/blog/1785361,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

区块链银行应用探索(Hyperledger fabric)

本文节选自电子书《Netkiller Blockchain 手札》

Netkiller Blockchain 手札

本文作者提供有偿顾问服务,有意向致电 13113668890

Mr. Neo Chan, 陈景峯(BG7NYT)

中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 <netkiller@msn.com>

文档始创于2018-02-10

版权 © 2018 Netkiller(Neo Chan). All rights reserved.

版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

微信订阅号 netkiller-ebook (微信扫描二维码)

QQ:13721218 请注明“读者”

QQ群:128659835 请注明“读者”

网站:http://www.netkiller.cn

内容摘要

这一部关于区块链开发及运维的电子书。

为什么会写区块链电子书?因为2018年是区块链年。

这本电子书是否会出版(纸质图书)? 不会,因为互联网技术更迭太快,纸质书籍的内容无法实时更新,一本书动辄百元,很快就成为垃圾,你会发现目前市面的上区块链书籍至少是一年前写的,内容已经过时,很多例子无法正确运行。所以我不会出版,电子书的内容会追逐技术发展,及时跟进软件版本的升级,做到内容最新,至少是主流。

这本电子书与其他区块链书籍有什么不同?市面上大部分区块链书籍都是用2/3去讲区块链原理,只要不到 1/3 的干货,干货不够理论来凑,通篇将理论或是大谈特谈区块链行业,这些内容更多是头脑风暴,展望区块链,均无法落地实施。本书与那些书籍完全不同,不讲理论和原理,面向应用落地,注重例子,均是干货。

电子书更新频率?每天都会有新内容加入,更新频率最迟不会超过一周,更新内容请关注 https://github.com/netkiller/netkiller.github.io/commits/master

本文采用碎片化写作,原文会不定期更新,请尽量阅读原文。

http://www.netkiller.cn/blockchain/index.html

您的打赏是我的写作动力:http://www.netkiller.cn/blockchain/donations.html

==============================

33.8. Hyperledger fabric 银行应用探索

一直想写这篇文章,可是我个人对银行系统了解甚少,网上很多文章有多拿银行来举例,铺天盖地的文章,却没有一篇告诉你究竟如何落地。

其中不少文章中提到银行SWIFT系统,什么事 SWIFT 呢?

33.8.1. 电汇年代

这要从电汇说起,年轻时候上学,每个学期都有一笔学费,那时主要交通是铁路,携带现金非常不便,母亲将5000元人民币缝在我的贴身内裤边上。到了学校拆开线取出,味道好极了,呵呵。

后来从同学那里得知,可以使用邮局汇款,首先去邮局,拿一个特殊信封填好地址,然后将钱交给工作人员。一周以后信封皮会记挂号信到收款人手里,那个这个信封去指定邮局取款。

记得第二学期就出现电汇,银行提供的电汇服务比邮政的速度快,也比邮局更方便。

用户A ----- 汇票 -----> 用户B    |                     |    申请                   提款    |                     |    V                     V   银行A ----- 划账 -----> 银行B

电汇是用户A银行提出申请,将钱交给A银行。银行马上通过网络通知B银行,用户B就可以提款。没有多久邮政的系统也换成这套系统了。

那个年代只有拨号网络,帧中继,ATM(是一种网络,不是ATM取款机) 等窄带网络,现在用宽带上网的90后无法想法那个网速。

33.8.2. 通存通取年代

ISDN,DDN 专线的出现,才有了稳定窄带通信,银行网点互联成为可能。

MasterCard万事达,Visa维萨卡率先进入中国。很快银行内部就能实现转账了,ATM机互联成为可能,这时结算全部使用 MasterCard万事达,Visa维萨卡。银行需向MasterCard万事达,Visa维萨机构支付费用。促使一些有实力银行研发自己的内部系统,但是这些系统仅限内部使用,如果银行卡上没有MasterCard/Visa 的只能本银行使用,无法跨行。没有实力的银行则会选择门槛稍低的 INTERLINK、PLUS 等机构合作。

98年在学校寝室,一位同学拿了一张牡丹万事达卡,全寝室传看,那个年代在哈尔滨提款机都不普及,只有较大的银行网点才有。

2000来深圳,那时有个深银联,深圳首先实现了跨行业务,2年后(2002年)银联出现,国家强推,所有银行开始支持银联。当时银行卡上同时有两个标示,MasterCard/Visa 和 银联。

同年招商银行率先推出网上银行。招商银行电脑部一度成为IT红黑榜上评价最高的公司,可惜没有跟上互联网的步伐......

目前新开的银行卡已经看不到 MasterCard/Visa 标志了,甚至香港的银行卡也默认使用银联,出国旅游耍刷 UnionPay 跨境支付非常方便。

33.8.3. 跨境汇款

跨境汇款你别想像银联一样,填写一个姓名一个账号,点击一下转账按钮这样的操作。每个国家的政策也不同,政策不允许这样操作。

跨境只能汇款,无法转账,又回到了电汇时代,只是不再主要纸质的汇票了

用户A ----- SWIFT CODE -----> 用户B    |                             |    申请                           提款    |                             |    V                             V   银行A -------- SWIFT --------> 银行B

跨境汇款必须依赖 SWIFT 系统,由于我国的政策问题,个人很少涉及跨境业务,所以多数人对 SWIFT 不是很了解。 如果你在香港开一张银行卡例如汇丰银行,拿到银行给的信封里,就会有一个 SWIFT 码。

你会遇到这个问题,无法输入对方的名字,例如:

Nickname:netkiller English name: Neo chen  Nippon name: ちんけいほう (音訳)  Korean name: 천징봉 Thailand name: ภูมิภาพภูเขา Vietnam: Trần Cảnh Phong

所以就需要每个银行一个代码,每个账号一个代码,由于全世界银行太多,银行系统各种各样,每个国家的语言也不同,难以达成一致,联合国也没有能力统一标准。新建一套系统不太可能,所以80年代的标准仍然沿用至今。

使用 SWIFT 面临的问题

  • 网络速度慢
  • 手续费高
  • 技术落后
  • 不能实时到账
  • 脆弱容易被攻击

SWIFT的诞生甚至早于数字时代,可以说是目前最好的跨境通讯和交易系统,但它的确需要与时俱进。

牵头做一个世界银联不太可能,世界各国银行无法想政府一样,一个红头文件,下面招办,行政手段推动。且业务差异大,系统复杂超乎想象,这个中心数据库谁来管理呢?

SWIFT早就意识到了这些问题,并宣布进军区块链,同时加入超级账本项目(Hyperledger Project)成为会员。可以肯定下一个版本的SWIFT灰使用区块链技术,一步一步逐渐取代就系统。

33.8.4. 区块链能做什么

区块链可以解决银行哪些痛点,先说说 SWIFT 2.0 (区块链SWIFT)我想SWIFT仍然会兼容现有的协议。SWIFT CODE协议仍然会保留。短时间不可能被取代SWIFT CODE因为这个体系已经使用很多年。

用户A ----- SWIFT CODE -----> 用户B    |                             |    申请                           提款    |                             |    V                             V   银行A -------- 划账  --------> 银行B		     \                            /      \                          /       V                        V   +---------------------------------+   | Hyperledger Fabric 盟链          |   +---------------------------------+   | Smart Contract                  |   +---------------------------------+

后端将会被区块链取代

另外银行的跨国业务将会走自己的区块链,不再依赖 SWIFT, 因为费用等问题。

用户A --------- 转账 ---------> 用户B    |                             |    申请                           提款    |                             |    V                             V 英国渣打银行 ----- 划账  -----> 深圳渣打银行		     \                            /      \                          /       V                        V   +---------------------------------+   | Hyperledger Fabric 盟链          |   +---------------------------------+   | Smart Contract                  |   +---------------------------------+

33.8.5. 智能合约怎么落地

我对银行业务实在不了解,这里只能设想一下场景。下面是我之前写的一个Token合约,我将它应用到这个场景中

package main    import ( 	"encoding/json" 	"fmt" 	"strconv"  	"github.com/hyperledger/fabric/core/chaincode/shim" 	pb "github.com/hyperledger/fabric/protos/peer" )  type Msg struct{ 	Status 	bool	`json:"Status"` 	Code 	int		`json:"Code"` 	Message string	`json:"Message"` }  type Currency struct{ 	TokenName 		string	`json:"TokenName"` 	TokenSymbol 	string	`json:"TokenSymbol"` 	TotalSupply 	float64	`json:"TotalSupply"` }  type Token struct { 	Lock		bool	`json:"Lock"` 	Currency	map[string]Currency	`json:"Currency"` }  func (token *Token) transfer (_from *Account, _to *Account, _currency string, _value float64) []byte{  	var rev []byte 	if (token.Lock){ 		msg := &Msg{Status: false, Code: 0, Message: "锁仓状态,停止一切转账活动"} 		rev, _ = json.Marshal(msg) 		return rev 	} 	if(_from.Frozen ) { 		msg := &Msg{Status: false, Code: 0, Message: "From 账号冻结"} 		rev, _ = json.Marshal(msg) 		return rev 	} 	if( _to.Frozen) { 		msg := &Msg{Status: false, Code: 0, Message: "To 账号冻结"} 		rev, _ = json.Marshal(msg) 		return rev 	} 	if(!token.isCurrency(_currency)){ 		msg := &Msg{Status: false, Code: 0, Message: "货币符号不存在"} 		rev, _ = json.Marshal(msg) 		return rev 	} 	if(_from.BalanceOf[_currency] >= _value){ 		_from.BalanceOf[_currency] -= _value; 		_to.BalanceOf[_currency] += _value;  		msg := &Msg{Status: true, Code: 0, Message: "转账成功"} 		rev, _ = json.Marshal(msg) 		return rev 	}else{ 		msg := &Msg{Status: false, Code: 0, Message: "余额不足"} 		rev, _ = json.Marshal(msg) 		return rev 	} 	 } func (token *Token) initialSupply(_name string, _symbol string, _supply float64, _account *Account) []byte{ 	if _,ok := token.Currency[_symbol]; ok { 		msg := &Msg{Status: false, Code: 0, Message: "已经存在"} 		rev, _ := json.Marshal(msg) 		return rev 	}  	if _account.BalanceOf[_symbol] > 0 { 		msg := &Msg{Status: false, Code: 0, Message: "账号中存在代币"} 		rev, _ := json.Marshal(msg) 		return rev 	}else{ 		token.Currency[_symbol] = Currency{TokenName: _name, TokenSymbol: _symbol, TotalSupply: _supply} 		_account.BalanceOf[_symbol] = _supply  		msg := &Msg{Status: true, Code: 0, Message: "货币初始化成功"} 		rev, _ := json.Marshal(msg) 		return rev 	}  }  func (token *Token) mint(_currency string, _amount float64, _account *Account) []byte{ 	if(!token.isCurrency(_currency)){ 		msg := &Msg{Status: false, Code: 0, Message: "货币符号不存在"} 		rev, _ := json.Marshal(msg) 		return rev 	} 	cur := token.Currency[_currency] 	cur.TotalSupply += _amount; 	token.Currency[_currency] = cur 	_account.BalanceOf[_currency] += _amount;  	msg := &Msg{Status: true, Code: 0, Message: "货币增发成功"} 	rev, _ := json.Marshal(msg) 	return rev 	 } func (token *Token) burn(_currency string, _amount float64, _account *Account) []byte{ 	if(!token.isCurrency(_currency)){ 		msg := &Msg{Status: false, Code: 0, Message: "货币符号不存在"} 		rev, _ := json.Marshal(msg) 		return rev 	} 	if(token.Currency[_currency].TotalSupply >= _amount){ 		cur := token.Currency[_currency] 		cur.TotalSupply -= _amount; 		token.Currency[_currency] = cur 		_account.BalanceOf[_currency] -= _amount;  		msg := &Msg{Status: false, Code: 0, Message: "货币回收成功"} 		rev, _ := json.Marshal(msg) 		return rev 	}else{ 		msg := &Msg{Status: false, Code: 0, Message: "回收失败,回收额度不足"} 		rev, _ := json.Marshal(msg) 		return rev 	} 	 } func (token *Token) isCurrency(_currency string) bool { 	if _, ok := token.Currency[_currency]; ok { 		return true 	}else{ 		return false 	} } func (token *Token) setLock(_look bool) bool { 	token.Lock = _look 	return token.Lock } type Account struct { 	Name			string	`json:"Name"` 	Frozen			bool	`json:"Frozen"` 	BalanceOf		map[string]float64	`json:"BalanceOf"` } func (account *Account) balance (_currency string) map[string]float64{ 	bal	:= map[string]float64{_currency:account.BalanceOf[_currency]} 	return bal }  func (account *Account) balanceAll() map[string]float64{ 	return account.BalanceOf }  // ----------- const TokenKey = "Token"  // Define the Smart Contract structure type SmartContract struct { 	 }  func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) pb.Response {  	token := &Token{Currency: map[string]Currency{}}  	tokenAsBytes, err := json.Marshal(token) 	err = stub.PutState(TokenKey, tokenAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Init Token %s \n", string(tokenAsBytes)) 	} 	return shim.Success(nil) }  func (s *SmartContract) Query(stub shim.ChaincodeStubInterface) pb.Response { 	function, args := stub.GetFunctionAndParameters() 	if function == "balance" { 		return s.balance(stub, args) 	} else if function == "balanceAll" { 		return s.balanceAll(stub, args) 	} else if function == "showAccount" { 		return s.showAccount(stub, args) 	} 	return shim.Error("Invalid Smart Contract function name.") }  func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) pb.Response {  	// Retrieve the requested Smart Contract function and arguments 	function, args := stub.GetFunctionAndParameters() 	// Route to the appropriate handler function to interact with the ledger appropriately 	if function == "initLedger" { 		return s.initLedger(stub, args) 	} else if function == "createAccount" { 		return s.createAccount(stub, args) 	} else if function == "initCurrency" { 		return s.initCurrency(stub, args) 	} else if function == "setLock" { 		return s.setLock(stub, args) 	} else if function == "transferToken" { 		return s.transferToken(stub, args) 	} else if function == "frozenAccount" { 		return s.frozenAccount(stub, args) 	} else if function == "mintToken" { 		return s.mintToken(stub, args) 	} else if function == "balance" { 		return s.balance(stub, args) 	} else if function == "balanceAll" { 		return s.balanceAll(stub, args) 	} else if function == "showAccount" { 		return s.showAccount(stub, args) 	} else if function == "showToken" { 		return s.showToken(stub, args) 	}  	return shim.Error("Invalid Smart Contract function name.") }  func (s *SmartContract) createAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response {  	if len(args) != 1 { 		return shim.Error("Incorrect number of arguments. Expecting 1") 	}  	key  := args[0] 	name  := args[0] 	existAsBytes,err := stub.GetState(key) 	fmt.Printf("GetState(%s) %s \n", key, string(existAsBytes)) 	if string(existAsBytes) != "" { 		fmt.Println("Failed to create account, Duplicate key.") 		return shim.Error("Failed to create account, Duplicate key.") 	}  	account := Account{ 		Name: name, 		Frozen: false, 		BalanceOf: map[string]float64{}}  	accountAsBytes, _ := json.Marshal(account) 	err = stub.PutState(key, accountAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("createAccount %s \n", string(accountAsBytes))  	return shim.Success(accountAsBytes) } func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	return shim.Success(nil) } func (s *SmartContract) showToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	tokenAsBytes,err := stub.GetState(TokenKey) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("GetState(%s)) %s \n", TokenKey, string(tokenAsBytes)) 	} 	return shim.Success(tokenAsBytes) }  func (s *SmartContract) initCurrency(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	if len(args) != 4 { 		return shim.Error("Incorrect number of arguments. Expecting 4") 	}  	_name  := args[0] 	_symbol:= args[1] 	_supply,_:= strconv.ParseFloat(args[2], 64) 	_account := args[3]  	coinbaseAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("Coinbase before %s \n", string(coinbaseAsBytes))  	coinbase := &Account{}  	json.Unmarshal(coinbaseAsBytes, &coinbase)  	token := Token{} 	existAsBytes,err := stub.GetState(TokenKey) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("GetState(%s)) %s \n", TokenKey, string(existAsBytes)) 	} 	json.Unmarshal(existAsBytes, &token) 	 	result := token.initialSupply(_name,_symbol,_supply, coinbase)  	tokenAsBytes, _ := json.Marshal(token) 	err = stub.PutState(TokenKey, tokenAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Init Token %s \n", string(tokenAsBytes)) 	}  	coinbaseAsBytes, _ = json.Marshal(coinbase) 	err = stub.PutState(_account, coinbaseAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("Coinbase after %s \n", string(coinbaseAsBytes))  	  	return shim.Success(result) }  func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string) pb.Response {  	if len(args) != 4 { 		return shim.Error("Incorrect number of arguments. Expecting 4") 	} 	_from 		:= args[0] 	_to			:= args[1] 	_currency 	:= args[2] 	_amount,_	:= strconv.ParseFloat(args[3], 32) 	 	if(_amount <= 0){ 		return shim.Error("Incorrect number of amount") 	}  	fromAsBytes,err := stub.GetState(_from) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("fromAccount %s \n", string(fromAsBytes)) 	fromAccount := &Account{} 	json.Unmarshal(fromAsBytes, &fromAccount)  	toAsBytes,err := stub.GetState(_to) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("toAccount %s \n", string(toAsBytes)) 	toAccount := &Account{} 	json.Unmarshal(toAsBytes, &toAccount)  	tokenAsBytes,err := stub.GetState(TokenKey) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("Token %s \n", string(toAsBytes)) 	token := Token{Currency: map[string]Currency{}} 	json.Unmarshal(tokenAsBytes, &token)  	result := token.transfer(fromAccount, toAccount, _currency, _amount) 	fmt.Printf("Result %s \n", string(result))  	fromAsBytes, err = json.Marshal(fromAccount) 	if err != nil { 		return shim.Error(err.Error()) 	} 	err = stub.PutState(_from, fromAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("fromAccount %s \n", string(fromAsBytes)) 	}  	toAsBytes, err = json.Marshal(toAccount) 	if err != nil { 		return shim.Error(err.Error()) 	} 	err = stub.PutState(_to, toAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("toAccount %s \n", string(toAsBytes)) 	}  	return shim.Success(result) } func (s *SmartContract) mintToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	 	if len(args) != 3 { 		return shim.Error("Incorrect number of arguments. Expecting 3") 	} 	_currency 	:= args[0] 	_amount,_	:= strconv.ParseFloat(args[1], 32) 	_account	:= args[2]  	coinbaseAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Coinbase before %s \n", string(coinbaseAsBytes)) 	}  	coinbase := &Account{} 	json.Unmarshal(coinbaseAsBytes, &coinbase)  	tokenAsBytes,err := stub.GetState(TokenKey) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("Token before %s \n", string(tokenAsBytes))  	token := Token{}  	json.Unmarshal(tokenAsBytes, &token) 	 	result := token.mint(_currency, _amount, coinbase)  	tokenAsBytes, err = json.Marshal(token) 	if err != nil { 		return shim.Error(err.Error()) 	} 	err = stub.PutState(TokenKey, tokenAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("Token after %s \n", string(tokenAsBytes))  	coinbaseAsBytes, _ = json.Marshal(coinbase) 	err = stub.PutState(_account, coinbaseAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Coinbase after %s \n", string(coinbaseAsBytes)) 	}  	fmt.Printf("mintToken %s \n", string(tokenAsBytes))  	return shim.Success(result) }  func (s *SmartContract) setLock(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	 	if len(args) != 1 { 		return shim.Error("Incorrect number of arguments. Expecting 2") 	}  	_look := args[0]  	tokenAsBytes,err := stub.GetState(TokenKey) 	if err != nil { 		return shim.Error(err.Error()) 	} 	// fmt.Printf("setLock - begin %s \n", string(tokenAsBytes))  	token := Token{}  	json.Unmarshal(tokenAsBytes, &token)  	if(_look == "true"){ 		token.setLock(true) 	}else{ 		token.setLock(false) 	}  	tokenAsBytes, err = json.Marshal(token) 	if err != nil { 		return shim.Error(err.Error()) 	} 	err = stub.PutState(TokenKey, tokenAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	} 	fmt.Printf("setLock - end %s \n", string(tokenAsBytes))  	return shim.Success(nil) } func (s *SmartContract) frozenAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response { 	 	if len(args) != 2 { 		return shim.Error("Incorrect number of arguments. Expecting 2") 	}  	_account	:= args[0] 	_status		:= args[1]  	accountAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	} 	// fmt.Printf("setLock - begin %s \n", string(tokenAsBytes))  	account := Account{}  	json.Unmarshal(accountAsBytes, &account)  	var status bool 	if(_status == "true"){ 		status = true; 	}else{ 		status = false 	}  	account.Frozen = status 	 	accountAsBytes, err = json.Marshal(account) 	if err != nil { 		return shim.Error(err.Error()) 	} 	err = stub.PutState(_account, accountAsBytes) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("frozenAccount - end %s \n", string(accountAsBytes)) 	}  	return shim.Success(nil) }  func (s *SmartContract) showAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response {  	if len(args) != 1 { 		return shim.Error("Incorrect number of arguments. Expecting 1") 	} 	_account 	:= args[0]  	accountAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Account balance %s \n", string(accountAsBytes)) 	} 	return shim.Success(accountAsBytes) }  func (s *SmartContract) balance(stub shim.ChaincodeStubInterface, args []string) pb.Response {  	if len(args) != 2 { 		return shim.Error("Incorrect number of arguments. Expecting 1") 	} 	_account 	:= args[0] 	_currency 	:= args[1]  	accountAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Account balance %s \n", string(accountAsBytes)) 	}  	account := Account{} 	json.Unmarshal(accountAsBytes, &account) 	result := account.balance(_currency)  	resultAsBytes, _ := json.Marshal(result) 	fmt.Printf("%s balance is %s \n", _account, string(resultAsBytes))	  	return shim.Success(resultAsBytes) }  func (s *SmartContract) balanceAll(stub shim.ChaincodeStubInterface, args []string) pb.Response {  	if len(args) != 1 { 		return shim.Error("Incorrect number of arguments. Expecting 1") 	} 	_account 	:= args[0]  	accountAsBytes,err := stub.GetState(_account) 	if err != nil { 		return shim.Error(err.Error()) 	}else{ 		fmt.Printf("Account balance %s \n", string(accountAsBytes)) 	}  	account := Account{} 	json.Unmarshal(accountAsBytes, &account) 	result := account.balanceAll() 	resultAsBytes, _ := json.Marshal(result) 	fmt.Printf("%s balance is %s \n", _account, string(resultAsBytes))	  	return shim.Success(resultAsBytes) }  // 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) 	} }

部署链码,然后实例化链码

peer chaincode install -n token3 -v 1.0 -p chaincodedev/chaincode/token peer chaincode instantiate -C myc -n token3 -v 1.0 -c '{"Args":[""]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

首先初始化账号,需要将现有账号同步到区块链上,这是上链操作。账号分为两种,一个是 coinbase 银行的总账号,另外是用户账号

peer chaincode invoke -C myc -n token3 -c '{"function":"createAccount","Args":["coinbase"]}'

初始化外币,银行有多少外币存量,初始化到 coinbase 账号

peer chaincode invoke -C myc -n token3 -c '{"function":"initCurrency","Args":["Chain","RMB","1000000000","coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"initCurrency","Args":["Japan","JPY","1000000000","coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"initCurrency","Args":["USA","USD","1000000000","coinbase"]}'

为用户创建账号

peer chaincode invoke -C myc -n token3 -c '{"function":"createAccount","Args":["netkiller"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"createAccount","Args":["neo"]}'

同步用户账号中的外币

peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["coinbase","netkiller","RMB","10000"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["coinbase","netkiller","USD","100"]}'   peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["coinbase","neo","RMB","10000"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["coinbase","neo","USD","100"]}'

现在区块链上的用户资金已经跟数据库中的资金同步。

现在netkiller这个用户需要给neo转账 50 美金

peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["netkiller","neo","USD","50"]}'

现在 netkiller 账号中又 50美金,neo 账号中有 150美金。

peer chaincode invoke -C myc -n token3 -c '{"function":"balanceAll","Args":["netkiller"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"balanceAll","Args":["neo"]}'

如果 neo 账号被法院申请冻结了,怎么办?可以使用下面方法设置冻结账号

peer chaincode invoke -C myc -n token3 -c '{"function":"frozenAccount","Args":["neo","true"]}'

此时 neo 账号被冻结,资金无法转入,转出。

33.8.6. 总结

以上仅仅是提供一个区块链学历案例,作者也设想了一个场景。但是真是情况怎样作者也不清楚。

上面通正合约没有考虑到汇率和中间价问题,需要进一步完善。

另外还需要一个守护进程订阅 Event 状态,每做一笔转账交易,event 会受到然后将这个操作同步到中心化数据库。

用户A ------------- 转账 ------------> 用户B            |                                    |            申请                                 提款            |                                    |            V                                    V        英国渣打银行 --------- 划账  ---------> 深圳渣打银行		        /        \                            /      \       /          \                          /        \      V            V                        V          V +----------+  +---------------------------------+  +----------+  |          |  | Hyperledger Fabric 盟链          |  |          | | Database |  +---------------------------------+  | Database | |          |  | Smart Contract                  |  |          | +----------+  +---------------------------------+  +----------+       ^                 o               o                 ^      |                 |               |                 |      +----- Event -----+               +----- Event -----+

作者相关文章:

Hyperledger Fabric 积分代币上链方案

Hyperledger fabric Chaincode 开发详解

Hyperledger也能实现Token代币

食品安全溯源区块链解决方案探索

征信区块链解决方案探索(Hyperledger)

使用代币替代传统积分系统

竞猜活动区块链方案探索

游戏领域区块链探索

传统数据库也能实现区块链存储

本文发表于2018年03月27日 22:38
(c)注:本文转载自https://my.oschina.net/neochen/blog/1785361,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1768 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1