崛起於Springboot2.X + 多節點mongodb實現區塊鏈交易記錄(36)

《SpringBoot2.X心法總綱》   html

  (本篇博客已於2019-08-28 優化更新)java

      序言:根據前兩篇區塊鏈單節點mysql實現交易記錄Mongodb多數據源處理,進行整合,實現區塊鏈多節點mongodb實現交易記錄方案。因此本篇博客算是一個升級篇。node

      技術棧:mysql

        SpringBoot2.0.X、mongodb:(存儲區塊數據)、mysql:(獲取業務邏輯數據)、Scheduled:(或者Quartz)git

        redis:(單節點--【能夠升級到哨兵模式或者集羣】)web

        區塊鏈思想:信息不可篡改,公式機制,分佈式全劇記帳。redis

        碼雲地址: https://gitee.com/mdxl/most_block_cj.git算法

一、pom依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.2</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

二、application.properties

server.port=8092

#mysql:
spring.datasource.url=jdbc:mysql://localhost:3306/xx?characterEncoding=utf8&useSSL=false
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5


mybatis.mapper-Locations=classpath:mapper/entity/*.xml
mybatis.type-aliases-package=com.dtb.trade.entity

spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=10000


spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.suffix=.html

#mongodb

spring.data.mongodb.first.database=node1
spring.data.mongodb.first.uri=localhost:27017

spring.data.mongodb.second.database=node2
spring.data.mongodb.second.uri=localhost:27017

spring.data.mongodb.third.database=node3
spring.data.mongodb.third.uri=localhost:27017

spring.data.mongodb.fourth.database=node4
spring.data.mongodb.fourth.uri=localhost:27017

三、項目目錄架構

四、代碼實現

4.1 mysql表結構

CREATE TABLE `t_point_deal` (
  `DEAL_ID` varchar(200) NOT NULL COMMENT '交易單id',
  `BUY_USER_ID` int(10) NOT NULL COMMENT '買方id',
  `BUY_ORDER_ID` bigint(10) unsigned NOT NULL,
  `SELL_USER_ID` int(11) NOT NULL COMMENT '賣方id',
  `SELL_ORDER_ID` bigint(10) unsigned NOT NULL,
  `POINT_ID` int(11) NOT NULL COMMENT '基金id號',
  `DEAL_DATE` datetime NOT NULL COMMENT '交易日期',
  `DEAL_NUM` int(11) unsigned NOT NULL COMMENT '交易數量',
  `DEAL_UNIT_PRICE` double(8,2) unsigned NOT NULL COMMENT '交易單價',
  `DEAL_PRICE` double(10,2) unsigned NOT NULL COMMENT '成交額',
  PRIMARY KEY (`DEAL_ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

CREATE TABLE `t_block` (
  `block_index` int(10) NOT NULL AUTO_INCREMENT COMMENT '區塊索引號',
  `block_hash` varchar(100) NOT NULL COMMENT 'hash值',
  `block_stamp` varchar(40) NOT NULL COMMENT '時間戳',
  `pointDeals` mediumtext COMMENT '基金交易記錄',
  `block_nonce` int(10) NOT NULL COMMENT '隨機數',
  `previousHash` varchar(100) NOT NULL COMMENT '上一個區塊hash值',
  PRIMARY KEY (`block_index`)
) ENGINE=MyISAM AUTO_INCREMENT=83 DEFAULT CHARSET=utf8

4.2 配置類層

import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class MultipleMongoProperties {

    @Bean(name="firstMongoProperties")
    @Primary
    @ConfigurationProperties(prefix="spring.data.mongodb.first")
    public MongoProperties firstMongoProperties() {
        return new MongoProperties();
    }

    @Bean(name="secondMongoProperties")
    @ConfigurationProperties(prefix="spring.data.mongodb.second")
    public MongoProperties secondMongoProperties() {
        return new MongoProperties();
    }

    @Bean(name="thirdMongoProperties")
    @ConfigurationProperties(prefix="spring.data.mongodb.third")
    public MongoProperties thirdMongoProperties() {
        return new MongoProperties();
    }

    @Bean(name="fourthMongoProperties")
    @ConfigurationProperties(prefix="spring.data.mongodb.fourth")
    public MongoProperties fourthMongoProperties() {
        return new MongoProperties();
    }
}
@Configuration
@EnableMongoRepositories(basePackages = "com.dtb.trade.dao.mongodb.first", mongoTemplateRef = "firstMongo")
public class FirstMongoTemplate {

    @Autowired
    @Qualifier("firstMongoProperties")
    private MongoProperties mongoProperties;

    @Primary
    @Bean(name = "firstMongo")
    public MongoTemplate firstMongoTemplate() throws Exception {
        return new MongoTemplate(firstFactory(this.mongoProperties));
    }

    @Bean
    @Primary
    public MongoDbFactory firstFactory(MongoProperties mongoProperties) throws Exception {

        ServerAddress serverAdress = new ServerAddress(mongoProperties.getUri());

        return new SimpleMongoDbFactory(new MongoClient(serverAdress), mongoProperties.getDatabase());

    }
}
@Configuration
@EnableMongoRepositories(basePackages = "com.dtb.trade.dao.mongodb.second", mongoTemplateRef = "secondMongo")
public class SecondMongoTemplate {
    @Autowired
    @Qualifier("secondMongoProperties")
    private MongoProperties mongoProperties;

    @Bean(name = "secondMongo")
    public MongoTemplate secondTemplate() throws Exception {
        return new MongoTemplate(secondFactory(this.mongoProperties));
    }

    @Bean
    public MongoDbFactory secondFactory(MongoProperties mongoProperties) throws Exception {
        ServerAddress serverAdress = new ServerAddress(mongoProperties.getUri());
        return new SimpleMongoDbFactory(new MongoClient(serverAdress), mongoProperties.getDatabase());
    }
}
@Configuration
@EnableMongoRepositories(basePackages = "com.dtb.trade.dao.mongodb.third", mongoTemplateRef = "thirdMongo")
public class ThirdMongoTemplate {

    @Autowired
    @Qualifier("thirdMongoProperties")
    private MongoProperties mongoProperties;

    @Bean(name = "thirdMongo")
    public MongoTemplate thirdTemplate() throws Exception {
        return new MongoTemplate(thirdFactory(this.mongoProperties));
    }

    @Bean
    public MongoDbFactory thirdFactory(MongoProperties mongoProperties) throws Exception {
        ServerAddress serverAdress = new ServerAddress(mongoProperties.getUri());
        return new SimpleMongoDbFactory(new MongoClient(serverAdress), mongoProperties.getDatabase());

    }
}
@Configuration
@EnableMongoRepositories(basePackages = "com.dtb.trade.dao.mongodb.fourth", mongoTemplateRef = "fourthMongo")
public class FourthMongoTemplate {

    @Autowired
    @Qualifier("fourthMongoProperties")
    private MongoProperties mongoProperties;

    @Bean(name = "fourthMongo")
    public MongoTemplate fourthTemplate() throws Exception {
        return new MongoTemplate(fourthFactory(this.mongoProperties));
    }

    @Bean
    public MongoDbFactory fourthFactory(MongoProperties mongoProperties) throws Exception {
        ServerAddress serverAdress = new ServerAddress(mongoProperties.getUri());
        return new SimpleMongoDbFactory(new MongoClient(serverAdress), mongoProperties.getDatabase());

    }

}

4.3 dao層

public interface FirstRepository extends MongoRepository<FirstBlock,String> {

    FirstBlock findBlockByIndex(long index);
    @Query("{'index':{'$gte':?0}}")
    List<FirstBlock> findFirstBlockByIndex(int index);
}
public interface SecondRepository extends MongoRepository<SecondBlock,String> {

    SecondBlock findBlockByIndex(long index);

    @Query("{'index':{'$gte':?0}}")
    List<SecondBlock> findSecondBlockByIndex(int index);
}
public interface ThirdRepository extends MongoRepository<ThirdBlock,String> {

    ThirdBlock findBlockByIndex(long index);

    @Query("{'index':{'$gte':?0}}")
    List<ThirdBlock> findThirdBlockByIndex(int index);
}
public interface FourthRepository extends MongoRepository<FourthBlock,String> {

    FourthBlock findBlockByIndex(long index);

    @Query("{'index':{'$gte':?0}}")
    List<FourthBlock> findFourthBlockByIndex(int index);
}
public interface TradeDao {

    @Select({
            "select * from t_point_deal where DEAL_DATE >= #{start} and DEAL_DATE <= #{end}"
    })
    @Results({
            @Result(column = "DEAL_ID",property = "dealId",jdbcType = JdbcType.VARCHAR),
            @Result(column = "BUY_USER_ID",property = "buyUserId",jdbcType = JdbcType.INTEGER),
            @Result(column = "BUY_ORDER_ID",property = "buyOrderId",jdbcType = JdbcType.BIGINT),
            @Result(column = "SELL_USER_ID",property = "sellUserId",jdbcType = JdbcType.INTEGER),
            @Result(column = "SELL_ORDER_ID",property = "sellOrderId",jdbcType = JdbcType.BIGINT),
            @Result(column = "POINT_ID",property = "pointId",jdbcType = JdbcType.INTEGER),
            @Result(column = "DEAL_DATE",property = "dealDate",jdbcType = JdbcType.DATE),
            @Result(column = "DEAL_NUM",property = "dealNum",jdbcType = JdbcType.INTEGER),
            @Result(column = "DEAL_UNIT_PRICE",property = "dealUnitPrice",jdbcType = JdbcType.DOUBLE),
            @Result(column = "DEAL_PRICE",property = "dealPrice",jdbcType = JdbcType.DOUBLE),
    })
    List<PointDeal> getAll(Map<String,Object> map);

    @Select({
            "select * from t_block"
    })
    @Results({
            @Result(column = "block_index",property = "index",jdbcType = JdbcType.INTEGER),
            @Result(column = "block_hash",property = "hash",jdbcType = JdbcType.VARCHAR),
            @Result(column = "block_stamp",property = "timestamp",jdbcType = JdbcType.TIMESTAMP),
            @Result(column = "pointDeals",property = "data",jdbcType = JdbcType.LONGVARCHAR),
            @Result(column = "block_nonce",property = "nonce",jdbcType = JdbcType.INTEGER),
            @Result(column = "previousHash",property = "previousHash",jdbcType = JdbcType.VARCHAR)
    })
    List<Block> isHave();

    @Select({
            "select * from t_block order by block_index desc limit 0,1"
    })
    @Results({
            @Result(column = "block_index",property = "index",jdbcType = JdbcType.INTEGER),
            @Result(column = "block_hash",property = "hash",jdbcType = JdbcType.VARCHAR),
            @Result(column = "block_stamp",property = "timestamp",jdbcType = JdbcType.TIMESTAMP),
            @Result(column = "pointDeals",property = "data",jdbcType = JdbcType.LONGVARCHAR),
            @Result(column = "block_nonce",property = "nonce",jdbcType = JdbcType.INTEGER),
            @Result(column = "previousHash",property = "previousHash",jdbcType = JdbcType.VARCHAR)
    })
    Block getBlockIndex();

    @Insert({
            "insert into t_block (block_hash,block_stamp,pointDeals,block_nonce,previousHash) values(#{hash},#{timestamp},#{data},#{nonce},#{previousHash})"
    })
    int insertBlock(Block block);

    @Update({
            "update t_block set pointDeals = #{data} where block_index = #{index}"
    })
    int updateBlock(Block block);


    @Select({
            "select * from t_block where block_index = #{index}"
    })
    @Results({
            @Result(column = "block_index",property = "index",jdbcType = JdbcType.INTEGER),
            @Result(column = "block_hash",property = "hash",jdbcType = JdbcType.VARCHAR),
            @Result(column = "block_stamp",property = "timestamp",jdbcType = JdbcType.TIMESTAMP),
            @Result(column = "pointDeals",property = "data",jdbcType = JdbcType.LONGVARCHAR),
            @Result(column = "block_nonce",property = "nonce",jdbcType = JdbcType.INTEGER),
            @Result(column = "previousHash",property = "previousHash",jdbcType = JdbcType.VARCHAR)
    })
    Block selectBlock(@Param("index")int index);
}

4.4 entity層

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "first_block")
public class FirstBlock {


    private int index;

    private String hash;

    private long timestamp;

    private List<PointDeal> pointDeals;

    private String data;

    private int nonce;

    private String previousHash;

}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "second_block")
public class SecondBlock {


    private int index;

    private String hash;

    private long timestamp;

    private List<PointDeal> pointDeals;

    private String data;

    private int nonce;

    private String previousHash;

}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "third_block")
public class ThirdBlock {

    private int index;
    private String hash;
    private long timestamp;
    private List<PointDeal> pointDeals;
    private String data;
    private int nonce;
    private String previousHash;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "fourth_block")
public class FourthBlock {

    private int index;
    private String hash;
    private long timestamp;
    private List<PointDeal> pointDeals;
    private String data;
    private int nonce;
    private String previousHash;
}
@Data
public class Block {

    /**

     * 區塊索引號

     */

    private int index;

    /**

     * 當前區塊的hash值,區塊惟一標識

     */

    private String hash;

    /**

     * 生成區塊的時間戳

     */

    private long timestamp;

    /**

     * 當前區塊的交易集合

     */

    private List<PointDeal> pointDeals;

    private String data;

    /**

     * 工做量證實,計算正確hash值的次數

     */
    private int nonce;
    /**

     * 前一個區塊的hash值

     */

    private String previousHash;

    public Block() {
        super();
    }

    public Block(int index, long timestamp, List<PointDeal> pointDeals, String data, int nonce, String previousHash, String hash) {
        super();
        this.index = index;
        this.timestamp = timestamp;
        this.pointDeals= pointDeals;
        this.nonce = nonce;
        this.previousHash = previousHash;
        this.hash = hash;
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PointDeal {

    private String dealId;

    private Integer buyUserId;

    private Long buyOrderId;

    private Integer sellUserId;

    private Long sellOrderId;

    private Integer pointId;

    private Date dealDate;

    private Integer dealNum;

    private Double dealUnitPrice;

    private Double dealPrice;

}

4.5 service層 業務邏輯層

public interface BaseService<T> {

    //添加區塊
    void addBlock(T t);

    //是否包含區塊
    boolean isHaveBlock();

    //獲得最新區塊信息
    T getNewest();

    //根據索引號查詢區塊
    T getBlockByIndex(int index);

    //區塊記帳
    boolean hyperledger(T block, List<PointDeal> pointDeals);

    //生成新區塊
    void tally(T block,List<PointDeal> pointDeals);

    //刪除區塊交易記錄
    void deleteAllBlock();

    //驗證區塊過程當中是否被篡改
    boolean prove();

    //查詢當前索引號及之後的最新區塊
    List<T> getCurrentBlocks(int index);

}
@Service
public class TradeService {

    @Autowired
    TradeDao tradeDao;

    @Autowired
    RedisService redisService;

    //區塊擁有交易記錄的最大個數
    private static final int blockMax = 5;

    //該區塊已經擁有的交易記錄個數
    private static int blockNum = 0;

    //獲取定時刷新的交易記錄
    public List<PointDeal> gainAllTrade(){

        Map<String,Object> map = new HashMap<>();
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        map.put("start",today+" 00:00:00");
        map.put("end",today+" 23:58:58");
        return tradeDao.getAll(map);
    }

    //查詢是否擁有數據塊
    public boolean isBlock(){
        List<Block> list = tradeDao.isHave();
        if (list == null || list.isEmpty() || list.size()==0){
            return false;
        }
        return true;

    }

    //新增區塊信息
    public boolean insertBlock(Block block){
        tradeDao.insertBlock(block);
        return true;
    }

    //更新區塊信息
    public boolean updateBlock(Block block){
        tradeDao.updateBlock(block);
        return true;
    }

    //根據索引號查詢區塊信息
    public Block selectBlock(int index){
        return tradeDao.selectBlock(index);
    }

    //查詢最新區塊信息
    public Block getNewBlock(){
        Block block = tradeDao.getBlockIndex();

        block.setPointDeals(JSONObject.parseArray(block.getData(),PointDeal.class));

        return block;
    }

    //記帳
    public boolean hyperledger(Block block,List<PointDeal> pointDeals){



        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //準備記帳的記憶記錄個數
        int recordNum  = pointDeals.size();

        //欠缺,補足到最大區塊個數
        int deficiency = blockMax - blockNum;

        //該區塊是否能知足記帳交易記錄的個數,0恰好知足,正數綽綽有餘,負數不知足,生成新的區塊
        int surplusNum = deficiency-recordNum;

        if (blockNum < blockMax){
            //更新區塊信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                tradeDao.updateBlock(block);
            }else {
                //填補區塊剩餘
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到數據庫
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    tradeDao.updateBlock(block);
                    redisService.set("blockIndex",block.getIndex()+"");
                }
                //生成下一區塊
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                Block nextBlock = new Block();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                hyperledgerTwo(nextBlock,pointDeals);
            }
        }else {
            //直接生成新區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            Block nextBlock = new Block();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            hyperledgerTwo(nextBlock,pointDeals);

        }

        return true;

    }

    //新區塊記帳
    public void hyperledgerTwo(Block block,List<PointDeal> pointDeals){

        int recordNum  = pointDeals.size();
        int deficiency = blockMax - blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //知足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            tradeDao.insertBlock(block);
            redisService.set("blockIndex",block.getIndex()+"");
        }else {
            //不知足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到數據庫
            tradeDao.insertBlock(block);

            //生成下一區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            Block nextBlock = new Block();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            hyperledgerTwo(nextBlock,pointDeals);
        }

    }

    //獲取全部區塊
    public List<Block> getAllBlock(){
        List<Block> blocks = tradeDao.isHave();
        if (blocks != null || blocks.size() > 0){
            return blocks;
        }
        return null;
     }
     
}
@Service
public class MongoTradeService {

