长安链搭建区块链实战

本文介绍了如何在服务器上通过docker和docker-compose部署ChainMaker管理台,创建和部署智能合约,包括版本检查、组织和节点证书申请、长安链创建、合约编写(如IssueCredit、QueryCredit和TransferCredit)以及合约部署和升级的过程。
摘要由CSDN通过智能技术生成

        本教程以本人真实开发经历结合官方文档所写,如需详细教程可以参考官方文档文档导航 — chainmaker-docs v2.3.3 documentation

 一、版本检查

        首先确认服务器的环境,这里我们需要docker版本为20.10.7或以上 docker-compose 版本为1.29.2或以上

        可以通过如下链接下载

        https://docs.docker.com/engine/install/

        ​​​​​​​Overview of installing Docker Compose | Docker Docs

        下载后确认版本,使用docker -v和docker-compose -v检查版本。

图1.1 版本查看

二、部署管理台

            使用

git clone -b v3.0.0 --depth=1 chainmaker / management-backend · ChainMaker

            下载管理台代码,下载后端代码后,进入management-backend目录,执行以下命令

cd management-backend
docker-compose up

            如有端口占用可以修改docker-compose.yml文件中的端口

图2.1 docker-compose文件

三、通过管理台部署长安链

        进入管理平台,网址为(ip:刚刚docker-compose的写的端口),初始用户名为admin,密码为a123456

图3.1 长安链管理平台界面

        登录后进入链账户管理,在组织证书,节点证书,用户证书中分别申请4个证书,

        首先是组织证书:

图3.2 申请组织证书

        共计生成4个

图3.3 组织证书账户

        然后是节点证书

图3.4 申请节点证书

        共计生成4个

图3.5 节点证书账户

        最后是用户证书

图3.6 用户证书

        共计生成4个

图3.7 用户证书账户

        生成后的证书都生成了签名证书和私钥,都可进行下载

图3.8 组织签名证书

        然后进入区块链管理,在上面点击新建区块链

图3.9 区块链管理

        在新建区块链中,依次输入区块链ID,区块链名称

图3.10 链参数配置1

图3.11 链参数配置2

        ip输入自己服务器的IP地址即可,端口填写如下

图3.12 链参数配置3

        下一步之后下载链配置文件,解压进入到release文件夹,

        使用./start.sh启动区块链

图3.13 部署长安链

                并在下一步确认订阅

图3.14 订阅长安链

至此,区块链搭建完成

图3.15 区块链概览

四、合约编写

        打开长安链IDE,右键Workspace创建合约工程,合约工程名自定,以我项目实战中的CarbonCoin为例

图4.1 创建合约工程

        具体合约代码如下

package main



import (

    "chainmaker.org/chainmaker/contract-sdk-go/v2/pb/protogo"

    "chainmaker.org/chainmaker/contract-sdk-go/v2/sandbox"

    "chainmaker.org/chainmaker/contract-sdk-go/v2/sdk"

    "encoding/json"

    "strconv"

)



// CarbonCoinContract 碳币合约实现

type CarbonCoinContract struct{}



// CreditInfo 用于存储和转移的碳币和碳额度信息

type CreditInfo struct {

    CarbonCoin   int `json:"carbonCoin"`

    CarbonCredit int `json:"carbonCredit"`

}



// InitContract 初始化合约

func (c *CarbonCoinContract) InitContract() protogo.Response {

    return sdk.Success(nil)

}



// UpgradeContract 升级合约

func (c *CarbonCoinContract) UpgradeContract() protogo.Response {

    return sdk.Success(nil)

}



// InvokeContract 调用合约方法

func (c *CarbonCoinContract) InvokeContract(method string) (result protogo.Response) {



    switch method {

    case "IssueCredit":

       return c.IssueCredit()

    case "QueryCredit":

       return c.QueryCredit()

    case "TransferCredit":

       return c.TransferCredit()

    default:

       return sdk.Error("invalid method")

    }

}



