diff --git a/pom.xml b/pom.xml index bb0ae3f85b701862325f0f97c65f4c318317ce11..01a581f8ff53bb954ae1df7385f5b700ca88c864 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,12 @@ + + org.projectlombok + lombok + 1.16.16 + + org.springframework.boot spring-boot-starter @@ -134,7 +140,10 @@ org.springframework.boot spring-boot-maven-plugin - + + true + + diff --git a/src/main/java/com/mindata/blockchain/ApplicationContextProvider.java b/src/main/java/com/mindata/blockchain/ApplicationContextProvider.java index a5d0ed6d313e4660d63be67729cae0f23fe04208..85bd70928cdf528c24a60e9875a4fca671eae848 100644 --- a/src/main/java/com/mindata/blockchain/ApplicationContextProvider.java +++ b/src/main/java/com/mindata/blockchain/ApplicationContextProvider.java @@ -7,6 +7,8 @@ import org.springframework.context.ApplicationEvent; import org.springframework.stereotype.Component; /** + * 获取spring 容器组件,操作spring容器及其中的Bean + * * @author wuweifeng on 2018/3/13. */ @Component diff --git a/src/main/java/com/mindata/blockchain/MdBlockchainApplication.java b/src/main/java/com/mindata/blockchain/MdBlockchainApplication.java index 3051163639a59feec04ab5dfd3d1cfb838c9bbf3..54d764463bb6b8195c6e558228a965ab280d30ab 100644 --- a/src/main/java/com/mindata/blockchain/MdBlockchainApplication.java +++ b/src/main/java/com/mindata/blockchain/MdBlockchainApplication.java @@ -2,12 +2,14 @@ package com.mindata.blockchain; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling @EnableAsync +@ServletComponentScan public class MdBlockchainApplication { public static void main(String[] args) { diff --git a/src/main/java/com/mindata/blockchain/block/Block.java b/src/main/java/com/mindata/blockchain/block/Block.java index e1c1a8891757d31ca43648492c0af2857deb56b4..d10117b95ad8b99bc2ca1e49d789772beb927db7 100644 --- a/src/main/java/com/mindata/blockchain/block/Block.java +++ b/src/main/java/com/mindata/blockchain/block/Block.java @@ -4,6 +4,7 @@ import cn.hutool.crypto.digest.DigestUtil; /** * 区块 + * * @author wuweifeng wrote on 2018/2/27. */ public class Block { @@ -22,13 +23,11 @@ public class Block { /** * 根据该区块所有属性计算sha256 - * @return - * sha256hex + * + * @return sha256hex */ private String calculateHash() { - return DigestUtil.sha256Hex( - blockHeader.toString() + blockBody.toString() - ); + return DigestUtil.sha256Hex(blockHeader.toString() + blockBody.toString()); } public BlockHeader getBlockHeader() { diff --git a/src/main/java/com/mindata/blockchain/block/db/RocksDbStoreImpl.java b/src/main/java/com/mindata/blockchain/block/db/RocksDbStoreImpl.java index 28fb3fc8c3bf54f9c387e5f4259ed654a8c9e974..dfc73e7cb2e2af7ad403ef63b5a973e6f23f5e0c 100644 --- a/src/main/java/com/mindata/blockchain/block/db/RocksDbStoreImpl.java +++ b/src/main/java/com/mindata/blockchain/block/db/RocksDbStoreImpl.java @@ -3,7 +3,6 @@ package com.mindata.blockchain.block.db; import com.mindata.blockchain.socket.common.Const; import org.rocksdb.RocksDB; import org.rocksdb.RocksDBException; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -14,7 +13,6 @@ import java.io.UnsupportedEncodingException; * @author wuweifeng wrote on 2018/3/13. */ @Component -@ConditionalOnProperty("db.rocksDB") public class RocksDbStoreImpl implements DbStore { @Resource private RocksDB rocksDB; @@ -34,7 +32,7 @@ public class RocksDbStoreImpl implements DbStore { try { byte[] bytes = rocksDB.get(key.getBytes(Const.CHARSET)); if (bytes != null) { - return new String(bytes); + return new String(bytes, Const.CHARSET); } return null; } catch (Exception e) { diff --git a/src/main/java/com/mindata/blockchain/common/Sha256.java b/src/main/java/com/mindata/blockchain/common/Sha256.java index 319851eab497dfa2aeaf5556c2bf19c2818e6253..bd2916d306462aa3542b988d8f575a5b489ac38b 100644 --- a/src/main/java/com/mindata/blockchain/common/Sha256.java +++ b/src/main/java/com/mindata/blockchain/common/Sha256.java @@ -10,4 +10,8 @@ public class Sha256 { return DigestUtil.sha256Hex(input); } + public static void main(String[] args) { + System.out.println(Sha256.sha256("jasper")); + } + } diff --git a/src/main/java/com/mindata/blockchain/common/TrustSDK.java b/src/main/java/com/mindata/blockchain/common/TrustSDK.java index 97d4aac4153f78c3a2ced5b60bf60d332b1694c6..612f645a7dac1a0c5237b76da0b39826b3610c47 100755 --- a/src/main/java/com/mindata/blockchain/common/TrustSDK.java +++ b/src/main/java/com/mindata/blockchain/common/TrustSDK.java @@ -4,7 +4,6 @@ * Package Name:com.tencent.trustsql.sdk * Date:Jul 26, 201710:30:31 AM * Copyright (c) 2017, Tencent All Rights Reserved. - * */ package com.mindata.blockchain.common; @@ -21,214 +20,215 @@ import java.io.UnsupportedEncodingException; /** * ClassName:TrustSDK
* Date: Jul 26, 2017 10:30:31 AM
- * + * * @author Rony * @since JDK 1.7 */ public class TrustSDK { - /** - * generatePairKey:产生一对公私钥, 并返回.
- * - * @author Rony - * @return 返回公私钥对 - * @throws TrustSDKException - * TrustSDKException - * @since JDK 1.7 - */ - public static PairKey generatePairKey() throws TrustSDKException { - return generatePairKey(false); - } - - /** - * generatePairKey:生成私钥公钥对.
- * - * @author ronyyang - * @param encodePubKey 是否压缩 - * @return PairKey - * @throws TrustSDKException - * TrustSDKException - * @since JDK 1.7 - */ - public static PairKey generatePairKey(boolean encodePubKey) throws TrustSDKException { - try { - PairKey pair = new PairKey(); - String privateKey = ECDSAAlgorithm.generatePrivateKey(); - String pubKey = ECDSAAlgorithm.generatePublicKey(privateKey.trim(), encodePubKey); - pair.setPrivateKey(privateKey); - pair.setPublicKey(pubKey); - return pair; - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * checkPairKey:验证一对公私钥是否匹配.
- * - * @author ronyyang - * @param prvKey 输入 存放私钥 长度必须为PRVKEY_DIGEST_LENGTH - * @param pubKey 输入 存放公钥 长度必须为PUBKEY_DIGEST_LENGTH - * @return true 公私钥匹配 false 公私钥不匹配 - * @throws TrustSDKException TrustSDKException - * @since JDK 1.7 - */ - public static boolean checkPairKey(String prvKey, String pubKey) throws TrustSDKException { - if (StringUtils.isEmpty(prvKey) || StringUtils.isEmpty(pubKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { - String correctPubKey = ECDSAAlgorithm.generatePublicKey(prvKey.trim(), true); + /** + * generatePairKey:产生一对公私钥, 并返回.
+ * + * @return 返回公私钥对 + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static PairKey generatePairKey() throws TrustSDKException { + return generatePairKey(false); + } + + /** + * generatePairKey:生成私钥公钥对.
+ * + * @param encodePubKey 是否压缩 + * @return PairKey + * @throws TrustSDKException TrustSDKException + * @author ronyyang + * @since JDK 1.7 + */ + public static PairKey generatePairKey(boolean encodePubKey) throws TrustSDKException { + try { + PairKey pair = new PairKey(); + String privateKey = ECDSAAlgorithm.generatePrivateKey(); + String pubKey = ECDSAAlgorithm.generatePublicKey(privateKey.trim(), encodePubKey); + pair.setPrivateKey(privateKey); + pair.setPublicKey(pubKey); + return pair; + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * checkPairKey:验证一对公私钥是否匹配.
+ * + * @param prvKey 输入 存放私钥 长度必须为PRVKEY_DIGEST_LENGTH + * @param pubKey 输入 存放公钥 长度必须为PUBKEY_DIGEST_LENGTH + * @return true 公私钥匹配 false 公私钥不匹配 + * @throws TrustSDKException TrustSDKException + * @author ronyyang + * @since JDK 1.7 + */ + public static boolean checkPairKey(String prvKey, String pubKey) throws TrustSDKException { + if (StringUtils.isEmpty(prvKey) || StringUtils.isEmpty(pubKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { + String correctPubKey = ECDSAAlgorithm.generatePublicKey(prvKey.trim(), true); return pubKey.trim().equals(correctPubKey); - } catch(Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * generatePubkeyByPrvkey: 通过私钥计算相应公钥.
- * - * @author Rony - * @param privateKey - * 私钥字符串 - * @param encode - * 是否压缩公钥 - * @return 返回公钥字符串 - * @throws TrustSDKException - * TrustSDKException - * @since JDK 1.7 - */ - public static String generatePubkeyByPrvkey(String privateKey, boolean encode) throws TrustSDKException { - if (StringUtils.isEmpty(privateKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * generatePubkeyByPrvkey: 通过私钥计算相应公钥.
+ * + * @param privateKey 私钥字符串 + * @param encode 是否压缩公钥 + * @return 返回公钥字符串 + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static String generatePubkeyByPrvkey(String privateKey, boolean encode) throws TrustSDKException { + if (StringUtils.isEmpty(privateKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { return ECDSAAlgorithm.generatePublicKey(privateKey, encode); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * generatePubkeyByPrvkey: 通过私钥计算相应公钥.
- * - * @author Rony - * @param privateKey - * 私钥字符串 - * @return 返回公钥字符串 - * @throws TrustSDKException TrustSDKException - * @since JDK 1.7 - */ - public static String generatePubkeyByPrvkey(String privateKey) throws TrustSDKException { - return generatePubkeyByPrvkey(privateKey, false); - } - - public static String decodePubkey(String encodePubKey) throws TrustSDKException { - if (StringUtils.isEmpty(encodePubKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * generatePubkeyByPrvkey: 通过私钥计算相应公钥.
+ * + * @param privateKey 私钥字符串 + * @return 返回公钥字符串 + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static String generatePubkeyByPrvkey(String privateKey) throws TrustSDKException { + return generatePubkeyByPrvkey(privateKey, false); + } + + public static String decodePubkey(String encodePubKey) throws TrustSDKException { + if (StringUtils.isEmpty(encodePubKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { return ECDSAAlgorithm.decodePublicKey(encodePubKey); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * generateAddrByPubkey:通过公钥获取对应地址.
- * - * @author Rony - * @param pubKey - * 公钥字符串 - * @return address - * @throws TrustSDKException - * TrustSDKException - * @since JDK 1.7 - */ - public static String generateAddrByPubkey(String pubKey) throws TrustSDKException { - if (StringUtils.isEmpty(pubKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * generateAddrByPubkey:通过公钥获取对应地址.
+ * + * @param pubKey 公钥字符串 + * @return address + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static String generateAddrByPubkey(String pubKey) throws TrustSDKException { + if (StringUtils.isEmpty(pubKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { return ECDSAAlgorithm.getAddress(Base64.decodeBase64(pubKey)); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * generateAddrByPrvkey:通过私钥计算相应地址.
- * - * @author Rony - * @param privateKey - * 私钥字符串 - * @return Address - * @throws TrustSDKException TrustSDKException - * @since JDK 1.7 - */ - public static String generateAddrByPrvkey(String privateKey) throws TrustSDKException { - if (StringUtils.isEmpty(privateKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { - String pubKey = ECDSAAlgorithm.generatePublicKey(privateKey); + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * generateAddrByPrvkey:通过私钥计算相应地址.
+ * + * @param privateKey 私钥字符串 + * @return Address + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static String generateAddrByPrvkey(String privateKey) throws TrustSDKException { + if (StringUtils.isEmpty(privateKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { + String pubKey = ECDSAAlgorithm.generatePublicKey(privateKey); return generateAddrByPubkey(pubKey); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } - - /** - * signString:为字符串进行签名, 并返回签名.
- * - * @author Rony - * @param privateKey - * 私钥字符串 - * @param data - * 需要签名的字符数组 - * @return 返回签名字符串 - * @throws TrustSDKException TrustSDKException - * @since JDK 1.7 - */ - public static String signString(String privateKey, byte[] data) throws TrustSDKException { - if (StringUtils.isEmpty(privateKey)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + /** + * signString:为字符串进行签名, 并返回签名.
+ * + * @param privateKey 私钥字符串 + * @param data 需要签名的字符数组 + * @return 返回签名字符串 + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static String signString(String privateKey, byte[] data) throws TrustSDKException { + if (StringUtils.isEmpty(privateKey)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { return ECDSAAlgorithm.sign(privateKey, data); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.SIGN_ERROR.getRetCode(), ErrorNum.SIGN_ERROR.getRetMsg(), e); - } - } - - public static String signString(String privateKey, String data) throws TrustSDKException, UnsupportedEncodingException { - return signString(privateKey, data.getBytes("UTF-8")); - } - - /** - * verifyString:验证一个签名是否有效.
- * - * @author Rony - * @param pubKey - * 公钥字符串 - * @param srcString - * 源字符串 - * @param sign - * 签名字符串 - * @return 返回验证是否通过 true:验证成功 false:验证失败 - * @throws TrustSDKException TrustSDKException - * @since JDK 1.7 - */ - public static boolean verifyString(String pubKey, String srcString, String sign) throws TrustSDKException { - if (StringUtils.isEmpty(pubKey) || StringUtils.isEmpty(srcString) || StringUtils.isEmpty(sign)) { - throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); - } - try { - return ECDSAAlgorithm.verify(srcString, sign, pubKey); - } catch (Exception e) { - throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); - } - } + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.SIGN_ERROR.getRetCode(), ErrorNum.SIGN_ERROR.getRetMsg(), e); + } + } + + public static String signString(String privateKey, String data) throws TrustSDKException, UnsupportedEncodingException { + return signString(privateKey, data.getBytes("UTF-8")); + } + + /** + * verifyString:验证一个签名是否有效.
+ * + * @param pubKey 公钥字符串 + * @param srcString 源字符串 + * @param sign 签名字符串 + * @return 返回验证是否通过 true:验证成功 false:验证失败 + * @throws TrustSDKException TrustSDKException + * @author Rony + * @since JDK 1.7 + */ + public static boolean verifyString(String pubKey, String srcString, String sign) throws TrustSDKException { + if (StringUtils.isEmpty(pubKey) || StringUtils.isEmpty(srcString) || StringUtils.isEmpty(sign)) { + throw new TrustSDKException(ErrorNum.INVALID_PARAM_ERROR.getRetCode(), ErrorNum.INVALID_PARAM_ERROR.getRetMsg()); + } + try { + return ECDSAAlgorithm.verify(srcString, sign, pubKey); + } catch (Exception e) { + throw new TrustSDKException(ErrorNum.ECDSA_ENCRYPT_ERROR.getRetCode(), ErrorNum.ECDSA_ENCRYPT_ERROR.getRetMsg(), e); + } + } + + public static void main(String[] args) throws Exception { + PairKey pairKey = TrustSDK.generatePairKey(true); + String pubKey = pairKey.getPublicKey(); + String priKey = pairKey.getPrivateKey(); + System.out.println("pubKey:" + pubKey); + System.out.println("priKey:" + priKey); + + String addrPub = TrustSDK.generateAddrByPubkey(pubKey); + String addrPrv = TrustSDK.generateAddrByPrvkey(priKey); + System.out.println(addrPub); + System.out.println(addrPrv); + + System.out.println("checkPairKey:" + TrustSDK.checkPairKey(priKey, pubKey)); + } } diff --git a/src/main/java/com/mindata/blockchain/common/algorithm/ECDSAAlgorithm.java b/src/main/java/com/mindata/blockchain/common/algorithm/ECDSAAlgorithm.java index 611b7dbba77dbf31662b56a7679d3dc63764778d..32777512f20132e25fabf733f19a0d9477ae7935 100755 --- a/src/main/java/com/mindata/blockchain/common/algorithm/ECDSAAlgorithm.java +++ b/src/main/java/com/mindata/blockchain/common/algorithm/ECDSAAlgorithm.java @@ -37,6 +37,8 @@ import java.security.MessageDigest; import java.security.SecureRandom; /** + * 椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟 + * * ClassName:ECDSAAlgoUtil
* Date: Jul 26, 2017 5:17:04 PM
* @@ -297,6 +299,12 @@ public class ECDSAAlgorithm { } } + /** + * 椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟 + * + * @param bytes + * @return + */ public static ECDSASignature decodeFromDER(byte[] bytes) { ASN1InputStream decoder = null; try { diff --git a/src/main/java/com/mindata/blockchain/common/algorithm/RSACoder.java b/src/main/java/com/mindata/blockchain/common/algorithm/RSACoder.java new file mode 100644 index 0000000000000000000000000000000000000000..b0816d253ad7925e2ea5ca46e3a80e5ffaac038e --- /dev/null +++ b/src/main/java/com/mindata/blockchain/common/algorithm/RSACoder.java @@ -0,0 +1,254 @@ +package com.mindata.blockchain.common.algorithm; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +/** + * User: jasperxgwang + * Date: 2018-7-17 9:08 + */ +public class RSACoder { + public static final String KEY_ALGORITHM = "RSA"; + public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; + + private static final String PUBLIC_KEY = "RSAPublicKey"; + private static final String PRIVATE_KEY = "RSAPrivateKey"; + + public static byte[] decryptBASE64(String key) { + return Base64.decodeBase64(key); + } + + public static String encryptBASE64(byte[] bytes) { + return Base64.encodeBase64String(bytes); + } + + /** + * 用私钥对信息生成数字签名 + * + * @param data 加密数据 + * @param privateKey 私钥 + * @return + * @throws Exception + */ + public static String sign(byte[] data, String privateKey) throws Exception { + // 解密由base64编码的私钥 + byte[] keyBytes = decryptBASE64(privateKey); + // 构造PKCS8EncodedKeySpec对象 + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); + // KEY_ALGORITHM 指定的加密算法 + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + // 取私钥匙对象 + PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); + // 用私钥对信息生成数字签名 + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + signature.initSign(priKey); + signature.update(data); + return encryptBASE64(signature.sign()); + } + + /** + * 校验数字签名 + * + * @param data 加密数据 + * @param publicKey 公钥 + * @param sign 数字签名 + * @return 校验成功返回true 失败返回false + * @throws Exception + */ + public static boolean verify(byte[] data, String publicKey, String sign) + throws Exception { + // 解密由base64编码的公钥 + byte[] keyBytes = decryptBASE64(publicKey); + // 构造X509EncodedKeySpec对象 + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + // KEY_ALGORITHM 指定的加密算法 + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + // 取公钥匙对象 + PublicKey pubKey = keyFactory.generatePublic(keySpec); + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + signature.initVerify(pubKey); + signature.update(data); + // 验证签名是否正常 + return signature.verify(decryptBASE64(sign)); + } + + public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception { + // 对密钥解密 + byte[] keyBytes = decryptBASE64(key); + // 取得私钥 + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); + // 对数据解密 + Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + return cipher.doFinal(data); + } + + /** + * 解密
+ * 用私钥解密 + * + * @param data + * @param key + * @return + * @throws Exception + */ + public static byte[] decryptByPrivateKey(String data, String key) + throws Exception { + return decryptByPrivateKey(decryptBASE64(data), key); + } + + /** + * 解密
+ * 用公钥解密 + * + * @param data + * @param key + * @return + * @throws Exception + */ + public static byte[] decryptByPublicKey(byte[] data, String key) + throws Exception { + // 对密钥解密 + byte[] keyBytes = decryptBASE64(key); + // 取得公钥 + X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + Key publicKey = keyFactory.generatePublic(x509KeySpec); + // 对数据解密 + Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + return cipher.doFinal(data); + } + + /** + * 加密
+ * 用公钥加密 + * + * @param data + * @param key + * @return + * @throws Exception + */ + public static byte[] encryptByPublicKey(String data, String key) + throws Exception { + // 对公钥解密 + byte[] keyBytes = decryptBASE64(key); + // 取得公钥 + X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + Key publicKey = keyFactory.generatePublic(x509KeySpec); + // 对数据加密 + Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return cipher.doFinal(data.getBytes()); + } + + /** + * 加密
+ * 用私钥加密 + * + * @param data + * @param key + * @return + * @throws Exception + */ + public static byte[] encryptByPrivateKey(byte[] data, String key) + throws Exception { + // 对密钥解密 + byte[] keyBytes = decryptBASE64(key); + // 取得私钥 + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); + // 对数据加密 + Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); + cipher.init(Cipher.ENCRYPT_MODE, privateKey); + return cipher.doFinal(data); + } + + /** + * 取得私钥 + * + * @param keyMap + * @return + * @throws Exception + */ + public static String getPrivateKey(Map keyMap) + throws Exception { + Key key = (Key) keyMap.get(PRIVATE_KEY); + return encryptBASE64(key.getEncoded()); + } + + /** + * 取得公钥 + * + * @param keyMap + * @return + * @throws Exception + */ + public static String getPublicKey(Map keyMap) + throws Exception { + Key key = keyMap.get(PUBLIC_KEY); + return encryptBASE64(key.getEncoded()); + } + + /** + * 初始化密钥 + * + * @return + * @throws Exception + */ + public static Map initKey() throws Exception { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); + keyPairGen.initialize(1024); + KeyPair keyPair = keyPairGen.generateKeyPair(); + Map keyMap = new HashMap(2); + keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公钥 + keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私钥 + return keyMap; + } + + public static void main(String[] args) throws Exception { + Map keyMap = initKey(); + String publicKey = getPublicKey(keyMap); + String privateKey = getPrivateKey(keyMap); + System.out.println(keyMap); + System.out.println("-----------------------------------"); + System.out.println(publicKey); + System.out.println("-----------------------------------"); + System.out.println(privateKey); + System.out.println("-----------------------------------"); + byte[] encryptByPrivateKey = encryptByPrivateKey("123456".getBytes(), privateKey); + byte[] encryptByPublicKey = encryptByPublicKey("123456", publicKey); + System.out.println(new String(encryptByPrivateKey)); + System.out.println("-----------------------------------"); + System.out.println(new String(encryptByPublicKey)); + System.out.println("-----------------------------------"); + String sign = sign(encryptByPrivateKey, privateKey); + System.out.println(sign); + System.out.println("-----------------------------------"); + boolean verify = verify(encryptByPrivateKey, publicKey, sign); + System.out.println(verify); + System.out.println("-----------------------------------"); + byte[] decryptByPublicKey = decryptByPublicKey(encryptByPrivateKey, publicKey); + byte[] decryptByPrivateKey = decryptByPrivateKey(encryptByPublicKey, privateKey); + System.out.println(new String(decryptByPublicKey)); + System.out.println("-----------------------------------"); + System.out.println(new String(decryptByPrivateKey)); + + } +} diff --git a/src/main/java/com/mindata/blockchain/common/timer/TimerManager.java b/src/main/java/com/mindata/blockchain/common/timer/TimerManager.java index 914ad6b12070e69a13828a32c625d799a8d66d3c..69edb4e95ea59262da49e46101b6343c85656a12 100644 --- a/src/main/java/com/mindata/blockchain/common/timer/TimerManager.java +++ b/src/main/java/com/mindata/blockchain/common/timer/TimerManager.java @@ -8,39 +8,24 @@ import java.util.function.Supplier; /** * 异步延时执行 * 需要调用延迟执行的时候可使用,避免在代码里面直接调用Thread.sleep()方法 - * + * * @author andylo25 wrote on 2018/6/11. */ public class TimerManager { - private volatile static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); - - public static void schedule(Supplier action, long delay){ - executorService.schedule(new Runnable() { - @Override - public void run() { - action.get(); - } - }, delay, TimeUnit.MILLISECONDS); - } - - public static void scheduleAtFixedRate(Supplier action,long initialDelay, long period ){ - executorService.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - action.get(); - } - }, initialDelay,period, TimeUnit.MILLISECONDS); - } - - public static void scheduleWithFixedDelay(Supplier action,long initialDelay, long period ){ - executorService.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - action.get(); - } - }, initialDelay,period, TimeUnit.MILLISECONDS); - } - - + private volatile static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); + + public static void schedule(Supplier action, long delay) { + executorService.schedule(() -> action.get(), delay, TimeUnit.MILLISECONDS); + } + + public static void scheduleAtFixedRate(Supplier action, long initialDelay, long period) { + executorService.scheduleAtFixedRate(() -> action.get(), initialDelay, period, TimeUnit.MILLISECONDS); + } + + public static void scheduleWithFixedDelay(Supplier action, long initialDelay, long period) { + executorService.scheduleWithFixedDelay(() -> action.get(), initialDelay, period, TimeUnit.MILLISECONDS); + } + + } diff --git a/src/main/java/com/mindata/blockchain/core/bean/Member.java b/src/main/java/com/mindata/blockchain/core/bean/Member.java index 81106b0291453d93eb5bbe1ee9765b0cf3c0ef33..f7d23f86ebaffbb0531a10ef94ed0d541f2ed835 100644 --- a/src/main/java/com/mindata/blockchain/core/bean/Member.java +++ b/src/main/java/com/mindata/blockchain/core/bean/Member.java @@ -1,10 +1,13 @@ package com.mindata.blockchain.core.bean; +import com.mindata.blockchain.socket.common.Const; + import java.util.Date; /** * 联盟的成员 + * * @author wuweifeng wrote on 2018/3/5. */ public class Member { @@ -21,6 +24,11 @@ public class Member { */ private String ip; + /** + * 服务端口 + */ + private int port = Const.PORT; + private Date createTime; private Date updateTime; @@ -58,4 +66,11 @@ public class Member { this.ip = ip; } + public void setPort(int port) { + this.port = port; + } + + public int getPort() { + return port; + } } diff --git a/src/main/java/com/mindata/blockchain/core/controller/BlockController.java b/src/main/java/com/mindata/blockchain/core/controller/BlockController.java index eed6922ef0fa11d0a6e82f0e8304acca44163ab2..d2b36044a851ac3630bd4d39a83fdd0d35de8184 100644 --- a/src/main/java/com/mindata/blockchain/core/controller/BlockController.java +++ b/src/main/java/com/mindata/blockchain/core/controller/BlockController.java @@ -3,9 +3,12 @@ package com.mindata.blockchain.core.controller; import javax.annotation.Resource; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.Mapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -34,6 +37,7 @@ import com.mindata.blockchain.socket.packet.PacketBuilder; import com.mindata.blockchain.socket.packet.PacketType; import cn.hutool.core.collection.CollectionUtil; +import org.tio.utils.json.Json; /** * @author wuweifeng wrote on 2018/3/7. @@ -41,6 +45,7 @@ import cn.hutool.core.collection.CollectionUtil; @RestController @RequestMapping("/block") public class BlockController { + private static final Logger logger = LoggerFactory.getLogger(BlockController.class); @Resource private BlockService blockService; @Resource @@ -59,13 +64,12 @@ public class BlockController { /** * 添加一个block,需要先在InstructionController构建1-N个instruction指令,然后调用该接口生成Block * - * @param blockRequestBody - * 指令的集合 + * @param blockRequestBody 指令的集合 * @return 结果 */ @PostMapping public BaseData add(@RequestBody BlockRequestBody blockRequestBody) throws TrustSDKException { - String msg = blockService.check(blockRequestBody); + String msg = blockService.check(blockRequestBody); if (msg != null) { return ResultGenerator.genFailResult(msg); } @@ -74,15 +78,15 @@ public class BlockController { /** * 测试生成一个insert:Block,公钥私钥可以通过PairKeyController来生成 - * @param content - * sql内容 + * + * @param content sql内容 */ @GetMapping public BaseData test(String content) throws Exception { InstructionBody instructionBody = new InstructionBody(); instructionBody.setOperation(Operation.ADD); instructionBody.setTable("message"); - instructionBody.setJson("{\"content\":\"" + content + "\"}"); + instructionBody.setJson("{\"content\":\"" + content + "\",\"origin\":\"jg\",\"target\":\"mz\"}"); instructionBody.setPublicKey("A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54"); instructionBody.setPrivateKey("yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8="); Instruction instruction = instructionService.build(instructionBody); @@ -94,61 +98,65 @@ public class BlockController { blockRequestBody.setBlockBody(blockBody); + logger.info("add block:{}", Json.toJson(blockRequestBody)); + return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); } - + /** * 测试生成一个update:Block,公钥私钥可以通过PairKeyController来生成 - * @param id 更新的主键 - * @param content - * sql内容 + * + * @param id 更新的主键 + * @param content sql内容 */ - @GetMapping("testUpdate") - public BaseData testUpdate(String id,String content) throws Exception { - if(StringUtils.isBlank(id)) ResultGenerator.genSuccessResult("主键不可为空"); - InstructionBody instructionBody = new InstructionBody(); - instructionBody.setOperation(Operation.UPDATE); - instructionBody.setTable("message"); - instructionBody.setInstructionId(id); - instructionBody.setJson("{\"content\":\"" + content + "\"}"); - instructionBody.setPublicKey("A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54"); - instructionBody.setPrivateKey("yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8="); - Instruction instruction = instructionService.build(instructionBody); - - BlockRequestBody blockRequestBody = new BlockRequestBody(); - blockRequestBody.setPublicKey(instructionBody.getPublicKey()); - com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody(); - blockBody.setInstructions(CollectionUtil.newArrayList(instruction)); - - blockRequestBody.setBlockBody(blockBody); - - return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); + @RequestMapping(path = "testUpdate") + public BaseData testUpdate(String id, String content) throws Exception { + if (StringUtils.isBlank(id)) ResultGenerator.genSuccessResult("主键不可为空"); + InstructionBody instructionBody = new InstructionBody(); + instructionBody.setOperation(Operation.UPDATE); + instructionBody.setTable("message"); + instructionBody.setInstructionId(id); + instructionBody.setJson("{\"content\":\"" + content + "\",\"origin\":\"jg_update\",\"target\":\"mz_update\"}"); + instructionBody.setPublicKey("A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54"); + instructionBody.setPrivateKey("yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8="); + Instruction instruction = instructionService.build(instructionBody); + + BlockRequestBody blockRequestBody = new BlockRequestBody(); + blockRequestBody.setPublicKey(instructionBody.getPublicKey()); + com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody(); + blockBody.setInstructions(CollectionUtil.newArrayList(instruction)); + + blockRequestBody.setBlockBody(blockBody); + + return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); } - + /** * 测试生成一个delete:Block,公钥私钥可以通过PairKeyController来生成 + * * @param id 待删除记录的主键 - * sql内容 + * sql内容 */ - @GetMapping("testDel") + @RequestMapping("testDel") public BaseData testDel(String id) throws Exception { - if(StringUtils.isBlank(id)) ResultGenerator.genSuccessResult("主键不可为空"); - InstructionBody instructionBody = new InstructionBody(); - instructionBody.setOperation(Operation.DELETE); - instructionBody.setTable("message"); - instructionBody.setInstructionId(id); - instructionBody.setPublicKey("A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54"); - instructionBody.setPrivateKey("yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8="); - Instruction instruction = instructionService.build(instructionBody); - - BlockRequestBody blockRequestBody = new BlockRequestBody(); - blockRequestBody.setPublicKey(instructionBody.getPublicKey()); - com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody(); - blockBody.setInstructions(CollectionUtil.newArrayList(instruction)); - - blockRequestBody.setBlockBody(blockBody); - - return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); + if (StringUtils.isBlank(id)) ResultGenerator.genSuccessResult("主键不可为空"); + InstructionBody instructionBody = new InstructionBody(); + instructionBody.setOperation(Operation.DELETE); + instructionBody.setTable("message"); + instructionBody.setInstructionId(id); + instructionBody.setJson("{\"content\":\"content\",\"origin\":\"jg\",\"target\":\"mz\"}"); + instructionBody.setPublicKey("A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54"); + instructionBody.setPrivateKey("yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8="); + Instruction instruction = instructionService.build(instructionBody); + + BlockRequestBody blockRequestBody = new BlockRequestBody(); + blockRequestBody.setPublicKey(instructionBody.getPublicKey()); + com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody(); + blockBody.setInstructions(CollectionUtil.newArrayList(instruction)); + + blockRequestBody.setBlockBody(blockBody); + + return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); } /** @@ -170,48 +178,58 @@ public class BlockController { /** * 获取最后一个block的信息 */ - @GetMapping("db") - public BaseData getRockDB() { + @GetMapping("getLastBlock") + public BaseData getLastBlock() { return ResultGenerator.genSuccessResult(dbBlockManager.getLastBlock()); } + @RequestMapping(path ="getBlockByHash") + public BaseData getBlockByHash(String blockHash) { + return ResultGenerator.genSuccessResult(dbBlockManager.getBlockByHash(blockHash)); + } + + @RequestMapping(path ="getBlockByNumber") + public BaseData getBlockByNumber(long blockNumber) { + return ResultGenerator.genSuccessResult(dbBlockManager.getBlockByNumber(blockNumber)); + } + /** * 手工执行区块内sql落地到sqlite操作 - * @param pageable - * 分页 - * @return - * 已同步到哪块了的信息 + * + * @param pageable 分页 + * @return 已同步到哪块了的信息 */ - @GetMapping("sync") + @RequestMapping("sync") public BaseData sync(@PageableDefault Pageable pageable) { ApplicationContextProvider.publishEvent(new DbSyncEvent("")); return ResultGenerator.genSuccessResult(syncManager.findAll(pageable)); } - + /** * 全量检测区块是否正常 - * @return - * null - 通过 + * + * @return null - 通过 * hash - 第一个异常hash */ @GetMapping("checkb") public BaseData checkAllBlock() { - - Block block = dbBlockManager.getFirstBlock(); - - String hash = null; - while(block != null && hash == null) { - hash = blockChecker.checkBlock(block); - block = dbBlockManager.getNextBlock(block); - } - return ResultGenerator.genSuccessResult(hash); + + Block block = dbBlockManager.getFirstBlock(); + + String hash = null; + while (block != null && hash == null) { + logger.info("check block:{} done....",block.getBlockHeader().getNumber()); + hash = blockChecker.checkBlock(block); + block = dbBlockManager.getNextBlock(block); + } + return ResultGenerator.genSuccessResult(hash); } @GetMapping("/next") public BaseData nextBlock() { Block block = dbBlockManager.getFirstBlock(); BlockPacket packet = new PacketBuilder() - .setType(PacketType.NEXT_BLOCK_INFO_REQUEST) + .setType(PacketType.NEXT_BLOCK_INFO_REQUEST.getKey()) .setBody(new RpcBlockBody(block)).build(); packetSender.sendGroup(packet); return null; diff --git a/src/main/java/com/mindata/blockchain/core/controller/InstructionController.java b/src/main/java/com/mindata/blockchain/core/controller/InstructionController.java index 80182183ff0f240fa5535ecd0e05bbe6822a054b..c535181c23ce6782738cebc4b42744a97dffc5ac 100644 --- a/src/main/java/com/mindata/blockchain/core/controller/InstructionController.java +++ b/src/main/java/com/mindata/blockchain/core/controller/InstructionController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.util.List; /** * 区块body内单个指令的controller diff --git a/src/main/java/com/mindata/blockchain/core/event/AddBlockEvent.java b/src/main/java/com/mindata/blockchain/core/event/AddBlockEvent.java index 8559a56ccb04051397ad53873e39e7272849413b..8729d425e21cdeecb10a045329364b1031018804 100644 --- a/src/main/java/com/mindata/blockchain/core/event/AddBlockEvent.java +++ b/src/main/java/com/mindata/blockchain/core/event/AddBlockEvent.java @@ -1,6 +1,7 @@ package com.mindata.blockchain.core.event; import com.mindata.blockchain.block.Block; +import com.mindata.blockchain.socket.packet.BlockPacket; import org.springframework.context.ApplicationEvent; /** @@ -11,4 +12,9 @@ public class AddBlockEvent extends ApplicationEvent { public AddBlockEvent(Block block) { super(block); } + + @Override + public Block getSource() { + return (Block) source; + } } diff --git a/src/main/java/com/mindata/blockchain/core/event/ClientRequestEvent.java b/src/main/java/com/mindata/blockchain/core/event/ClientRequestEvent.java index 4f95f76deb65d09ab625244c3eb4743038a0c93d..69f2f2d3c95e2b3cc3d61691ccbd1c82c4765b08 100644 --- a/src/main/java/com/mindata/blockchain/core/event/ClientRequestEvent.java +++ b/src/main/java/com/mindata/blockchain/core/event/ClientRequestEvent.java @@ -11,4 +11,9 @@ public class ClientRequestEvent extends ApplicationEvent { public ClientRequestEvent(BlockPacket blockPacket) { super(blockPacket); } + + @Override + public BlockPacket getSource() { + return (BlockPacket) source; + } } diff --git a/src/main/java/com/mindata/blockchain/core/event/NodesConnectedEvent.java b/src/main/java/com/mindata/blockchain/core/event/NodesConnectedEvent.java index d2690136c3c68a6f50b5e5f77994d83ce8479c66..9a7489ee21b00b427b5f28161da98fed46e51cd0 100644 --- a/src/main/java/com/mindata/blockchain/core/event/NodesConnectedEvent.java +++ b/src/main/java/com/mindata/blockchain/core/event/NodesConnectedEvent.java @@ -14,7 +14,8 @@ public class NodesConnectedEvent extends ApplicationEvent { super(channelContext); } - public ChannelContext getSource() { + @Override + public ChannelContext getSource() { return (ChannelContext) source; } diff --git a/src/main/java/com/mindata/blockchain/core/filter/EncodingFilter.java b/src/main/java/com/mindata/blockchain/core/filter/EncodingFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..a7a9118db46695325cf4f795fe5eb26b5d784f88 --- /dev/null +++ b/src/main/java/com/mindata/blockchain/core/filter/EncodingFilter.java @@ -0,0 +1,54 @@ +package com.mindata.blockchain.core.filter; + +import com.mindata.blockchain.socket.common.Const; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * User: jasperxgwang + * Date: 2018-7-17 10:03 + */ +@WebFilter(urlPatterns = "/*") +@Slf4j(topic = "EncodingFilter") +public class EncodingFilter implements Filter { + private String charset; + + public EncodingFilter() { + this.charset = Const.CHARSET; + } + + @Override + public void init(FilterConfig config) throws ServletException { + String paramCharset = config.getInitParameter("charset"); + if ((paramCharset != null) && (paramCharset.length() > 0)) { + this.charset = paramCharset; + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + String uri = req.getRequestURI(); + if ((uri.endsWith("html")) || (uri.endsWith("htm")) || (uri.endsWith("xml"))) { + chain.doFilter(request, response); + return; + } + request.setCharacterEncoding(this.charset); + response.setCharacterEncoding(this.charset); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } +} diff --git a/src/main/java/com/mindata/blockchain/core/filter/PrintRequestFilter.java b/src/main/java/com/mindata/blockchain/core/filter/PrintRequestFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..37ba17405639124ee707704a6f8a00f977b280bf --- /dev/null +++ b/src/main/java/com/mindata/blockchain/core/filter/PrintRequestFilter.java @@ -0,0 +1,51 @@ +package com.mindata.blockchain.core.filter; + +import com.mindata.blockchain.core.utils.RequestThreadLocal; +import com.mindata.blockchain.core.utils.RequestUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * User: jasperxgwang + * Date: 2018-7-12 14:26 + */ +@WebFilter(urlPatterns = "/*") +@Slf4j(topic = "PrintRequestFilter") +public class PrintRequestFilter implements Filter { + + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + log.info(">>>>>>PrintRequestFilter init"); + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request2 = (HttpServletRequest) request; + String uri = request2.getRequestURI(); + if (!StringUtils.endsWith(uri, ".js") && !StringUtils.endsWith(uri, ".css") && !StringUtils.endsWith(uri, ".png")) { + String ip = request2.getHeader("X-Real-IP"); + ip = StringUtils.defaultIfEmpty(ip, "127.0.0.1"); + log.info(request2.getRequestURI() + "[ip=" + ip + "]"); + RequestThreadLocal.set(request2.getRequestURI()); + RequestUtil.printAll(request, this, true, null); + } + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } +} diff --git a/src/main/java/com/mindata/blockchain/core/manager/ClientRequestManager.java b/src/main/java/com/mindata/blockchain/core/manager/ClientRequestManager.java new file mode 100644 index 0000000000000000000000000000000000000000..4eac3dea2ccccf95f8d34a5ce779131c214cd991 --- /dev/null +++ b/src/main/java/com/mindata/blockchain/core/manager/ClientRequestManager.java @@ -0,0 +1,26 @@ +package com.mindata.blockchain.core.manager; + +import com.mindata.blockchain.core.event.ClientRequestEvent; +import com.mindata.blockchain.socket.packet.BlockPacket; +import com.mindata.blockchain.socket.packet.PacketType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +/** + * User: jasperxgwang + * Date: 2018-7-13 10:22 + */ +@Service +@Slf4j(topic = "ClientRequestManager") +public class ClientRequestManager { + + @Order(1) + @EventListener(ClientRequestEvent.class) + public synchronized void clientRequest(ClientRequestEvent event) { + BlockPacket blockPacket = event.getSource(); + PacketType packetType = PacketType.fromValue(blockPacket.getType()); + log.info("发起请求消息 type:{} packet:{}", packetType.getValue(), blockPacket); + } +} diff --git a/src/main/java/com/mindata/blockchain/core/manager/DbBlockManager.java b/src/main/java/com/mindata/blockchain/core/manager/DbBlockManager.java index 00153d675b768acb9c7aa7b378bdfaf7f33235c3..6684d449f8c41a5ba038240808130eefee2c2d62 100644 --- a/src/main/java/com/mindata/blockchain/core/manager/DbBlockManager.java +++ b/src/main/java/com/mindata/blockchain/core/manager/DbBlockManager.java @@ -5,6 +5,8 @@ import com.mindata.blockchain.block.Block; import com.mindata.blockchain.block.db.DbStore; import com.mindata.blockchain.common.Constants; import com.mindata.blockchain.common.FastJsonUtil; +import com.mindata.blockchain.core.model.SyncEntity; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -16,6 +18,8 @@ import javax.annotation.Resource; public class DbBlockManager { @Resource private DbStore dbStore; + @Autowired + private SyncManager syncManager; /** * 查找第一个区块 @@ -58,6 +62,7 @@ public class DbBlockManager { /** * 获取最后一个block的number + * * @return number */ public int getLastBlockNumber() { @@ -71,8 +76,7 @@ public class DbBlockManager { /** * 获取某一个block的下一个Block * - * @param block - * block + * @param block block * @return block */ public Block getNextBlock(Block block) { @@ -102,4 +106,12 @@ public class DbBlockManager { return FastJsonUtil.toBean(blockJson, Block.class); } + public Block getBlockByNumber(long blockNumber) { + SyncEntity syncEntity = syncManager.findOne(blockNumber); + if (syncEntity != null) { + String blockHash = syncEntity.getHash(); + return this.getBlockByHash(blockHash); + } + return null; + } } diff --git a/src/main/java/com/mindata/blockchain/core/manager/SyncManager.java b/src/main/java/com/mindata/blockchain/core/manager/SyncManager.java index 65304402d4aa09bc92fadc900975e9c4402c83d2..42ae5516b8408b56abd338baed6c2fd4228ccc3f 100644 --- a/src/main/java/com/mindata/blockchain/core/manager/SyncManager.java +++ b/src/main/java/com/mindata/blockchain/core/manager/SyncManager.java @@ -30,4 +30,8 @@ public class SyncManager { public void deleteAll() { syncRepository.deleteAll(); } + + public SyncEntity findOne(long blockNumber) { + return syncRepository.findOne(blockNumber); + } } diff --git a/src/main/java/com/mindata/blockchain/core/model/MessageEntity.java b/src/main/java/com/mindata/blockchain/core/model/MessageEntity.java index e7e4359fd88b7981899f1e2fcfef3f222e249f60..292fbcf0c3d1a5bc3f4790d5359480a29dd08347 100644 --- a/src/main/java/com/mindata/blockchain/core/model/MessageEntity.java +++ b/src/main/java/com/mindata/blockchain/core/model/MessageEntity.java @@ -1,5 +1,6 @@ package com.mindata.blockchain.core.model; +import com.mindata.blockchain.common.FastJsonUtil; import com.mindata.blockchain.core.model.base.BaseEntity; import javax.persistence.Entity; @@ -69,4 +70,14 @@ public class MessageEntity extends BaseEntity { public void setOrigin(String origin) { this.origin = origin; } + + public static void main(String[] args) { + +// {"content":"this is block","origin":"jg","target":"mz"} + MessageEntity en = new MessageEntity(); + en.setTarget("mz"); + en.setOrigin("jg"); + en.setContent("this is block"); + System.out.println(FastJsonUtil.toJSONString(en)); + } } diff --git a/src/main/java/com/mindata/blockchain/core/repository/MessageRepository.java b/src/main/java/com/mindata/blockchain/core/repository/MessageRepository.java index 097c7a14d6bf0cf4c789c28d1884ae2b76ba63e0..aae283a16b80cdd8d86e28f5663eea9df400aca4 100644 --- a/src/main/java/com/mindata/blockchain/core/repository/MessageRepository.java +++ b/src/main/java/com/mindata/blockchain/core/repository/MessageRepository.java @@ -2,6 +2,8 @@ package com.mindata.blockchain.core.repository; import com.mindata.blockchain.core.model.MessageEntity; +import javax.transaction.Transactional; + /** * @author wuweifeng wrote on 2017/10/25. */ @@ -10,6 +12,7 @@ public interface MessageRepository extends BaseRepository { * 删除一条记录 * @param messageId messageId */ + @Transactional void deleteByMessageId(String messageId); /** diff --git a/src/main/java/com/mindata/blockchain/core/requestbody/BlockRequestBody.java b/src/main/java/com/mindata/blockchain/core/requestbody/BlockRequestBody.java index 20467291aa6dfbdf0ba0783eb77a45a362cf4754..49a2044cc7f915a17cf3f6d4a0816f0970e056e5 100644 --- a/src/main/java/com/mindata/blockchain/core/requestbody/BlockRequestBody.java +++ b/src/main/java/com/mindata/blockchain/core/requestbody/BlockRequestBody.java @@ -3,6 +3,21 @@ package com.mindata.blockchain.core.requestbody; import com.mindata.blockchain.block.BlockBody; /** + * { + * "blockBody": { + * "instructions": [{ + * "hash": "fc0fca8d240f4f688360ae040c904783ae21cc66d5cb8cbbc91b2b9d5fa7e983", + * "instructionId": "c4e958b1-6b7c-4784-bd81-c4475217e712", + * "json": "{\"content\":\"block\"}", + * "operation": 1, + * "publicKey": "A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54", + * "sign": "MEQCIDImpBfp2x7Zh+0y1z4V/eQsZkhnqLlDvqn/rNVHccm2AiAR+wUVYckMQ2CXxVcrfTV5dSCPbc9mY6xOOUdEz6mukQ==", + * "table": "message", + * "timeStamp": 1531135646925 + * }] * }, + * "publicKey": "A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54" + * } + * * 生成Block时传参 * @author wuweifeng wrote on 2018/3/8. */ diff --git a/src/main/java/com/mindata/blockchain/core/requestbody/InstructionBody.java b/src/main/java/com/mindata/blockchain/core/requestbody/InstructionBody.java index 4413ce140553cc5bce6314f9f981026d04d3ea3d..6d65df48b3482f87e79b151ffd23bb1a51887139 100644 --- a/src/main/java/com/mindata/blockchain/core/requestbody/InstructionBody.java +++ b/src/main/java/com/mindata/blockchain/core/requestbody/InstructionBody.java @@ -1,5 +1,7 @@ package com.mindata.blockchain.core.requestbody; +import com.mindata.blockchain.common.FastJsonUtil; + /** * @author wuweifeng wrote on 2018/3/7. */ @@ -101,4 +103,17 @@ public class InstructionBody { public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } + + public static void main(String[] args) { + InstructionBody body = new InstructionBody(); + body.setOperation((byte) 1); + body.setTable("data_log"); + body.setPrivateKey("folF5JzZ66wQOtq2nUPxkJpkMwsIij4cG+I016NDiVo="); + body.setPublicKey("BL/tXNQRVJ/WvKp60C3TQwdt68gvDDBPY8lKLOp42HvsH5SWWlkF5Lzlcm36RzZid0ICk+JXPz99uf/m1oV/hZo="); + body.setInstructionId(String.valueOf(System.currentTimeMillis())); + body.setJson("json"); + body.setOldJson("oldJson"); + + System.out.println(FastJsonUtil.toJSONString(body)); + } } diff --git a/src/main/java/com/mindata/blockchain/core/service/BlockService.java b/src/main/java/com/mindata/blockchain/core/service/BlockService.java index f023afef835500ed676ea18a2d41b1cb342d2e76..3cb785e8489d07fab4e19859c91e8cb7fa5fa3cd 100644 --- a/src/main/java/com/mindata/blockchain/core/service/BlockService.java +++ b/src/main/java/com/mindata/blockchain/core/service/BlockService.java @@ -85,8 +85,7 @@ public class BlockService { public Block addBlock(BlockRequestBody blockRequestBody) { com.mindata.blockchain.block.BlockBody blockBody = blockRequestBody.getBlockBody(); List instructions = blockBody.getInstructions(); - List hashList = instructions.stream().map(Instruction::getHash).collect(Collectors - .toList()); + List hashList = instructions.stream().map(Instruction::getHash).collect(Collectors.toList()); BlockHeader blockHeader = new BlockHeader(); blockHeader.setHashList(hashList); @@ -103,7 +102,7 @@ public class BlockService { block.setBlockHeader(blockHeader); block.setHash(Sha256.sha256(blockHeader.toString() + blockBody.toString())); - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.GENERATE_BLOCK_REQUEST).setBody(new + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.GENERATE_BLOCK_REQUEST.getKey()).setBody(new RpcBlockBody(block)).build(); //广播给其他人做验证 diff --git a/src/main/java/com/mindata/blockchain/core/sqlite/SqliteManager.java b/src/main/java/com/mindata/blockchain/core/sqlite/SqliteManager.java index af1d7901ddbe43799d18934125b7dd65f6eb0f30..f78ae6f86998a5d493a14a80520f91c080cf50e7 100644 --- a/src/main/java/com/mindata/blockchain/core/sqlite/SqliteManager.java +++ b/src/main/java/com/mindata/blockchain/core/sqlite/SqliteManager.java @@ -82,6 +82,7 @@ public class SqliteManager { for (Instruction instruction : instructions) { instruction.setOldJson(instruction.getJson()); } +// insert into message (create_time, public_key, update_time, content, message_id, origin, target) values (?, ?, ?, ?, ?, ?, ?) doSqlParse(instructions); //保存已同步的进度 diff --git a/src/main/java/com/mindata/blockchain/core/sqlite/config/DataSourceConfiguration.java b/src/main/java/com/mindata/blockchain/core/sqlite/config/DataSourceConfiguration.java index 2ec97e28c8bd245d430f0e23329460bea2ea5fe3..b457f6f6734b5df897f46ae3f1d778ec60662447 100644 --- a/src/main/java/com/mindata/blockchain/core/sqlite/config/DataSourceConfiguration.java +++ b/src/main/java/com/mindata/blockchain/core/sqlite/config/DataSourceConfiguration.java @@ -10,6 +10,8 @@ import javax.sql.DataSource; /** + * https://blog.csdn.net/tianyaleixiaowu/article/details/79445561 + * * 配置sqlite数据库的DataSource * @author wuweifeng wrote on 2018/3/2. */ diff --git a/src/main/java/com/mindata/blockchain/core/sqlparser/InstructionParserImpl.java b/src/main/java/com/mindata/blockchain/core/sqlparser/InstructionParserImpl.java index b120be88145ca3842b2f3d99440a4206ed1811c0..f00f72cce69000e207528945bb2f65ba8f6c52da 100644 --- a/src/main/java/com/mindata/blockchain/core/sqlparser/InstructionParserImpl.java +++ b/src/main/java/com/mindata/blockchain/core/sqlparser/InstructionParserImpl.java @@ -1,17 +1,17 @@ package com.mindata.blockchain.core.sqlparser; -import javax.annotation.Resource; - -import org.springframework.stereotype.Service; - import com.mindata.blockchain.block.Instruction; import com.mindata.blockchain.block.InstructionBase; import com.mindata.blockchain.common.FastJsonUtil; import com.mindata.blockchain.core.model.base.BaseEntity; import com.mindata.blockchain.core.model.convert.ConvertTableName; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; /** * 将区块内指令解析并入库 + * * @author wuweifeng wrote on 2018/3/21. */ @Service @@ -31,9 +31,9 @@ public class InstructionParserImpl implements InstructionP T object = FastJsonUtil.toBean(json, clazz); for (AbstractSqlParser sqlParser : sqlParsers) { if (clazz.equals(sqlParser.getEntityClass())) { - if(instructionBase instanceof Instruction){ - object.setPublicKey(((Instruction)instructionBase).getPublicKey()); - } + if (instructionBase instanceof Instruction) { + object.setPublicKey(((Instruction) instructionBase).getPublicKey()); + } sqlParser.parse(operation, instructionBase.getInstructionId(), object); break; } diff --git a/src/main/java/com/mindata/blockchain/core/utils/RequestThreadLocal.java b/src/main/java/com/mindata/blockchain/core/utils/RequestThreadLocal.java new file mode 100644 index 0000000000000000000000000000000000000000..0467d30e3e6f112d744515b5c4eed8227e00825b --- /dev/null +++ b/src/main/java/com/mindata/blockchain/core/utils/RequestThreadLocal.java @@ -0,0 +1,20 @@ +package com.mindata.blockchain.core.utils; + + +import org.apache.commons.lang3.StringUtils; + +public class RequestThreadLocal { + + public static final ThreadLocal serviceApiNames = new ThreadLocal(); + + public static final void set(String serviceApiName) { + serviceApiNames.set(serviceApiName); + } + + public static String get() { + String name = serviceApiNames.get(); + name = StringUtils.defaultString(name, "unknowuri"); + return name; + } + +} diff --git a/src/main/java/com/mindata/blockchain/core/utils/RequestUtil.java b/src/main/java/com/mindata/blockchain/core/utils/RequestUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..0e8eec50052646b3697503d4fd200b86eb0676f2 --- /dev/null +++ b/src/main/java/com/mindata/blockchain/core/utils/RequestUtil.java @@ -0,0 +1,125 @@ +package com.mindata.blockchain.core.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +@Slf4j(topic = "RequestUtil") +public class RequestUtil { + + + public static void printAll(ServletRequest request, Object obj, Set ignoreParams) { + HttpServletRequest request2 = (HttpServletRequest) request; + + printAll(request2, obj, ignoreParams); + } + + public static void printAll(ServletRequest request, Object obj, boolean onlyDebugAble, Set ignoreParams) { + HttpServletRequest request2 = (HttpServletRequest) request; + + printAll(request2, obj, onlyDebugAble, ignoreParams); + } + + public static void printAll(HttpServletRequest request, Object obj, Set ignoreParams) { + printAll(request, obj, true, ignoreParams); + } + + public static void printAll(HttpServletRequest request, Object obj, boolean onlyDebugAble, Set ignoreParams) { + if (onlyDebugAble && !log.isDebugEnabled()) { + return; + } + log.debug("------------------------------print request start.------------------------------------"); + log.debug("class:" + obj.getClass()); + String uri = request.getRequestURI(); + log.debug("request uri:" + uri); + String sessionId = request.getRequestedSessionId(); + log.debug("request sessionId:" + sessionId); + Map headerMap = new HashMap(); + Map paramMap = new HashMap(); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String headerKey = (String) headers.nextElement(); + String headerValue = request.getHeader(headerKey); + headerMap.put(headerKey, headerValue); + } + + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String paramName = (String) params.nextElement(); + String paramValue = request.getParameter(paramName); + paramMap.put(paramName, paramValue); + } + + log.debug("header:"); + for (Entry entry : headerMap.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + log.debug(" " + key + ":" + value); + } + log.debug("param:"); + for (Entry entry : paramMap.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + + //敏感字符不打印 + if (!CollectionUtils.isEmpty(ignoreParams) && ignoreParams.contains(key)) { + value = "****"; + } + + log.debug(" " + key + "=" + value); + } + + StringBuffer requestURL = request.getRequestURL(); + + StringBuffer sb = new StringBuffer(); + sb.append("curl "); + sb.append("\'").append(requestURL).append("\' "); + for (Entry entry : headerMap.entrySet()) { + sb.append(" -H "); + String key = entry.getKey(); + String value = entry.getValue(); +// value = value.replaceAll("=", "=\"").replaceAll(",", "\","); +// value = value.replaceAll("\'", "'"); + sb.append("\'"); + sb.append(key); + sb.append(":"); + sb.append(value); + sb.append("\'"); + } + sb.append(" --data "); + sb.append("\""); + for (Entry entry : paramMap.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + sb.append(key); + sb.append("="); + sb.append(value); + sb.append("&"); + } + sb.append("\""); + log.debug(sb.toString()); + log.debug("===============================print request end.==================================="); + } + + public static String getRequestHeader(HttpServletRequest request, + String headerName) { + String header = request.getHeader(headerName); + header = StringUtils.defaultIfEmpty(header, ""); + return header; + } + + public static String getRequestParameter(HttpServletRequest request, + String paramName) { + String value = request.getParameter(paramName); + value = StringUtils.defaultIfEmpty(value, ""); + return value; + } +} diff --git a/src/main/java/com/mindata/blockchain/socket/client/BlockClientAioHandler.java b/src/main/java/com/mindata/blockchain/socket/client/BlockClientAioHandler.java index cc064f1d3beafef36545b339d416da8961803d01..aa04511d7e44d69a56370624a44f5e8cc1e6a97c 100644 --- a/src/main/java/com/mindata/blockchain/socket/client/BlockClientAioHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/client/BlockClientAioHandler.java @@ -5,6 +5,8 @@ import com.mindata.blockchain.socket.base.AbstractAioHandler; import com.mindata.blockchain.socket.distruptor.base.BaseEvent; import com.mindata.blockchain.socket.distruptor.base.MessageProducer; import com.mindata.blockchain.socket.packet.BlockPacket; +import com.mindata.blockchain.socket.packet.PacketType; +import lombok.extern.slf4j.Slf4j; import org.tio.client.intf.ClientAioHandler; import org.tio.core.ChannelContext; import org.tio.core.intf.Packet; @@ -12,6 +14,7 @@ import org.tio.core.intf.Packet; /** * @author wuweifeng wrote on 2018/3/12. */ +@Slf4j(topic = "BlockClientAioHandler") public class BlockClientAioHandler extends AbstractAioHandler implements ClientAioHandler { @Override @@ -25,9 +28,12 @@ public class BlockClientAioHandler extends AbstractAioHandler implements ClientA * server端返回的响应会先进到该方法,将消息全丢到Disruptor中 */ @Override - public void handler(Packet packet, ChannelContext channelContext) { + public void handler(Packet packet, ChannelContext channelContext) { BlockPacket blockPacket = (BlockPacket) packet; + PacketType type = PacketType.fromValue(blockPacket.getType()); + log.info(">>>>>>>>>>>>>>>>客户端接收消息 type:{} packet:{}", type.getValue(), blockPacket); + //使用Disruptor来publish消息。所有收到的消息都进入Disruptor,同BlockServerAioHandler ApplicationContextProvider.getBean(MessageProducer.class).publish(new BaseEvent(blockPacket, channelContext)); } diff --git a/src/main/java/com/mindata/blockchain/socket/client/BlockGeneratedListener.java b/src/main/java/com/mindata/blockchain/socket/client/BlockGeneratedListener.java index f950ecdb4aba3620fefa53a444cdd9c84f45047a..fa568bf6386472cf047c4f15b39309842cea4fcf 100644 --- a/src/main/java/com/mindata/blockchain/socket/client/BlockGeneratedListener.java +++ b/src/main/java/com/mindata/blockchain/socket/client/BlockGeneratedListener.java @@ -25,7 +25,7 @@ public class BlockGeneratedListener { @EventListener(AddBlockEvent.class) public void blockGenerated(AddBlockEvent addBlockEvent) { Block block = (Block) addBlockEvent.getSource(); - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.GENERATE_COMPLETE_REQUEST).setBody(new + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.GENERATE_COMPLETE_REQUEST.getKey()).setBody(new RpcSimpleBlockBody(block.getHash())).build(); //广播给其他人做验证 diff --git a/src/main/java/com/mindata/blockchain/socket/client/ClientStarter.java b/src/main/java/com/mindata/blockchain/socket/client/ClientStarter.java index 404382116ee72b9a0bd9e14cb7535e11dedca3e6..4f1c276a11e807e9acbdf97928a637de83110ec7 100644 --- a/src/main/java/com/mindata/blockchain/socket/client/ClientStarter.java +++ b/src/main/java/com/mindata/blockchain/socket/client/ClientStarter.java @@ -1,16 +1,17 @@ package com.mindata.blockchain.socket.client; -import static com.mindata.blockchain.socket.common.Const.GROUP_NAME; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.stream.Collectors; - -import javax.annotation.Resource; - +import com.google.common.collect.Maps; +import com.mindata.blockchain.common.AppId; +import com.mindata.blockchain.common.CommonUtil; +import com.mindata.blockchain.core.bean.Member; +import com.mindata.blockchain.core.bean.MemberData; +import com.mindata.blockchain.core.bean.Permission; +import com.mindata.blockchain.core.bean.PermissionData; +import com.mindata.blockchain.core.event.NodesConnectedEvent; +import com.mindata.blockchain.core.manager.PermissionManager; +import com.mindata.blockchain.socket.common.Const; +import com.mindata.blockchain.socket.packet.BlockPacket; +import com.mindata.blockchain.socket.packet.NextBlockPacketBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -19,25 +20,21 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.tio.client.AioClient; -import org.tio.client.ClientChannelContext; import org.tio.client.ClientGroupContext; import org.tio.core.Aio; import org.tio.core.ChannelContext; import org.tio.core.Node; import org.tio.utils.lock.SetWithLock; -import com.google.common.collect.Maps; -import com.mindata.blockchain.common.AppId; -import com.mindata.blockchain.common.CommonUtil; -import com.mindata.blockchain.core.bean.Member; -import com.mindata.blockchain.core.bean.MemberData; -import com.mindata.blockchain.core.bean.Permission; -import com.mindata.blockchain.core.bean.PermissionData; -import com.mindata.blockchain.core.event.NodesConnectedEvent; -import com.mindata.blockchain.core.manager.PermissionManager; -import com.mindata.blockchain.socket.common.Const; -import com.mindata.blockchain.socket.packet.BlockPacket; -import com.mindata.blockchain.socket.packet.NextBlockPacketBuilder; +import javax.annotation.Resource; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.stream.Collectors; + +import static com.mindata.blockchain.socket.common.Const.GROUP_NAME; /** * @author wuweifeng wrote on 2018/3/18. @@ -64,19 +61,19 @@ public class ClientStarter { private Logger logger = LoggerFactory.getLogger(getClass()); private Set nodes = new HashSet<>(); - + // 节点连接状态 - private Map nodesStatus = Maps.newConcurrentMap(); + private Map nodesStatus = Maps.newConcurrentMap(); private volatile boolean isNodesReady = false; // 节点是否已准备好 /** * 从麦达区块链管理端获取已登记的各服务器ip * 隔5分钟去获取一次 */ - @Scheduled(fixedRate = 300000) + @Scheduled(fixedRate = 10000) public void fetchOtherServer() { String localIp = CommonUtil.getLocalIp(); - logger.info("本机IP:{}",localIp); + logger.info("本机IP:{}", localIp); try { //如果连不上服务器,就不让启动 MemberData memberData = restTemplate.getForEntity(managerUrl + "member?name=" + name + "&appId=" + AppId @@ -91,7 +88,7 @@ public class ClientStarter { nodes.clear(); for (Member member : memberList) { - Node node = new Node(member.getIp(), Const.PORT); + Node node = new Node(member.getIp(), member.getPort()); nodes.add(node); } //开始尝试绑定到对方开启的server @@ -137,7 +134,7 @@ public class ClientStarter { */ @Scheduled(fixedRate = 30000) public void heartBeat() { - if(!isNodesReady)return; + if (!isNodesReady) return; logger.info("---------开始心跳包--------"); BlockPacket blockPacket = NextBlockPacketBuilder.build(); packetSender.sendGroup(blockPacket); @@ -190,33 +187,33 @@ public class ClientStarter { logger.info("开始绑定" + ":" + serverNode.toString()); aioClient.asynConnect(serverNode); } catch (Exception e) { - logger.info("异常"); + logger.error("绑定服务[" + serverNode + "]失败", e); } } - + @EventListener(NodesConnectedEvent.class) - public void onConnected(NodesConnectedEvent connectedEvent){ - ChannelContext channelContext = connectedEvent.getSource(); - Node node = channelContext.getServerNode(); - if (channelContext.isClosed()) { + public void onConnected(NodesConnectedEvent connectedEvent) { + ChannelContext channelContext = connectedEvent.getSource(); + Node node = channelContext.getServerNode(); + if (channelContext.isClosed()) { logger.info("连接" + node.toString() + "失败"); nodesStatus.put(node.getIp(), -1); return; - }else{ - logger.info("连接" + node.toString() + "成功"); - nodesStatus.put(node.getIp(), 1); - //绑group是将要连接的各个服务器节点做为一个group - Aio.bindGroup(channelContext, GROUP_NAME); - - int csize = Aio.getAllChannelContexts(clientGroupContext).size(); - if(csize >= pbftAgreeCount()){ - synchronized (nodesStatus) { - if(!isNodesReady){ - isNodesReady = true; - onNodesReady(); - } - } - } + } else { + logger.info("连接" + node.toString() + "成功"); + nodesStatus.put(node.getIp(), 1); + //绑group是将要连接的各个服务器节点做为一个group + Aio.bindGroup(channelContext, GROUP_NAME); + + int csize = Aio.getAllChannelContexts(clientGroupContext).size(); + if (csize >= pbftAgreeCount()) { + synchronized (nodesStatus) { + if (!isNodesReady) { + isNodesReady = true; + onNodesReady(); + } + } + } } } @@ -238,7 +235,7 @@ public class ClientStarter { pbft = 1; } //如果要单节点测试,此处返回值改为0 - if(singeNode) return 0; + if (singeNode) return 0; return pbft; } diff --git a/src/main/java/com/mindata/blockchain/socket/common/Const.java b/src/main/java/com/mindata/blockchain/socket/common/Const.java index 9b2c7307114a6fed462d05cdf95f938c9750863b..e9a17f33765233b6d95c4a0986d17b7caf39f013 100644 --- a/src/main/java/com/mindata/blockchain/socket/common/Const.java +++ b/src/main/java/com/mindata/blockchain/socket/common/Const.java @@ -22,5 +22,5 @@ public interface Const { */ int TIMEOUT = 5000; - String CHARSET = "utf-8"; + String CHARSET = "UTF-8"; } diff --git a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorClientConsumer.java b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorClientConsumer.java index 1177225084763e739c734f09b5588c3a3570dfac..31e4ebd488e448f764fd3b7d8bccd972a57da15c 100644 --- a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorClientConsumer.java +++ b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorClientConsumer.java @@ -2,10 +2,10 @@ package com.mindata.blockchain.socket.distruptor; import cn.hutool.core.util.StrUtil; import com.mindata.blockchain.common.AppId; -import com.mindata.blockchain.socket.distruptor.base.BaseEvent; -import com.mindata.blockchain.socket.distruptor.base.MessageConsumer; import com.mindata.blockchain.socket.base.AbstractBlockHandler; import com.mindata.blockchain.socket.body.BaseBody; +import com.mindata.blockchain.socket.distruptor.base.BaseEvent; +import com.mindata.blockchain.socket.distruptor.base.MessageConsumer; import com.mindata.blockchain.socket.handler.client.FetchBlockResponseHandler; import com.mindata.blockchain.socket.handler.client.NextBlockResponseHandler; import com.mindata.blockchain.socket.handler.client.TotalBlockInfoResponseHandler; @@ -21,6 +21,7 @@ import java.util.Map; /** * 所有server发来的消息都在这里处理 + * * @author wuweifeng wrote on 2018/4/20. */ @Component @@ -29,9 +30,9 @@ public class DisruptorClientConsumer implements MessageConsumer { private Logger logger = LoggerFactory.getLogger(getClass()); static { - handlerMap.put(PacketType.TOTAL_BLOCK_INFO_RESPONSE, new TotalBlockInfoResponseHandler()); - handlerMap.put(PacketType.NEXT_BLOCK_INFO_RESPONSE, new NextBlockResponseHandler()); - handlerMap.put(PacketType.FETCH_BLOCK_INFO_RESPONSE, new FetchBlockResponseHandler()); + handlerMap.put(PacketType.TOTAL_BLOCK_INFO_RESPONSE.getKey(), new TotalBlockInfoResponseHandler()); + handlerMap.put(PacketType.NEXT_BLOCK_INFO_RESPONSE.getKey(), new NextBlockResponseHandler()); + handlerMap.put(PacketType.FETCH_BLOCK_INFO_RESPONSE.getKey(), new FetchBlockResponseHandler()); } @Override @@ -45,7 +46,7 @@ public class DisruptorClientConsumer implements MessageConsumer { //消费消息 BaseBody baseBody = Json.toBean(new String(blockPacket.getBody()), BaseBody.class); - //logger.info("收到来自于<" + baseBody.getAppId() + ">针对msg<" + baseBody.getResponseMsgId() + ">的回应"); + logger.info("收到来自于<" + baseBody.getAppId() + ">针对msg<" + baseBody.getResponseMsgId() + ">的回应"); String appId = baseBody.getAppId(); if (StrUtil.equals(AppId.value, appId)) { diff --git a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerConsumer.java b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerConsumer.java index 108eaa3ae334f3795fef39b72328ba2060cc79d8..cc74d8a0d6f378ed61e60fd4bd7f76d0f11b374f 100644 --- a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerConsumer.java +++ b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerConsumer.java @@ -21,13 +21,13 @@ public class DisruptorServerConsumer implements MessageConsumer { private static Map> handlerMap = new HashMap<>(); static { - handlerMap.put(PacketType.GENERATE_COMPLETE_REQUEST, new GenerateCompleteRequestHandler()); - handlerMap.put(PacketType.GENERATE_BLOCK_REQUEST, new GenerateBlockRequestHandler()); - handlerMap.put(PacketType.TOTAL_BLOCK_INFO_REQUEST, new TotalBlockInfoRequestHandler()); - handlerMap.put(PacketType.FETCH_BLOCK_INFO_REQUEST, new FetchBlockRequestHandler()); - handlerMap.put(PacketType.HEART_BEAT, new HeartBeatHandler()); - handlerMap.put(PacketType.NEXT_BLOCK_INFO_REQUEST, new NextBlockRequestHandler()); - handlerMap.put(PacketType.PBFT_VOTE, new PbftVoteHandler()); + handlerMap.put(PacketType.GENERATE_COMPLETE_REQUEST.getKey(), new GenerateCompleteRequestHandler()); + handlerMap.put(PacketType.GENERATE_BLOCK_REQUEST.getKey(), new GenerateBlockRequestHandler()); + handlerMap.put(PacketType.TOTAL_BLOCK_INFO_REQUEST.getKey(), new TotalBlockInfoRequestHandler()); + handlerMap.put(PacketType.FETCH_BLOCK_INFO_REQUEST.getKey(), new FetchBlockRequestHandler()); + handlerMap.put(PacketType.HEART_BEAT.getKey(), new HeartBeatHandler()); + handlerMap.put(PacketType.NEXT_BLOCK_INFO_REQUEST.getKey(), new NextBlockRequestHandler()); + handlerMap.put(PacketType.PBFT_VOTE.getKey(), new PbftVoteHandler()); } @Override diff --git a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerHandler.java b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerHandler.java index 032c81d84af67a3ee42754328db8c1dc48e9a117..4185c041600dee1f92dcbf4ff5493ee877b0a72d 100644 --- a/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/distruptor/DisruptorServerHandler.java @@ -1,12 +1,10 @@ package com.mindata.blockchain.socket.distruptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.lmax.disruptor.EventHandler; import com.mindata.blockchain.ApplicationContextProvider; import com.mindata.blockchain.socket.distruptor.base.BaseEvent; -import com.mindata.blockchain.socket.handler.server.PbftVoteHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author wuweifeng wrote on 2018/4/20. diff --git a/src/main/java/com/mindata/blockchain/socket/handler/client/NextBlockResponseHandler.java b/src/main/java/com/mindata/blockchain/socket/handler/client/NextBlockResponseHandler.java index 6f79aeaadd0433a89658dea2c9fdccdb5a4450b0..81196fbe9ef1d1e8d5afa705d18d0ba5390dab29 100644 --- a/src/main/java/com/mindata/blockchain/socket/handler/client/NextBlockResponseHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/handler/client/NextBlockResponseHandler.java @@ -16,7 +16,7 @@ import org.tio.core.ChannelContext; * @author wuweifeng wrote on 2018/3/16. */ public class NextBlockResponseHandler extends AbstractBlockHandler { - private Logger logger = LoggerFactory.getLogger(TotalBlockInfoResponseHandler.class); + private Logger logger = LoggerFactory.getLogger(NextBlockResponseHandler.class); @Override public Class bodyClass() { diff --git a/src/main/java/com/mindata/blockchain/socket/handler/server/FetchBlockRequestHandler.java b/src/main/java/com/mindata/blockchain/socket/handler/server/FetchBlockRequestHandler.java index 38c2c471350547df1116eca6178632fd3941f1ed..bc4d4a9caa06915c269e55b63685d3cd28c89ea0 100644 --- a/src/main/java/com/mindata/blockchain/socket/handler/server/FetchBlockRequestHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/handler/server/FetchBlockRequestHandler.java @@ -31,7 +31,7 @@ public class FetchBlockRequestHandler extends AbstractBlockHandler<请求该Block>消息,block hash为[" + rpcBlockBody.getHash() + "]"); Block block = ApplicationContextProvider.getBean(DbBlockManager.class).getBlockByHash(rpcBlockBody.getHash()); - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.FETCH_BLOCK_INFO_RESPONSE).setBody(new + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.FETCH_BLOCK_INFO_RESPONSE.getKey()).setBody(new RpcBlockBody(block)).build(); Aio.send(channelContext, blockPacket); diff --git a/src/main/java/com/mindata/blockchain/socket/handler/server/NextBlockRequestHandler.java b/src/main/java/com/mindata/blockchain/socket/handler/server/NextBlockRequestHandler.java index 6d87adfe865cc4c9b2ba7d9a7833a5661d14e02e..6451200505e7764794b8cd354081f9994b9b06a1 100644 --- a/src/main/java/com/mindata/blockchain/socket/handler/server/NextBlockRequestHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/handler/server/NextBlockRequestHandler.java @@ -21,7 +21,7 @@ import org.tio.utils.json.Json; * @author wuweifeng wrote on 2018/3/16. */ public class NextBlockRequestHandler extends AbstractBlockHandler { - private Logger logger = LoggerFactory.getLogger(TotalBlockInfoRequestHandler.class); + private Logger logger = LoggerFactory.getLogger(NextBlockRequestHandler.class); @Override public Class bodyClass() { @@ -43,8 +43,7 @@ public class NextBlockRequestHandler extends AbstractBlockHandler().setType(PacketType - .NEXT_BLOCK_INFO_RESPONSE).setBody(respBody).build(); + BlockPacket blockPacket = new PacketBuilder().setType(PacketType.NEXT_BLOCK_INFO_RESPONSE.getKey()).setBody(respBody).build(); Aio.send(channelContext, blockPacket); logger.info("回复给<" + rpcBlockBody.getAppId() + ">,我的nextBlock是" + respBody.toString()); diff --git a/src/main/java/com/mindata/blockchain/socket/packet/BlockPacket.java b/src/main/java/com/mindata/blockchain/socket/packet/BlockPacket.java index 2e0064c6a38712695b49b5f25fc2dd8baea406e5..90e6825a313322aee67898e7ee02224a6448579b 100644 --- a/src/main/java/com/mindata/blockchain/socket/packet/BlockPacket.java +++ b/src/main/java/com/mindata/blockchain/socket/packet/BlockPacket.java @@ -1,16 +1,19 @@ package com.mindata.blockchain.socket.packet; import com.mindata.blockchain.socket.common.Const; +import lombok.extern.slf4j.Slf4j; import org.tio.core.intf.Packet; import java.io.UnsupportedEncodingException; +import java.util.Arrays; /** * @author wuweifeng wrote on 2018/3/9. */ +@Slf4j(topic = "BlockPacket") public class BlockPacket extends Packet { /** - * 消息头的长度 1+4 + * 消息头的长度 1+4 */ public static final int HEADER_LENGTH = 5; /** @@ -61,8 +64,7 @@ public class BlockPacket extends Packet { } /** - * @param body - * the body to set + * @param body the body to set */ public void setBody(byte[] body) { this.body = body; @@ -72,15 +74,22 @@ public class BlockPacket extends Packet { try { this.body = body.getBytes(Const.CHARSET); } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + log.error("set body error", e); } } /** - * @param type - * the type to set + * @param type the type to set */ public void setType(byte type) { this.type = type; } + + @Override + public String toString() { + return "BlockPacket{" + + "type=" + type + + ", body=" + new String(body) + + '}'; + } } diff --git a/src/main/java/com/mindata/blockchain/socket/packet/NextBlockPacketBuilder.java b/src/main/java/com/mindata/blockchain/socket/packet/NextBlockPacketBuilder.java index 2eb1071c947c4a1f18dcb9086184cad003b8398a..a206363b7ae6c6ed765e9c3bbfef4689cccec223 100644 --- a/src/main/java/com/mindata/blockchain/socket/packet/NextBlockPacketBuilder.java +++ b/src/main/java/com/mindata/blockchain/socket/packet/NextBlockPacketBuilder.java @@ -19,7 +19,7 @@ public class NextBlockPacketBuilder { RpcSimpleBlockBody rpcBlockBody = new RpcSimpleBlockBody(hash); rpcBlockBody.setResponseMsgId(responseId); - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.NEXT_BLOCK_INFO_REQUEST).setBody + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.NEXT_BLOCK_INFO_REQUEST.getKey()).setBody (rpcBlockBody).build(); //发布client请求事件 ApplicationContextProvider.publishEvent(new ClientRequestEvent(blockPacket)); diff --git a/src/main/java/com/mindata/blockchain/socket/packet/PacketType.java b/src/main/java/com/mindata/blockchain/socket/packet/PacketType.java index 41c0d9e7d056d14621ea8742035dc7b2ef7274a3..e841e1f42268f3aa133c6ebfb65a7140544432b1 100644 --- a/src/main/java/com/mindata/blockchain/socket/packet/PacketType.java +++ b/src/main/java/com/mindata/blockchain/socket/packet/PacketType.java @@ -1,56 +1,54 @@ package com.mindata.blockchain.socket.packet; +import java.util.HashMap; +import java.util.Map; + /** * packetType大于0时是请求类型,小于0时为响应类型 + * * @author wuweifeng wrote on 2018/3/9. */ -public interface PacketType { - /** - * 心跳包 - */ - byte HEART_BEAT = 0; - /** - * 已生成新的区块 - */ - byte GENERATE_COMPLETE_REQUEST = 1; - /** - * 已生成新的区块回应 - */ - byte GENERATE_COMPLETE_RESPONSE = -1; - /** - * 请求生成block - */ - byte GENERATE_BLOCK_REQUEST = 2; - /** - * 同意、拒绝生成 - */ - byte GENERATE_BLOCK_RESPONSE = -2; - /** - * 获取所有block信息 - */ - byte TOTAL_BLOCK_INFO_REQUEST = 3; - /** - * 我的所有块信息 - */ - byte TOTAL_BLOCK_INFO_RESPONSE = -3; - /** - * 获取一个block信息 - */ - byte FETCH_BLOCK_INFO_REQUEST = 4; - /** - * 获取一块信息响应 - */ - byte FETCH_BLOCK_INFO_RESPONSE = -4; - /** - * 获取下一个区块的信息 - */ - byte NEXT_BLOCK_INFO_REQUEST = 5; - /** - * 获取下一个区块的信息 - */ - byte NEXT_BLOCK_INFO_RESPONSE = -5; - /** - * pbft投票 - */ - byte PBFT_VOTE = 10; +public enum PacketType { + + HEART_BEAT(new Byte("0"), "心跳包"), + GENERATE_COMPLETE_REQUEST(new Byte("1"), "已生成新的区块"), + GENERATE_COMPLETE_RESPONSE(new Byte("-1"), "已生成新的区块回应"), + GENERATE_BLOCK_REQUEST(new Byte("2"), "请求生成block"), + GENERATE_BLOCK_RESPONSE(new Byte("-2"), "同意、拒绝生成"), + TOTAL_BLOCK_INFO_REQUEST(new Byte("3"), "获取所有block信息"), + TOTAL_BLOCK_INFO_RESPONSE(new Byte("-3"), "我的所有块信息"), + FETCH_BLOCK_INFO_REQUEST(new Byte("4"), "获取一个block信息"), + FETCH_BLOCK_INFO_RESPONSE(new Byte("-4"), "获取一块信息响应"), + NEXT_BLOCK_INFO_REQUEST(new Byte("5"), "获取下一个区块的信息"), + NEXT_BLOCK_INFO_RESPONSE(new Byte("-5"), "获取下一个区块的信息"), + PBFT_VOTE(new Byte("10"), "pbft投票"); + + private Byte key; + private String value; + + PacketType(Byte key, String value) { + this.key = key; + this.value = value; + } + + public Byte getKey() { + return key; + } + + public String getValue() { + return value; + } + + + private static final Map ENUMMAP = new HashMap(); + + static { + for (PacketType packetType : PacketType.values()) { + ENUMMAP.put(packetType.getKey(), packetType); + } + } + + public static PacketType fromValue(Byte key) { + return ENUMMAP.get(key); + } } diff --git a/src/main/java/com/mindata/blockchain/socket/pbft/listener/CommitEventListener.java b/src/main/java/com/mindata/blockchain/socket/pbft/listener/CommitEventListener.java index cd00ed5c518982242fd3bb105d4c678b9ab82f1c..c7ae4ee8037a8d5295916221454feee48c10c383 100644 --- a/src/main/java/com/mindata/blockchain/socket/pbft/listener/CommitEventListener.java +++ b/src/main/java/com/mindata/blockchain/socket/pbft/listener/CommitEventListener.java @@ -32,7 +32,7 @@ public class CommitEventListener { VoteMsg voteMsg = (VoteMsg) msgCommitEvent.getSource(); //群发消息,通知所有节点,我已对该Block Prepare - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.PBFT_VOTE).setBody(new + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.PBFT_VOTE.getKey()).setBody(new VoteBody(voteMsg)).build(); //广播给所有人我已commit diff --git a/src/main/java/com/mindata/blockchain/socket/pbft/listener/PrepareEventListener.java b/src/main/java/com/mindata/blockchain/socket/pbft/listener/PrepareEventListener.java index 59ff448dfeb985cd5a18d5da8a29d2374f75194d..65e8b39868adc3fbc02da461789f5b5a76c9f623 100644 --- a/src/main/java/com/mindata/blockchain/socket/pbft/listener/PrepareEventListener.java +++ b/src/main/java/com/mindata/blockchain/socket/pbft/listener/PrepareEventListener.java @@ -32,7 +32,7 @@ public class PrepareEventListener { VoteMsg voteMsg = (VoteMsg) msgPrepareEvent.getSource(); //群发消息,通知别的节点,我已对该Block Prepare - BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.PBFT_VOTE).setBody(new + BlockPacket blockPacket = new PacketBuilder<>().setType(PacketType.PBFT_VOTE.getKey()).setBody(new VoteBody(voteMsg)).build(); //广播给所有人我已Prepare diff --git a/src/main/java/com/mindata/blockchain/socket/pbft/queue/MsgQueueManager.java b/src/main/java/com/mindata/blockchain/socket/pbft/queue/MsgQueueManager.java index 8e9169c712fbdd36aa5068e25cb6b241f061b306..e95df2f088a30f220be4d47209f5261ca1faecc1 100644 --- a/src/main/java/com/mindata/blockchain/socket/pbft/queue/MsgQueueManager.java +++ b/src/main/java/com/mindata/blockchain/socket/pbft/queue/MsgQueueManager.java @@ -12,10 +12,9 @@ import org.springframework.stereotype.Component; public class MsgQueueManager { public void pushMsg(VoteMsg voteMsg) { - BaseMsgQueue baseMsgQueue = null; + BaseMsgQueue baseMsgQueue = null; switch (voteMsg.getVoteType()) { - case VoteType - .PREPREPARE: + case VoteType.PREPREPARE: baseMsgQueue = ApplicationContextProvider.getBean(PreMsgQueue.class); break; case VoteType.PREPARE: @@ -27,8 +26,8 @@ public class MsgQueueManager { default: break; } - if(baseMsgQueue != null) { - baseMsgQueue.push(voteMsg); + if (baseMsgQueue != null) { + baseMsgQueue.push(voteMsg); } } } diff --git a/src/main/java/com/mindata/blockchain/socket/pbft/queue/NextBlockQueue.java b/src/main/java/com/mindata/blockchain/socket/pbft/queue/NextBlockQueue.java index a15a0fbcd46f4aa124090c9696a185570be3e6d6..42937e9ece4563f978946db5abaf2e9744699026 100644 --- a/src/main/java/com/mindata/blockchain/socket/pbft/queue/NextBlockQueue.java +++ b/src/main/java/com/mindata/blockchain/socket/pbft/queue/NextBlockQueue.java @@ -150,7 +150,7 @@ public class NextBlockQueue { wantHashs.add(wantHash); //请求拉取该hash的Block BlockPacket blockPacket = new PacketBuilder().setType(PacketType - .FETCH_BLOCK_INFO_REQUEST).setBody(new RpcSimpleBlockBody(wantHash)).build(); + .FETCH_BLOCK_INFO_REQUEST.getKey()).setBody(new RpcSimpleBlockBody(wantHash)).build(); packetSender.sendGroup(blockPacket); //remove后,这一次请求内的后续回复就凑不够agreeCount了,就不会再次触发全员请求block remove(prevHash); diff --git a/src/main/java/com/mindata/blockchain/socket/pbft/queue/PreMsgQueue.java b/src/main/java/com/mindata/blockchain/socket/pbft/queue/PreMsgQueue.java index 7c34551f9ce081ae0571a3fe37d8e32c4c5f1ac9..ec3818768311333a7f8649d851f9dfaaf333d826 100644 --- a/src/main/java/com/mindata/blockchain/socket/pbft/queue/PreMsgQueue.java +++ b/src/main/java/com/mindata/blockchain/socket/pbft/queue/PreMsgQueue.java @@ -62,12 +62,13 @@ public class PreMsgQueue extends BaseMsgQueue { } catch (Exception e) { if(!"00001".equals(e.getMessage())){ // 执行异常 + logger.error("tryExecute error",e); return; }else{ logger.info("指令预校验执行成功!"); } } - + //存入Pre集合中 blockConcurrentHashMap.put(hash, votePreMsg); diff --git a/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioHandler.java b/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioHandler.java index 843463025c705787dbe980048c68fed5580ecb5c..8b94068857fbb9786f04a2b9ed6fd38944fc3194 100644 --- a/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioHandler.java +++ b/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioHandler.java @@ -5,14 +5,18 @@ import com.mindata.blockchain.socket.distruptor.base.BaseEvent; import com.mindata.blockchain.socket.distruptor.base.MessageProducer; import com.mindata.blockchain.socket.base.AbstractAioHandler; import com.mindata.blockchain.socket.packet.BlockPacket; +import com.mindata.blockchain.socket.packet.PacketType; +import lombok.extern.slf4j.Slf4j; import org.tio.core.ChannelContext; import org.tio.core.intf.Packet; import org.tio.server.intf.ServerAioHandler; /** * server端处理所有client请求的入口 + * * @author wuweifeng wrote on 2018/3/12. */ +@Slf4j(topic = "BlockServerAioHandler") public class BlockServerAioHandler extends AbstractAioHandler implements ServerAioHandler { @@ -22,6 +26,8 @@ public class BlockServerAioHandler extends AbstractAioHandler implements ServerA @Override public void handler(Packet packet, ChannelContext channelContext) { BlockPacket blockPacket = (BlockPacket) packet; + PacketType type = PacketType.fromValue(blockPacket.getType()); + log.info("<<<<<<<<<<<<<<<<<服务端接收消息 type:{} packet:{}", type.getValue(), blockPacket); //使用Disruptor来publish消息。所有收到的消息都进入Disruptor,同BlockClientAioHandler ApplicationContextProvider.getBean(MessageProducer.class).publish(new BaseEvent(blockPacket, channelContext)); diff --git a/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioListener.java b/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioListener.java index 9b751755c5417c02738eb683f1f5c3adc3a5d3ca..407b26bb8e1da700b852ca128f9a377aaef8754a 100644 --- a/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioListener.java +++ b/src/main/java/com/mindata/blockchain/socket/server/BlockServerAioListener.java @@ -30,7 +30,7 @@ public class BlockServerAioListener implements ServerAioListener { @Override public void onAfterReceivedBytes(ChannelContext channelContext, int i) throws Exception { - log.info("onAfterReceived channelContext:{}, packet:{}, packetSize:{}"); + log.info("onAfterReceived channelContext:{}, packet:{}, packetSize:{}",channelContext); } diff --git a/src/main/java/com/mindata/blockchain/socket/server/BlockServerStarter.java b/src/main/java/com/mindata/blockchain/socket/server/BlockServerStarter.java index e8d798f7ab24c148ccd5f0d5fbd3378affc5483d..270bbd372ae11b3ea601c72cb08f9b8149c0ff03 100644 --- a/src/main/java/com/mindata/blockchain/socket/server/BlockServerStarter.java +++ b/src/main/java/com/mindata/blockchain/socket/server/BlockServerStarter.java @@ -1,6 +1,10 @@ package com.mindata.blockchain.socket.server; +import com.mindata.blockchain.common.CommonUtil; import com.mindata.blockchain.socket.common.Const; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.tio.server.AioServer; import org.tio.server.ServerGroupContext; @@ -16,8 +20,14 @@ import java.io.IOException; * @author wuweifeng wrote on 2018/3/12. */ @Component +@Slf4j(topic = "BlockServerStarter") public class BlockServerStarter { + @Value("${peer.listen.ip}") + private String ip; + @Value("${peer.listen.port}") + private int port; + @PostConstruct public void serverStart() throws IOException { ServerAioHandler serverAioHandler = new BlockServerAioHandler(); @@ -25,6 +35,14 @@ public class BlockServerStarter { ServerGroupContext serverGroupContext = new ServerGroupContext(serverAioHandler, serverAioListener); AioServer aioServer = new AioServer(serverGroupContext); //本机启动服务 - aioServer.start(null, Const.PORT); + if (port == 0) { + port = Const.PORT; + log.warn("server port not config use default port:{}", port); + } + if (StringUtils.isBlank(ip)) { + ip = CommonUtil.getLocalIp(); + log.warn("server ip not config use default ip:{}", port); + } + aioServer.start(ip, port); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c3b8cd1f7246e5411a08696b9072030d2062db5d..243f00501422557bed0c4a2b3747488b272f4e09 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,14 +1,35 @@ spring: + http: + encoding: + force: true + charset: UTF-8 + enabled: true jpa: - show-sql: false + show-sql: true database-platform: com.mindata.blockchain.core.sqlite.config.SQLiteDialect generate-ddl: true + +server: + tomcat: + uri-encoding: UTF-8 + port: 8080 + + +# 业务配置 sqlite: - dbName: a.db #本地sqlite的名字 + dbName: sqlite-0.db #本地sqlite的名字 + db: levelDB: false #在部分Windows机器上rocksDB会报错dll找不到,那么就用levelDB来替代 rocksDB: true + version: 1 -name: ${NAME:maida} -appId: ${APP_ID:wolf} -managerUrl: ${MANAGER_URL:http://localhost:8888/} \ No newline at end of file +name: ${NAME:mz} +appId: ${APP_ID:srv-0} +managerUrl: ${MANAGER_URL:http://localhost:8888/} +singeNode: true + +peer: + listen: + ip: 172.17.140.61 + port: 6780 diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml deleted file mode 100644 index 766ceeb8b9fec4dcf686fa9b5b7e1e2c31f7605d..0000000000000000000000000000000000000000 --- a/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - true - - logFile.%d{yyyy-MM-dd}.log - - 30 - 3GB - - - - %d{yyyy-MM-dd HH:mm:ss} -%msg%n - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3c9a0f87b9b8bd70293a6d384a324473d94673e --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,49 @@ + + + + + + + + + + %d{HH:mm:ss} [%t] %p %c - %msg%n + + + + + ./logs/md_blockchain.log + + + ./logs/md_blockchain-%d{yyyy-MM-dd_HH}.log.zip + + 720 + 500MB + + + %d{HH:mm:ss} [%t] %p %c - %msg%n + + + TRACE + + + + + + 0 + + + + 100 + + + + + + + + + + + +