    @Autowired
    FirstRepository firstRepository;


    @Autowired
    RedisService redisService;

    //是否包含區塊
    public boolean isHaveBlock(){
        List<FirstBlock> list = firstRepository.findAll();
        if (list != null && list.size() >0){
            return true;
        }
        return false;
    }

    //添加新區塊
    public void addBlock(FirstBlock block){
        firstRepository.save(block);
    }

    //獲取最新區塊信息
    public FirstBlock getNewest(){
        long count = firstRepository.count();
        return firstRepository.findBlockByIndex(count);
    }

    //根據索引號查詢區塊
    public FirstBlock getBlockByIndex(int index){
        return firstRepository.findBlockByIndex(index);
    }


    //區塊基礎上記帳
    public boolean hyperledger(FirstBlock block,List<PointDeal> pointDeals){

        int blockNum   = 0;


        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //準備記帳的記憶記錄個數
        int recordNum  = pointDeals.size();

        //欠缺,補足到最大區塊個數
        int deficiency = BlockConstant.blockMax - BlockConstant.blockNum;

        //該區塊是否能知足記帳交易記錄的個數,0恰好知足,正數綽綽有餘,負數不知足,生成新的區塊
        int surplusNum = deficiency-recordNum;

        if (blockNum < BlockConstant.blockMax){
            //更新區塊信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                firstRepository.save(block);
            }else {
                //填補區塊剩餘
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到數據庫
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    firstRepository.save(block);
                    redisService.set("blockIndex",block.getIndex()+"");
                }
                //生成下一區塊
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                FirstBlock nextBlock = new FirstBlock();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                tally(nextBlock,pointDeals);
            }
        }else {
            //直接生成新區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            FirstBlock nextBlock = new FirstBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            tally(nextBlock,pointDeals);

        }

        return true;

    }


    //生成新區塊

    public void tally(FirstBlock block,List<PointDeal> pointDeals){

        int recordNum  = pointDeals.size();
        int deficiency = BlockConstant.blockMax - BlockConstant.blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //知足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            firstRepository.insert(block);
            redisService.set("blockIndex",block.getIndex()+"");
        }else {
            //不知足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到數據庫
            firstRepository.insert(block);

            //生成下一區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            FirstBlock nextBlock = new FirstBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            tally(nextBlock,pointDeals);
        }
    }

    //刪除區塊交易記錄
    public void deleteAllBlock(){
        firstRepository.deleteAll();
    }

    //驗證區塊交易過程是否被竄改
    public boolean prove(){
        List<FirstBlock> list = firstRepository.findAll();
        // 首先判斷創世區塊是否被篡改
        FirstBlock first = list.get(0);
        String hash      = EncryptUtil.Encrypt(first.getPreviousHash()+first.getIndex()+first.getNonce()+first.getTimestamp());

        if (!hash.equals(first.getHash())){
            return false;
        }

        for (int i =0;i<list.size()-1;i++){

            FirstBlock pre = list.get(i);

            String preHash  = pre.getHash();
            int nextIndex   = pre.getIndex()+1;
            int nextnonce   = pre.getNonce();
            long nextTime   = list.get(i+1).getTimestamp();
            String nextHash = EncryptUtil.Encrypt(preHash+nextIndex+nextnonce+nextTime+pre.getData());

            if (!nextHash.equals(list.get(i+1).getHash())){
                return false;
            }
        }

        return true;
    }

    public List<FirstBlock> getCurrentBlocks(int index){
        return firstRepository.findFirstBlockByIndex(index);
    }
}
@Service(value = "secondBlockService")
public class SecondBlockService implements BaseService<SecondBlock> {

