代币系统需要支持新种类代币发行、代币转账,额度查询,代币增发,代币回收、账户冻结,锁仓等功能。 代币(token)数据内容包括代币简称、代币名称、代币发行者、总供应量、锁仓标识等信息; 代币发行方可以发行代币、增发代币、回收代币、锁仓、冻结账户; 可以根据key值前缀进行范围查询,查询出账户名拥有的各种代币。 参考:
1. 应用场景
代币增发后转入coinbase账户,coinbase账户与普通账户之间可以互相转账。这样就实现了代币流通。2. 数据的生命周期
账户(account)数据内容包括账户名、账户的代币类型、冻结标识、余额等信息。
用户可以将代币转账从自己的账户给别人的账户。3. 数据结构
TokenSymbol
type Token struct { TokenSymbol string `json:"TokenSymbol"` TokenName string `json:"TokenName"` Owner string `json:"Owner"` TotalSupply int64 `json:"TotalSupply"` Lock bool `json:"Lock"` }
accountKey, err := stub.CreateCompositeKey("account", []string{accountName, symbol})
type Account struct { AccountName string `json:"AccountName"` TokenSymbol string `json:"TokenSymbol"` Frozen bool `json:"Frozen"` Balance int64 `json:"Balance"` }
4. 合约源码
package main import ( "encoding/json" "errors" "fmt" "strconv" "github.com/hyperledger/fabric-chaincode-go/shim" pb "github.com/hyperledger/fabric-protos-go/peer" ) // Token 代币数据 type Token struct { TokenSymbol string `json:"TokenSymbol"` TokenName string `json:"TokenName"` Owner string `json:"Owner"` TotalSupply int64 `json:"TotalSupply"` Lock bool `json:"Lock"` } // Account 代币账户数据 type Account struct { AccountName string `json:"AccountName"` TokenSymbol string `json:"TokenSymbol"` Frozen bool `json:"Frozen"` Balance int64 `json:"Balance"` } func (token *Token) transfer(from *Account, to *Account, amount int64) error { if token.Lock { return errors.New("锁仓状态,无法转账") } if from.Frozen { return errors.New("From 账户已被冻结") } if to.Frozen { return errors.New("To 账户已被冻结") } if from.Balance >= amount { from.Balance -= amount to.Balance += amount } else { return errors.New("From 账户余额不足") } return nil } func (token *Token) mint(amount int64, account *Account) error { if token.Lock { return errors.New("锁仓状态,无法增发代币") } token.TotalSupply += amount account.Balance += amount return nil } func (token *Token) burn(amount int64, account *Account) error { if token.Lock { return errors.New("锁仓状态,无法回收代币") } if account.Balance >= amount { account.Balance -= amount token.TotalSupply -= amount } return nil } func (token *Token) setLock(lock bool) { token.Lock = lock } func (account *Account) setFrozen(status bool) { account.Frozen = status } func (account *Account) balance() int64 { return account.Balance } // Contract ... type Contract struct { } // Init ... func (tc *Contract) Init(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(nil) } // Invoke ... func (tc *Contract) Invoke(stub shim.ChaincodeStubInterface) pb.Response { functions, args := stub.GetFunctionAndParameters() if functions == "issueNewToken" { return tc.issueNewToken(stub, args) } else if functions == "mintToken" { return tc.mintToken(stub, args) } else if functions == "burnToken" { return tc.burnToken(stub, args) } else if functions == "transferToken" { return tc.transferToken(stub, args) } else if functions == "setLock" { return tc.setLock(stub, args) } else if functions == "frozenAccount" { return tc.frozenAccount(stub, args) } else if functions == "queryToken" { return tc.queryToken(stub, args) } else if functions == "queryAccount" { return tc.queryAccount(stub, args) } return shim.Error("Invalid function name in Contract.") } func (tc *Contract) issueNewToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 3") } tokenSymbol := args[0] tokenName := args[1] supply, err := strconv.ParseInt(args[2], 10, 64) if err != nil { return shim.Error(err.Error()) } // 判断token是否已存在 exist, err := stub.GetState(tokenSymbol) if exist != nil { return shim.Error("Token existed!") } token := &Token{ TokenSymbol: tokenSymbol, TokenName: tokenName, Owner: "coinbase", TotalSupply: supply, Lock: false, } account := Account{ AccountName: token.Owner, TokenSymbol: tokenSymbol, Frozen: false, Balance: supply, } tokenAsBytes, err := json.Marshal(token) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(tokenSymbol, tokenAsBytes) if err != nil { return shim.Error(err.Error()) } accountKey, err := stub.CreateCompositeKey("account", []string{token.Owner, tokenSymbol}) if err != nil { return shim.Error(err.Error()) } acountAsBytes, err := json.Marshal(account) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(accountKey, acountAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) mintToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2.") } symbol := args[0] amount, err := strconv.ParseInt(args[1], 10, 64) if err != nil { return shim.Error(err.Error()) } tokenAsBytes, err := stub.GetState(symbol) if err != nil { return shim.Error(err.Error()) } if tokenAsBytes == nil { return shim.Error("Entity not found") } token := Token{} err = json.Unmarshal(tokenAsBytes, &token) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + symbol + ""}") } accountKey, err := stub.CreateCompositeKey("account", []string{token.Owner, symbol}) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err := stub.GetState(accountKey) if err != nil { return shim.Error(err.Error()) } if accountAsBytes == nil { return shim.Error("Entity not found") } account := Account{} err = json.Unmarshal(accountAsBytes, &account) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + token.Owner + symbol + ""}") } err = token.mint(amount, &account) if err != nil { return shim.Error(err.Error()) } tokenAsBytes, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(symbol, tokenAsBytes) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err = json.Marshal(account) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(accountKey, accountAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) burnToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 3.") } symbol := args[0] amount, err := strconv.ParseInt(args[1], 10, 64) if err != nil { return shim.Error(err.Error()) } accountName := args[2] tokenAsBytes, err := stub.GetState(symbol) if err != nil { return shim.Error(err.Error()) } if tokenAsBytes == nil { return shim.Error("Entity not found") } token := Token{} err = json.Unmarshal(tokenAsBytes, &token) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + symbol + ""}") } accountKey, err := stub.CreateCompositeKey("account", []string{accountName, symbol}) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err := stub.GetState(accountKey) if err != nil { return shim.Error(err.Error()) } if accountAsBytes == nil { return shim.Error("Entity not found") } account := Account{} err = json.Unmarshal(accountAsBytes, &account) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + accountName + symbol + ""}") } err = token.burn(amount, &account) if err != nil { return shim.Error(err.Error()) } tokenAsBytes, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(symbol, tokenAsBytes) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err = json.Marshal(account) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(accountKey, accountAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) transferToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { symbol := args[0] from := args[1] to := args[2] amount, err := strconv.ParseInt(args[3], 10, 64) if err != nil { return shim.Error(err.Error()) } if amount <= 0 { return shim.Error("Incorrect amount!") } // 源账户处理 fromKey, err := stub.CreateCompositeKey("account", []string{from, symbol}) if err != nil { return shim.Error(err.Error()) } fromAsBytes, err := stub.GetState(fromKey) if err != nil { return shim.Error(err.Error()) } if fromAsBytes == nil { return shim.Error("Entity not found") } fromAccount := Account{} err = json.Unmarshal(fromAsBytes, &fromAccount) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + from + symbol + ""}") } // 目的账户处理 toKey, err := stub.CreateCompositeKey("account", []string{to, symbol}) if err != nil { return shim.Error(err.Error()) } toAsBytes, err := stub.GetState(toKey) if err != nil { return shim.Error(err.Error()) } toAccount := Account{} if toAsBytes == nil { toAccount.AccountName = to toAccount.Balance = 0 toAccount.Frozen = false toAccount.TokenSymbol = symbol } else { err = json.Unmarshal(toAsBytes, &toAccount) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + to + symbol + ""}") } } // token处理 tokenAsBytes, err := stub.GetState(symbol) if err != nil { return shim.Error(err.Error()) } if tokenAsBytes == nil { return shim.Error("Entity not found") } token := &Token{} err = json.Unmarshal(tokenAsBytes, &token) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + symbol + ""}") } // 转账 err = token.transfer(&fromAccount, &toAccount, amount) if err != nil { return shim.Error(err.Error()) } // 入库 fromAsBytes, err = json.Marshal(fromAccount) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(fromKey, fromAsBytes) if err != nil { return shim.Error(err.Error()) } toAsBytes, err = json.Marshal(toAccount) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(toKey, toAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) setLock(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } symbol := args[0] lock, err := strconv.ParseBool(args[1]) if err != nil { return shim.Error(err.Error()) } tokenAsBytes, err := stub.GetState(symbol) if err != nil { return shim.Error(err.Error()) } if tokenAsBytes == nil { return shim.Error("Entity not found") } token := Token{} err = json.Unmarshal(tokenAsBytes, &token) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + symbol + ""}") } token.setLock(lock) tokenAsBytes, _ = json.Marshal(token) err = stub.PutState(symbol, tokenAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) frozenAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 3") } symbol := args[0] accountName := args[1] frozen, err := strconv.ParseBool(args[2]) if err != nil { return shim.Error(err.Error()) } accountKey, err := stub.CreateCompositeKey("account", []string{accountName, symbol}) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err := stub.GetState(accountKey) if err != nil { return shim.Error(err.Error()) } if accountAsBytes == nil { return shim.Error("Entity not found") } account := Account{} err = json.Unmarshal(accountAsBytes, &account) if err != nil { return shim.Error("{"Error":"Failed to decode JSON of: " + accountName + symbol + ""}") } account.setFrozen(frozen) accountAsBytes, _ = json.Marshal(account) err = stub.PutState(accountKey, accountAsBytes) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (tc *Contract) queryToken(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } symbol := args[0] tokenAsBytes, err := stub.GetState(symbol) if err != nil { return shim.Error(err.Error()) } if tokenAsBytes == nil { return shim.Error("{"Error":"Nil value for " + symbol + ""}") } fmt.Printf("Query Response:%sn", string(tokenAsBytes)) return shim.Success(tokenAsBytes) } func (tc *Contract) queryAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } accountName := args[0] symbol := args[1] accountKey, err := stub.CreateCompositeKey("account", []string{accountName, symbol}) if err != nil { return shim.Error(err.Error()) } accountAsBytes, err := stub.GetState(accountKey) if err != nil { return shim.Error(err.Error()) } if accountAsBytes == nil { return shim.Error("{"Error":"Nil value for " + accountName + symbol + ""}") } fmt.Printf("Query Response:%sn", string(accountAsBytes)) return shim.Success(accountAsBytes) } func main() { err := shim.Start(new(Contract)) if err != nil { fmt.Printf("Error starting Contract chaincode: %s", err) } }
https://www.netkiller.cn/blockchain/hyperledger/chaincode/chaincode.example.html#chaincode.token
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算