知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
一直想寫這篇文章,可是我個人對銀行系統瞭解甚少,網上很多文章有多拿銀行來舉例,鋪天蓋地的文章,卻沒有一篇告訴你究竟如何落地。
其中不少文章中提到銀行SWIFT系統,什麼事 SWIFT 呢?
這要從電匯說起,年輕時候上學,每個學期都有一筆學費,那時主要交通是鐵路,攜帶現金非常不便,母親將5000元人民幣縫在我的貼身內褲邊上。到了學校拆開綫取出,味道好極了,呵呵。
後來從同學那裡得知,可以使用郵局匯款,首先去郵局,拿一個特殊信封填好地址,然後將錢交給工作人員。一周以後信封皮會記掛號信到收款人手裡,那個這個信封去指定郵局取款。
記得第二學期就出現電匯,銀行提供的電匯服務比郵政的速度快,也比郵局更方便。
用戶A ----- 匯票 -----> 用戶B | | 申請 提款 | | V V 銀行A ----- 劃賬 -----> 銀行B
電匯是用戶A銀行提出申請,將錢交給A銀行。銀行馬上通過網絡通知B銀行,用戶B就可以提款。沒有多久郵政的系統也換成這套系統了。
那個年代只有撥號網絡,幀中繼,ATM(是一種網絡,不是ATM取款機) 等窄帶網絡,現在用寬頻上網的90後無法想法那個網速。
ISDN,DDN 專線的出現,才有了穩定窄帶通信,銀行網點互聯成為可能。
MasterCard萬事達,Visa維薩卡率先進入中國。很快銀行內部就能實現轉賬了,ATM機互聯成為可能,這時結算全部使用 MasterCard萬事達,Visa維薩卡。銀行需向MasterCard萬事達,Visa維薩機構支付費用。促使一些有實力銀行研發自己的內部系統,但是這些系統僅限內部使用,如果銀行卡上沒有MasterCard/Visa 的只能本銀行使用,無法跨行。沒有實力的銀行則會選擇門檻稍低的 INTERLINK、PLUS 等機構合作。
98年在學校寢室,一位同學拿了一張牡丹萬事達卡,全寢室傳看,那個年代在哈爾濱提款機都不普及,只有較大的銀行網點才有。
2000來深圳,那時有個深銀聯,深圳首先實現了跨行業務,2年後(2002年)銀聯出現,國家強推,所有銀行開始支持銀聯。當時銀行卡上同時有兩個標示,MasterCard/Visa 和 銀聯。
同年招商銀行率先推出網上銀行。招商銀行電腦部一度成為IT紅黑榜上評價最高的公司,可惜沒有跟上互聯網的步伐......
目前新開的銀行卡已經看不到 MasterCard/Visa 標誌了,甚至香港的銀行卡也預設使用銀聯,出國旅遊耍刷 UnionPay 跨境支付非常方便。
跨境匯款你別想像銀聯一樣,填寫一個姓名一個賬號,點擊一下轉賬按鈕這樣的操作。每個國家的政策也不同,政策不允許這樣操作。
跨境只能匯款,無法轉賬,又回到了電匯時代,只是不再主要紙質的匯票了
用戶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灰使用區塊鏈技術,一步一步逐漸取代就系統。
區塊鏈可以解決銀行哪些痛點,先說說 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 | +---------------------------------+
我對銀行業務實在不瞭解,這裡只能設想一下場景。下面是我之前寫的一個Token合約,我將它應用到這個場景中
package main /* -------------------------------------------------- Author: netkiller <netkiller@msn.com> Home: http://www.netkiller.cn Data: 2018-03-20 11:00 PM -------------------------------------------------- CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=token3:1.0 chaincode/token/token3 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')" peer chaincode invoke -C myc -n token3 -c '{"function":"createAccount","Args":["coinbase"]}' peer chaincode invoke -C myc -n token3 -v 1.0 -c '{"function":"showAccount","Args":["coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"balanceAll","Args":["coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"initCurrency","Args":["Netkiller Token","NKC","1000000","coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"initCurrency","Args":["NEO Token","NEC","1000000","coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"setLock","Args":["true"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"setLock","Args":["false"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"mintToken","Args":["NKC","5000","coinbase"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"createAccount","Args":["netkiller"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"transferToken","Args":["coinbase","netkiller","NKC","100"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"balance","Args":["netkiller","NKC"]}' peer chaincode invoke -C myc -n token3 -c '{"function":"frozenAccount","Args":["netkiller","true"]}' -------------------------------------------------- */ 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 賬號被凍結,資金無法轉入,轉出。
以上僅僅是提供一個區塊鏈學歷案例,作者也設想了一個場景。但是真是情況怎樣作者也不清楚。
上面通正合約沒有考慮到匯率和中間價問題,需要進一步完善。
另外還需要一個守護進程訂閲 Event 狀態,每做一筆轉賬交易,event 會受到然後將這個操作同步到中心化資料庫。
用戶A ------------- 轉賬 ------------> 用戶B | | 申請 提款 | | V V 英國渣打銀行 --------- 劃賬 ---------> 深圳渣打銀行 / \ / \ / \ / \ V V V V +----------+ +---------------------------------+ +----------+ | | | Hyperledger Fabric 盟鏈 | | | | Database | +---------------------------------+ | Database | | | | Smart Contract | | | +----------+ +---------------------------------+ +----------+ ^ o o ^ | | | | +----- Event -----+ +----- Event -----+