    @Autowired
    SecondRepository secondRepository;

    @Autowired
    RedisService redisService;


    @Override
    public void addBlock(SecondBlock secondBlock) {
       secondRepository.save(secondBlock);
    }

    @Override
    public SecondBlock getNewest() {
        long count = secondRepository.count();
        if (count == 0){
            return null;
        }
        return secondRepository.findBlockByIndex(count);
    }

    @Override
    public SecondBlock getBlockByIndex(int index) {
        return secondRepository.findBlockByIndex(index);
    }

    @Override
    public boolean hyperledger(SecondBlock block, List<PointDeal> pointDeals) {

        int blockNum = BlockConstant.blockNum;

        int blockMax = BlockConstant.blockMax;


        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //準備記帳的記憶記錄個數
        int recordNum  = pointDeals.size();

        //欠缺,補足到最大區塊個數
        int deficiency = blockMax - blockNum;

        //該區塊是否能知足記帳交易記錄的個數,0恰好知足,正數綽綽有餘,負數不知足,生成新的區塊
        int surplusNum = deficiency-recordNum;

        if (blockNum < blockMax){
            //更新區塊信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                secondRepository.save(block);
            }else {
                //填補區塊剩餘
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到數據庫
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    secondRepository.save(block);
                    redisService.set("blockIndexSecond",block.getIndex()+"");
                }
                //生成下一區塊
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                SecondBlock nextBlock = new SecondBlock();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                tally(nextBlock,pointDeals);
            }
        }else {
            //直接生成新區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            SecondBlock nextBlock = new SecondBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            tally(nextBlock,pointDeals);

        }

        return true;
    }

    @Override
    public void tally(SecondBlock block, List<PointDeal> pointDeals) {

        int recordNum  = pointDeals.size();
        int deficiency = BlockConstant.blockMax - BlockConstant.blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //知足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            secondRepository.insert(block);
            redisService.set("blockIndexSecond",block.getIndex()+"");
        }else {
            //不知足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到數據庫
            secondRepository.insert(block);

            //生成下一區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            SecondBlock nextBlock = new SecondBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            tally(nextBlock,pointDeals);
        }
    }

    @Override
    public void deleteAllBlock() {
        secondRepository.deleteAll();
    }

    @Override
    public boolean prove() {
        List<SecondBlock> list = secondRepository.findAll();
        // 首先判斷創世區塊是否被篡改
        SecondBlock first = list.get(0);
        String hash      = EncryptUtil.Encrypt(first.getPreviousHash()+first.getIndex()+first.getNonce()+first.getTimestamp());

        if (!hash.equals(first.getHash())){
            return false;
        }

        for (int i =0;i<list.size()-1;i++){

            SecondBlock pre = list.get(i);

            String preHash  = pre.getHash();
            int nextIndex   = pre.getIndex()+1;
            int nextnonce   = pre.getNonce();
            long nextTime   = list.get(i+1).getTimestamp();
            String nextHash = EncryptUtil.Encrypt(preHash+nextIndex+nextnonce+nextTime+pre.getData());

            if (!nextHash.equals(list.get(i+1).getHash())){
                return false;
            }
        }

        return true;
    }

    @Override
    public List<SecondBlock> getCurrentBlocks(int index) {
        return secondRepository.findSecondBlockByIndex(index);
    }

    @Override
    public boolean isHaveBlock() {
        List<SecondBlock> list = secondRepository.findAll();
        if (list != null && list.size() >0){
            return true;
        }
        return false;
    }
}
@Service("thirdBlockService")
public class ThirdBlockService implements BaseService<ThirdBlock>{

