go语言实现NFT

此文章以及链码/合约,均为原创,已通过以heco-nft记录为NFT资产(HecoInfo Transaction Hash (Txhash) Details | HecoInfo),请勿转载,如有兴趣,可扫描文章最后的二维码。

基于erc721的以太坊NFT的流转基本上是这样的:

    发布NFT合约A  ---->    基于合约A,存储NFT内容,生成基于合约A的 token   -->调用转赠函数可以转赠token给某个钱包地址  

如何通过Fabric go语言实现类似以太坊NFT的功能?

以下是基础。

   1 需要对以太坊NFT合约,ERC721协议进行深入研究,了解协议原理和协议内容

   2 通过基于以太坊/heco-火币链等发布ERC721协议成功过,并且执行成功过,熟悉流程

   3 基于ERC721协议的内容,通过go语言的链码 实现基于Fabric的NFT

说明:

    签名部分,做了校验,如需改动,把签名部分去掉即可。

功能:

该链码,实现了ERC721协议的全部内容功能包括:

   1 生成NFT-token 

   2转赠NFT-token

   3 授权NFT-token给其他人

   4 提现NFT-token(即取消授权给其他人)

   5 查看NFT基本信息

   6 发布多种NFT资产

   7 转赠NFT资产的控制人

   8 查看资产余额

   9 资产信息

   10 资产转移记录列表

   ...等

存在的问题:

1 fabric的mvcc机制,不支持针对同一个key,在同一个块中的关联交易

•交易的模拟执行mvcc阶段,生成读写集,同一块中多笔涉及同一个key的修改操作,只有第一笔会别认为成功。

•假设:A余额100  A-B 转账 1
•                             A-C 转账 1
•          两笔交易发生在一个区块中,则只有第一笔会成功。

2 fabric的councdb存在诸多问题,

  •CouchDB一旦失败,就要终止所有正在运行的查询,甚至包括数据复制与压缩

 •CouchDB常常会发生视图丢失索引的情况,除非删除视图文件并重启数据库,否则很难做到重新索引

代码如下:

package main
 
import (
	"bccsp"
	"crypto"
	"crypto/rsa"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
	"math/big"
	"sort"
	"strconv"
	"strings"
	"time"
)
 
// NFT资产
type address string
type tokenId string
type url string
type transTime int
 
type Asset struct {
	NftName          string                            `json:"nftName"`               //资产token名称
	NftSymbol        string                            `json:"nftSymbol"`             //资产token简称
	Owner            string                            `json:"owner"`                 //资产token创建人
	AssetOf          map[address]map[tokenId]url       `json:"assetOf"`               //资产token的持有人和持有资产的集合
	AssetHistory     map[tokenId]map[transTime]address `json:"assetHistory"`          //资产token转移记录
	AssetApprove     map[tokenId]address               `json:"assetApprove"`          //资产授权人
	AssetExit        map[url]bool                      `json:"assetExit"`             //资产token是否已经存在
	AssetTokenIdExit map[tokenId]bool                  `json:"assetTokenIdExit"`      //资产token是否已经存在
	TotalSupply      int                               `json:"totalSupply,omitempty"` //资产总量 0代表不限量NFT 非0  则代表限量版本的NFT
}
 
// 交易结构
type TransferAsset struct {
	_From      address `json:"_from,omitempty"`      // 转出人 / 资产owner
	_To        address `json:"_to"`                  // 确权/转移到的地址
	_TokenId   tokenId `json:"_tokenId"`             // 每一个存证确权为一个资产token 每个资产token有唯一的tokenId
	_Url       url     `json:"_url"`                 // 存证的txid  或者 资产的url
	_Data      string  `json:"_data,omitempty"`      // 备注
	_Signature string  `json:"_signature,omitempty"` // 签名
	_SignType  string  `json:"_signType,omitempty"`  // 签名类型
	_NftSymbol string  `json:"_nftSymbol"`           //资产token简称
}
 
func (u *Asset) Init(stub shim.ChaincodeStubInterface) peer.Response {
	return shim.Success(nil)
}
 
