中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Hyperledger Fabric開發ERC20標準的代幣

發布時間:2021-12-06 14:08:23 來源:億速云 閱讀:418 作者:小新 欄目:互聯網科技

這篇文章給大家分享的是有關如何使用Hyperledger Fabric開發ERC20標準的代幣的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

用Hyperledger Fabric開發ERC20標準的代幣

  • 利用ca身份用戶名作為代幣地址(通過stub.GetCreator獲取)

  • 實現ERC20的標準的所有方法

直接上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"`      //符號
	Decimals    uint8   `json:"decimals"`    //小數位
	TotalSupply float64 `json:"totalSupply"` //總數
}

func (t *TokenChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {

	fcn, args := stub.GetFunctionAndParameters()
	fmt.Printf("方法: %s  參數 : %s \n", fcn, args)
	if len(args) != 1 {
		return shim.Error("參數個數不是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())
	}
	//創建人
	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 {

	//獲取要調用的方法名和方法參數
	fn, args := stub.GetFunctionAndParameters()
	fmt.Printf("方法: %s  參數 : %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("參數個數不為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("參數個數不為2")
	}
	to := args[0]
	v, err := strconv.ParseFloat(args[1], 64)
	//v不能小于零
	if v < 0 {
		return shim.Error("v less than 0")
	}
	//檢查是否是創建人
	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")
	}

	//代幣總數增加
	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())
	}
	// 重新寫回賬本
	err = stub.PutState(balanceKey(to), parseDecimals(token.Decimals, a))
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

//調用transfer函數將自己的token轉賬給to地址,value為轉賬個數
func (t *TokenChaincode) transfer(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("參數個數不為2")
	}
	//to
	to := args[0]
	//交易數量
	val := args[1]
	//from
	from := initiator(stub)
	//保留獲取小數位
	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)
}

//實現賬戶的凍結和解凍 (true 凍結,false 解凍)
func (t *TokenChaincode) freezeAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("參數個數不為2")
	}
	to := args[0]
	isFreeze := args[1]
	if isFreeze != "true" && isFreeze != "false" {
		return shim.Error("isFreeze is true or false")
	}
	//檢查是否是創建人
	err := checkOwner(stub)
	if err != nil {
		return shim.Error(err.Error())
	}
	//賬戶凍結和解凍
	err = stub.PutState(freezeKey(to), []byte(isFreeze))
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

//轉移擁有者
func (t *TokenChaincode) transferOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("參數個數不為1")
	}
	toOwner := args[0]
	//檢查是否是創建人
	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)
}

//批準spender賬戶從自己的賬戶轉移value個token。可以分多次轉移
func (t *TokenChaincode) approve(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("參數個數不為2")
	}
	//授權人
	spender := args[0]
	val := args[1]
	_, err := strconv.ParseFloat(val, 64)
	if err != nil {
		return shim.Error("Invalid transaction amount")
	}
	//發起人
	sponsor := initiator(stub)
	//批準
	err = stub.PutState(approveKey(sponsor, spender), []byte(val))
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

//與approve搭配使用,approve批準之后,調用transferFrom函數來轉移token。
func (t *TokenChaincode) transferFrom(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 3 {
		return shim.Error("參數個數不為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)
	//授權數量
	v, err := getApprove(stub, sponsor, spender)
	if err != nil {
		return shim.Error(err.Error())
	}
	//超出授權
	if valf > v {
		return shim.Error("approve not enough")
	}
	//保留獲取小數位
	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())
	}
	//計算approve剩余
	v -= valf
	//跟新授權數量
	err = stub.PutState(approveKey(sponsor, spender), parseDecimals(decimals, v))
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}

//返回spender還能提取sponsor的token的個數
func (t *TokenChaincode) allowance(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("參數個數不為1")
	}
	//批準人
	sponsor := args[0]
	//發起人
	spender := initiator(stub)
	val, err := stub.GetState(approveKey(sponsor, spender))
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(val)
}

//增加spender賬戶從自己的賬戶轉移value個token。可以分多次轉移
func (t *TokenChaincode) increaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	return changeAllowance(stub, args, "+")
}

//減少spender賬戶從自己的賬戶轉移value個token。可以分多次轉移
func (t *TokenChaincode) decreaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	return changeAllowance(stub, args, "-")
}

//改變spender賬戶從自己的賬戶轉移value個token。可以分多次轉移
func changeAllowance(stub shim.ChaincodeStubInterface, args []string, operation string) pb.Response {
	if len(args) != 2 {
		return shim.Error("參數個數不為2")
	}
	//授權人
	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")
	}
	//發起人
	sponsor := initiator(stub)
	//獲取當前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())
	}
	//批準
	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("參數個數不為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")
	}
	//代幣總數減少
	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())
	}
	// 重新寫回賬本
	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
	}
	//判斷兩個帳號不能相同
	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)
	// 重新寫回賬本
	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
}

//獲取批準數量
func getApprove(stub shim.ChaincodeStubInterface, sponsor, spender string) (float64, error) {
	//批準數量
	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) {
	//檢查帳號是否凍結
	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
}

//校驗創建人
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
}

//校驗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
}

//轉換為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
}

//交易發起人
func initiator(stub shim.ChaincodeStubInterface) string {
	//獲取當前用戶
	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)
	}
}

感謝各位的閱讀!關于“如何使用Hyperledger Fabric開發ERC20標準的代幣”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

石柱| 孟连| 托里县| 运城市| 邢台县| 海宁市| 新建县| 买车| 中山市| 罗田县| 中阳县| 那曲县| 安庆市| 龙里县| 航空| 营山县| 白城市| 洛浦县| 如东县| 南丰县| 拉萨市| 梁平县| 腾冲县| 大城县| 麻阳| 麻江县| 江口县| 宜丰县| 苏尼特右旗| 晋城| 塔城市| 白朗县| 聊城市| 忻州市| 双桥区| 靖江市| 金昌市| 云南省| 玉田县| 云浮市| 刚察县|