    @Autowired
    ThirdRepository thirdRepository;

    @Autowired
    RedisService redisService;


    @Override
    public void addBlock(ThirdBlock thirdBlock) {
        thirdRepository.save(thirdBlock);
    }

    @Override
    public boolean isHaveBlock() {

        List<ThirdBlock> list = thirdRepository.findAll();
        if (list != null && list.size() >0){
            return true;
        }
        return false;
    }

    @Override
    public ThirdBlock getNewest() {
        long count = thirdRepository.count();
        return thirdRepository.findBlockByIndex(count);
    }

    @Override
    public ThirdBlock getBlockByIndex(int index) {
        return thirdRepository.findBlockByIndex(index);
    }

    @Override
    public boolean hyperledger(ThirdBlock block, List<PointDeal> pointDeals) {

        int blockNum = BlockConstant.blockNum;

        int blockMax = BlockConstant.blockMax;


        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //準備記帳的記憶記錄個數
        int recordNum  = pointDeals.size();

        //欠缺,補足到最大區塊個數
        int deficiency = blockMax - blockNum;

        //該區塊是否能知足記帳交易記錄的個數,0恰好知足,正數綽綽有餘,負數不知足,生成新的區塊
        int surplusNum = deficiency-recordNum;

        if (blockNum < blockMax){
            //更新區塊信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                thirdRepository.save(block);
            }else {
                //填補區塊剩餘
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到數據庫
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    thirdRepository.save(block);
                    redisService.set("blockIndexThird",block.getIndex()+"");
                }
                //生成下一區塊
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                ThirdBlock nextBlock = new ThirdBlock();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                tally(nextBlock,pointDeals);
            }
        }else {
            //直接生成新區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            ThirdBlock nextBlock = new ThirdBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            tally(nextBlock,pointDeals);

        }

        return true;
    }

    @Override
    public void tally(ThirdBlock block, List<PointDeal> pointDeals) {
        int recordNum  = pointDeals.size();
        int deficiency = BlockConstant.blockMax - BlockConstant.blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //知足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            thirdRepository.insert(block);
            redisService.set("blockIndexThird",block.getIndex()+"");
        }else {
            //不知足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到數據庫
            thirdRepository.insert(block);

            //生成下一區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            ThirdBlock nextBlock = new ThirdBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            tally(nextBlock,pointDeals);
        }
    }

    @Override
    public void deleteAllBlock() {
        thirdRepository.deleteAll();
    }

    @Override
    public boolean prove() {
        List<ThirdBlock> list = thirdRepository.findAll();
        // 首先判斷創世區塊是否被篡改
        ThirdBlock first = list.get(0);
        String hash      = EncryptUtil.Encrypt(first.getPreviousHash()+first.getIndex()+first.getNonce()+first.getTimestamp());

        if (!hash.equals(first.getHash())){
            return false;
        }

        for (int i =0;i<list.size()-1;i++){

            ThirdBlock pre = list.get(i);

            String preHash  = pre.getHash();
            int nextIndex   = pre.getIndex()+1;
            int nextnonce   = pre.getNonce();
            long nextTime   = list.get(i+1).getTimestamp();
            String nextHash = EncryptUtil.Encrypt(preHash+nextIndex+nextnonce+nextTime+pre.getData());

            if (!nextHash.equals(list.get(i+1).getHash())){
                return false;
            }
        }

        return true;
    }

    @Override
    public List<ThirdBlock> getCurrentBlocks(int index) {
        return thirdRepository.findThirdBlockByIndex(index);
    }
}
@Service("fourthBlockService")
public class FourthBlockService implements BaseService<FourthBlock> {