// 初始化NFT资产合约 名称 简称 创造人
func (s *Asset) initLedger(stub shim.ChaincodeStubInterface, args []string) peer.Response {
 
	if len(args) != 4 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}
 
	name := args[0]                         // nft资产名称
	symbol := args[1]                       // nft资产简称
	owner := args[2]                        // nft资产创始人  pubkey
	totalSupply, _ := strconv.Atoi(args[3]) // nft资产是否为限量资产
 
	// 检查当前token是否已经被创建
	value, err := stub.GetState(symbol)
	if err != nil {
		return shim.Error(err.Error())
	}
	if value != nil || len(value) > 0 {
		return shim.Error("symbol 已存在")
	}
 
	assetHistory := make(map[tokenId]map[transTime]address)
	assetApprove := make(map[tokenId]address)
	assetOf := make(map[address]map[tokenId]url)
	assetExit := make(map[url]bool)
	assetTokenIdExit := make(map[tokenId]bool)
 
	// 创建新的token
	asset := &Asset{
		NftName:          name,
		NftSymbol:        symbol,
		Owner:            owner,
		AssetOf:          assetOf,
		AssetHistory:     assetHistory,
		AssetApprove:     assetApprove,
		AssetExit:        assetExit,
		AssetTokenIdExit: assetTokenIdExit,
		TotalSupply:      totalSupply,
	}
 
	//存储token
	tokenAsBytes, _ := json.Marshal(asset)
	err = stub.PutState(symbol, tokenAsBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Printf("Init %s \n", string(tokenAsBytes))
	return shim.Success(nil)
}
 
// invoke 执行
func (u *Asset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	funcName, args := stub.GetFunctionAndParameters()
	switch funcName {
	case "mine":
		return u.mine(stub, args)
	case "initLedger":
		return u.initLedger(stub, args)
	case "transFrom":
		return u.transFrom(stub, args)
	case "approve":
		return u.approve(stub, args)
	case "withDrawal":
		return u.withDrawal(stub, args)
	case "balanceof":
		return u.balanceof(stub, args)
	case "getApproved":
		return u.getApproved(stub, args)
	case "ownerof":
		return u.ownerof(stub, args)
	case "tokenURL":
		return u.tokenURL(stub, args)
	case "name":
		return u.name(stub, args)
	case "owner":
		return u.owner(stub, args)
	case "symbol":
		return u.symbol(stub, args)
	case "totalSupply":
		return u.totalSupply(stub, args)
	case "tokenBasic":
		return u.tokenBasic(stub, args)
	default:
		return shim.Error("no such function")
	}
}
 
