您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)如何使用Hyperledger Fabric開(kāi)發(fā)ERC20標(biāo)準(zhǔn)的代幣的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
利用ca身份用戶名作為代幣地址(通過(guò)stub.GetCreator獲取)
實(shí)現(xiàn)ERC20的標(biāo)準(zhǔn)的所有方法
直接上chaincode源碼
package main import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" "encoding/json" "bytes" "encoding/pem" "crypto/x509" ) const ( TokenId = "MyToken" TokenOwner = TokenId + "-Owner" TokenBalance = TokenId + "-%s-Balance" TokenFreeze = TokenId + "-%s-Freeze" TokenApprove = TokenId + "-%s-Approve-%s" ) type TokenChaincode struct { } type ERC20Token struct { Name string `json:"name"` //名稱 Symbol string `json:"symbol"` //符號(hào) Decimals uint8 `json:"decimals"` //小數(shù)位 TotalSupply float64 `json:"totalSupply"` //總數(shù) } func (t *TokenChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { fcn, args := stub.GetFunctionAndParameters() fmt.Printf("方法: %s 參數(shù) : %s \n", fcn, args) if len(args) != 1 { return shim.Error("參數(shù)個(gè)數(shù)不是1") } tokenBts := []byte(args[0]) var token ERC20Token err := json.Unmarshal(tokenBts, &token) if err != nil { return shim.Error(err.Error()) } //檢查 err = checkToken(token) if err != nil { return shim.Error(err.Error()) } //添加代幣 err = stub.PutState(TokenId, tokenBts) if err != nil { return shim.Error(err.Error()) } //創(chuàng)建人 creator := initiator(stub) err = stub.PutState(TokenOwner, []byte(creator)) if err != nil { return shim.Error(err.Error()) } //擁有者初始化擁有所有代幣 err = stub.PutState(balanceKey(creator), parseDecimals(token.Decimals, token.TotalSupply)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (t *TokenChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { //獲取要調(diào)用的方法名和方法參數(shù) fn, args := stub.GetFunctionAndParameters() fmt.Printf("方法: %s 參數(shù) : %s \n", fn, args) if fn == "tokenInfo" { return t.tokenInfo(stub) } else if fn == "balanceOf" { return t.balanceOf(stub, args) } else if fn == "minter" { return t.minter(stub, args) } else if fn == "transfer" { return t.transfer(stub, args) } else if fn == "freezeAccount" { return t.freezeAccount(stub, args) } else if fn == "approve" { return t.approve(stub, args) } else if fn == "transferFrom" { return t.transferFrom(stub, args) } else if fn == "allowance" { return t.allowance(stub, args) } else if fn == "transferOwner" { return t.transferOwner(stub, args) } else if fn == "increaseAllowance" { return t.increaseAllowance(stub, args) } else if fn == "decreaseAllowance" { return t.decreaseAllowance(stub, args) } else if fn == "burn" { return t.burn(stub, args) } return shim.Error("方法不存在") } //獲取token信息 func (t *TokenChaincode) tokenInfo(stub shim.ChaincodeStubInterface) pb.Response { token, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } return shim.Success(token) } //輸入地址,可以獲取該地址代幣的余額 func (t *TokenChaincode) balanceOf(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("參數(shù)個(gè)數(shù)不為1") } name := args[0] balance, err := stub.GetState(balanceKey(name)) if err != nil { return shim.Error(err.Error()) } return shim.Success(balance) } //挖礦 func (t *TokenChaincode) minter(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("參數(shù)個(gè)數(shù)不為2") } to := args[0] v, err := strconv.ParseFloat(args[1], 64) //v不能小于零 if v < 0 { return shim.Error("v less than 0") } //檢查是否是創(chuàng)建人 err = checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //獲取to的balance a, err := getBalance(stub, to) if err != nil { return shim.Error(err.Error()) } a += v if a < 0 { return shim.Error("a balance less than 0") } //代幣總數(shù)增加 tks, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } var token ERC20Token err = json.Unmarshal(tks, &token) if err != nil { return shim.Error(err.Error()) } token.TotalSupply += v tks, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } //跟新代幣 err = stub.PutState(TokenId, tks) if err != nil { return shim.Error(err.Error()) } // 重新寫(xiě)回賬本 err = stub.PutState(balanceKey(to), parseDecimals(token.Decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //調(diào)用transfer函數(shù)將自己的token轉(zhuǎn)賬給to地址,value為轉(zhuǎn)賬個(gè)數(shù) func (t *TokenChaincode) transfer(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("參數(shù)個(gè)數(shù)不為2") } //to to := args[0] //交易數(shù)量 val := args[1] //from from := initiator(stub) //保留獲取小數(shù)位 decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //交易 err = deal(stub, from, to, val, decimals) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //實(shí)現(xiàn)賬戶的凍結(jié)和解凍 (true 凍結(jié),false 解凍) func (t *TokenChaincode) freezeAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("參數(shù)個(gè)數(shù)不為2") } to := args[0] isFreeze := args[1] if isFreeze != "true" && isFreeze != "false" { return shim.Error("isFreeze is true or false") } //檢查是否是創(chuàng)建人 err := checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //賬戶凍結(jié)和解凍 err = stub.PutState(freezeKey(to), []byte(isFreeze)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //轉(zhuǎn)移擁有者 func (t *TokenChaincode) transferOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("參數(shù)個(gè)數(shù)不為1") } toOwner := args[0] //檢查是否是創(chuàng)建人 err := checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //改變owner err = stub.PutState(TokenOwner, []byte(toOwner)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //批準(zhǔn)spender賬戶從自己的賬戶轉(zhuǎn)移value個(gè)token。可以分多次轉(zhuǎn)移 func (t *TokenChaincode) approve(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("參數(shù)個(gè)數(shù)不為2") } //授權(quán)人 spender := args[0] val := args[1] _, err := strconv.ParseFloat(val, 64) if err != nil { return shim.Error("Invalid transaction amount") } //發(fā)起人 sponsor := initiator(stub) //批準(zhǔn) err = stub.PutState(approveKey(sponsor, spender), []byte(val)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //與approve搭配使用,approve批準(zhǔn)之后,調(diào)用transferFrom函數(shù)來(lái)轉(zhuǎn)移token。 func (t *TokenChaincode) transferFrom(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 3 { return shim.Error("參數(shù)個(gè)數(shù)不為3") } //from sponsor := args[0] //to to := args[1] //val val := args[2] valf, err := strconv.ParseFloat(val, 64) if err != nil { return shim.Error("Invalid transaction amount") } //spender spender := initiator(stub) //授權(quán)數(shù)量 v, err := getApprove(stub, sponsor, spender) if err != nil { return shim.Error(err.Error()) } //超出授權(quán) if valf > v { return shim.Error("approve not enough") } //保留獲取小數(shù)位 decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //交易 err = deal(stub, sponsor, to, val, decimals) if err != nil { return shim.Error(err.Error()) } //計(jì)算approve剩余 v -= valf //跟新授權(quán)數(shù)量 err = stub.PutState(approveKey(sponsor, spender), parseDecimals(decimals, v)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //返回spender還能提取sponsor的token的個(gè)數(shù) func (t *TokenChaincode) allowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("參數(shù)個(gè)數(shù)不為1") } //批準(zhǔn)人 sponsor := args[0] //發(fā)起人 spender := initiator(stub) val, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return shim.Error(err.Error()) } return shim.Success(val) } //增加spender賬戶從自己的賬戶轉(zhuǎn)移value個(gè)token??梢苑侄啻无D(zhuǎn)移 func (t *TokenChaincode) increaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { return changeAllowance(stub, args, "+") } //減少spender賬戶從自己的賬戶轉(zhuǎn)移value個(gè)token??梢苑侄啻无D(zhuǎn)移 func (t *TokenChaincode) decreaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { return changeAllowance(stub, args, "-") } //改變spender賬戶從自己的賬戶轉(zhuǎn)移value個(gè)token。可以分多次轉(zhuǎn)移 func changeAllowance(stub shim.ChaincodeStubInterface, args []string, operation string) pb.Response { if len(args) != 2 { return shim.Error("參數(shù)個(gè)數(shù)不為2") } //授權(quán)人 spender := args[0] v, err := strconv.ParseFloat(args[1], 64) if err != nil { return shim.Error("Invalid transaction amount") } //v不能小于零 if v < 0 { return shim.Error("v less than 0") } //發(fā)起人 sponsor := initiator(stub) //獲取當(dāng)前allowance val, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return shim.Error(err.Error()) } a, err := strconv.ParseFloat(string(val), 64) if err != nil { return shim.Error(err.Error()) } if operation == "+" { //增加 a += v } if operation == "-" { //減少 a -= v } //不能溢出 if a < 0 { return shim.Error("a less than 0") } decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //批準(zhǔn) err = stub.PutState(approveKey(sponsor, spender), parseDecimals(decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //銷毀代幣 func (t *TokenChaincode) burn(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("參數(shù)個(gè)數(shù)不為1") } v, err := strconv.ParseFloat(args[0], 64) //v不能小于零 if v < 0 { return shim.Error("v less than 0") } from := initiator(stub) //獲取from的balance a, err := getBalance(stub, from) if err != nil { return shim.Error(err.Error()) } a -= v if a < 0 { return shim.Error("a balance less than 0") } //代幣總數(shù)減少 tks, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } var token ERC20Token err = json.Unmarshal(tks, &token) if err != nil { return shim.Error(err.Error()) } token.TotalSupply -= v tks, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } //跟新代幣 err = stub.PutState(TokenId, tks) if err != nil { return shim.Error(err.Error()) } // 重新寫(xiě)回賬本 err = stub.PutState(balanceKey(from), parseDecimals(token.Decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } //交易處理 from to val decimals func deal(stub shim.ChaincodeStubInterface, from, to, val string, decimals uint8) (error) { v, err := strconv.ParseFloat(val, 64) if err != nil { return err } //v不能小于零 if v < 0 { return fmt.Errorf("v less than 0") } //獲取from的balance a, err := getBalance(stub, from) if err != nil { return err } //判斷兩個(gè)帳號(hào)不能相同 if from == to { return fmt.Errorf("from and to is the same address") } //獲取to的balance b, err := getBalance(stub, to) if err != nil { return err } //execution a b v 交易 a -= v if a < 0 { return fmt.Errorf("from balance not enough") } b += v if b < 0 { return fmt.Errorf("to balance less than 0") } fmt.Println(" a: ", a, " b: ", b) // 重新寫(xiě)回賬本 err = stub.PutState(balanceKey(from), parseDecimals(decimals, a)) if err != nil { return err } err = stub.PutState(balanceKey(to), parseDecimals(decimals, b)) if err != nil { return err } return nil } //獲取批準(zhǔn)數(shù)量 func getApprove(stub shim.ChaincodeStubInterface, sponsor, spender string) (float64, error) { //批準(zhǔn)數(shù)量 val, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return 0, err } b, err := strconv.ParseFloat(string(val), 64) if err != nil { return 0, err } return b, nil } //獲取balance func getBalance(stub shim.ChaincodeStubInterface, addr string) (float64, error) { //檢查帳號(hào)是否凍結(jié) isFreeze, err := stub.GetState(freezeKey(addr)) if err != nil { return 0, err } if isFreeze != nil && bytes.Equal(isFreeze, []byte("true")) { return 0, fmt.Errorf("addr is freeze") } //查詢balance addrVal, err := stub.GetState(balanceKey(addr)) if err != nil { return 0, err } //為空返回0 if addrVal == nil { return 0, nil } b, err := strconv.ParseFloat(string(addrVal), 64) if err != nil { return 0, err } return b, nil } //校驗(yàn)創(chuàng)建人 func checkOwner(stub shim.ChaincodeStubInterface) error { creator := initiator(stub) owner, err := stub.GetState(TokenOwner) if err != nil { return err } if !bytes.Equal([]byte(creator), owner) { return fmt.Errorf("is not owner") } return nil } //校驗(yàn)token func checkToken(token ERC20Token) error { if token.Name == "" { return fmt.Errorf("name不能為空") } if token.Symbol == "" { return fmt.Errorf("symbol不能為空") } if token.TotalSupply <= 0 { return fmt.Errorf("totalSupply要大于0") } return nil } //轉(zhuǎn)換為token decimals func parseDecimals(decimals uint8, value float64) []byte { val := strconv.FormatFloat(value, 'f', int(decimals), 64) return []byte(val) } //獲取token decimals func getDecimals(stub shim.ChaincodeStubInterface) (uint8, error) { tokenBts, err := stub.GetState(TokenId) if err != nil { return 0, err } var token ERC20Token err = json.Unmarshal(tokenBts, &token) if err != nil { return 0, err } return token.Decimals, nil } //交易發(fā)起人 func initiator(stub shim.ChaincodeStubInterface) string { //獲取當(dāng)前用戶 creatorByte, _ := stub.GetCreator() certStart := bytes.IndexAny(creatorByte, "-----BEGIN") if certStart == -1 { fmt.Println("No certificate found") } certText := creatorByte[certStart:] bl, _ := pem.Decode(certText) if bl == nil { fmt.Println("Could not decode the PEM structure") } cert, err := x509.ParseCertificate(bl.Bytes) if err != nil { fmt.Println("ParseCertificate failed") } name := cert.Subject.CommonName fmt.Println("initiator:" + name) return name } //封裝balance key func balanceKey(name string) string { return fmt.Sprintf(TokenBalance, name) } //封裝freeze key func freezeKey(name string) string { return fmt.Sprintf(TokenFreeze, name) } //封裝approve key func approveKey(from, to string) string { return fmt.Sprintf(TokenApprove, from, to) } func main() { err := shim.Start(new(TokenChaincode)) if err != nil { fmt.Printf("Error starting Token chaincode: %s", err) } }
感謝各位的閱讀!關(guān)于“如何使用Hyperledger Fabric開(kāi)發(fā)ERC20標(biāo)準(zhǔn)的代幣”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。