    @Autowired
    FourthRepository fourthRepository;

    @Autowired
    RedisService redisService;

    @Override
    public void addBlock(FourthBlock fourthBlock) {
        fourthRepository.save(fourthBlock);
    }

    @Override
    public boolean isHaveBlock() {
        List<FourthBlock> list = fourthRepository.findAll();
        if (list != null && list.size() >0){
            return true;
        }
        return false;
    }

    @Override
    public FourthBlock getNewest() {
        long count = fourthRepository.count();
        return fourthRepository.findBlockByIndex(count);
    }

    @Override
    public FourthBlock getBlockByIndex(int index) {
        return fourthRepository.findBlockByIndex(index);
    }

    @Override
    public boolean hyperledger(FourthBlock block, List<PointDeal> pointDeals) {

        int blockNum = BlockConstant.blockNum;

        int blockMax = BlockConstant.blockMax;


        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //準備記帳的記憶記錄個數
        int recordNum  = pointDeals.size();

        //欠缺,補足到最大區塊個數
        int deficiency = blockMax - blockNum;

        //該區塊是否能知足記帳交易記錄的個數,0恰好知足,正數綽綽有餘,負數不知足,生成新的區塊
        int surplusNum = deficiency-recordNum;

        if (blockNum < blockMax){
            //更新區塊信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                fourthRepository.save(block);
            }else {
                //填補區塊剩餘
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到數據庫
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    fourthRepository.save(block);
                    redisService.set("blockIndexFourth",block.getIndex()+"");
                }
                //生成下一區塊
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                FourthBlock nextBlock = new FourthBlock();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                tally(nextBlock,pointDeals);
            }
        }else {
            //直接生成新區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            FourthBlock nextBlock = new FourthBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            tally(nextBlock,pointDeals);

        }

        return true;
    }

    @Override
    public void tally(FourthBlock block, List<PointDeal> pointDeals) {
        int recordNum  = pointDeals.size();
        int deficiency = BlockConstant.blockMax - BlockConstant.blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //知足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            fourthRepository.insert(block);
            redisService.set("blockIndexFourth",block.getIndex()+"");
        }else {
            //不知足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到數據庫
            fourthRepository.insert(block);

            //生成下一區塊
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            FourthBlock nextBlock = new FourthBlock();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            tally(nextBlock,pointDeals);
        }
    }

    @Override
    public void deleteAllBlock() {
        fourthRepository.deleteAll();
    }

    @Override
    public boolean prove() {
        List<FourthBlock> list = fourthRepository.findAll();
        // 首先判斷創世區塊是否被篡改
        FourthBlock first = list.get(0);
        String hash      = EncryptUtil.Encrypt(first.getPreviousHash()+first.getIndex()+first.getNonce()+first.getTimestamp());

        if (!hash.equals(first.getHash())){
            return false;
        }

        for (int i =0;i<list.size()-1;i++){

            FourthBlock pre = list.get(i);

            String preHash  = pre.getHash();
            int nextIndex   = pre.getIndex()+1;
            int nextnonce   = pre.getNonce();
            long nextTime   = list.get(i+1).getTimestamp();
            String nextHash = EncryptUtil.Encrypt(preHash+nextIndex+nextnonce+nextTime+pre.getData());

            if (!nextHash.equals(list.get(i+1).getHash())){
                return false;
            }
        }

        return true;
    }

    @Override
    public List<FourthBlock> getCurrentBlocks(int index) {
        return fourthRepository.findFourthBlockByIndex(index);
    }
}