// 确权资产
func (u *Asset) mine(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 6 {
		return shim.Error("expect six args")
	}
 
	// 生成资产的唯一id  uuid 由外部传入 因为fabric机制原因 内务无法统一uuid
	transferAsset := TransferAsset{
		_NftSymbol: args[0],
		_From:      address(args[1]),
		_To:        address(args[1]),
		_TokenId:   tokenId(args[2]),
		_Url:       url(args[3]),
		_Signature: args[4],
		_SignType:  args[5],
	}
	fmt.Printf("mine tokenname:%s \n _to:%s \n _tokenId:%s \n url:%s...\n", transferAsset._NftSymbol, transferAsset._To, transferAsset._TokenId, transferAsset._Url)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(transferAsset._NftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//只有存在,也就是初始化过了的nft token 进行下一步   验签
	veriftResul, errVerify := u.onlyOwner(transferAsset)
	if errVerify != nil || veriftResul == false {
		return shim.Error("Signature verification failed")
	}
 
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	if nftToken.AssetTokenIdExit[transferAsset._TokenId] {
		return shim.Error("tokenId already exit")
	}
 
	// 资产的添加
	errMine := nftToken.mineOnly(stub, &transferAsset)
	if errMine != nil {
		return shim.Error(errMine.Error())
	}
 
	// 存储
	assetBytes, err := json.Marshal(&nftToken)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[0], assetBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("putState success...")
	return shim.Success(nil)
}
 
//确权时更改资产持有属性
func (u *Asset) mineOnly(stub shim.ChaincodeStubInterface, trans *TransferAsset) error {
 
	//判断是否已经存在该url
	_, ok := u.AssetExit[trans._Url]
	if !ok {
		//添加资产持有记录
		if u.AssetOf[trans._To] == nil {
			mc := make(map[tokenId]url)
			mc[trans._TokenId] = trans._Url
			u.AssetOf[trans._To] = mc
		} else {
			u.AssetOf[trans._To][trans._TokenId] = trans._Url
		}
 
		//添加资产已经存在的标志
		u.AssetExit[trans._Url] = true
 
		if u.AssetHistory[trans._TokenId] == nil {
			//添加资产转移记录
			mh := make(map[transTime]address)
			t1, _ := stub.GetTxTimestamp()
			time1 := time.Unix(t1.Seconds, int64(t1.Nanos))
			timeMi:=time1.UnixNano()/1e6
 
			mh[transTime(timeMi)] = trans._To
			u.AssetHistory[trans._TokenId] = mh
		} else {
			t1, _ := stub.GetTxTimestamp()
			time1 := time.Unix(t1.Seconds, int64(t1.Nanos))
			timeMi:=time1.UnixNano()/1e6
			u.AssetHistory[trans._TokenId][transTime(timeMi)] = trans._To
		}
 
		u.AssetTokenIdExit[trans._TokenId] = true
 
		//判断资产总量是否是否到达限制
		if len(u.AssetExit) > u.TotalSupply {
			fmt.Println("当前nft资产已达到限制")
			return errors.New("TotalSupply already run out")
		}
		return nil
	} else {
		return errors.New("url already exist")
	}
 
}
 
//交易时更改资产持有属性
func (u *Asset) transOnly(stub shim.ChaincodeStubInterface, trans *TransferAsset) error {
 
	//修改资产持有记录 1 删除当前from的资产 2 增加to的资产
	delete(u.AssetOf[(trans._From)], trans._TokenId)
 
	if u.AssetOf[(trans._To)] == nil {
		mc := make(map[tokenId]url)
		mc[trans._TokenId] = trans._Url
		u.AssetOf[(trans._To)] = mc
	} else {
		u.AssetOf[(trans._To)][trans._TokenId] = trans._Url
	}
 
	//添加资产转移记录
	t1, _ := stub.GetTxTimestamp()
	time1 := time.Unix(t1.Seconds, int64(t1.Nanos))
	timeMi:=time1.UnixNano()/1e6
	u.AssetHistory[trans._TokenId][transTime(timeMi)] = trans._To
	return nil
 
}
 
//资产转移
func (u *Asset) transFrom(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 6 {
		return shim.Error("expect six args")
	}
 
	transferAsset := TransferAsset{
		_NftSymbol: args[0],
		_From:      address(args[1]),
		_To:        address(args[2]),
		_TokenId:   tokenId(args[3]),
		_Signature: args[4],
		_SignType:  args[5],
	}
	fmt.Printf("transFrom tokenname:%s \n _to:%s \n _tokenId:%s \n url:%s...\n", transferAsset._NftSymbol, transferAsset._To, transferAsset._TokenId, transferAsset._Url)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(transferAsset._NftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol not exist")
	}
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	if !nftToken.AssetTokenIdExit[transferAsset._TokenId] {
		return shim.Error("_tokenId not exist")
	}
 
	// 判断是否有权限进行交易 是否是token持有人 是否是token授权人
	beProved :=false
	if nftToken.AssetOf[transferAsset._From] != nil && nftToken.AssetOf[transferAsset._From][transferAsset._TokenId] == "" {
		if(nftToken.AssetApprove[transferAsset._TokenId]==transferAsset._From){
			fmt.Println("tokenId will be approved trans")
			beProved = true
		}else {
			return shim.Error("your have No permission")
		}
	}
 
	// 判断授权后的交易是否交易给自己
	var keys []int
	for k := range nftToken.AssetHistory[tokenId(transferAsset._TokenId)] {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)
	_keyInt := keys[len(keys)-1]
	_Owner := nftToken.AssetHistory[tokenId(transferAsset._TokenId)][transTime(_keyInt)]
	if transferAsset._To ==_Owner {
		return shim.Error("You are not allowed to sell it to yourself")
	}
 
	transferAsset._Url = nftToken.AssetOf[_Owner][transferAsset._TokenId]
	//只有存在,也就是初始化过了的nft token 进行下一步   验签
	veriftResul, errVerify := nftToken.onlyOwner(transferAsset)
	if errVerify != nil || veriftResul == false {
		return shim.Error("Signature verification failed")
	}
 
	// 资产的转移
	errMine := nftToken.transOnly(stub, &transferAsset)
	if errMine != nil {
		return shim.Error(errMine.Error())
	}
	// 如果是授权账户发起的 则取消授权
	if beProved{
		delete(nftToken.AssetApprove,transferAsset._TokenId)
	}
 
	// 存储
	assetBytes, err := json.Marshal(&nftToken)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[0], assetBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("putState success...")
	return shim.Success(nil)
}
 
//资产授权--授权后,资产权限归平台所有,资产所有人无法转移
func (u *Asset) approve(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 5 {
		return shim.Error("expect five args")
	}
 
	_nftSymbol := args[0]
	_approved := args[1]
	_tokenId := args[2]
	_signature := args[3]
	_signType := args[4]
 
	// todo  缺少_approved地址的合法性校验
 
	fmt.Printf("approve _nftSymbol:%s \n _approved:%s \n  _tokenId:%s \n", _nftSymbol, _approved, _tokenId)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	// nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	var keys []int
	for k := range nftToken.AssetHistory[tokenId(_tokenId)] {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)
	_keyInt := keys[len(keys)-1]
	_Owner := nftToken.AssetHistory[tokenId(_tokenId)][transTime(_keyInt)]
	if _Owner == address(_approved) {
		return shim.Error("You can't delegate to yourself")
	}
 
	_url := nftToken.AssetOf[_Owner][tokenId(_tokenId)]
 
	transferAsset := TransferAsset{
		_Url:       _url,
		_From:      _Owner,
		_Signature: _signature,
		_SignType:  _signType,
	}
 
	//  验签
	veriftResul, errVerify := nftToken.onlyOwner(transferAsset)
	if errVerify != nil || veriftResul == false {
		return shim.Error("Signature verification failed")
	}
 
	// 资产的授权
	if len(nftToken.AssetApprove[tokenId(_tokenId)]) != 0 {
		return shim.Error("Authorization cannot be repeated")
	} else {
		nftToken.AssetApprove[tokenId(_tokenId)] = address(_approved)
	}
 
	// 存储
	assetBytes, err := json.Marshal(&nftToken)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[0], assetBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("putState success...")
	return shim.Success(nil)
}
 
//资产提现--授权的资产 取消授权  即为提现,提现后的资产可以交易转移,授权后未提现的,无法转移
func (u *Asset) withDrawal(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 4 {
		return shim.Error("expect four args")
	}
 
	_nftSymbol := args[0]
	_tokenId := args[1]
	_signature := args[2]
	_signType := args[3]
 
	fmt.Printf("withDrawal _nftSymbol:%s \n  _tokenId:%s \n", _nftSymbol, _tokenId)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol not exist ")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	//判断是否已经授权过
	if len(nftToken.AssetApprove[tokenId(_tokenId)]) == 0 {
		return shim.Error("have not approve,no promission do")
	}
 
	var keys []int
	for k := range nftToken.AssetHistory[tokenId(_tokenId)] {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)
	_keyInt := keys[len(keys)-1]
	_Owner := nftToken.AssetHistory[tokenId(_tokenId)][transTime(_keyInt)]
 
	_url := nftToken.AssetOf[_Owner][tokenId(_tokenId)]
 
	transferAsset := TransferAsset{
		_Url:       _url,
		_From:      _Owner,
		_Signature: _signature,
		_SignType:  _signType,
	}
 
	//  验签
	veriftResul, errVerify := nftToken.onlyOwner(transferAsset)
	if errVerify != nil || veriftResul == false {
		return shim.Error("Signature verification failed")
	}
 
	// 提现
	delete(nftToken.AssetApprove, tokenId(_tokenId))
 
	// 存储
	assetBytes, err := json.Marshal(&nftToken)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[0], assetBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("putState success...")
	return shim.Success(nil)
}
 
//查询资产余额
func (u *Asset) balanceof(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 2 {
		return shim.Error("expect two args")
	}
 
	_nftSymbol := args[0]
	_owner := args[1]
	fmt.Printf("balanceof _nftSymbol:%s \n  _owner:%s \n", _nftSymbol, _owner)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	_ownerMap := nftToken.AssetOf[address(_owner)]
 
	_ownerMapAsBytes, _ := json.Marshal(_ownerMap)
 
	fmt.Println("putState success...")
	return shim.Success(_ownerMapAsBytes)
}
 
//查询资产是否已经被授权  返回 true /false
func (u *Asset) getApproved(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 2 {
		return shim.Error("expect two args")
	}
 
	_nftSymbol := args[0]
	_tokenId := args[1]
	fmt.Printf("getApproved _nftSymbol:%s \n  _tokenId:%s \n", _nftSymbol, _tokenId)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	if len(nftToken.AssetApprove[tokenId(_tokenId)]) == 0 {
		res, _ := json.Marshal(false)
		return shim.Success(res)
	}
	res, _ := json.Marshal(true)
	return shim.Success(res)
}
 
//资产tokenId 获取实际持有人
func (u *Asset) ownerof(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 2 {
		return shim.Error("expect two args")
	}
 
	_nftSymbol := args[0]
	_tokenId := args[1]
 
	fmt.Printf("ownerof _nftSymbol:%s \n  _tokenId:%s \n", _nftSymbol, _tokenId)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	// 判断tokenId存不存在
	if len(nftToken.AssetHistory[tokenId(_tokenId)]) == 0 {
		return shim.Error("tokenId 不存在")
	}
 
	//查找实际控制人
	var keys []int
	for k := range nftToken.AssetHistory[tokenId(_tokenId)] {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)
	_keyInt := keys[len(keys)-1]
	_Owner := nftToken.AssetHistory[tokenId(_tokenId)][transTime(_keyInt)]
 
	ownerBytes, _ := json.Marshal(_Owner)
 
	return shim.Success(ownerBytes)
}
 
//资产tokenId 获取token的url指向 源文件所在位置
func (u *Asset) tokenURL(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 2 {
		return shim.Error("expect two args")
	}
 
	_nftSymbol := args[0]
	_tokenId := args[1]
 
	fmt.Printf("ownerof _nftSymbol:%s \n  _tokenId:%s \n", _nftSymbol, _tokenId)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	// 判断tokenId存不存在
	if len(nftToken.AssetHistory[tokenId(_tokenId)]) == 0 {
		return shim.Error("tokenId 不存在")
	}
 
	//查找实际控制人
	var keys []int
	for k := range nftToken.AssetHistory[tokenId(_tokenId)] {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)
	_keyInt := keys[len(keys)-1]
	_Owner := nftToken.AssetHistory[tokenId(_tokenId)][transTime(_keyInt)]
 
	// 获取url
	urlFinal := nftToken.AssetOf[_Owner][tokenId(_tokenId)]
 
	urlBytes, _ := json.Marshal(urlFinal)
	return shim.Success(urlBytes)
}
 
//资产 获取token name
func (u *Asset) name(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("expect one args")
	}
 
	_nftSymbol := args[0]
 
	fmt.Printf("name _nftSymbol:%s \n", _nftSymbol)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	nameBytes, _ := json.Marshal(nftToken.NftName)
	return shim.Success(nameBytes)
}
 
