《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算法
<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>
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
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
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()); } }
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); }
@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; }
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); } }
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)); } }
@SpringBootApplication @MapperScan(basePackages={"com.dtb.trade"}) @EnableScheduling public class TradeApplication { public static void main(String[] args) { SpringApplication.run(TradeApplication.class, args); } }
@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
ok!sql