4.6 util層

public class BlockConstant {
    //區塊擁有交易記錄的最大個數
    public static final int blockMax = 5;

    //該區塊已經擁有的交易記錄個數
    public static int blockNum = 0;
}
public class BlockException extends Exception {

    private static final long serialVersionUID = 1l;

    public BlockException(){
        super();
    }

    public BlockException(String msg){
        super(msg);
    }

    public BlockException(String msg,Throwable cause){
        super(msg,cause);
    }

    public BlockException(String msg,String message){

    }

    public BlockException(Throwable cause){
        super(cause);
    }
}
public class ConvertUtil {

    public static SecondBlock convertSecond(FirstBlock firstBlock){

        SecondBlock block = new SecondBlock();
        block.setData(firstBlock.getData());
        block.setHash(firstBlock.getHash());
        block.setIndex(firstBlock.getIndex());
        block.setNonce(firstBlock.getNonce());
        block.setPreviousHash(firstBlock.getPreviousHash());
        block.setTimestamp(firstBlock.getTimestamp());
        block.setPointDeals(firstBlock.getPointDeals());
        return block;
    }

    public static ThirdBlock convertThird(FirstBlock firstBlock){


        ThirdBlock block = new ThirdBlock();
        block.setData(firstBlock.getData());
        block.setHash(firstBlock.getHash());
        block.setIndex(firstBlock.getIndex());
        block.setNonce(firstBlock.getNonce());
        block.setPreviousHash(firstBlock.getPreviousHash());
        block.setTimestamp(firstBlock.getTimestamp());
        block.setPointDeals(firstBlock.getPointDeals());
        return block;
    }