//资产 获取token owner
func (u *Asset) owner(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("expect one args")
	}
 
	_nftSymbol := args[0]
 
	fmt.Printf("owner _nftSymbol:%s \n", _nftSymbol)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	ownerBytes, _ := json.Marshal(nftToken.Owner)
	return shim.Success(ownerBytes)
}
 
//资产 获取token symbol
func (u *Asset) symbol(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("expect one args")
	}
 
	_nftSymbol := args[0]
 
	fmt.Printf("symbol _nftSymbol:%s \n", _nftSymbol)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	nameBytes, _ := json.Marshal(nftToken.NftSymbol)
	return shim.Success(nameBytes)
}
 
//资产 获取token totalSupply
func (u *Asset) totalSupply(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("expect one args")
	}
 
	_nftSymbol := args[0]
 
	fmt.Printf("totalSupply _nftSymbol:%s \n", _nftSymbol)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
 
	//nfttoken
	nftToken := Asset{}
	json.Unmarshal(assetValue, &nftToken)
 
	TotalSupplyBytes, _ := json.Marshal(nftToken.TotalSupply)
	return shim.Success(TotalSupplyBytes)
}
 
//资产 获取token 所有基本信息
func (u *Asset) tokenBasic(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("expect one args")
	}
 
	_nftSymbol := args[0]
 
	fmt.Printf("totalSupply _nftSymbol:%s \n", _nftSymbol)
 
	//验证  当前的 nft token symbol简称存不存在
	assetValue, errAsset := stub.GetState(_nftSymbol)
	if errAsset != nil {
		return shim.Error(errAsset.Error())
	}
	if assetValue == nil || len(assetValue) == 0 {
		return shim.Error("_symbol 不存在")
	}
	return shim.Success(assetValue)
}
 