// IssueCredit 分配碳币和碳额度

func (c *CarbonCoinContract) IssueCredit() protogo.Response {

    params := sdk.Instance.GetArgs()

    companyID := string(params["companyID"])

    carbonCoin, err := strconv.Atoi(string(params["carbonCoin"]))

    if err != nil {

       return sdk.Error(err.Error())

    }

    carbonCredit, err := strconv.Atoi(string(params["carbonCredit"]))

    if err != nil {

       return sdk.Error(err.Error())

    }



    creditInfo := CreditInfo{CarbonCoin: carbonCoin, CarbonCredit: carbonCredit}

    creditInfoBytes, err := json.Marshal(creditInfo)

    if err != nil {

       return sdk.Error(err.Error())

    }



    err = sdk.Instance.PutStateByte(companyID, "creditInfo", creditInfoBytes)

    if err != nil {

       return sdk.Error(err.Error())

    }



    return sdk.Success(nil)

}



// QueryCredit 查询公司的碳币和碳额度

func (c *CarbonCoinContract) QueryCredit() protogo.Response {

    params := sdk.Instance.GetArgs()

    companyID := string(params["companyID"])



    creditInfoBytes, err := sdk.Instance.GetStateByte(companyID, "creditInfo")

    if err != nil {

       return sdk.Error(err.Error())

    }

    if creditInfoBytes == nil {

       return sdk.Error("credit info not found")

    }



    return sdk.Success(creditInfoBytes)

}



// TransferCredit 两公司之间转移碳币和碳额度

func (c *CarbonCoinContract) TransferCredit() protogo.Response {

    params := sdk.Instance.GetArgs()

    companyAID := string(params["companyAID"])

    companyBID := string(params["companyBID"])

    carbonCoinToTransfer, err := strconv.Atoi(string(params["carbonCoin"]))

    if err != nil {

       return sdk.Error("invalid carbonCoin: " + err.Error())

    }

    carbonCreditToTransfer, err := strconv.Atoi(string(params["carbonCredit"]))

    if err != nil {

       return sdk.Error("invalid carbonCredit: " + err.Error())

    }



    // 查询公司A的碳币和碳额度信息

    creditInfoABytes, err := sdk.Instance.GetStateByte(companyAID, "creditInfo")

    if err != nil {

       return sdk.Error("failed to get credit info for company A: " + err.Error())

    }

    if creditInfoABytes == nil {

       return sdk.Error("credit info for company A not found")

    }

    var creditInfoA CreditInfo

    err = json.Unmarshal(creditInfoABytes, &creditInfoA)

    if err != nil {

       return sdk.Error("failed to unmarshal credit info for company A: " + err.Error())

    }



    // 查询公司B的碳币和碳额度信息

    creditInfoBBytes, err := sdk.Instance.GetStateByte(companyBID, "creditInfo")

    if err != nil {

       return sdk.Error("failed to get credit info for company B: " + err.Error())

    }

    if creditInfoBBytes == nil {

       return sdk.Error("credit info for company B not found")

    }

    var creditInfoB CreditInfo

    err = json.Unmarshal(creditInfoBBytes, &creditInfoB)

    if err != nil {

       return sdk.Error("failed to unmarshal credit info for company B: " + err.Error())

    }



    // 执行转移逻辑

    if creditInfoA.CarbonCoin < carbonCoinToTransfer || creditInfoA.CarbonCredit < carbonCreditToTransfer {

       return sdk.Error("company A does not have enough carbonCoin or carbonCredit to transfer")

    }

    creditInfoA.CarbonCoin -= carbonCoinToTransfer

    creditInfoA.CarbonCredit -= carbonCreditToTransfer

    creditInfoB.CarbonCoin += carbonCoinToTransfer

    creditInfoB.CarbonCredit += carbonCreditToTransfer



    // 更新公司A的碳币和碳额度信息

    creditInfoABytes, err = json.Marshal(creditInfoA)

    if err != nil {

       return sdk.Error("failed to marshal updated credit info for company A: " + err.Error())

    }

    err = sdk.Instance.PutStateByte(companyAID, "creditInfo", creditInfoABytes)

    if err != nil {

       return sdk.Error("failed to update credit info for company A: " + err.Error())

    }



    // 更新公司B的碳币和碳额度信息

    creditInfoBBytes, err = json.Marshal(creditInfoB)

    if err != nil {

       return sdk.Error("failed to marshal updated credit info for company B: " + err.Error())

    }

    err = sdk.Instance.PutStateByte(companyBID, "creditInfo", creditInfoBBytes)

    if err != nil {

       return sdk.Error("failed to update credit info for company B: " + err.Error())

    }



    return sdk.Success(nil)

}



