Likt's Blog

天空一直都在,是云来了又去。

0%

了解区块链中的交易,了解智能合约的使用

一、实验目的

  1. 了解区块链中的交易;
  2. 了解智能合约的使用;
  3. 编写测试两个智能合约;
  4. 简单的存储参数及抽奖程序;

二、实验环境

  • Windows 11
  • IDEA java、maven、springboot
  • navicat
  • postman

三、实验步骤

第一部分 区块链中的交易

区块链中,交易是指两方之间价值的转移。货币、资产或数据的交换。交易的基本概念建立在信任与透明的基础上,通过区块链的分布式账本,所有参与者都可以验证交易的有效性,没人能篡改历史记录。这种机制使得区块链特别适用于金融系统和需要去中心化信任的场景。

交易的组成部分:金额amount,交易ID(hashNo),时间戳

交易的生命周期:

  • 创建交易(基本信息:接收方地址,金额
  • 签名(私钥
  • 广播(所有节点接收到该交易信息
  • 验证(有效性:检查输入是否有效,签名是否正确
  • 打包(被矿工打包成区块,与其他交易一起处理
  • 确认(通过工作量证明等机制确认区块,交易被写入区块链
  • 最终性(一旦被多个区块确认后,被认为是不可更改的,完成整个交易流程
  1. 交易实体类:TradeObject

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    package com.example.blockchain.entity;
    public class TradeObject {

    private String from;
    private String to;
    private String hashNo;
    private String type;
    private String imgUrl;
    private String content;
    private String blockIndex;
    private String contentjson;
    private String jsoncreatetime;
    private String uId;
    private String annexPath;
    private String filePath;
    private String blockHash;
    private String createTime;
    private String sign;
    private String contractContent;
    private String paramStr;
    private String lastData;
    private String objToString;
    private String dataStr;

    @Override
    public String toString() {
    return "TradeObject{" +
    "from='" + from + '\'' +
    ", to='" + to + '\'' +
    ", type='" + type + '\'' +
    ", imgUrl='" + imgUrl + '\'' +
    ", content='" + content + '\'' +
    ", blockIndex='" + blockIndex + '\'' +
    ", contentjson='" + contentjson + '\'' +
    ", jsoncreatetime='" + jsoncreatetime + '\'' +
    ", uId='" + uId + '\'' +
    ", annexPath='" + annexPath + '\'' +
    ", filePath='" + filePath + '\'' +
    ", contractContent='" + contractContent + '\'' +
    ", paramStr='" + paramStr + '\'' +
    ", lastData='" + lastData + '\'' +
    '}';
    }
    //剩下一些get,set方法
    }
  2. 交易接口

    @RequestBody要求传递的参数需要以json形式传递

    type=1普通交易,2创建合约的交易,3调用合约的交易

    from发起方,to目的方(system)

    content字符串类型,上链。

    非空的判断验证,完成之后进行构建tradeobject,

    签名用的就是toString内容,键值对的形式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Override
    public String toString() {
    return "TradeObject{" +
    "from='" + from + '\'' +
    ", to='" + to + '\'' +
    ", type='" + type + '\'' +
    ", imgUrl='" + imgUrl + '\'' +
    ", content='" + content + '\'' +
    ", blockIndex='" + blockIndex + '\'' +
    ", contentjson='" + contentjson + '\'' +
    ", jsoncreatetime='" + jsoncreatetime + '\'' +
    ", uId='" + uId + '\'' +
    ", annexPath='" + annexPath + '\'' +
    ", filePath='" + filePath + '\'' +
    ", contractContent='" + contractContent + '\'' +
    ", paramStr='" + paramStr + '\'' +
    ", lastData='" + lastData + '\'' +
    '}';
    }

    /data/getWallet接口,返回私钥、地址

  3. navicat新建数据库,运行SQL文件选择xxl_job,关闭数据库后双击打开数据库进行刷新。

    屏幕截图 2024-10-26 164835

    屏幕截图 2024-10-26 165145

    image-20241026165321946

  4. block_contract项目中查看pom.xml文件,application.properties文件更改IP配置

    启动引导节点p2p_bootstrap,运行block_contract获得交易对象,/data/getWallet接口,postman请求http://localhost:8001/data/getWallet,配套使用钱包的数据;获取交易实体类(才能发起交易请求)/data/getTradeObjectJSON形式传递。

    开启另外一个节点,共:一个p2p_bootstrap,两个block_contract(至少一个引导节点,两个分节点)

    有了交易对象可以发起交易,/data/trade交易接口,发送成功,然矿工挖出来,两个节点要分别启动starMining

    browser浏览器,看到详细信息

    ①运行block_contract,/data/getWallet接口,postman请求http://localhost:8001/data/getWallet获得交易对象

image-20241026210545801

1
2
3
4
5
6
7
8
9
{
"code": "1",
"msg": "生成钱包成功",
"o": {
"publicKey": "13aae02db917ba3cf26eb5201f55d9fe094be2ad8df09437918c3d278adde0af77ae39ae6a1575d592536287a78b58594638951bd7cc3f04153381f0a0fa6618",
"privateKey": "8676da2a245a145b1cc7e158d6b2221e892478c386dc0dcc28b9ed6772b08975",
"address": "0x4dd32f368a54e39ee7da24d6eb5ebecf7d062eb5"
}
}

②获取交易实体类(才能发起交易请求)/data/getTradeObjectJSON形式传递。

image-20241026210821012

交易对象生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"from": "0x4dd32f368a54e39ee7da24d6eb5ebecf7d062eb5",
"to": "system",
"hashNo": null,
"type": "1",
"imgUrl": null,
"content": "hello likt 时针一直倒数着 ",
"blockIndex": null,
"contentjson": null,
"jsoncreatetime": "2024-10-26 21:07:55",
"uId": null,
"annexPath": null,
"filePath": null,
"blockHash": null,
"createTime": null,
"sign": "b64ee84d8c2fe18ffc883419fb27f02572c2251b101a88f3f179cfbcf066e93770008c098796142b8b512a962ac5f9f547ca61218215d32205d6b1d45adbb2771b",
"contractContent": null,
"paramStr": null,
"lastData": null,
"objToString": "TradeObject{from='0x4dd32f368a54e39ee7da24d6eb5ebecf7d062eb5', to='system', type='1', imgUrl='null', content='hello likt 时针一直倒数着 ', blockIndex='null', contentjson='null', jsoncreatetime='2024-10-26 21:07:55', uId='null', annexPath='null', filePath='null', contractContent='null', paramStr='null', lastData='null'}",
"dataStr": null
}

③有了交易对象可以发起交易,/data/trade交易接口,发送成功,然后启动矿工挖出来,两个节点要分别启动starMining

image-20241026211008540

④启动引导节点

image-20241026205827057

⑤启动两个对等节点,本机启动一个,队友启动一个

image-20241026205727922

⑥两个对等节点在postman使用接口开始挖矿

image-20241026212620265

⑦browser浏览器,看到详细区块信息

image-20241026211813503

⑧这里可以查看到先前提交的交易信息,被矿工挖出来了。

image-20241026211359642

第二部分 智能合约

智能合约是一种自执行的合约,协议条款直接写入代码,并存储在区块链上。他能够在特定条件被满足时,自动执行合约的条款。确保交易的透明性和可信性,因为所有操作都记录在区块链上,且不可篡改。

工作原理:①区块链(去中心化的分布式账本技术,能够安全记录交易和信息)数据以区块的形式存储,每个区块包含一组交易信息,并通过加密技术连接成链。②去中心化。③共识机制④不可篡改

如何执行智能合约:①合约的编写:solidity编程语言;②部署到区块链(合约的地址会被记录,任何人可以与其交互);③触发条件;④自动执行;⑤记录与验证(执行结果会被记录到区块链上,通过共识机制进行验证,每个节点都有相同信息);⑥反馈与更新。

solidity编程语言:支持静态类型检查,减少运行时错误;允许定义合约、库、接口,便于代码组织和重用;提供事件日志功能,便于在区块链上跟踪状态变化和交易。常用的开发环境包括Remix,Truffle,Hardhat这些工具提供了测试、编译和部署功能。

以太坊平台:开发的区块链平台,支持智能合约和去中心化应用的开发;以太坊使用以太坊虚拟机EVM来执行智能合约(完全去中心化);原生代币(以太ETH),用户调用智能合约时需要支付Gas费用;丰富生态系统;发展方向,2.0版本更新采用权益证明机制。

智能合约应用场景:金融服务(去中心化,自动化清算与结算,保险理赔);供应链管理(透明度与追踪;自动执行合同条款;防止伪造与欺诈);投票系统(安全透明;减少舞弊行为;快速统计结果)

一)以太坊智能合约

①测试智能合约

https://remix.ethereum.org/#lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.26+commit.8a97fa7a.js

②solidity合约通常包括几部分:SPDX许可标识;pragma指令 指定solidity版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}

image-20241026222036500

③步骤:solidity compiler编译,左侧部署,environment,account,deploy,deployed contracts,

交易哈希,block哈希,from,

④输入值13,存store,区块号增长,to store方法;retrieve取

image-20241026222441116

image-20241026222515136

二)智能合约系统

https://gitee.com/daitoulin/contract_admin.git

结构:三个模块

xxl-job-exector-samples两个事例:无框架,spring boot框架

xxl-job-core核心

xxl-job-admin后台管理系统

对application.properties修改,Email暂时用不到

1
xxl.job.accessToken=abbbq.bbc!

①启动引导节点

image-20241028225306327

②启动contract_admin智能合约系统【node.ip其中一个分节点的IP(可以任意)】

image-20241027231630848

③启动分节点block_contract【本机启动一个,队友启动一个】这里附带一些关于分节点的配置信息

image-20241027231032911

image-20241028220237204

④分节点成功注册到智能合约系统

image-20241028220312832

⑤访问合约后台,localhost:7896/xxl-job-admin,进行登录admin、123456,选择“执行器管理”查看注册节点如下

image-20241028220204647

1)最简单的存储参数

⑥创建合约,新增,填写,私钥、钱包地址(之前保存的一整套),GLUE(Java),保存

image-20241028221204855

⑦修改合约内容 操作- GLUE ide,修改合约信息如下

image-20241028221248367

⑧postman开启挖矿http://localhost:8001/starMining,登录节点的浏览器index.html查看最新区块信息

查看到 交易对象,合约信息,toString

image-20241028221226901

image-20241028221147615

⑨挖到交易内容

image-20241028221027748

2)抽奖程序

⑥新建合约(同上)

image-20241028225902705

⑦修改合约

image-20241028225914931

⑧保存,源码备注+私钥

image-20241028225927384

⑨执行一次,构造参数(一定要带上私钥,传一个list随机选一个获奖,participants

image-20241028225944840

海豚Baas Block Explorer查看挖出的区块信息,挖到交易【小婷中奖】

image-20241028222248573

三)navicate连接blockchain.db

①新建Sqlite连接,选择数据库文件,测试连接成功

D:\BlockChain\IdeaProjects\block_contract\db\block\blockchain.db

image-20241028222751350

②打开连接,查看dictionary,pending表信息如下,即挖到的交易信息

image-20241028231700330

image-20241028225007691

四、实验结果与讨论

  1. 生成公私钥、钱包地址,交易体,发起交易

    image-20241026211008540

  2. 挖到提交的交易信息

    image-20250112175939430

  3. printData信息成功上链

    image-20250112175714872

  4. 抽奖程序

    image-20250112175721268

五、总结

  1. 区块链交易的流程:【一个p2p_bootstrap,两个block_contract(至少一个引导节点,两个分节点)】①启动引导节点p2p_bootstrap;②运行block_contract获得交易对象,/data/getWallet接口;③postman请求http://localhost:8001/data/getWallet,配套使用钱包的数据;④获取交易实体类(才能发起交易请求)``/data/getTradeObject``JSON形式传递。⑤有了交易对象可以发起交易,``/data/trade``交易接口,发送成功;⑥开启另一个节点block_contract;⑦然矿工挖出来,两个节点要分别启动starMining;⑧browser浏览器,看到详细信息。

  2. ①引导节点启动,先运行admin即智能合约系统【node.ip其中一个分节点的IP(可以任意)】,启动分节点【自己一个,队友一个】等合约写完了再进行挖矿;②访问合约后台,localhost:7896/xxl-job-admin③账号密码admin,123456登录;④观察节点是否成功注册到合约系统,执行器管理;⑤data=map.get("printData");任何想上链的东西都可以放到data中;⑥修改、保存合约,“测试参数”,私钥还是刚刚的,保存成功;⑦执行一次:调用合约即构造任务参数输入JSON字符串形式的参数,私钥(JSON可以在线校验格式是否正确);⑧调度日志查看是否调度执行成功,如果成功的话会被放到交易池中;⑨使用postman调用接口starMining开始挖矿;⑩海豚Baas Block Explorer刷新查看最新区块信息;

  3. JSON形式各数据结构

    ①普通形式

    1
    {"privateKey":"your_private"}

    ②List形式(有序集合,0则abc,1则bcd中奖)

    1
    {"privateKey":"your_private","printData":["abc","bcd"]}

    ③Map形式

    1
    {"privateKey":"your_private","printData":{"eee":"sfsdf","www":"qqai"}}
  4. 这里用到两个简单的智能合约,构造JSON参数如下:

    1
    2
    3
    4
    {
    "privateKey":"8676da2a245a145b1cc7e158d6b2221e892478c386dc0dcc28b9ed6772b08975",
    "printData":"时针一直倒数着"
    }
  5. 这里用到List形式的JSON 用于抽奖程序

    1
    2
    3
    4
    5
    6
    7
    8
    {
    "privateKey": "8676da2a245a145b1cc7e158d6b2221e892478c386dc0dcc28b9ed6772b08975",
    "participants": [
    "小婷",
    "小庆",
    "菲菲公主"
    ]
    }
  6. 抽奖的合约代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package com.xxl.job.service.handler;

    import com.xxl.job.core.context.XxlJobHelper;
    import com.xxl.job.core.handler.IJobHandler;
    import java.util.*;
    import com.example.blockchain.service.impl.ContractServiceImpl;
    import javax.annotation.Resource;
    import com.example.blockchain.entity.TradeObject;
    import com.google.gson.Gson;
    import com.example.blockchain.entity.TContract;

    public class DemoGlueJobHandler extends IJobHandler {

    @Resource
    private ContractServiceImpl contractServiceImpl;
    @Override
    public void execute() throws Exception {
    XxlJobHelper.log("XXL-JOB, Hello World.");
    String Param = XxlJobHelper.getJobParam();
    HashMap<String, Object> map = contractServiceImpl.jsonToMap(Param);
    System.out.println(map);
    XxlJobHelper.log(map.toString());
    TradeObject trade = new Gson().fromJson(map.get("tradeObject"),TradeObject.class);
    TContract contract = new TContract();
    String data = "";

    List<String> participants = map.get("participants");

    // 生成随机数并确定中奖者
    Random random = new Random();
    int index = random.nextInt(participants.size());//random.nextInt不取右边的
    String winner = participants.get(index);
    data = winner;

    trade.setDataStr(data);
    contract.setId(Integer.valueOf(map.get("contractId")));
    contract.setData(data);
    contract.setLastData(trade.getLastData());
    contractServiceImpl.setData(contract);
    contractServiceImpl.toChain(trade);
    }
    }

-------------本文结束感谢您的阅读-------------