// 获取公钥
/*func getRSAPubkey(codeStr string) (*rsa.PublicKey, error) {
	n := &big.Int{}
	_, flag := n.SetString(codeStr, 16)
	if flag != true {
		return nil, errors.New(fmt.Sprintf("publicKey.n=%s err", codeStr))
	}
	// 构造返回PublicKey引用
	publicKeyObj := &rsa.PublicKey{}
	publicKeyObj.E = 65537
	publicKeyObj.N = n
	return publicKeyObj, nil
}*/
 
// 获取公钥
func getRSAPubkey(codeStr string) (pubKey bccsp.Key, err error) {
	pubArr := strings.Split(codeStr, "|")
	if pubArr == nil || len(pubArr) != 2 {
		return nil, errors.New("pubkey array length invalid")
	}
	e_str := pubArr[0]
	n_str := pubArr[1]
 
	//转换e
	e, err := strconv.Atoi(e_str)
	if err != nil {
		return nil, errors.New("strconv e error")
	}
	//转换n
	n := &big.Int{}
	_, flag := n.SetString(n_str, 16)
	if flag != true {
		return nil, errors.New("strconv n error")
	}
	//构造key
	publickObj := &rsa.PublicKey{}
	publickObj.E = e
	publickObj.N = n
	return &bccsp.RSAPublicKey{publickObj}, nil
}
 