func main() {

    err := sandbox.Start(new(CarbonCoinContract))

    if err != nil {

       sdk.Instance.Errorf(err.Error())

    }

}

        接着点击右边保存

图4.2 点击保存

        然后分析这里面的代码,

        看如下代码得知,我们有IssueCredit,QueryCredit,TransferCredit方法:

// InvokeContract 调用合约方法

func (c *CarbonCoinContract) InvokeContract(method string) (result protogo.Response) {



    switch method {

    case "IssueCredit":

       return c.IssueCredit()

    case "QueryCredit":

       return c.QueryCredit()

    case "TransferCredit":

       return c.TransferCredit()

    default:

       return sdk.Error("invalid method")

    }

}

以IssueCredit方法举例,这里看到具体的方法:

func (c *CarbonCoinContract) IssueCredit() protogo.Response {

    params := sdk.Instance.GetArgs()

    companyID := string(params["companyID"])

    carbonCoin, err := strconv.Atoi(string(params["carbonCoin"]))

    if err != nil {

       return sdk.Error(err.Error())

    }

    carbonCredit, err := strconv.Atoi(string(params["carbonCredit"]))

    if err != nil {

       return sdk.Error(err.Error())

    }



    creditInfo := CreditInfo{CarbonCoin: carbonCoin, CarbonCredit: carbonCredit}

    creditInfoBytes, err := json.Marshal(creditInfo)

    if err != nil {

       return sdk.Error(err.Error())

    }



    err = sdk.Instance.PutStateByte(companyID, "creditInfo", creditInfoBytes)

    if err != nil {

       return sdk.Error(err.Error())

    }



    return sdk.Success(nil)

}

        这里可以看到companyID, carbonCoin,carbonCredit,这个是我们在调试中所用到的key,value就是具体传的值

图4.3 部署长安链

        这里选择合约,然后选择合约方法,输入对应信息,然后构建合约,执行合约,在模拟区块链上进行调试。

        合约没问题之后点击第三个按钮合约编译,编译完会有一个.7z的下载包下载下来。

图4.4 合约编译

五、合约部署

        进入区块链管理平台,进来之后找到区块链管理,合约管理,这里部署合约,

图5.1 合约管理界面

        具体部署合约如下,合约名称和一开始在IDE里新建的合约名称一致,合约版本自定义,虚拟机类型DOCKER_GO,合约文件则将刚刚下载的.7z后缀文件上传。

        这里尤其注意合约调用方法,这里需要把合约里的方法都写上去,这里我以IssueCredit举例,写了这么一个方法,然后它的key是companyID,carbonCoin,carbonCredit,需把这些都要写进去,将下面的图一一对应起来。

图5.2 部署合约界面

        部署后点击确定,然后如果要升级合约,具体操作和原来大致相同,部署完成后找到上链管理,发起上链。

图5.3 上链管理界面        

        选择合约,交互类型,调用方法,对应添加每个参数,运行一下可以检查每个功能能否正确部署

图5.4 发起上链界面

        能正确上链的基本都是交易成功,如果不成功可能是value输入有误。

图5.5 上链列表

        然后点击合约可以查看具体信息

图5.6 上链信息

        至此示例合约部署完成。

  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值