    public static FourthBlock convertFourth(FirstBlock firstBlock){

        FourthBlock block = new FourthBlock();

        block.setData(firstBlock.getData());
        block.setHash(firstBlock.getHash());
        block.setIndex(firstBlock.getIndex());
        block.setNonce(firstBlock.getNonce());
        block.setPreviousHash(firstBlock.getPreviousHash());
        block.setTimestamp(firstBlock.getTimestamp());
        block.setPointDeals(firstBlock.getPointDeals());
        return block;

    }
}
public class EncryptUtil {

    /**
     * 對字符串加密,加密算法使用MD5,SHA-1,SHA-256,默認使用SHA-256
     *
     * @param strSrc
     *            要加密的字符串
     * @param encName
     *            加密類型
     * @return
     */
    public static String Encrypt(String strSrc) {

        MessageDigest md = null;
        String strDes    = null;
        String encName   = "SHA-256";
        byte[] bt        = strSrc.getBytes();

        try {
            md = MessageDigest.getInstance(encName);
            md.update(bt);
            strDes = bytes2Hex(md.digest()); //to HexString
        } catch (NoSuchAlgorithmException e) {
            return null;
        }

        return strDes;
    }

    public static String bytes2Hex(byte[] bts) {

        String des = "";
        String tmp = null;

        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }
}
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    private String reidsKeyTitle = "pc_enterprise";

    public String getString(String key) {
        return stringRedisTemplate.opsForValue().get(changereidsKeyTitle(key));
    }

    /**
     * 向redis存入key和value
     * 若是key已經存在 則覆蓋
     * @param key
     * @param value
     */
    public void set(String key, String value){
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.set(changereidsKeyTitle(key), value);
    }
   /**
     * 向redis指定的db中存入key和value以及設置生存時間
     * 若是key已經存在 則覆蓋
     * @param key
     * @param value
     * @param time    有效時間(默認時間單位爲秒)
     * @param
     */
    public void set(String key, String value, Long time){
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        // 默認時間單位爲秒
        opsForValue.set(changereidsKeyTitle(key), value, time, TimeUnit.SECONDS);
    }

    /**
     * 經過key獲取指定的value
     * @param key
     * @param
     * @return 沒有返回null
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(changereidsKeyTitle(key));
    }
}

4.7 啓動類

@SpringBootApplication
@MapperScan(basePackages={"com.dtb.trade"})
@EnableScheduling
public class TradeApplication {

    public static void main(String[] args) {

        SpringApplication.run(TradeApplication.class, args);
    }
}

4.8 定時任務層,功能展現層

@Component
public class TradeTask {


    @Autowired
    RedisService redisService;

    @Autowired
    TradeService tradeService;

    @Autowired
    MongoTradeService mongoTradeService;

    @Autowired
    SecondBlockService secondService;

    @Autowired
    ThirdBlockService thirdService;

    @Autowired
    FourthBlockService fourthService;


    //單節點mysql 區塊記帳
    @Scheduled(cron = "0 0 16 * * ?")
    private void task(){
        List<PointDeal> list = tradeService.gainAllTrade();

        if (list.size()>0){
            //獲取交易塊
            Block block = null;
            String index = redisService.get("blockIndex");
            if (StringUtils.isEmpty(index)){
                //直接從數據庫查詢
                boolean isHave = tradeService.isBlock();
                if (!isHave){
                    //生成創世區塊
                    tradeService.hyperledgerTwo(firstBlockforMysql(),list);
                }else {
                    block = tradeService.getNewBlock();
                    tradeService.hyperledger(block,list);
                }

            }else {
                //查詢區塊信息
                block = tradeService.selectBlock(Integer.valueOf(index));
                if (block != null){
                    tradeService.hyperledger(block,list);
                }else {
                    System.out.println("區塊出現異常");
                }
            }
        }
    }

    //單節點mongodb區塊記帳
    @Scheduled(cron = "0 0 18 * * ?")
    public void singleTask(){
        List<PointDeal> list = tradeService.gainAllTrade();

        if (list.size()>0){
            //獲取交易塊
            FirstBlock block = new FirstBlock();
            String index = redisService.get("blockIndex");
            if (StringUtils.isEmpty(index) && index == null){
                //直接從數據庫查詢
                boolean isHave = mongoTradeService.isHaveBlock();
                if (!isHave){
                    //生成創世區塊
                    mongoTradeService.tally(firstBlockforMongodb(),list);
                }else{
                    block = mongoTradeService.getNewest();
                    mongoTradeService.hyperledger(block,list);
                }

            }else {
                //查詢區塊信息
                block = mongoTradeService.getBlockByIndex(Integer.valueOf(index));
                if (block != null){
                    mongoTradeService.hyperledger(block,list);
                }else {
                    System.out.println("區塊出現異常");
                }
            }
        }
    }

    //多節點mongodb區塊記帳
    @Scheduled(cron = "0 0 17 * * ?")
    public void mostTask(){
        boolean isHave = mongoTradeService.isHaveBlock();

        if (isHave){

            boolean first  = prove(1);
            boolean second = prove(2);
            boolean third  = prove(3);
            boolean fourth = prove(4);

            int sumtrue = 0;


            if (first){
                sumtrue += 1;
            }

            if (second){
                sumtrue += 1;
            }

            if (third){
                sumtrue += 1;
            }

            if (fourth){
                sumtrue += 1;
            }

            if (sumtrue <3 ){
                try {
                    throw new BlockException("msg","節點故障太多");
                } catch (BlockException e) {
                    e.printStackTrace();
                }
            }
            //查詢N節點最新區塊
            FirstBlock firstBlock   = mongoTradeService.getNewest();
            SecondBlock secondBlock = secondService.getNewest();
            ThirdBlock thirdBlock   = thirdService.getNewest();
            FourthBlock fourthBlock = fourthService.getNewest();

            String firstHash        = firstBlock.getHash();
            String secondHash       = secondBlock.getHash();
            String thirdHash        = thirdBlock.getHash();
            String fourthHash       = fourthBlock.getHash();

            if (!((firstHash.equals(secondHash))|(secondHash.equals(thirdHash))|(thirdHash.equals(fourthHash)))){
                try {
                    throw new BlockException("msg","多節點最新區塊信息不一樣,有人篡改信息或者程序出現問題");
                } catch (BlockException e) {
                    e.printStackTrace();
                }
            }
        }


        List<PointDeal> list = tradeService.gainAllTrade();

        if (list.size()>0){

            FirstBlock block = new FirstBlock();
            String index = redisService.get("blockIndex");
            if (StringUtils.isEmpty(index) && index == null){
                //直接從數據庫查詢
                if (!isHave){
                    //生成創世區塊
                    mongoTradeService.tally(firstBlockforMongodb(),list);
                }else{
                    block = mongoTradeService.getNewest();
                    mongoTradeService.hyperledger(block,list);
                }

            }else {
                //查詢區塊信息
                block = mongoTradeService.getBlockByIndex(Integer.valueOf(index));
                if (block != null){
                    mongoTradeService.hyperledger(block,list);
                }else {
                    System.out.println("區塊出現異常");
                }
            }

            //同步更新到其餘三個節點
            SecondBlock secondBlock = secondService.getNewest();
            if (secondBlock == null){
                List<FirstBlock> firstBlocks = mongoTradeService.getCurrentBlocks(0);
                for (FirstBlock firstBlock : firstBlocks){
                    secondService.addBlock(ConvertUtil.convertSecond(firstBlock));
                    thirdService.addBlock(ConvertUtil.convertThird(firstBlock));
                    fourthService.addBlock(ConvertUtil.convertFourth(firstBlock));
                }
            }else {
                int secondNum           = secondBlock.getPointDeals().size();
                int secondIndex         = secondBlock.getIndex();
                if (BlockConstant.blockMax == secondNum){
                    //從下一區塊開始同步
                    List<FirstBlock> firstBlocks = mongoTradeService.getCurrentBlocks(secondIndex+1);
                    for (FirstBlock firstBlock : firstBlocks){
                        secondService.addBlock(ConvertUtil.convertSecond(firstBlock));
                        thirdService.addBlock(ConvertUtil.convertThird(firstBlock));
                        fourthService.addBlock(ConvertUtil.convertFourth(firstBlock));
                    }
                }else {
                    //不然從當前更新區塊
                    List<FirstBlock> firstBlocks = mongoTradeService.getCurrentBlocks(secondIndex);
                    for (FirstBlock firstBlock : firstBlocks){
                        secondService.addBlock(ConvertUtil.convertSecond(firstBlock));
                        thirdService.addBlock(ConvertUtil.convertThird(firstBlock));
                        fourthService.addBlock(ConvertUtil.convertFourth(firstBlock));
                    }
                }
            }
        }

    }



    public static Block firstBlockforMysql(){

        Block block = new Block();

        String prev          = "0000000000000000000000000000000000000000000000000000000000000000";
        int index            = 1;
        int nonce            = 1;
        long time            = System.currentTimeMillis();
        String hash          = EncryptUtil.Encrypt(prev+index+nonce+time);
        List<PointDeal> list = new ArrayList<>();

        block.setPreviousHash(prev);
        block.setIndex(index);
        block.setNonce(nonce);
        block.setHash(hash);
        block.setTimestamp(time);
        block.setPointDeals(list);
        block.setPointDeals(null);

        return block;
    }

    public static FirstBlock firstBlockforMongodb(){

        FirstBlock block = new FirstBlock();

        String prev = "0000000000000000000000000000000000000000000000000000000000000000";
        int index   = 1;
        int nonce   = 1;
        long time   = System.currentTimeMillis();
        String hash = EncryptUtil.Encrypt(prev+index+nonce+time);
        List<PointDeal> list = new ArrayList<>();


        block.setPreviousHash(prev);
        block.setIndex(index);
        block.setNonce(nonce);
        block.setHash(hash);
        block.setTimestamp(time);
        block.setPointDeals(null);
        block.setPointDeals(list);

        return block;
    }

    public boolean prove(int node){

        boolean isProve = false;


        switch (node){
            case 1:
                isProve = mongoTradeService.prove();
                break;
            case 2:
                isProve = secondService.prove();
                break;
            case 3:
                isProve = thirdService.prove();
                break;
            case 4:
                isProve = fourthService.prove();
                break;
            default:
                return false;

        }

        return isProve;
    }
}

五、成功截圖

    四個節點成功數據圖:spring

5.1 node1

5.2 node2

5.3 node3

5.4 node4

    ok!sql

相關文章
相關標籤/搜索