//验证owner所有人 验签
func (u *Asset) onlyOwner(transferAsset TransferAsset) (bool, error) {
	veriftAccount := ""
 
	//是否授权 授权优先验证授权账户 未授权 验证from存不存在,不存在,代表是mine确权资产,使用to验签,存在,代表是资产转移
	if len(u.AssetApprove[transferAsset._TokenId]) != 0 {
		veriftAccount = string(u.AssetApprove[transferAsset._TokenId])
	} else {
		veriftAccount = string(transferAsset._From)
	}
 
	var bccspInstance, _ = bccsp.NewBccsp()
	if transferAsset._SignType == "RSA" {
		//验签
		signBytes := HexToByte(transferAsset._Signature)
 
		// 验签的转换
		var hash bccsp.HashOpts
		var pubKey bccsp.Key
		rsaPubkey, err := getRSAPubkey(veriftAccount)
		if err != nil {
			return false, err
		}
		pubKey = rsaPubkey
 
		hash = &bccsp.SHA1Opts{}
		bytesUrl, _ := json.Marshal(transferAsset._Url)
		digest, err := bccspInstance.Hash(bytesUrl, hash)
 
		isVerify, err := bccspInstance.Verify(pubKey, signBytes, digest, &bccsp.RsaPKCS1V15Opts{Hash: crypto.SHA1})
		fmt.Println("isVerify:%s", isVerify)
		if err != nil {
			return false, err
		}
		fmt.Println("check sign success...")
		return true, nil
	} else {
		return true, nil
	}
}
 
//16进制字符串转[]byte
func HexToByte(hex string) []byte {
	length := len(hex) / 2
	slice := make([]byte, length)
	rs := []rune(hex)
 
	for i := 0; i < length; i++ {
		s := string(rs[i*2 : i*2+2])
		value, _ := strconv.ParseInt(s, 16, 10)
		slice[i] = byte(value & 0xFF)
	}
	return slice
}
 
func main() {
	err := shim.Start(new(Asset))
	if err != nil {
		fmt.Println("poe chaincode start error")
	}
	return
}

               

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值