Browse Source

Turn core directory into submodule;

tags/1.2.0^2
huanghaiquan 5 years ago
parent
commit
8083782e76
100 changed files with 0 additions and 7639 deletions
  1. +0
    -55
      core/consensus/consensus-bftsmart/pom.xml
  2. +0
    -67
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartClientIncomingConfig.java
  3. +0
    -22
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartClientIncomingSettings.java
  4. +0
    -35
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartCommitBlockConfig.java
  5. +0
    -17
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartCommitBlockSettings.java
  6. +0
    -54
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusConfig.java
  7. +0
    -42
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusProvider.java
  8. +0
    -20
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettings.java
  9. +0
    -308
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java
  10. +0
    -66
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartNodeConfig.java
  11. +0
    -45
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartNodeSettings.java
  12. +0
    -73
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartSettingsFactory.java
  13. +0
    -30
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartTopology.java
  14. +0
    -16
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartTransactionType.java
  15. +0
    -79
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientConfig.java
  16. +0
    -56
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientIdentification.java
  17. +0
    -12
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientSettings.java
  18. +0
    -129
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java
  19. +0
    -133
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClientFactory.java
  20. +0
    -73
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java
  21. +0
    -47
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyFactory.java
  22. +0
    -25
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyPool.java
  23. +0
    -32
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyPoolConfig.java
  24. +0
    -71
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java
  25. +0
    -549
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
  26. +0
    -110
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServerFactory.java
  27. +0
    -40
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartServerSettingConfig.java
  28. +0
    -10
      core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartServerSettings.java
  29. +0
    -144
      core/consensus/consensus-bftsmart/src/main/resources/bftsmart.config
  30. +0
    -137
      core/consensus/consensus-bftsmart/src/test/java/test/com/jd/blockchain/consensus/bftsmart/ProxyClientTest.java
  31. +0
    -178
      core/consensus/consensus-bftsmart/src/test/resources/bftsmart.config
  32. +0
    -121
      core/consensus/consensus-bftsmart/src/test/resources/system.config
  33. +0
    -71
      core/consensus/consensus-mq/pom.xml
  34. +0
    -55
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusProvider.java
  35. +0
    -301
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java
  36. +0
    -311
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/DefaultMessageTransmitter.java
  37. +0
    -30
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MessageTransmitter.java
  38. +0
    -92
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueClientFactory.java
  39. +0
    -74
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueClientIdentification.java
  40. +0
    -100
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueConsensusClient.java
  41. +0
    -47
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueBlockConfig.java
  42. +0
    -65
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueClientConfig.java
  43. +0
    -69
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueClientIncomingConfig.java
  44. +0
    -65
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueConsensusConfig.java
  45. +0
    -71
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueNetworkConfig.java
  46. +0
    -46
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueNodeConfig.java
  47. +0
    -72
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueServerConfig.java
  48. +0
    -105
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueSettingsFactory.java
  49. +0
    -44
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/AbstractConsumer.java
  50. +0
    -28
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/MsgQueueConsumer.java
  51. +0
    -76
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/NatsConsumer.java
  52. +0
    -92
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/RabbitConsumer.java
  53. +0
    -64
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/BlockEvent.java
  54. +0
    -44
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/MessageEvent.java
  55. +0
    -58
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/TxBlockedEvent.java
  56. +0
    -30
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/BytesEventFactory.java
  57. +0
    -40
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/BytesEventProducer.java
  58. +0
    -31
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEntityFactory.java
  59. +0
    -30
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventFactory.java
  60. +0
    -53
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventInnerEntity.java
  61. +0
    -40
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventProducer.java
  62. +0
    -23
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeType.java
  63. +0
    -23
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/MsgQueueConfig.java
  64. +0
    -52
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/MsgQueueFactory.java
  65. +0
    -32
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/NatsFactory.java
  66. +0
    -52
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/RabbitFactory.java
  67. +0
    -36
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/MsgQueueProducer.java
  68. +0
    -100
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/NatsProducer.java
  69. +0
    -106
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/RabbitProducer.java
  70. +0
    -297
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/DefaultMsgQueueMessageDispatcher.java
  71. +0
    -126
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/ExtendMsgQueueMessageExecutor.java
  72. +0
    -70
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueConsensusManageService.java
  73. +0
    -28
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueMessageDispatcher.java
  74. +0
    -182
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueMessageExecutor.java
  75. +0
    -196
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueNodeServer.java
  76. +0
    -61
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueNodeServerFactory.java
  77. +0
    -30
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueBlockSettings.java
  78. +0
    -30
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueClientIncomingSettings.java
  79. +0
    -23
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueClientSettings.java
  80. +0
    -33
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueConsensusSettings.java
  81. +0
    -36
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueNetworkSettings.java
  82. +0
    -25
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueNodeSettings.java
  83. +0
    -25
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueServerSettings.java
  84. +0
    -95
      core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/util/MessageConvertUtil.java
  85. +0
    -17
      core/consensus/pom.xml
  86. +0
    -27
      core/contract/README.MD
  87. +0
    -43
      core/contract/contract-jvm/pom.xml
  88. +0
    -105
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java
  89. +0
    -24
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/ContractDefinition.java
  90. +0
    -25
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java
  91. +0
    -41
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
  92. +0
    -20
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractServiceProvider.java
  93. +0
    -108
      core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  94. +0
    -274
      core/contract/contract-maven-plugin/ReadME.MD
  95. +0
    -1
      core/contract/contract-maven-plugin/conf/jd-com.priv
  96. +0
    -1
      core/contract/contract-maven-plugin/conf/jd-com.pub
  97. +0
    -1
      core/contract/contract-maven-plugin/conf/ownerPassword.txt
  98. +0
    -74
      core/contract/contract-maven-plugin/pom.xml
  99. +0
    -19
      core/contract/contract-maven-plugin/readme.txt
  100. +0
    -178
      core/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java

+ 0
- 55
core/consensus/consensus-bftsmart/pom.xml View File

@@ -1,55 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-core</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-bftsmart</artifactId>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>bft-smart</artifactId>
<version>${bftsmart.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-framework</artifactId>
<version>${framework.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>utils-common</artifactId>
<version>${framework.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-model</artifactId>
<version>${framework.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>tools-keygen</artifactId>
<version>${project.version}</version>
</dependency>
<!-- <dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-core</artifactId>
<version>${project.version}</version>
</dependency> -->
</dependencies>


</project>

+ 0
- 67
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartClientIncomingConfig.java View File

@@ -1,67 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.crypto.PubKey;

public class BftsmartClientIncomingConfig implements BftsmartClientIncomingSettings {

private BftsmartConsensusSettings consensusSettings;

private byte[] topology;

private byte[] tomConfig;

private int clientId;

private PubKey pubKey;


@Override
public BftsmartConsensusSettings getConsensusSettings() {
return consensusSettings;
}

public void setConsensusSettings(BftsmartConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
}

@Override
public byte[] getTopology() {
return topology;
}

public void setTopology(byte[] topology) {
this.topology = topology;
}

@Override
public int getClientId() {
return clientId;
}

@Override
public String getProviderName() {
return BftsmartConsensusProvider.NAME;
}

public void setClientId(int clientId) {
this.clientId = clientId;
}

@Override
public byte[] getTomConfig() {
return tomConfig;
}

public void setTomConfig(byte[] tomConfig) {
this.tomConfig = tomConfig;
}

@Override
public PubKey getPubKey() {
return pubKey;
}

public void setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
}
}

+ 0
- 22
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartClientIncomingSettings.java View File

@@ -1,22 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.PubKey;

@DataContract(code = DataCodes.CONSENSUS_BFTSMART_CLI_INCOMING_SETTINGS)
public interface BftsmartClientIncomingSettings extends ClientIncomingSettings {

@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
byte[] getTopology();

@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
byte[] getTomConfig();

@DataField(order = 3, primitiveType=PrimitiveType.BYTES)
PubKey getPubKey();

}

+ 0
- 35
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartCommitBlockConfig.java View File

@@ -1,35 +0,0 @@
//package com.jd.blockchain.consensus.bftsmart;
//
//public class BftsmartCommitBlockConfig implements BftsmartCommitBlockSettings {
//
// private int txSizePerBlock;
//
// private long maxDelayMilliSecondsPerBlock;
//
//
// public BftsmartCommitBlockConfig() {
//
// }
//
// public BftsmartCommitBlockConfig(int txSizePerBlock, long maxDelayMilliSecondsPerBlock) {
// this.txSizePerBlock = txSizePerBlock;
// this.maxDelayMilliSecondsPerBlock = maxDelayMilliSecondsPerBlock;
// }
// @Override
// public int getTxSizePerBlock() {
// return txSizePerBlock;
// }
//
// public void setTxSizePerBlock(int txSizePerBlock) {
// this.txSizePerBlock = txSizePerBlock;
// }
//
// @Override
// public long getMaxDelayMilliSecondsPerBlock() {
// return maxDelayMilliSecondsPerBlock;
// }
//
// public void setMaxDelayMilliSecondsPerBlock(long maxDelayMilliSecondsPerBlock) {
// this.maxDelayMilliSecondsPerBlock = maxDelayMilliSecondsPerBlock;
// }
//}

+ 0
- 17
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartCommitBlockSettings.java View File

@@ -1,17 +0,0 @@
//package com.jd.blockchain.consensus.bftsmart;
//
//import com.jd.blockchain.binaryproto.DataContract;
//import com.jd.blockchain.binaryproto.DataField;
//import com.jd.blockchain.binaryproto.PrimitiveType;
//import com.jd.blockchain.consts.DataCodes;
//
//
//@DataContract(code = DataCodes.CONSENSUS_BFTSMART_BLOCK_SETTINGS)
//public interface BftsmartCommitBlockSettings {
//
// @DataField(order = 0, primitiveType = PrimitiveType.INT32)
// int getTxSizePerBlock();
//
// @DataField(order = 1, primitiveType = PrimitiveType.INT64)
// long getMaxDelayMilliSecondsPerBlock();
//}

+ 0
- 54
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusConfig.java View File

@@ -1,54 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.utils.Property;

public class BftsmartConsensusConfig implements BftsmartConsensusSettings {

private Property[] bftsmartSystemConfig;

private BftsmartNodeSettings[] nodes;

// private BftsmartCommitBlockSettings commitBlockSettings;

static {
DataContractRegistry.register(BftsmartConsensusSettings.class);
}
/**
* 创建 bftsmart 共识配置;
*
* @param nodes
* 节点列表
* @param commitBlockSettings
* 结块设置;
* @param bftsmartSystemConfigs
* bftsmart系统配置;
*/
public BftsmartConsensusConfig(BftsmartNodeSettings[] nodes,
// BftsmartCommitBlockSettings commitBlockSettings,
Property[] bftsmartSystemConfigs) {
this.nodes = nodes;
// this.commitBlockSettings = commitBlockSettings;
this.bftsmartSystemConfig = bftsmartSystemConfigs;
}

@Override
public BftsmartNodeSettings[] getNodes() {
return nodes;
}

@Override
public Property[] getSystemConfigs() {
return bftsmartSystemConfig;
}

// @Override
// public BftsmartCommitBlockSettings getCommitBlockSettings() {
// return commitBlockSettings;
// }
//
//
// public void setCommitBlockSettings(BftsmartCommitBlockSettings commitBlockSettings) {
// this.commitBlockSettings = commitBlockSettings;
// }
}

+ 0
- 42
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusProvider.java View File

@@ -1,42 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.SettingsFactory;
import com.jd.blockchain.consensus.bftsmart.client.BftsmartConsensusClientFactory;
import com.jd.blockchain.consensus.bftsmart.service.BftsmartNodeServerFactory;
import com.jd.blockchain.consensus.client.ClientFactory;
import com.jd.blockchain.consensus.service.NodeServerFactory;

public class BftsmartConsensusProvider implements ConsensusProvider {

public static final String NAME = BftsmartConsensusProvider.class.getName();
private static BftsmartSettingsFactory settingsFactory = new BftsmartSettingsFactory();
private static BftsmartConsensusClientFactory clientFactory = new BftsmartConsensusClientFactory();

private static BftsmartNodeServerFactory nodeServerFactory = new BftsmartNodeServerFactory();


@Override
public String getName() {
return NAME;
}

@Override
public SettingsFactory getSettingsFactory() {
return settingsFactory;
}
@Override
public ClientFactory getClientFactory() {
return clientFactory;
}

@Override
public NodeServerFactory getServerFactory() {
return nodeServerFactory;
}


}

+ 0
- 20
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettings.java View File

@@ -1,20 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.Property;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

@DataContract(code = DataCodes.CONSENSUS_BFTSMART_SETTINGS)
public interface BftsmartConsensusSettings extends ConsensusSettings {

@DataField(order = 1, primitiveType = PrimitiveType.BYTES, list=true)
Property[] getSystemConfigs();

// @DataField(order = 2, refContract = true)
// BftsmartCommitBlockSettings getCommitBlockSettings();

}

+ 0
- 308
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java View File

@@ -1,308 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.ledger.ParticipantInfo;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.Property;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;

import org.springframework.core.io.ClassPathResource;

import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.ConsensusSettingsBuilder;
import com.jd.blockchain.crypto.PubKey;

public class BftsmartConsensusSettingsBuilder implements ConsensusSettingsBuilder {

private static final int DEFAULT_TXSIZE = 1000;

private static final int DEFAULT_MAXDELAY = 1000;

private static final String CONFIG_TEMPLATE_FILE = "bftsmart.config";

private static final String CONFIG_LEDGER_INIT = "ledger.init";

/**
* 参数键:节点数量;
*/
public static final String SERVER_NUM_KEY = "system.servers.num";

/**
* 参数键:结块条件设置;
*/
public static final String BFTSMART_BLOCK_TXSIZE_KEY = "system.block.txsize";

public static final String BFTSMART_BLOCK_MAXDELAY_KEY = "system.block.maxdelay";

// /**
// * 参数键格式:节点地址;
// */
// public static final String ADDRESS_PATTERN = "node.%s.address";

/**
* 参数键格式:节点公钥;
*/
public static final String PUBKEY_PATTERN = "system.server.%s.pubkey";

/**
* 参数键格式:节点共识服务的网络地址;
*/
public static final String CONSENSUS_HOST_PATTERN = "system.server.%s.network.host";

/**
* 参数键格式:节点共识服务的端口;
*/
public static final String CONSENSUS_PORT_PATTERN = "system.server.%s.network.port";

/**
* 参数键格式:节点共识服务的通讯是否开启安全选项;
*/
public static final String CONSENSUS_SECURE_PATTERN = "system.server.%s.network.secure";

public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider";



private static Properties CONFIG_TEMPLATE;
static {
ClassPathResource configResource = new ClassPathResource(CONFIG_TEMPLATE_FILE);
try {
try (InputStream in = configResource.getInputStream()) {
CONFIG_TEMPLATE = PropertiesUtils.load(in, BytesUtils.DEFAULT_CHARSET);
}
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}

//解析得到结块的相关配置信息
// public BftsmartCommitBlockConfig createBlockConfig(Properties resolvingProps) {
// BftsmartCommitBlockConfig blockConfig = new BftsmartCommitBlockConfig();
//
// String txSizeString = PropertiesUtils.getRequiredProperty(resolvingProps, BFTSMART_BLOCK_TXSIZE_KEY);
// resolvingProps.remove(BFTSMART_BLOCK_TXSIZE_KEY);
//
// if (txSizeString == null || txSizeString.length() == 0) {
// blockConfig.setTxSizePerBlock(DEFAULT_TXSIZE);
// }
// else {
// blockConfig.setTxSizePerBlock(Integer.parseInt(txSizeString));
// }
//
// String maxDelayString = PropertiesUtils.getRequiredProperty(resolvingProps, BFTSMART_BLOCK_MAXDELAY_KEY);
// resolvingProps.remove(BFTSMART_BLOCK_MAXDELAY_KEY);
//
// if (maxDelayString == null || maxDelayString.length() == 0) {
// blockConfig.setMaxDelayMilliSecondsPerBlock(DEFAULT_MAXDELAY);
// }
// else {
// blockConfig.setMaxDelayMilliSecondsPerBlock(Long.parseLong(maxDelayString));
// }
//
// return blockConfig;
// }

@Override
public Properties createPropertiesTemplate() {
return PropertiesUtils.cloneFrom(CONFIG_TEMPLATE);
}

@Override
public BftsmartConsensusSettings createSettings(Properties props, ParticipantNode[] participantNodes) {
Properties resolvingProps = PropertiesUtils.cloneFrom(props);
int serversNum = PropertiesUtils.getInt(resolvingProps, SERVER_NUM_KEY);
if (serversNum < 0) {
throw new IllegalArgumentException(String.format("Property[%s] is negative!", SERVER_NUM_KEY));
}
if (serversNum < 4) {
throw new IllegalArgumentException(String.format("Property[%s] is less than 4!", SERVER_NUM_KEY));
}
if (participantNodes == null) {
throw new IllegalArgumentException("ParticipantNodes is Empty !!!");
}
if (serversNum != participantNodes.length) {
throw new IllegalArgumentException(String.format("Property[%s] which is [%s] unequal " +
"ParticipantNodes's length which is [%s] !", SERVER_NUM_KEY, serversNum, participantNodes.length));
}

// BftsmartCommitBlockConfig blockConfig = createBlockConfig(resolvingProps);

BftsmartNodeSettings[] nodesSettings = new BftsmartNodeSettings[serversNum];
for (int i = 0; i < serversNum; i++) {
int id = i;

// String keyOfPubkey = keyOfNode(PUBKEY_PATTERN, id);
// String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey);
// PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey));
// PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey);
PubKey pubKey = participantNodes[i].getPubKey();
// resolvingProps.remove(keyOfPubkey);

String keyOfHost = keyOfNode(CONSENSUS_HOST_PATTERN, id);
String networkAddressHost = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfHost);
resolvingProps.remove(keyOfHost);

String keyOfPort = keyOfNode(CONSENSUS_PORT_PATTERN, id);
int networkAddressPort = PropertiesUtils.getInt(resolvingProps, keyOfPort);
resolvingProps.remove(keyOfPort);

String keyOfSecure = keyOfNode(CONSENSUS_SECURE_PATTERN, id);
boolean networkAddressSecure = PropertiesUtils.getBoolean(resolvingProps, keyOfSecure);
resolvingProps.remove(keyOfSecure);

BftsmartNodeConfig nodeConfig = new BftsmartNodeConfig(pubKey, id,
new NetworkAddress(networkAddressHost, networkAddressPort, networkAddressSecure));
nodesSettings[i] = nodeConfig;
}

BftsmartConsensusConfig config = new BftsmartConsensusConfig(nodesSettings,
// blockConfig,
PropertiesUtils.getOrderedValues(resolvingProps));
return config;
}

@Override
public Bytes updateSettings(Bytes oldConsensusSettings, ParticipantInfo participantInfo) {

//update consensus setting through node and system config two aspects
BftsmartConsensusSettings consensusSettings = (BftsmartConsensusSettings) ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(oldConsensusSettings.toBytes());

Property[] systemConfigs = systemConfigs(consensusSettings.getSystemConfigs());

BftsmartNodeSettings[] nodeSettings = nodeSettings(consensusSettings.getNodes(), participantInfo);

BftsmartConsensusConfig bftsmartConsensusConfig = new BftsmartConsensusConfig(nodeSettings, systemConfigs);

// for(int i = 0 ;i < bftsmartConsensusConfig.getNodes().length; i++) {
// System.out.printf("id = %d, host = %s, port = %d\r\n", bftsmartConsensusConfig.getNodes()[i].getId(), bftsmartConsensusConfig.getNodes()[i].getNetworkAddress().getHost(), bftsmartConsensusConfig.getNodes()[i].getNetworkAddress().getPort());
// }
//
// for(int i = 0 ;i < bftsmartConsensusConfig.getSystemConfigs().length; i++) {
// System.out.printf("property name = %s, property value = %s\r\n",bftsmartConsensusConfig.getSystemConfigs()[i].getName(), bftsmartConsensusConfig.getSystemConfigs()[i].getValue());
// }

return new Bytes(ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().encode(bftsmartConsensusConfig));

}

private static String keyOfNode(String pattern, int id) {
return String.format(pattern, id);
}

@Override
public void writeSettings(ConsensusSettings settings, Properties props) {
int serversNum = PropertiesUtils.getInt(props, SERVER_NUM_KEY);
if (serversNum > 0) {
for (int i = 0; i < serversNum; i++) {
int id = i;
// String keyOfPubkey = keyOfNode(PUBKEY_PATTERN, id);
// props.remove(keyOfPubkey);

String keyOfHost = keyOfNode(CONSENSUS_HOST_PATTERN, id);
props.remove(keyOfHost);

String keyOfPort = keyOfNode(CONSENSUS_PORT_PATTERN, id);
props.remove(keyOfPort);

String keyOfSecure = keyOfNode(CONSENSUS_SECURE_PATTERN, id);
props.remove(keyOfSecure);
}
}

BftsmartConsensusSettings bftsmartSettings = (BftsmartConsensusSettings) settings;
BftsmartNodeSettings[] nodesSettings = (BftsmartNodeSettings[]) bftsmartSettings.getNodes();
serversNum = nodesSettings.length;
props.setProperty(SERVER_NUM_KEY, serversNum + "");

//获得结块相关的属性信息
// BftsmartCommitBlockSettings blockSettings = bftsmartSettings.getCommitBlockSettings();
// if (blockSettings == null) {
// props.setProperty(BFTSMART_BLOCK_TXSIZE_KEY, DEFAULT_TXSIZE + "");
// props.setProperty(BFTSMART_BLOCK_MAXDELAY_KEY, DEFAULT_MAXDELAY + "");
// } else {
// int txSize = blockSettings.getTxSizePerBlock();
// long maxDelay = blockSettings.getMaxDelayMilliSecondsPerBlock();
// props.setProperty(BFTSMART_BLOCK_TXSIZE_KEY, txSize + "");
// props.setProperty(BFTSMART_BLOCK_MAXDELAY_KEY, maxDelay + "");
// }

for (int i = 0; i < serversNum; i++) {
BftsmartNodeSettings ns = nodesSettings[i];
int id = i;
// String keyOfPubkey = keyOfNode(PUBKEY_PATTERN, id);
// props.setProperty(keyOfPubkey, ns.getPubKey().toBase58());

String keyOfHost = keyOfNode(CONSENSUS_HOST_PATTERN, id);
props.setProperty(keyOfHost, ns.getNetworkAddress() == null ? "" : ns.getNetworkAddress().getHost());

String keyOfPort = keyOfNode(CONSENSUS_PORT_PATTERN, id);
props.setProperty(keyOfPort, ns.getNetworkAddress() == null ? "" : ns.getNetworkAddress().getPort() + "");

String keyOfSecure = keyOfNode(CONSENSUS_SECURE_PATTERN, id);
props.setProperty(keyOfSecure, ns.getNetworkAddress() == null ? "false" : ns.getNetworkAddress().isSecure() + "");
}
PropertiesUtils.setValues(props, bftsmartSettings.getSystemConfigs());
}

/**
*
* update system.servers.num property
*
*/
private Property[] systemConfigs(Property[] systemConfigs) {
Map<String, Property> propertyMap = convert2Map(systemConfigs);
int serverNum = Integer.parseInt(propertyMap.get("system.servers.num").getValue());
propertyMap.put("system.servers.num", new Property("system.servers.num", String.valueOf(serverNum + 1)));
return convert2Array(propertyMap);

}

private Map<String, Property> convert2Map(Property[] properties) {
Map<String, Property> propertyMap = new HashMap<>();
for (Property property : properties) {
propertyMap.put(property.getName(), property);
}
return propertyMap;
}

private Property[] convert2Array(Map<String, Property> map) {
Property[] properties = new Property[map.size()];
int index = 0;
for (Map.Entry<String, Property> entry : map.entrySet()) {
properties[index++] = entry.getValue();
}
return properties;
}

/**
*
* update node setting
*
*/
private BftsmartNodeSettings[] nodeSettings(NodeSettings[] nodeSettings, ParticipantInfo participantInfo) {

BftsmartNodeConfig bftsmartNodeConfig = new BftsmartNodeConfig(participantInfo.getPubKey(), nodeSettings.length, participantInfo.getNetworkAddress());

BftsmartNodeSettings[] bftsmartNodeSettings = new BftsmartNodeSettings[nodeSettings.length + 1];
for (int i = 0; i < nodeSettings.length; i++) {
bftsmartNodeSettings[i] = (BftsmartNodeSettings)nodeSettings[i];
}
bftsmartNodeSettings[nodeSettings.length] = bftsmartNodeConfig;
return bftsmartNodeSettings;
}


}

+ 0
- 66
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartNodeConfig.java View File

@@ -1,66 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.utils.net.NetworkAddress;

public class BftsmartNodeConfig implements BftsmartNodeSettings {

private int id;

private String address;

private PubKey pubKey;

private NetworkAddress networkAddress;
public BftsmartNodeConfig() {
}

static {
DataContractRegistry.register(BftsmartNodeSettings.class);
}

public BftsmartNodeConfig(PubKey pubKey, int id, NetworkAddress networkAddress) {
this.address = AddressEncoding.generateAddress(pubKey).toBase58();
this.pubKey = pubKey;
this.id = id;
this.networkAddress = networkAddress;
}

@Override
public String getAddress() {
return address;
}

@Override
public int getId() {
return id;
}

@Override
public NetworkAddress getNetworkAddress() {
return networkAddress;
}

public void setId(int id) {
this.id = id;
}

public void setAddress(String address) {
this.address = address;
}

public void setNetworkAddress(NetworkAddress networkAddress) {
this.networkAddress = networkAddress;
}

public PubKey getPubKey() {
return pubKey;
}

public void setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
}
}

+ 0
- 45
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartNodeSettings.java View File

@@ -1,45 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.utils.net.NetworkAddress;

@DataContract(code = DataCodes.CONSENSUS_BFTSMART_NODE_SETTINGS)
public interface BftsmartNodeSettings extends NodeSettings {

/**
* 节点所属的参与方的区块链地址;
*/
// @DataField(order = 0, primitiveType = ValueType.TEXT)
// @Override
// String getAddress();

/**
* Base58 格式的公钥;
*
* @return
*/
// @DataField(order = 1, primitiveType = ValueType.BYTES)
// PubKey getPubKey();

/**
* 节点的ID;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.INT32)
int getId();

/**
* 共识协议的网络地址;
*
* @return
*/
@DataField(order = 3, primitiveType = PrimitiveType.BYTES)
NetworkAddress getNetworkAddress();

}

+ 0
- 73
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartSettingsFactory.java View File

@@ -1,73 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.consensus.*;
import com.jd.blockchain.utils.io.BytesEncoder;

public class BftsmartSettingsFactory implements SettingsFactory {
private static ConsensusSettingsEncoder CS_ENCODER = new ConsensusSettingsEncoder();
private static ClientIncomingSettingsEncoder CI_ENCODER =new ClientIncomingSettingsEncoder();

static {
DataContractRegistry.register(BftsmartConsensusSettings.class);

DataContractRegistry.register(BftsmartClientIncomingSettings.class);
}

@Override
public BftsmartConsensusSettingsBuilder getConsensusSettingsBuilder() {

return new BftsmartConsensusSettingsBuilder();
}

@Override
public BytesEncoder<ConsensusSettings> getConsensusSettingsEncoder() {
return CS_ENCODER;
}

@Override
public BytesEncoder<ClientIncomingSettings> getIncomingSettingsEncoder() {
return CI_ENCODER;
}
private static class ConsensusSettingsEncoder implements BytesEncoder<ConsensusSettings>{

@Override
public byte[] encode(ConsensusSettings data) {
if (data instanceof BftsmartConsensusSettings) {
return BinaryProtocol.encode(data, BftsmartConsensusSettings.class);
}
throw new IllegalArgumentException("Settings data isn't supported! Accept BftsmartConsensusSettings only!");
}

@Override
public ConsensusSettings decode(byte[] bytes) {
return BinaryProtocol.decodeAs(bytes, BftsmartConsensusSettings.class);
}
}
private static class ClientIncomingSettingsEncoder implements BytesEncoder<ClientIncomingSettings>{

@Override
public byte[] encode(ClientIncomingSettings data) {
if (data instanceof BftsmartClientIncomingSettings) {
return BinaryProtocol.encode(data, BftsmartClientIncomingSettings.class);
}
throw new IllegalArgumentException("Settings data isn't supported! Accept BftsmartClientIncomingSettings only!");
}

@Override
public ClientIncomingSettings decode(byte[] bytes) {
return BinaryProtocol.decodeAs(bytes, BftsmartClientIncomingSettings.class);
}
}


}

+ 0
- 30
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartTopology.java View File

@@ -1,30 +0,0 @@
package com.jd.blockchain.consensus.bftsmart;

import bftsmart.reconfiguration.views.View;
import com.jd.blockchain.consensus.Topology;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

public class BftsmartTopology implements Topology {

private static final long serialVersionUID = -3042599438265726240L;

private View view;

public BftsmartTopology(View view){
this.view = view;
}

@Override
public int getId() {
return view.getId();
}

@Override
public Topology copyOf() {
return BinarySerializeUtils.copyOf(this);
}

public View getView() {
return view;
}
}

+ 0
- 16
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartTransactionType.java View File

@@ -1,16 +0,0 @@
//package com.jd.blockchain.consensus.bftsmart;
//
//public enum BftsmartTransactionType {
// TRANSACTION((int)0),
// COMMITBLOCK((int)1);
//
// public final int CODE;
//
// public int getCode() {
// return CODE;
// }
// private BftsmartTransactionType(int code) {
// this.CODE = code;
// }
//
//}

+ 0
- 79
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientConfig.java View File

@@ -1,79 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartClientIncomingSettings;
import com.jd.blockchain.crypto.PubKey;


public class BftsmartClientConfig implements BftsmartClientSettings {

private int clientId;
private PubKey clientPubkey;
private ConsensusSettings consensusSettings;
private byte[] topology;
private byte[] tomConfig;
BftsmartClientIncomingSettings clientIncomingSettings;

public BftsmartClientConfig(int clientId, PubKey clientPubkey, ConsensusSettings consensusSettings, byte[] topology, byte[] tomConfig) {
this.clientId = clientId;
this.clientPubkey = clientPubkey;
this.consensusSettings = consensusSettings;
this.topology = topology;
this.tomConfig = tomConfig;
}

public BftsmartClientConfig(BftsmartClientIncomingSettings clientIncomingSettings) {
this.clientIncomingSettings = clientIncomingSettings;
this.clientId = clientIncomingSettings.getClientId();
this.clientPubkey = clientIncomingSettings.getPubKey();
this.consensusSettings = clientIncomingSettings.getConsensusSettings();
this.topology = clientIncomingSettings.getTopology();
this.tomConfig = clientIncomingSettings.getTomConfig();

}
@Override
public int getClientId() {
return clientId;
}

public void setClientId(int clientId) {
this.clientId = clientId;
}


@Override
public PubKey getClientPubKey() {
return clientPubkey;
}

public void setClientPubkey(PubKey clientPubkey) {
this.clientPubkey = clientPubkey;
}

@Override
public ConsensusSettings getConsensusSettings() {
return consensusSettings;
}

public void setConsensusSettings(ConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
}

public byte[] getTopology() {
return topology;
}

public void setTopology(byte[] topology) {
this.topology = topology;
}

@Override
public byte[] getTomConfig() {
return tomConfig;
}

public void setTomConfig(byte[] tomConfig) {
this.tomConfig = tomConfig;
}
}


+ 0
- 56
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientIdentification.java View File

@@ -1,56 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import com.jd.blockchain.consensus.ClientIdentification;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;

public class BftsmartClientIdentification implements ClientIdentification {

private byte[] identityInfo;
private PubKey pubKey;
private SignatureDigest signatureDigest;

public BftsmartClientIdentification() {

}

public BftsmartClientIdentification(ClientIdentification clientIdentification) {
identityInfo = clientIdentification.getIdentityInfo();
pubKey = clientIdentification.getPubKey();
signatureDigest = clientIdentification.getSignature();
}

@Override
public byte[] getIdentityInfo() {
return identityInfo;
}

public void setIdentityInfo(byte[] identityInfo) {
this.identityInfo = identityInfo;
}

@Override
public PubKey getPubKey() {
return pubKey;
}

public void setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
}

@Override
public SignatureDigest getSignature() {
return signatureDigest;
}

@Override
public String getProviderName() {
return BftsmartConsensusProvider.NAME;
}

public void setSignatureDigest(SignatureDigest signatureDigest) {
this.signatureDigest = signatureDigest;
}

}

+ 0
- 12
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartClientSettings.java View File

@@ -1,12 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import com.jd.blockchain.consensus.client.ClientSettings;


public interface BftsmartClientSettings extends ClientSettings {

byte[] getTopology();

byte[] getTomConfig();

}

+ 0
- 129
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java View File

@@ -1,129 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import com.jd.blockchain.consensus.MessageService;
import com.jd.blockchain.consensus.client.ClientSettings;
import com.jd.blockchain.consensus.client.ConsensusClient;
import java.util.concurrent.atomic.AtomicInteger;

public class BftsmartConsensusClient implements ConsensusClient {


private final AtomicInteger addId = new AtomicInteger();

private BftsmartPeerProxyPool asyncPeerProxyPool;

private int gatewayId;

private ClientSettings clientSettings;

public BftsmartConsensusClient(ClientSettings clientSettings) {

this.clientSettings = clientSettings;
this.gatewayId = clientSettings.getClientId();
}


public BftsmartPeerProxyPool getConsensusClientPool() {
return this.asyncPeerProxyPool;
}

@Override
public MessageService getMessageService() {
return new BftsmartMessageService(asyncPeerProxyPool);
}

@Override
public ClientSettings getSettings() {
return clientSettings;
}

@Override
public boolean isConnected() {
return this.asyncPeerProxyPool != null;
}

@Override
public synchronized void connect() {

//consensus client pool
BftsmartPeerProxyFactory peerProxyFactory = new BftsmartPeerProxyFactory((BftsmartClientSettings)clientSettings, gatewayId);
this.asyncPeerProxyPool = new BftsmartPeerProxyPool(peerProxyFactory);

// MemoryBasedViewStorage viewStorage = new MemoryBasedViewStorage(((BftsmartClientSettings)clientSettings).getTopology().getView());
// TOMConfiguration tomConfiguration = ((BftsmartConsensusConfig)clientSettings.getConsensusSettings()).getBftsmartConfig();
//
// //by serialize keep origin tom config
// byte[] tomBytes = BinarySerializeUtils.serialize(tomConfiguration);
// TOMConfiguration decodeTom = BinarySerializeUtils.deserialize(tomBytes);
//
// int clientId = gatewayId *100 + addId.incrementAndGet();
//
// //every proxy client has unique id;
// decodeTom.setProcessId(clientId);
// this.peerProxy = new AsynchServiceProxy(decodeTom, viewStorage);

}

@Override
public void close() {
if (asyncPeerProxyPool != null) {
asyncPeerProxyPool.close();
}
}

// public void asyncSendOrdered(byte[] message, AsyncCallback<byte[]> callback) {
// AsyncReplier replier = new AsyncReplier(callback, peerProxy);
// peerProxy.invokeAsynchRequest(message, replier, TOMMessageType.ORDERED_REQUEST);
// }

// private static class AsyncReplier implements ReplyListener {
//
// private AsynchServiceProxy peerProxy;
//
// private AtomicInteger replies = new AtomicInteger(0);
//
// private AsyncCallback<byte[]> messageHandle;
//
// public AsyncReplier(AsyncCallback<byte[]> messageHandle, AsynchServiceProxy peerProxy) {
// this.messageHandle = messageHandle;
// this.peerProxy = peerProxy;
// }
//
// @Override
// public void reset() {
// replies.set(0);
// }
//
// @Override
// public void replyReceived(RequestContext context, TOMMessage reply) {
// int replyCount = replies.incrementAndGet();
//
// double q = Math.ceil((double) (peerProxy.getViewManager().getCurrentViewN()
// + peerProxy.getViewManager().getCurrentViewF() + 1) / 2.0);
//
// if (replyCount >= q) {
// peerProxy.cleanAsynchRequest(context.getOperationId());
// messageHandle.complete(reply.getContent(), null);
// }
// }
//
// }

// private static class BftsmartAsyncFuture<T> extends CompletableAsyncFuture<T> {
// @Override
// public void setSuccess(T value) {
// super.setSuccess(value);
// }
//
// @Override
// public void setError(Throwable ex) {
// super.setError(ex);
// }
//
// @Override
// public void setError(String errorCode) {
// super.setError(errorCode);
// }
// }

}

+ 0
- 133
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClientFactory.java View File

@@ -1,133 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.bftsmart.BftsmartClientIncomingSettings;
import com.jd.blockchain.consensus.client.ClientFactory;
import com.jd.blockchain.consensus.client.ClientSettings;
import com.jd.blockchain.consensus.client.ConsensusClient;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.utils.net.NetworkAddress;

public class BftsmartConsensusClientFactory implements ClientFactory {


private AtomicInteger addId = new AtomicInteger();

private String localDomain = "localhost";
private String localIp = "127.0.0.1";

public BftsmartConsensusClientFactory() {

}


@Override
public BftsmartClientIdentification buildAuthId(AsymmetricKeypair clientKeyPair) {

PubKey pubKey = clientKeyPair.getPubKey();
PrivKey privKey = clientKeyPair.getPrivKey();

SignatureFunction signatureFunction =Crypto.getSignatureFunction(pubKey.getAlgorithm());
SignatureDigest signatureDigest = signatureFunction.sign(privKey, pubKey.toBytes());

BftsmartClientIdentification bftsmartClientIdentification = new BftsmartClientIdentification();
bftsmartClientIdentification.setIdentityInfo(pubKey.toBytes());
bftsmartClientIdentification.setPubKey(pubKey);
bftsmartClientIdentification.setSignatureDigest(signatureDigest);

return bftsmartClientIdentification;
}

@Override
public ClientSettings buildClientSettings(ClientIncomingSettings incomingSettings) {

BftsmartClientIncomingSettings clientIncomingSettings = (BftsmartClientIncomingSettings) incomingSettings;

BftsmartClientSettings clientSettings = new BftsmartClientConfig(clientIncomingSettings);

return clientSettings;
}

@Override
public ConsensusClient setupClient(ClientSettings settings) {

return new BftsmartConsensusClient(settings);
}

@Override
public ConsensusManageService createManageServiceClient(String[] serviceNodes) {
// BftsmartConsensusManageService consensusManageService = null;
// BftsmartClientIncomingSettings clientIncomingSettings;
//
//
// try {
// if (serviceNodes == null) {
// throw new ConsensusSecurityException("createManageServiceClient param error!");
// }
//
// for (int i = 0; i < serviceNodes.length; i++) {
//
// NetworkAddress networkAddress = getIpPortFromUrl(serviceNodes[i]);
// if (networkAddress == null) {
// continue;
// }
// ServiceEndpoint peerServer = new ServiceEndpoint(networkAddress.getHost(), networkAddress.getPort(), false);
// consensusManageService = HttpServiceAgent.createService(BftsmartConsensusManageService.class, peerServer);
// clientIncomingSettings = consensusManageService.authClientIncoming(clientIdentification);
//
// if (clientIncomingSettings == null) {
// consensusManageService = null;
// } else {
// //认证成功
// break;
// }
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// }

// return consensusManageService;
return null;
}

private NetworkAddress getIpPortFromUrl(String url) {

// 1.check null
if (url == null || url.trim().equals("")) {
return null;
}

// 2. localhost replace to 127.0.0.1
if(url.startsWith("http://" + localDomain) ){
url = url.replace("http://" + localDomain, "http://" + localIp) ;
}

String host = "";
Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+(:\\d{0,5})?");
Matcher matcher = p.matcher(url);
if (matcher.find()) {
host = matcher.group() ;
}

if(host.contains(":") == false){
//default port :80
return new NetworkAddress(host, 80);
}
else {
String[] ipPortArr = host.split(":");
return new NetworkAddress(ipPortArr[0], Integer.parseInt(ipPortArr[1]));
}
}

}

+ 0
- 73
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java View File

@@ -1,73 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import bftsmart.tom.AsynchServiceProxy;
import com.jd.blockchain.consensus.MessageService;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture;
import com.jd.blockchain.utils.io.BytesUtils;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BftsmartMessageService implements MessageService {

private BftsmartPeerProxyPool asyncPeerProxyPool;

public BftsmartMessageService(BftsmartPeerProxyPool peerProxyPool) {
this.asyncPeerProxyPool = peerProxyPool;
}

@Override
public AsyncFuture<byte[]> sendOrdered(byte[] message) {
return sendOrderedMessage(message);
}

private AsyncFuture<byte[]> sendOrderedMessage(byte[] message) {
CompletableAsyncFuture<byte[]> asyncFuture = new CompletableAsyncFuture<>();
AsynchServiceProxy asynchServiceProxy = null;
try {
asynchServiceProxy = asyncPeerProxyPool.borrowObject();
// //0: Transaction msg, 1: Commitblock msg
// byte[] msgType = BytesUtils.toBytes(0);
// byte[] wrapMsg = new byte[message.length + 4];
// System.arraycopy(message, 0, wrapMsg, 4, message.length);
// System.arraycopy(msgType, 0, wrapMsg, 0, 4);
//
// System.out.printf("BftsmartMessageService invokeOrdered time = %s, id = %s threadId = %s \r\n",
// System.currentTimeMillis(), asynchServiceProxy.getProcessId(), Thread.currentThread().getId());

byte[] result = asynchServiceProxy.invokeOrdered(message);
asyncFuture.complete(result);

} catch (Exception e) {
throw new RuntimeException(e);

} finally {
asyncPeerProxyPool.returnObject(asynchServiceProxy);
}

return asyncFuture;
}

@Override
public AsyncFuture<byte[]> sendUnordered(byte[] message) {
return sendUnorderedMessage(message);
}

private AsyncFuture<byte[]> sendUnorderedMessage(byte[] message) {
CompletableAsyncFuture<byte[]> asyncFuture = new CompletableAsyncFuture<>();
AsynchServiceProxy asynchServiceProxy = null;
try {
asynchServiceProxy = asyncPeerProxyPool.borrowObject();
byte[] result = asynchServiceProxy.invokeUnordered(message);
asyncFuture.complete(result);

} catch (Exception e) {
throw new RuntimeException(e);
} finally {
asyncPeerProxyPool.returnObject(asynchServiceProxy);
}
return asyncFuture;
}

}

+ 0
- 47
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyFactory.java View File

@@ -1,47 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.client;

import bftsmart.reconfiguration.util.TOMConfiguration;
import bftsmart.reconfiguration.views.MemoryBasedViewStorage;
import bftsmart.tom.AsynchServiceProxy;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusConfig;
import com.jd.blockchain.consensus.bftsmart.BftsmartTopology;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

import java.util.concurrent.atomic.AtomicInteger;

public class BftsmartPeerProxyFactory extends BasePooledObjectFactory<AsynchServiceProxy> {

private BftsmartClientSettings bftsmartClientSettings;

private int gatewayId;

private AtomicInteger index = new AtomicInteger(1);

public BftsmartPeerProxyFactory(BftsmartClientSettings bftsmartClientSettings, int gatewayId) {
this.bftsmartClientSettings = bftsmartClientSettings;
this.gatewayId = gatewayId;
}

@Override
public AsynchServiceProxy create() throws Exception {

BftsmartTopology topology = BinarySerializeUtils.deserialize(bftsmartClientSettings.getTopology());

MemoryBasedViewStorage viewStorage = new MemoryBasedViewStorage(topology.getView());
TOMConfiguration tomConfiguration = BinarySerializeUtils.deserialize(bftsmartClientSettings.getTomConfig());

//every proxy client has unique id;
tomConfiguration.setProcessId(gatewayId + index.getAndIncrement());
AsynchServiceProxy peerProxy = new AsynchServiceProxy(tomConfiguration, viewStorage);
return peerProxy;
}

@Override
public PooledObject<AsynchServiceProxy> wrap(AsynchServiceProxy asynchServiceProxy) {
return new DefaultPooledObject<>(asynchServiceProxy);
}
}

+ 0
- 25
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyPool.java View File

@@ -1,25 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.bft.BftsmartConsensusClientPool
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/10/30 下午6:50
* Description:
*/
package com.jd.blockchain.consensus.bftsmart.client;

import bftsmart.tom.AsynchServiceProxy;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class BftsmartPeerProxyPool extends GenericObjectPool<AsynchServiceProxy> {

public BftsmartPeerProxyPool(PooledObjectFactory<AsynchServiceProxy> factory) {
this(factory, null);
}

public BftsmartPeerProxyPool(PooledObjectFactory<AsynchServiceProxy> factory, GenericObjectPoolConfig config) {
super(factory, config == null ? new BftsmartPeerProxyPoolConfig() : config);
}
}

+ 0
- 32
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartPeerProxyPoolConfig.java View File

@@ -1,32 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.bft.BftsmartConsensusClientPool
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/10/30 下午6:50
* Description:
*/
package com.jd.blockchain.consensus.bftsmart.client;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class BftsmartPeerProxyPoolConfig extends GenericObjectPoolConfig {

public static final int MAX_TOTAL = 100;

private final int MIN_IDLE = 0;

private final int MAX_IDLE = 100;

public BftsmartPeerProxyPoolConfig() {
setMaxTotal(MAX_TOTAL);
setMinIdle(MIN_IDLE);
setMaxIdle(MAX_IDLE);
}

public BftsmartPeerProxyPoolConfig(int maxTotal, int minIdle, int maxIdle) {
setMaxTotal(maxTotal);
setMinIdle(minIdle);
setMaxIdle(maxIdle);
}
}

+ 0
- 71
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartConsensusManageService.java View File

@@ -1,71 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.service;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.jd.blockchain.consensus.ClientIdentification;
import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.bftsmart.BftsmartClientIncomingConfig;
import com.jd.blockchain.consensus.bftsmart.BftsmartClientIncomingSettings;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;

public class BftsmartConsensusManageService implements ConsensusManageService {

public static final int GATEWAY_SIZE = 100;

public static final int CLIENT_SIZE_PER_GATEWAY = 1000;

public static final int CLIENT_RANGE = GATEWAY_SIZE * CLIENT_SIZE_PER_GATEWAY;

private BftsmartNodeServer nodeServer;

private int clientId;

private static final Lock authLock = new ReentrantLock();

public BftsmartConsensusManageService(BftsmartNodeServer nodeServer) {
this.nodeServer = nodeServer;
// Assume that each peer node corresponds to up to 100 gateways
clientId = nodeServer.getServerId() * CLIENT_RANGE;
}

@Override
public BftsmartClientIncomingSettings authClientIncoming(ClientIdentification authId) {
if (verify(authId)) {
BftsmartClientIncomingConfig clientIncomingSettings = new BftsmartClientIncomingConfig();

clientIncomingSettings
.setTopology(BinarySerializeUtils.serialize(nodeServer.getTopology()));

clientIncomingSettings
.setTomConfig(BinarySerializeUtils.serialize(nodeServer.getTomConfig()));

clientIncomingSettings
.setConsensusSettings(nodeServer.getConsensusSetting());

clientIncomingSettings.setPubKey(authId.getPubKey());
// compute gateway id
authLock.lock();
try {
clientIncomingSettings.setClientId(clientId++);
clientId += CLIENT_SIZE_PER_GATEWAY;
} finally {
authLock.unlock();
}

return clientIncomingSettings;
}

return null;
}

public boolean verify(ClientIdentification authId) {

SignatureFunction signatureFunction = Crypto
.getSignatureFunction(authId.getPubKey().getAlgorithm());

return signatureFunction.verify(authId.getSignature(), authId.getPubKey(), authId.getIdentityInfo());
}
}

+ 0
- 549
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java View File

@@ -1,549 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.service;

import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import bftsmart.consensus.app.BatchAppResultImpl;
import bftsmart.tom.*;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.consensus.service.*;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.transaction.TxResponseMessage;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartTopology;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.jd.blockchain.utils.io.BytesUtils;
import bftsmart.reconfiguration.util.HostsConfig;
import bftsmart.reconfiguration.util.TOMConfiguration;
import bftsmart.tom.server.defaultservices.DefaultRecoverable;

public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer {

private static Logger LOGGER = LoggerFactory.getLogger(BftsmartNodeServer.class);

private static final String DEFAULT_BINDING_HOST = "0.0.0.0";

private List<StateHandle> stateHandles = new CopyOnWriteArrayList<>();

// TODO 暂不处理队列溢出问题
private ExecutorService notifyReplyExecutors = Executors.newSingleThreadExecutor();

private volatile Status status = Status.STOPPED;

private final Object mutex = new Object();

private volatile ServiceReplica replica;

private StateMachineReplicate stateMachineReplicate;

private ServerSettings serverSettings;

private BftsmartConsensusManageService manageService;


private volatile BftsmartTopology topology;

private volatile BftsmartConsensusSettings setting;

private TOMConfiguration tomConfig;

private TOMConfiguration outerTomConfig;

private HostsConfig hostsConfig;
private Properties systemConfig;

private MessageHandle messageHandle;

private String providerName;

private String realmName;

private int serverId;

public BftsmartNodeServer() {

}

public BftsmartNodeServer(ServerSettings serverSettings, MessageHandle messageHandler, StateMachineReplicate stateMachineReplicate) {
this.serverSettings = serverSettings;
this.realmName = serverSettings.getRealmName();
//used later
this.stateMachineReplicate = stateMachineReplicate;
this.messageHandle = messageHandler;
createConfig();
serverId = findServerId();
initConfig(serverId, systemConfig, hostsConfig);
this.manageService = new BftsmartConsensusManageService(this);
}

protected int findServerId() {
int serverId = 0;

for (int i = 0; i < hostsConfig.getNum(); i++) {
String host = ((BftsmartNodeSettings)serverSettings.getReplicaSettings()).getNetworkAddress().getHost();
int port = ((BftsmartNodeSettings)serverSettings.getReplicaSettings()).getNetworkAddress().getPort();

if (hostsConfig.getHost(i).equals(host) && hostsConfig.getPort(i) == port) {
serverId = i;
break;
}
}

return serverId;
}

public int getServerId() {
return serverId;
}

protected void createConfig() {

setting = ((BftsmartServerSettings) serverSettings).getConsensusSettings();

List<HostsConfig.Config> configList = new ArrayList<>();

NodeSettings[] nodeSettingsArray = setting.getNodes();
for (NodeSettings nodeSettings : nodeSettingsArray) {
BftsmartNodeSettings node = (BftsmartNodeSettings)nodeSettings;
configList.add(new HostsConfig.Config(node.getId(), node.getNetworkAddress().getHost(), node.getNetworkAddress().getPort()));
}

//create HostsConfig instance based on consensus realm nodes
hostsConfig = new HostsConfig(configList.toArray(new HostsConfig.Config[configList.size()]));

systemConfig = PropertiesUtils.createProperties(setting.getSystemConfigs());

return;
}

protected void initConfig(int id, Properties systemsConfig, HostsConfig hostConfig) {
byte[] serialHostConf = BinarySerializeUtils.serialize(hostConfig);
Properties sysConfClone = (Properties)systemsConfig.clone();
int port = hostConfig.getPort(id);
hostConfig.add(id, DEFAULT_BINDING_HOST, port);
this.tomConfig = new TOMConfiguration(id, systemsConfig, hostConfig);
this.outerTomConfig = new TOMConfiguration(id, sysConfClone, BinarySerializeUtils.deserialize(serialHostConf));
}

@Override
public ConsensusManageService getManageService() {
return manageService;
}

@Override
public ServerSettings getSettings() {
return serverSettings;
}

@Override
public String getProviderName() {
return BftsmartConsensusProvider.NAME;
}

public TOMConfiguration getTomConfig() {
return outerTomConfig;
}

public int getId() {
return tomConfig.getProcessId();
}

public void setId(int id) {
if (id < 0) {
throw new IllegalArgumentException("ReplicaID is negative!");
}
this.tomConfig.setProcessId(id);
this.outerTomConfig.setProcessId(id);
}

public BftsmartConsensusSettings getConsensusSetting() {
return setting;
}

public BftsmartTopology getTopology() {
return topology;
}

public Status getStatus() {
return status;
}

@Override
public boolean isRunning() {
return status == Status.RUNNING;
}

public byte[] appExecuteUnordered(byte[] bytes, MessageContext messageContext) {
return messageHandle.processUnordered(bytes).get();
}

/**
*
* Only block, no reply, used by state transfer when peer start
*
*/
private void block(List<byte[]> manageConsensusCmds) {

String batchId = messageHandle.beginBatch(realmName);
try {
int msgId = 0;
for (byte[] txContent : manageConsensusCmds) {
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId);
}
messageHandle.completeBatch(realmName, batchId);
messageHandle.commitBatch(realmName, batchId);
} catch (Exception e) {
// todo 需要处理应答码 404
LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e);
messageHandle.rollbackBatch(realmName, batchId, TransactionState.CONSENSUS_ERROR.CODE);
}

}

/**
*
* Local peer has cid diff with remote peer, used by state transfer when peer start
*
*/
private byte[][] appExecuteDiffBatch(byte[][] commands, MessageContext[] msgCtxs) {

int manageConsensusId = msgCtxs[0].getConsensusId();
List<byte[]> manageConsensusCmds = new ArrayList<>();

int index = 0;
for (MessageContext msgCtx : msgCtxs) {
if (msgCtx.getConsensusId() == manageConsensusId) {
manageConsensusCmds.add(commands[index]);
} else {
// 达到结块标准,需要进行结块并应答
block(manageConsensusCmds);
// 重置链表和共识ID
manageConsensusCmds = new ArrayList<>();
manageConsensusId = msgCtx.getConsensusId();
manageConsensusCmds.add(commands[index]);
}
index++;
}
// 结束时,肯定有最后一个结块请求未处理
if (!manageConsensusCmds.isEmpty()) {
block(manageConsensusCmds);
}
return null;

}

/**
*
* Invoked by state transfer when peer start
*
*/
@Override
public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus) {

// Not from consensus outcomes, from state transfer
if (!fromConsensus) {
return appExecuteDiffBatch(commands, msgCtxs);
}

return null;
}

/**
*
* From consensus outcomes, do nothing now
* The operation of executing the batch was moved to the consensus stage 2 and 3, in order to guaranteed ledger consistency
*/
@Override
public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs, boolean fromConsensus, List<ReplyContextMessage> replyList) {

// if (replyList == null || replyList.size() == 0) {
// throw new IllegalArgumentException();
// }
// // todo 此部分需要重新改造
// /**
// * 默认BFTSmart接口提供的commands是一个或多个共识结果的顺序集合
// * 根据共识的规定,目前的做法是将其根据msgCtxs的内容进行分组,每组都作为一个结块标识来处理
// * 从msgCtxs可以获取对应commands的分组情况
// */
// int manageConsensusId = msgCtxs[0].getConsensusId();
// List<byte[]> manageConsensusCmds = new ArrayList<>();
// List<ReplyContextMessage> manageReplyMsgs = new ArrayList<>();
//
// int index = 0;
// for (MessageContext msgCtx : msgCtxs) {
// if (msgCtx.getConsensusId() == manageConsensusId) {
// manageConsensusCmds.add(commands[index]);
// manageReplyMsgs.add(replyList.get(index));
// } else {
// // 达到结块标准,需要进行结块并应答
// blockAndReply(manageConsensusCmds, manageReplyMsgs);
// // 重置链表和共识ID
// manageConsensusCmds = new ArrayList<>();
// manageReplyMsgs = new ArrayList<>();
// manageConsensusId = msgCtx.getConsensusId();
// manageConsensusCmds.add(commands[index]);
// manageReplyMsgs.add(replyList.get(index));
// }
// index++;
// }
// // 结束时,肯定有最后一个结块请求未处理
// if (!manageConsensusCmds.isEmpty()) {
// blockAndReply(manageConsensusCmds, manageReplyMsgs);
// }
return null;
}

/**
*
* Block and reply are moved to consensus completion stage
*
*/
private void blockAndReply(List<byte[]> manageConsensusCmds, List<ReplyContextMessage> replyList) {
// consensusBatchId = messageHandle.beginBatch(realmName);
// List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(manageConsensusCmds.size());
// try {
// int msgId = 0;
// for (byte[] txContent : manageConsensusCmds) {
// AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, consensusBatchId);
// asyncFutureLinkedList.add(asyncFuture);
// }
// messageHandle.completeBatch(realmName, consensusBatchId);
// messageHandle.commitBatch(realmName, consensusBatchId);
// } catch (Exception e) {
// // todo 需要处理应答码 404
// LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e);
// messageHandle.rollbackBatch(realmName, consensusBatchId, TransactionState.CONSENSUS_ERROR.CODE);
// }
//
// // 通知线程单独处理应答
// notifyReplyExecutors.execute(() -> {
// // 应答对应的结果
// int replyIndex = 0;
// for(ReplyContextMessage msg : replyList) {
// msg.setReply(asyncFutureLinkedList.get(replyIndex).get());
// TOMMessage request = msg.getTomMessage();
// ReplyContext replyContext = msg.getReplyContext();
// request.reply = new TOMMessage(replyContext.getId(), request.getSession(), request.getSequence(),
// request.getOperationId(), msg.getReply(), replyContext.getCurrentViewId(),
// request.getReqType());
//
// if (replyContext.getNumRepliers() > 0) {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId() + " via ReplyManager");
// replyContext.getRepMan().send(request);
// } else {
// bftsmart.tom.util.Logger.println("(ServiceReplica.receiveMessages) sending reply to "
// + request.getSender() + " with sequence number " + request.getSequence()
// + " and operation ID " + request.getOperationId());
// replyContext.getReplier().manageReply(request, msg.getMessageContext());
// }
// replyIndex++;
// }
// });
}

/**
* Used by consensus write phase, pre compute new block hash
*/
public BatchAppResultImpl preComputeAppHash(byte[][] commands) {

List<AsyncFuture<byte[]>> asyncFutureLinkedList = new ArrayList<>(commands.length);
List<byte[]> responseLinkedList = new ArrayList<>();
StateSnapshot newStateSnapshot = null;
StateSnapshot preStateSnapshot = null;
StateSnapshot genisStateSnapshot = null;
BatchAppResultImpl result = null;
String batchId = null;
int msgId = 0;

try {

batchId = messageHandle.beginBatch(realmName);
genisStateSnapshot = messageHandle.getGenisStateSnapshot(realmName);
preStateSnapshot = messageHandle.getStateSnapshot(realmName);

if (preStateSnapshot == null) {
throw new IllegalStateException("Pre block state snapshot is null!");
}

for (int i = 0; i < commands.length; i++) {
byte[] txContent = commands[i];
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId);
asyncFutureLinkedList.add(asyncFuture);
}
newStateSnapshot = messageHandle.completeBatch(realmName, batchId);

for (int i = 0; i < asyncFutureLinkedList.size(); i++) {
responseLinkedList.add(asyncFutureLinkedList.get(i).get());
}

result = new BatchAppResultImpl(responseLinkedList, newStateSnapshot.getSnapshot(), batchId, genisStateSnapshot.getSnapshot());
result.setErrorCode((byte) 0);

} catch (Exception e) {
LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e);
for (int i = 0; i < commands.length; i++) {
responseLinkedList.add(createAppResponse(commands[i],TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK));
}

result = new BatchAppResultImpl(responseLinkedList,preStateSnapshot.getSnapshot(), batchId, genisStateSnapshot.getSnapshot());
result.setErrorCode((byte) 1);
}

return result;
}

// Block full rollback responses, generated in pre compute phase, due to tx exception
private byte[] createAppResponse(byte[] command, TransactionState transactionState) {
TransactionRequest txRequest = BinaryProtocol.decode(command);

TxResponseMessage resp = new TxResponseMessage(txRequest.getTransactionContent().getHash());

resp.setExecutionState(transactionState);

return BinaryProtocol.encode(resp, TransactionResponse.class);
}

public List<byte[]> updateAppResponses(List<byte[]> asyncResponseLinkedList, byte[] commonHash, boolean isConsistent) {
List<byte[]> updatedResponses = new ArrayList<>();
TxResponseMessage resp = null;

for(int i = 0; i < asyncResponseLinkedList.size(); i++) {
TransactionResponse txResponse = BinaryProtocol.decode(asyncResponseLinkedList.get(i));
if (isConsistent) {
resp = new TxResponseMessage(txResponse.getContentHash());
}
else {
resp = new TxResponseMessage(new HashDigest(commonHash));
}
resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK);
updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class));
}
return updatedResponses;
}
/**
*
* Decision has been made at the consensus stage, commit block
*
*/
public void preComputeAppCommit(String batchId) {
try {
messageHandle.commitBatch(realmName, batchId);
} catch (BlockRollbackException e) {
LOGGER.error("Error occurred while pre compute commit --" + e.getMessage(), e);
throw e;
}
}

/**
*
* Consensus write phase will terminate, new block hash values are inconsistent, rollback block
*
*/
public void preComputeAppRollback(String batchId) {
messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE);
LOGGER.debug("Rollback of operations that cause inconsistencies in the ledger");
}

//notice
public byte[] getSnapshot() {
LOGGER.debug("------- GetSnapshot...[replica.id=" + this.getId() + "]");

ByteArrayOutputStream out = new ByteArrayOutputStream();
BytesUtils.writeInt(stateHandles.size(), out);
for (StateHandle stateHandle : stateHandles) {
// TODO: 测试代码;
return stateHandle.takeSnapshot();
}
return out.toByteArray();
}

public void installSnapshot(byte[] snapshot) {
// System.out.println("Not implement!");
}

@Override
public void start() {
if (this.getId() < 0) {
throw new IllegalStateException("Unset server node ID!");
}
LOGGER.debug("=============================== Start replica ===================================");

if (status != Status.STOPPED) {
return;
}
synchronized (mutex) {
if (status != Status.STOPPED) {
return;
}
status = Status.STARTING;

try {
LOGGER.debug("Start replica...[ID=" + getId() + "]");
this.replica = new ServiceReplica(tomConfig, this, this);
this.topology = new BftsmartTopology(replica.getReplicaContext().getCurrentView());
status = Status.RUNNING;
// createProxyClient();
LOGGER.debug(
"=============================== Replica started success! ===================================");
} catch (RuntimeException e) {
status = Status.STOPPED;
throw e;
}
}

}

@Override
public void stop() {
if (status != Status.RUNNING) {
return;
}
synchronized (mutex) {
if (status != Status.RUNNING) {
return;
}
status = Status.STOPPING;

try {
ServiceReplica rep = this.replica;
if (rep != null) {
LOGGER.debug("Stop replica...[ID=" + rep.getId() + "]");
this.replica = null;
this.topology = null;

rep.kill();
LOGGER.debug("Replica had stopped! --[ID=" + rep.getId() + "]");
}
} finally {
status = Status.STOPPED;
}
}
}

enum Status {

STARTING,

RUNNING,

STOPPING,

STOPPED

}

}

+ 0
- 110
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServerFactory.java View File

@@ -1,110 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.service;

import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings;
import com.jd.blockchain.consensus.service.MessageHandle;
import com.jd.blockchain.consensus.service.NodeServer;
import com.jd.blockchain.consensus.service.NodeServerFactory;
import com.jd.blockchain.consensus.service.ServerSettings;
import com.jd.blockchain.consensus.service.StateMachineReplicate;
import com.jd.blockchain.utils.net.NetworkAddress;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BftsmartNodeServerFactory implements NodeServerFactory {

private static Map<String, NodeSettings[]> nodeServerMap = new ConcurrentHashMap<>();


@Override
public ServerSettings buildServerSettings(String realmName, ConsensusSettings consensusSetting, String currentNodeAddress) {

NodeSettings serverNode = null;

BftsmartServerSettingConfig serverSettings = new BftsmartServerSettingConfig();

//find current node according to current address
for (NodeSettings nodeSettings : consensusSetting.getNodes()) {
if (nodeSettings.getAddress().equals(currentNodeAddress)) {
serverNode = nodeSettings;
break;
}
}

if (serverNode == null) {
throw new IllegalArgumentException();
}

//set server settings
serverSettings.setRealmName(realmName);

serverSettings.setReplicaSettings(serverNode);

serverSettings.setConsensusSettings((BftsmartConsensusSettings) consensusSetting);

return serverSettings;

}

@Override
public NodeServer setupServer(ServerSettings serverSettings, MessageHandle messageHandler,
StateMachineReplicate stateMachineReplicator) {

NodeSettings[] currNodeSettings = (((BftsmartServerSettings)serverSettings).getConsensusSettings()).getNodes();

//check conflict realm
if (!hasIntersection(currNodeSettings)) {
BftsmartNodeServer nodeServer = new BftsmartNodeServer(serverSettings, messageHandler, stateMachineReplicator);
nodeServerMap.put(serverSettings.getRealmName(), currNodeSettings);
return nodeServer;
}
else {
throw new IllegalArgumentException("setupServer serverSettings parameters error!");
}
}


//check if consensus realm conflict, by this support multi ledgers
private boolean hasIntersection(NodeSettings[] currNodeSettings) {

int currHashCode = getHashcode(currNodeSettings);

//first check if is same consensus realm
for (NodeSettings[] exisitNodeSettings : nodeServerMap.values()) {
if (currHashCode == getHashcode(exisitNodeSettings)) {
return false;
}
}
//check conflict
for (NodeSettings[] exisitNodeSettings : nodeServerMap.values()) {
for (NodeSettings curr : currNodeSettings) {
for (NodeSettings exist : exisitNodeSettings) {
if (((BftsmartNodeSettings)curr).getNetworkAddress().equals(((BftsmartNodeSettings)exist).getNetworkAddress())) {
return true;
}
}
}
}

return false;
}

//compute hashcode for consensus nodes
private int getHashcode(NodeSettings[] nodeSettings) {

int i = 0;
NetworkAddress[] nodeAddrs = new NetworkAddress[nodeSettings.length];
for (NodeSettings setting : nodeSettings) {

nodeAddrs[i++] = ((BftsmartNodeSettings)setting).getNetworkAddress();
}
int hashCode = Arrays.hashCode(nodeAddrs);
return hashCode;

}

}

+ 0
- 40
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartServerSettingConfig.java View File

@@ -1,40 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.service;

import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings;

public class BftsmartServerSettingConfig implements BftsmartServerSettings {
private NodeSettings replicaSettings;
private String realmName;
private BftsmartConsensusSettings consensusSettings;


@Override
public String getRealmName() {
return realmName;
}

public void setRealmName(String realmName) {
this.realmName = realmName;
}


@Override
public NodeSettings getReplicaSettings() {
return replicaSettings;
}

public void setReplicaSettings(NodeSettings replicaSettings) {
this.replicaSettings = replicaSettings;
}


@Override
public BftsmartConsensusSettings getConsensusSettings() {
return consensusSettings;
}

public void setConsensusSettings(BftsmartConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
}
}

+ 0
- 10
core/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartServerSettings.java View File

@@ -1,10 +0,0 @@
package com.jd.blockchain.consensus.bftsmart.service;

import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings;
import com.jd.blockchain.consensus.service.ServerSettings;

public interface BftsmartServerSettings extends ServerSettings {

BftsmartConsensusSettings getConsensusSettings();

}

+ 0
- 144
core/consensus/consensus-bftsmart/src/main/resources/bftsmart.config View File

@@ -1,144 +0,0 @@
# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

############################################
####### Communication Configurations #######
############################################

#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value)
#This parameter is not currently being used being used
#system.authentication.hmacAlgorithm = HmacSHA1

#Specify if the communication system should use a thread to send data (true or false)
system.communication.useSenderThread = true

#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments
#and benchmarks, but must not be used in production systems.
system.communication.defaultkeys = true

############################################
### Replication Algorithm Configurations ###
############################################

#Timeout to asking for a client request
system.totalordermulticast.timeout = 2000


#Maximum batch size (in number of messages)
system.totalordermulticast.maxbatchsize = 400

#Number of nonces (for non-determinism actions) generated
system.totalordermulticast.nonces = 10

#if verification of leader-generated timestamps are increasing
#it can only be used on systems in which the network clocks
#are synchronized
system.totalordermulticast.verifyTimestamps = false

#Quantity of messages that can be stored in the receive queue of the communication system
system.communication.inQueueSize = 500000

# Quantity of messages that can be stored in the send queue of each replica
system.communication.outQueueSize = 500000

#Set to 1 if SMaRt should use signatures, set to 0 if otherwise
system.communication.useSignatures = 0

#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise
system.communication.useMACs = 1

#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise
system.debug = 0

#Print information about the replica when it is shutdown
system.shutdownhook = true

############################################
###### State Transfer Configurations #######
############################################

#Activate the state transfer protocol ('true' to activate, 'false' to de-activate)
system.totalordermulticast.state_transfer = true

#Maximum ahead-of-time message not discarded
system.totalordermulticast.highMark = 10000

#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered)
system.totalordermulticast.revival_highMark = 10

#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs
system.totalordermulticast.timeout_highMark = 200

############################################
###### Log and Checkpoint Configurations ###
############################################

system.totalordermulticast.log = true
system.totalordermulticast.log_parallel = false
system.totalordermulticast.log_to_disk = false
system.totalordermulticast.sync_log = false

#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol)
system.totalordermulticast.checkpoint_period = 1000
system.totalordermulticast.global_checkpoint_period = 120000

system.totalordermulticast.checkpoint_to_disk = false
system.totalordermulticast.sync_ckp = false


############################################
###### Reconfiguration Configurations ######
############################################

#The ID of the trust third party (TTP)
system.ttp.id = 7002

#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults
system.bft = true

#Custom View Storage;
#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage


#Number of servers in the group
system.servers.num = 4

#Maximum number of faulty replicas
system.servers.f = 1

#Replicas ID for the initial view, separated by a comma.
# The number of replicas in this parameter should be equal to that specified in 'system.servers.num'
system.initial.view = 0,1,2,3

#Configuration of all node servers;
#PubKey of node server with specified ID, with base58 encoding.
system.server.0.pubkey=
system.server.0.network.host=127.0.0.1
system.server.0.network.port=8900
system.server.0.network.secure=false

system.server.1.pubkey=
system.server.1.network.host=127.0.0.1
system.server.1.network.port=8910
system.server.1.network.secure=false

system.server.2.pubkey=
system.server.2.network.host=127.0.0.1
system.server.2.network.port=8920
system.server.2.network.secure=false

system.server.3.pubkey=
system.server.3.network.host=127.0.0.1
system.server.3.network.port=8920
system.server.3.network.secure=false

+ 0
- 137
core/consensus/consensus-bftsmart/src/test/java/test/com/jd/blockchain/consensus/bftsmart/ProxyClientTest.java View File

@@ -1,137 +0,0 @@
package test.com.jd.blockchain.consensus.bftsmart;

import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.bftsmart.*;
import com.jd.blockchain.consensus.bftsmart.client.BftsmartClientConfig;
import com.jd.blockchain.consensus.bftsmart.client.BftsmartConsensusClient;
import com.jd.blockchain.consensus.bftsmart.client.BftsmartMessageService;
import com.jd.blockchain.consensus.bftsmart.service.BftsmartNodeServer;
import com.jd.blockchain.consensus.bftsmart.service.BftsmartServerSettingConfig;
import com.jd.blockchain.consensus.service.ServerSettings;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ProxyClientTest {

int number = 1500000;

int peerStartPort = 11000;

int nodeNum = 4;

Random random = new Random();

byte[] bytes = null;

CountDownLatch startPeer = new CountDownLatch(nodeNum);

private static Properties bftsmartConf;

private final ExecutorService nodeStartPools = Executors.newCachedThreadPool();

private final ExecutorService txSendPools = Executors.newFixedThreadPool(20);

static {
ClassPathResource configResource = new ClassPathResource("system.config");
try {
try (InputStream in = configResource.getInputStream()) {
bftsmartConf = PropertiesUtils.load(in, BytesUtils.DEFAULT_CHARSET);
}
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}

public void peerStart(BftsmartNodeServer[] nodeServers) {

BftsmartNodeSettings[] nodesSettings = new BftsmartNodeSettings[nodeNum];

for (int i = 0; i < nodeNum; i++) {
BlockchainKeypair keyPair = BlockchainKeyGenerator.getInstance().generate();
PubKey pubKey = keyPair.getPubKey();
NetworkAddress peerNodeServ = new NetworkAddress("127.0.0.1", peerStartPort + i * 10);
NodeSettings node = new BftsmartNodeConfig(pubKey, i, peerNodeServ);
nodesSettings[i] = (BftsmartNodeSettings) node;
}

BftsmartConsensusConfig consensusConfig = new BftsmartConsensusConfig(nodesSettings,
// null,
PropertiesUtils.getOrderedValues(bftsmartConf));

for (int j = 0; j < nodeNum; j++) {
BftsmartServerSettingConfig serverSettings = new BftsmartServerSettingConfig();
serverSettings.setReplicaSettings(nodesSettings[j]);
serverSettings.setConsensusSettings(consensusConfig);
BftsmartNodeServer server = new BftsmartNodeServer(serverSettings, null, null);
nodeServers[j] = server;
nodeStartPools.execute(() -> {
server.start();
startPeer.countDown();
});
}
}

public void proxyClientSend(BftsmartNodeServer nodeServer) {
BftsmartClientIncomingConfig clientIncomingConfig = new BftsmartClientIncomingConfig();
BlockchainKeypair keyPair = BlockchainKeyGenerator.getInstance().generate();
clientIncomingConfig.setPubKey(keyPair.getPubKey());
clientIncomingConfig.setClientId(0);
clientIncomingConfig.setConsensusSettings(nodeServer.getConsensusSetting());
clientIncomingConfig.setTomConfig(BinarySerializeUtils.serialize(nodeServer.getTomConfig()));
clientIncomingConfig.setTopology(BinarySerializeUtils.serialize(nodeServer.getTopology()));

BftsmartClientConfig clientSettings = new BftsmartClientConfig(clientIncomingConfig);
BftsmartConsensusClient consensusClient = new BftsmartConsensusClient(clientSettings);
bytes = new byte[1024];

BftsmartMessageService messageService = (BftsmartMessageService) consensusClient.getMessageService();

for (int j = 0; j < number; j++) {
txSendPools.execute(() -> {
random.nextBytes(bytes);
messageService.sendOrdered(bytes);
});
}

}

// @Test
public void sendTest() {

BftsmartNodeServer[] nodeServers = new BftsmartNodeServer[nodeNum];
//启动服务
peerStart(nodeServers);

try {
startPeer.await();
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}

proxyClientSend(nodeServers[0]);


try {
Thread.sleep(50000);
System.out.println("send test complete!");
} catch (Exception e) {
e.printStackTrace();
}
}
}

+ 0
- 178
core/consensus/consensus-bftsmart/src/test/resources/bftsmart.config View File

@@ -1,178 +0,0 @@

# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


############################################
###### Consensus Commit Block Parameters: transaction count ######
############################################
system.block.txsize=15

############################################
###### Consensus Commit Block Parameters: delay time ######
############################################
system.block.maxdelay=500

############################################
###### Consensus Participant0 ######
############################################
system.server.0.pubkey=endPsK36koyFr1D245Sa9j83vt6pZUdFBJoJRB3xAsWM6cwhRbna

system.server.0.network.host=127.0.0.1

system.server.0.network.port=8910

system.server.0.network.secure=false

############################################
###### #Consensus Participant1 ######
############################################
system.server.1.pubkey=endPsK36sC5JdPCDPDAXUwZtS3sxEmqEhFcC4whayAsTTh8Z6eoZ

system.server.1.network.host=127.0.0.1

system.server.1.network.port=8920

system.server.1.network.secure=false

############################################
###### #Consensus Participant2 ######
############################################
system.server.2.pubkey=endPsK36jEG281HMHeh6oSqzqLkT95DTnCM6REDURjdb2c67uR3R

system.server.2.network.host=127.0.0.1

system.server.2.network.port=8930

system.server.2.network.secure=false

############################################
###### Consensus Participant3 ######
############################################
system.server.3.pubkey=endPsK36nse1dck4uF19zPvAMijCV336Y3zWdgb4rQG8QoRj5ktR

system.server.3.network.host=127.0.0.1

system.server.3.network.port=8940

system.server.3.network.secure=false

############################################
####### Communication Configurations #######
############################################

#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value)
#This parameter is not currently being used being used
#system.authentication.hmacAlgorithm = HmacSHA1

#Specify if the communication system should use a thread to send data (true or false)
system.communication.useSenderThread = true

#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments
#and benchmarks, but must not be used in production systems.
system.communication.defaultkeys = true

############################################
### Replication Algorithm Configurations ###
############################################

#Number of servers in the group
system.servers.num = 4

#Maximum number of faulty replicas
#system.servers.f = 1

#Timeout to asking for a client request
system.totalordermulticast.timeout = 2000


#Maximum batch size (in number of messages)
system.totalordermulticast.maxbatchsize = 400

#Number of nonces (for non-determinism actions) generated
system.totalordermulticast.nonces = 10

#if verification of leader-generated timestamps are increasing
#it can only be used on systems in which the network clocks
#are synchronized
system.totalordermulticast.verifyTimestamps = false

#Quantity of messages that can be stored in the receive queue of the communication system
system.communication.inQueueSize = 500000

# Quantity of messages that can be stored in the send queue of each replica
system.communication.outQueueSize = 500000

#Set to 1 if SMaRt should use signatures, set to 0 if otherwise
system.communication.useSignatures = 0

#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise
system.communication.useMACs = 1

#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise
system.debug = 0

#Print information about the replica when it is shutdown
system.shutdownhook = true

############################################
###### State Transfer Configurations #######
############################################

#Activate the state transfer protocol ('true' to activate, 'false' to de-activate)
system.totalordermulticast.state_transfer = true

#Maximum ahead-of-time message not discarded
system.totalordermulticast.highMark = 10000

#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered)
system.totalordermulticast.revival_highMark = 10

#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs
system.totalordermulticast.timeout_highMark = 200

############################################
###### Log and Checkpoint Configurations ###
############################################

system.totalordermulticast.log = true
system.totalordermulticast.log_parallel = false
system.totalordermulticast.log_to_disk = false
system.totalordermulticast.sync_log = false

#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol)
system.totalordermulticast.checkpoint_period = 1000
system.totalordermulticast.global_checkpoint_period = 120000

system.totalordermulticast.checkpoint_to_disk = false
system.totalordermulticast.sync_ckp = false


############################################
###### Reconfiguration Configurations ######
############################################

#Replicas ID for the initial view, separated by a comma.
# The number of replicas in this parameter should be equal to that specified in 'system.servers.num'
#system.initial.view = 0,1,2,3

#The ID of the trust third party (TTP)
system.ttp.id = 7002

#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults
system.bft = true

#Custom View Storage;
#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage


+ 0
- 121
core/consensus/consensus-bftsmart/src/test/resources/system.config View File

@@ -1,121 +0,0 @@
# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

############################################
####### Communication Configurations #######
############################################

#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value)
#This parameter is not currently being used being used
#system.authentication.hmacAlgorithm = HmacSHA1

#Specify if the communication system should use a thread to send data (true or false)
system.communication.useSenderThread = true

#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments
#and benchmarks, but must not be used in production systems.
system.communication.defaultkeys = true

############################################
### Replication Algorithm Configurations ###
############################################

#Number of servers in the group
system.servers.num = 4

#Maximum number of faulty replicas
#system.servers.f = 1

#Timeout to asking for a client request
system.totalordermulticast.timeout = 2000


#Maximum batch size (in number of messages)
system.totalordermulticast.maxbatchsize = 400

#Number of nonces (for non-determinism actions) generated
system.totalordermulticast.nonces = 10

#if verification of leader-generated timestamps are increasing
#it can only be used on systems in which the network clocks
#are synchronized
system.totalordermulticast.verifyTimestamps = false

#Quantity of messages that can be stored in the receive queue of the communication system
system.communication.inQueueSize = 500000

# Quantity of messages that can be stored in the send queue of each replica
system.communication.outQueueSize = 500000

#Set to 1 if SMaRt should use signatures, set to 0 if otherwise
system.communication.useSignatures = 0

#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise
system.communication.useMACs = 1

#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise
system.debug = 0

#Print information about the replica when it is shutdown
system.shutdownhook = true

############################################
###### State Transfer Configurations #######
############################################

#Activate the state transfer protocol ('true' to activate, 'false' to de-activate)
system.totalordermulticast.state_transfer = true

#Maximum ahead-of-time message not discarded
system.totalordermulticast.highMark = 10000

#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered)
system.totalordermulticast.revival_highMark = 10

#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs
system.totalordermulticast.timeout_highMark = 200

############################################
###### Log and Checkpoint Configurations ###
############################################

system.totalordermulticast.log = true
system.totalordermulticast.log_parallel = false
system.totalordermulticast.log_to_disk = false
system.totalordermulticast.sync_log = false

#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol)
system.totalordermulticast.checkpoint_period = 1000
system.totalordermulticast.global_checkpoint_period = 120000

system.totalordermulticast.checkpoint_to_disk = false
system.totalordermulticast.sync_ckp = false


############################################
###### Reconfiguration Configurations ######
############################################

#Replicas ID for the initial view, separated by a comma.
# The number of replicas in this parameter should be equal to that specified in 'system.servers.num'
#system.initial.view = 0,1,2,3

#The ID of the trust third party (TTP)
system.ttp.id = 7002

#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults
system.bft = true

#Custom View Storage;
#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage

+ 0
- 71
core/consensus/consensus-mq/pom.xml View File

@@ -1,71 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-core</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-mq</artifactId>

<name>consensus-mq</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus-framework</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>tools-keygen</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-model</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
<dependency>
<groupId>io.nats</groupId>
<artifactId>jnats</artifactId>
</dependency>
<!-- rabbitmq -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 0
- 55
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusProvider.java View File

@@ -1,55 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/18 下午2:50
* Description:
*/
package com.jd.blockchain.consensus.mq;

import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.SettingsFactory;
import com.jd.blockchain.consensus.client.ClientFactory;
import com.jd.blockchain.consensus.mq.client.MsgQueueClientFactory;
import com.jd.blockchain.consensus.mq.config.MsgQueueSettingsFactory;
import com.jd.blockchain.consensus.mq.server.MsgQueueNodeServerFactory;
import com.jd.blockchain.consensus.service.NodeServerFactory;

/**
*
* @author shaozhuguang
* @create 2018/12/18
* @since 1.0.0
*/

public class MsgQueueConsensusProvider implements ConsensusProvider {

public static final String NAME = MsgQueueConsensusProvider.class.getName();

private static MsgQueueSettingsFactory settingsFactory = new MsgQueueSettingsFactory();

private static MsgQueueClientFactory clientFactory = new MsgQueueClientFactory();

private static MsgQueueNodeServerFactory nodeServerFactory = new MsgQueueNodeServerFactory();

@Override
public String getName() {
return NAME;
}

@Override
public SettingsFactory getSettingsFactory() {
return settingsFactory;
}

@Override
public ClientFactory getClientFactory() {
return clientFactory;
}

@Override
public NodeServerFactory getServerFactory() {
return nodeServerFactory;
}
}

+ 0
- 301
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java View File

@@ -1,301 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.MsgQueueConsensusSettingsBuilder
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午1:46
* Description:
*/
package com.jd.blockchain.consensus.mq;

import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.ConsensusSettingsBuilder;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.mq.config.MsgQueueBlockConfig;
import com.jd.blockchain.consensus.mq.config.MsgQueueConsensusConfig;
import com.jd.blockchain.consensus.mq.config.MsgQueueNetworkConfig;
import com.jd.blockchain.consensus.mq.config.MsgQueueNodeConfig;
import com.jd.blockchain.consensus.mq.settings.MsgQueueBlockSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantInfo;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.BytesEncoder;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.io.FileUtils;
import com.jd.blockchain.utils.net.NetworkAddress;

import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilder {

private static final String DEFAULT_TOPIC_TX = "tx-topic";

private static final String DEFAULT_TOPIC_BL = "bl-topic";

private static final String DEFAULT_TOPIC_MSG = "msg-topic";

private static final int DEFAULT_TXSIZE = 1000;

private static final int DEFAULT_MAXDELAY = 1000;

/**
*
*/
private static final String CONFIG_TEMPLATE_FILE = "mq.config";

/**
* 参数键:节点数量;
*/
public static final String SERVER_NUM_KEY = "system.servers.num";

/**
* 参数键格式:节点公钥;
*/
public static final String PUBKEY_PATTERN = "system.server.%s.pubkey";

public static final String MSG_QUEUE_SERVER = "system.msg.queue.server";

public static final String MSG_QUEUE_TOPIC_TX = "system.msg.queue.topic.tx";

public static final String MSG_QUEUE_TOPIC_BL = "system.msg.queue.topic.bl";

public static final String MSG_QUEUE_TOPIC_MSG = "system.msg.queue.topic.msg";

public static final String MSG_QUEUE_BLOCK_TXSIZE = "system.msg.queue.block.txsize";

public static final String MSG_QUEUE_BLOCK_MAXDELAY = "system.msg.queue.block.maxdelay";

public static final String MSG_QUEUE_PROVIDER = "com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider";

private static Properties CONFIG_TEMPLATE;

static {
if (FileUtils.existFile(CONFIG_TEMPLATE_FILE)) {
ClassPathResource configResource = new ClassPathResource(CONFIG_TEMPLATE_FILE);
try {
try (InputStream in = configResource.getInputStream()) {
CONFIG_TEMPLATE = PropertiesUtils.load(in, BytesUtils.DEFAULT_CHARSET);
}
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}

@Override
public MsgQueueConsensusSettings createSettings(Properties props, ParticipantNode[] participantNodes) {
MsgQueueNetworkConfig networkConfig = new MsgQueueNetworkConfig();
Properties resolvingProps = PropertiesUtils.cloneFrom(props);

String server = PropertiesUtils.getProperty(resolvingProps, MSG_QUEUE_SERVER, true);
if (server == null || server.length()<= 0) {
throw new IllegalArgumentException(String.format("Property[%s] is empty!", MSG_QUEUE_SERVER));
}
networkConfig.setServer(server)
.setTxTopic(initProp(resolvingProps, MSG_QUEUE_TOPIC_TX, DEFAULT_TOPIC_TX))
.setBlTopic(initProp(resolvingProps, MSG_QUEUE_TOPIC_BL, DEFAULT_TOPIC_BL))
.setMsgTopic(initProp(resolvingProps, MSG_QUEUE_TOPIC_MSG, DEFAULT_TOPIC_MSG))
;

MsgQueueBlockConfig blockConfig = new MsgQueueBlockConfig()
.setTxSizePerBlock(initProp(resolvingProps, MSG_QUEUE_BLOCK_TXSIZE, DEFAULT_TXSIZE))
.setMaxDelayMilliSecondsPerBlock(initProp(resolvingProps, MSG_QUEUE_BLOCK_MAXDELAY, DEFAULT_MAXDELAY))
;

MsgQueueConsensusConfig consensusConfig = new MsgQueueConsensusConfig()
.setBlockSettings(blockConfig)
.setNetworkSettings(networkConfig)
;
// load node settings
int serversNum = PropertiesUtils.getInt(resolvingProps, SERVER_NUM_KEY);
for (int i = 0; i < serversNum; i++) {
int id = i;

String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id);

String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey);
PubKey pubKey = KeyGenUtils.decodePubKey(base58PubKey);

// PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey));
resolvingProps.remove(keyOfPubkey);
Bytes address = AddressEncoding.generateAddress(pubKey);

String networkAddress = address.toBase58();
MsgQueueNodeConfig nodeConfig = new MsgQueueNodeConfig()
.setAddress(networkAddress)
.setPubKey(pubKey)
;
consensusConfig.addNodeSettings(nodeConfig);
}
return consensusConfig;
}

private MsgQueueNodeSettings[] nodeSettings(NodeSettings[] nodeSettings, ParticipantInfo participantInfo) {

MsgQueueNodeSettings msgQueueNodeSettings = new MsgQueueNodeConfig();
((MsgQueueNodeConfig) msgQueueNodeSettings).setAddress(AddressEncoding.generateAddress(participantInfo.getPubKey()).toBase58());
((MsgQueueNodeConfig) msgQueueNodeSettings).setPubKey(participantInfo.getPubKey());

MsgQueueNodeSettings[] msgQueuetNodeSettings = new MsgQueueNodeSettings[nodeSettings.length + 1];
for (int i = 0; i < nodeSettings.length; i++) {
msgQueuetNodeSettings[i] = (MsgQueueNodeSettings)nodeSettings[i];
}
msgQueuetNodeSettings[nodeSettings.length] = msgQueueNodeSettings;

return msgQueuetNodeSettings;
}

@Override
public Bytes updateSettings(Bytes oldConsensusSettings, ParticipantInfo participantInfo) {

BytesEncoder<ConsensusSettings> consensusEncoder = ConsensusProviders.getProvider(MSG_QUEUE_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder();

MsgQueueConsensusSettings consensusSettings = (MsgQueueConsensusSettings) consensusEncoder.decode(oldConsensusSettings.toBytes());

MsgQueueNodeSettings[] nodeSettings = nodeSettings(consensusSettings.getNodes(), participantInfo);

MsgQueueConsensusConfig msgQueueConsensusConfig = new MsgQueueConsensusConfig();
for (int i = 0; i < nodeSettings.length; i++) {
msgQueueConsensusConfig.addNodeSettings(nodeSettings[i]);
}

msgQueueConsensusConfig.setBlockSettings(consensusSettings.getBlockSettings());

msgQueueConsensusConfig.setNetworkSettings(consensusSettings.getNetworkSettings());


// for(int i = 0 ;i < msgQueueConsensusConfig.getNodes().length; i++) {
// System.out.printf("node addr = %s\r\n", msgQueueConsensusConfig.getNodes()[i].getAddress());
// }

return new Bytes(consensusEncoder.encode(msgQueueConsensusConfig));

}

@Override
public Properties createPropertiesTemplate() {
return PropertiesUtils.cloneFrom(CONFIG_TEMPLATE);
}

@Override
public void writeSettings(ConsensusSettings settings, Properties props) {

if (!(settings instanceof MsgQueueConsensusSettings)) {
throw new IllegalArgumentException("ConsensusSettings data isn't supported! Accept MsgQueueConsensusSettings only!");
}

MsgQueueConsensusSettings consensusSettings = (MsgQueueConsensusSettings) settings;

MsgQueueNetworkSettings networkSettings = consensusSettings.getNetworkSettings();
if (networkSettings == null || networkSettings.getServer() == null || networkSettings.getServer().length() <= 0) {
throw new IllegalArgumentException("MsgQueue Consensus server is empty!");
}

String server = networkSettings.getServer();
props.setProperty(MSG_QUEUE_SERVER, server);

String txTopic = networkSettings.getTxTopic();
if (txTopic == null || txTopic.length() <= 0) {
txTopic = DEFAULT_TOPIC_TX;
}
props.setProperty(MSG_QUEUE_TOPIC_TX, txTopic);

String blTopic = networkSettings.getBlTopic();
if (blTopic == null || blTopic.length() <= 0) {
blTopic = DEFAULT_TOPIC_BL;
}
props.setProperty(MSG_QUEUE_TOPIC_BL, blTopic);

String msgTopic = networkSettings.getMsgTopic();
if (msgTopic == null || msgTopic.length() <= 0) {
msgTopic = DEFAULT_TOPIC_MSG;
}
props.setProperty(MSG_QUEUE_TOPIC_MSG, msgTopic);

MsgQueueBlockSettings blockSettings = consensusSettings.getBlockSettings();
if (blockSettings == null) {
props.setProperty(MSG_QUEUE_BLOCK_TXSIZE, DEFAULT_TXSIZE + "");
props.setProperty(MSG_QUEUE_BLOCK_MAXDELAY, DEFAULT_MAXDELAY + "");
} else {
int txSize = blockSettings.getTxSizePerBlock();
long maxDelay = blockSettings.getMaxDelayMilliSecondsPerBlock();
props.setProperty(MSG_QUEUE_BLOCK_TXSIZE, txSize + "");
props.setProperty(MSG_QUEUE_BLOCK_MAXDELAY, maxDelay + "");
}


// int serversNum = PropertiesUtils.getInt(props, SERVER_NUM_KEY);
// if (serversNum > 0) {
// for (int i = 0; i < serversNum; i++) {
// int id = i;
// String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id);
// props.remove(keyOfPubkey);
//
// String keyOfHost = nodeKey(CONSENSUS_HOST_PATTERN, id);
// props.remove(keyOfHost);
// }
// }
//
// NodeSettings[] nodesSettings = consensusSettings.getNodes();
// serversNum = nodesSettings.length;
// props.setProperty(SERVER_NUM_KEY, serversNum + "");
//
// for (int i = 0; i < serversNum; i++) {
// MsgQueueNodeSettings mqns = (MsgQueueNodeSettings) nodesSettings[i];
// int id = i;
// String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id);
// props.setProperty(keyOfPubkey, mqns.getPubKey().toBase58());
//
// String keyOfHost = nodeKey(CONSENSUS_HOST_PATTERN, id);
// props.setProperty(keyOfHost, mqns.getAddress() == null ? "" : mqns.getAddress());
// }
}

private String initProp(Properties resolvingProps, String key, String defaultVal) {
try {
String value = PropertiesUtils.getProperty(resolvingProps, key, true);
if (value == null || value.length() <= 0) {
value = defaultVal;
}
return value;
} catch (Exception e) {
return defaultVal;
}
}

private int initProp(Properties resolvingProps, String key, int defaultVal) {
try {
int value = PropertiesUtils.getInt(resolvingProps, key);
if (value <= 0) {
value = defaultVal;
}
return value;
} catch (Exception e) {
return defaultVal;
}
}

private static String nodeKey(String pattern, int id) {
return String.format(pattern, id);
}
}

+ 0
- 311
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/DefaultMessageTransmitter.java View File

@@ -1,311 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.client.DefaultMessageTransmitter
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午3:05
* Description:
*/
package com.jd.blockchain.consensus.mq.client;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

import com.jd.blockchain.consensus.event.EventEntity;
import com.lmax.disruptor.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jd.blockchain.consensus.MessageService;
import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.event.TxBlockedEvent;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.util.MessageConvertUtil;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class DefaultMessageTransmitter implements MessageTransmitter, MessageService {

private static final Logger LOGGER = LoggerFactory.getLogger(DefaultMessageTransmitter.class);

private final ExecutorService messageExecutorArray = Executors.newFixedThreadPool(10);

// private final ExecutorService blockExecutor = Executors.newSingleThreadExecutor();
//
// private final ExecutorService extendExecutor = Executors.newSingleThreadExecutor();

private final Map<String, MessageListener> messageListeners = new ConcurrentHashMap<>();

private final BlockEventHandler blockEventHandler = new BlockEventHandler();

private final ExtendEventHandler extendEventHandler = new ExtendEventHandler();

private MsgQueueProducer txProducer;

private MsgQueueProducer msgProducer;

private MsgQueueConsumer blConsumer;

private MsgQueueConsumer msgConsumer;

private boolean isConnected = false;

public DefaultMessageTransmitter setTxProducer(MsgQueueProducer txProducer) {
this.txProducer = txProducer;
return this;
}

public DefaultMessageTransmitter setMsgProducer(MsgQueueProducer msgProducer) {
this.msgProducer = msgProducer;
return this;
}

public DefaultMessageTransmitter setBlConsumer(MsgQueueConsumer blConsumer) {
this.blConsumer = blConsumer;
return this;
}

public DefaultMessageTransmitter setMsgConsumer(MsgQueueConsumer msgConsumer) {
this.msgConsumer = msgConsumer;
return this;
}

@Override
public AsyncFuture<byte[]> sendOrdered(byte[] message) {

AsyncFuture<byte[]> messageFuture;

try {
publishMessage(txProducer, message);
messageFuture = messageHandle(message);
} catch (Exception e) {
throw new RuntimeException(e);
}
return messageFuture;
}

@Override
public AsyncFuture<byte[]> sendUnordered(byte[] message) {
AsyncFuture<byte[]> messageFuture;
try {
publishMessage(msgProducer, message);
messageFuture = messageHandle(message);
} catch (Exception e) {
throw new RuntimeException(e);
}
return messageFuture;
}

@Override
public void connect() throws Exception{
if (!isConnected) {
this.txProducer.connect();
this.blConsumer.connect(blockEventHandler);
this.msgProducer.connect();
this.msgConsumer.connect(extendEventHandler);
isConnected = true;
blConsumer.start();
msgConsumer.start();
// blockConsumerListening();
// extendConsumerListening();
}
}

@Override
public void publishMessage(MsgQueueProducer producer, byte[] message) throws Exception {
producer.publish(message);
}

@Override
public void close() {
try {
txProducer.close();
blConsumer.close();
msgProducer.close();
msgConsumer.close();
isConnected = false;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private AsyncFuture<byte[]> messageHandle(byte[] message) throws Exception {
// 异步回调
// 需要监听MQ结块的应答
// 首先需要一个Consumer,在子类已实现
String messageKey = messageKey(message);
AsyncFuture<byte[]> messageFuture = registerMessageListener(messageKey);
return messageFuture;
}

private String messageKey(byte[] message) {
return MessageConvertUtil.messageKey(message);
}

private AsyncFuture<byte[]> registerMessageListener(String messageKey) {
CompletableAsyncFuture<byte[]> future = new CompletableAsyncFuture<>();
MessageListener messageListener = new MessageListener(messageKey, future);
messageListener.addListener();
return future;
}

// private void blockConsumerListening() {
// // 区块事件由单独一个线程处理
// blockExecutor.execute(() -> {
// while(isConnected) {
// try {
// byte[] txBlockedEventBytes = blConsumer.start();
// // 交由事件处理机制来处理
// if (txBlockedEventBytes != null && txBlockedEventBytes.length > 0) {
// txBlockedEventHandle(txBlockedEventBytes);
// }
// } catch (Exception e) {
// LOGGER.error("process block listening message exception {}", e.getMessage());
// }
// }
// });
// }

// private void extendConsumerListening() {
// extendExecutor.execute(() -> {
// while (isConnected) {
// try {
// byte[] msgBytes = msgConsumer.start();
// // 交由事件处理机制来处理
// if (msgBytes != null && msgBytes.length > 0) {
// extendMessageHandle(msgBytes);
// }
// } catch (Exception e) {
// LOGGER.error("process extend listening message exception {}", e.getMessage());
// }
// }
// });
// }

private void txBlockedEventHandle(byte[] bytes) {
messageExecutorArray.execute(() -> {
if (!this.messageListeners.isEmpty()) {
// 首先将字节数组转换为BlockEvent
final TxBlockedEvent txBlockedEvent =
MessageConvertUtil.convertBytes2TxBlockedEvent(bytes);
if (txBlockedEvent != null) {
// 需要判断该区块是否需要处理
if (isTxBlockedEventNeedManage(txBlockedEvent)) {
dealTxBlockedEvent(txBlockedEvent);
}
}
}
});
}

private void extendMessageHandle(byte[] message) {
messageExecutorArray.execute(() -> {
String messageKey = messageKey(message);
if (messageListeners.containsKey(messageKey)) {
dealExtendMessage(messageKey, message);
}
});
}

private boolean isTxBlockedEventNeedManage(final TxBlockedEvent txBlockedEvent) {
if (this.messageListeners.isEmpty()) {
return false;
}
if (messageListeners.containsKey(txBlockedEvent.getTxKey())) {
return true;
}
// 无须处理区块高度
return false;
}

private void dealTxBlockedEvent(final TxBlockedEvent txBlockedEvent) {
String txKey = txBlockedEvent.getTxKey();
MessageListener txListener = this.messageListeners.get(txKey);
if (txListener != null) {
txListener.received(txBlockedEvent);
this.messageListeners.remove(txKey);
}
}

private void dealExtendMessage(final String messageKey, final byte[] message) {
MessageListener txListener = this.messageListeners.get(messageKey);
if (txListener != null) {
txListener.received(message);
this.messageListeners.remove(messageKey);
}
}

private class MessageListener {

final String messageKey;

final CompletableAsyncFuture<byte[]> future;

final AtomicBoolean isDeal = new AtomicBoolean(false);

public MessageListener(String messageKey, CompletableAsyncFuture<byte[]> future) {
this.messageKey = messageKey;
this.future = future;
addListener();
}

public void addListener() {
synchronized (messageListeners) {
messageListeners.put(messageKey, this);
}
}

public void received(final TxBlockedEvent txBlockedEvent) {
// 期望是false,假设是false则设置为true,成功的情况下表示是第一次
byte[] txResp = txBlockedEvent.txResponseBytes();
if (txResp != null) {
if (isDeal.compareAndSet(false, true)) {
//生成对应的交易应答
future.complete(txResp);
}
}
}

public void received(final byte[] message) {
// 期望是false,假设是false则设置为true,成功的情况下表示是第一次
if (message != null) {
if (isDeal.compareAndSet(false, true)) {
//生成对应的交易应答
future.complete(message);
}
}
}
}

public class BlockEventHandler implements EventHandler<EventEntity<byte[]>> {

@Override
public void onEvent(EventEntity<byte[]> event, long sequence, boolean endOfBatch) throws Exception {
byte[] txBlockedEventBytes = event.getEntity();
if (txBlockedEventBytes != null && txBlockedEventBytes.length > 0) {
txBlockedEventHandle(txBlockedEventBytes);
}
}
}

public class ExtendEventHandler implements EventHandler<EventEntity<byte[]>> {

@Override
public void onEvent(EventEntity<byte[]> event, long sequence, boolean endOfBatch) throws Exception {
byte[] msgBytes = event.getEntity();
if (msgBytes != null && msgBytes.length > 0) {
extendMessageHandle(msgBytes);
}
}
}
}

+ 0
- 30
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MessageTransmitter.java View File

@@ -1,30 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.client.MessageTransmitter
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:21
* Description:
*/
package com.jd.blockchain.consensus.mq.client;


import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public interface MessageTransmitter {

void connect() throws Exception;

void publishMessage(MsgQueueProducer producer, byte[] message) throws Exception;

// void processMsg(byte[] message);

void close();
}

+ 0
- 92
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueClientFactory.java View File

@@ -1,92 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.client.MsgQueueClientFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:23
* Description:
*/
package com.jd.blockchain.consensus.mq.client;

import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.client.ClientFactory;
import com.jd.blockchain.consensus.client.ClientSettings;
import com.jd.blockchain.consensus.mq.config.MsgQueueClientConfig;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueClientFactory implements ClientFactory {

@Override
public MsgQueueClientIdentification buildAuthId(AsymmetricKeypair clientKeyPair) {
PubKey pubKey = clientKeyPair.getPubKey();
byte[] address = pubKey.toBytes(); // 使用公钥地址作为认证信息

SignatureFunction signatureFunction = Crypto.getSignatureFunction(pubKey.getAlgorithm());
SignatureDigest signatureDigest = signatureFunction.sign(clientKeyPair.getPrivKey(), address);

MsgQueueClientIdentification mqci = new MsgQueueClientIdentification()
.setPubKey(clientKeyPair.getPubKey())
.setIdentityInfo(address)
.setSignature(signatureDigest)
;
return mqci;
}

@Override
public MsgQueueClientSettings buildClientSettings(ClientIncomingSettings incomingSettings) {

MsgQueueClientIncomingSettings mqcic = (MsgQueueClientIncomingSettings)incomingSettings;
if (mqcic != null) {
return buildClientSettings(mqcic.getClientId(), mqcic.getPubKey(), (MsgQueueConsensusSettings)(mqcic.getConsensusSettings()));
}
throw new IllegalArgumentException("ClientIncomingSettings data isn't supported! Accept MsgQueueClientIncomingSettings only!");
}

private MsgQueueClientSettings buildClientSettings(int clientId, PubKey pubKey, MsgQueueConsensusSettings mqcs) {

MsgQueueClientSettings msgQueueClientConfig = new MsgQueueClientConfig()
.setId(clientId)
.setPubKey(pubKey)
.setConsensusSettings(mqcs)
;
return msgQueueClientConfig;
}

@Override
public ConsensusManageService createManageServiceClient(String[] serviceNodes) {
// todo serviceNodes // IP:port
return null;
}

@Override
public MsgQueueConsensusClient setupClient(ClientSettings settings) {
if (settings instanceof MsgQueueClientSettings) {
return setupClient((MsgQueueClientSettings)settings);
}
throw new IllegalArgumentException("ClientSettings data isn't supported! Accept MsgQueueClientSettings only!");
}

private MsgQueueConsensusClient setupClient(MsgQueueClientSettings settings) {
MsgQueueConsensusClient mqcc = new MsgQueueConsensusClient()
.setClientSettings(settings)
.setMsgQueueNetworkSettings(settings.getMsgQueueNetworkSettings())
;
mqcc.init();
return mqcc;
}
}

+ 0
- 74
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueClientIdentification.java View File

@@ -1,74 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.client.MsgQueueClientIdentification
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午2:04
* Description:
*/
package com.jd.blockchain.consensus.mq.client;

import com.jd.blockchain.consensus.ClientIdentification;
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueClientIdentification implements ClientIdentification {

private byte[] identityInfo;

private PubKey pubKey;

private SignatureDigest signature;

public MsgQueueClientIdentification() {
}

public MsgQueueClientIdentification(ClientIdentification clientIdentification) {
identityInfo = clientIdentification.getIdentityInfo();
pubKey = clientIdentification.getPubKey();
signature = clientIdentification.getSignature();
}

public MsgQueueClientIdentification setIdentityInfo(byte[] identityInfo) {
this.identityInfo = identityInfo;
return this;
}

public MsgQueueClientIdentification setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
return this;
}

public MsgQueueClientIdentification setSignature(SignatureDigest signature) {
this.signature = signature;
return this;
}

@Override
public byte[] getIdentityInfo() {
return this.identityInfo;
}

@Override
public PubKey getPubKey() {
return this.pubKey;
}

@Override
public SignatureDigest getSignature() {
return this.signature;
}

@Override
public String getProviderName() {
return MsgQueueConsensusProvider.NAME;
}
}

+ 0
- 100
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/client/MsgQueueConsensusClient.java View File

@@ -1,100 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.client.MsgQueueConsensusClient
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午3:23
* Description:
*/
package com.jd.blockchain.consensus.mq.client;

import com.jd.blockchain.consensus.MessageService;
import com.jd.blockchain.consensus.client.ClientSettings;
import com.jd.blockchain.consensus.client.ConsensusClient;
import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.factory.MsgQueueFactory;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueConsensusClient implements ConsensusClient {

private boolean isConnected;

private DefaultMessageTransmitter transmitter;

private MsgQueueNetworkSettings msgQueueNetworkSettings;

private MsgQueueClientSettings clientSettings;

public MsgQueueConsensusClient setClientSettings(MsgQueueClientSettings clientSettings) {
this.clientSettings = clientSettings;
return this;
}

public MsgQueueConsensusClient setMsgQueueNetworkSettings(MsgQueueNetworkSettings msgQueueNetworkSettings) {
this.msgQueueNetworkSettings = msgQueueNetworkSettings;
return this;
}

public void init() {
String server = msgQueueNetworkSettings.getServer();
String txTopic = msgQueueNetworkSettings.getTxTopic();
String blTopic = msgQueueNetworkSettings.getBlTopic();
String msgTopic = msgQueueNetworkSettings.getMsgTopic();

MsgQueueProducer txProducer = MsgQueueFactory.newProducer(server, txTopic);
MsgQueueProducer msgProducer = MsgQueueFactory.newProducer(server, msgTopic);
MsgQueueConsumer blConsumer = MsgQueueFactory.newConsumer(server, blTopic);
MsgQueueConsumer msgConsumer = MsgQueueFactory.newConsumer(server, msgTopic);

transmitter = new DefaultMessageTransmitter()
.setTxProducer(txProducer)
.setMsgProducer(msgProducer)
.setBlConsumer(blConsumer)
.setMsgConsumer(msgConsumer)
;
}

@Override
public MessageService getMessageService() {
return transmitter;
}

@Override
public ClientSettings getSettings() {
return clientSettings;
}

@Override
public boolean isConnected() {
return isConnected;
}

@Override
public synchronized void connect() {
if (!isConnected) {
try {
this.transmitter.connect();
isConnected = true;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

@Override
public synchronized void close() {
if (isConnected) {
transmitter.close();
isConnected = false;
}
}
}

+ 0
- 47
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueBlockConfig.java View File

@@ -1,47 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueBlockConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午2:57
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.mq.settings.MsgQueueBlockSettings;

import java.lang.reflect.Method;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public class MsgQueueBlockConfig implements MsgQueueBlockSettings {

private int txSizePerBlock;

private long maxDelayMilliSecondsPerBlock;

@Override
public int getTxSizePerBlock() {
return txSizePerBlock;
}

public MsgQueueBlockConfig setTxSizePerBlock(int txSizePerBlock) {
this.txSizePerBlock = txSizePerBlock;
return this;
}

@Override
public long getMaxDelayMilliSecondsPerBlock() {
return maxDelayMilliSecondsPerBlock;
}

public MsgQueueBlockConfig setMaxDelayMilliSecondsPerBlock(long maxDelayMilliSecondsPerBlock) {
this.maxDelayMilliSecondsPerBlock = maxDelayMilliSecondsPerBlock;
return this;
}
}

+ 0
- 65
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueClientConfig.java View File

@@ -1,65 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueClientConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午2:23
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.mq.settings.MsgQueueClientSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;
import com.jd.blockchain.crypto.PubKey;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueClientConfig implements MsgQueueClientSettings {

private int id;

private PubKey pubKey;

private MsgQueueConsensusSettings consensusSettings;

public MsgQueueClientConfig setId(int id) {
this.id = id;
return this;
}

public MsgQueueClientConfig setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
return this;
}

public MsgQueueClientConfig setConsensusSettings(MsgQueueConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
return this;
}

@Override
public int getClientId() {
return this.id;
}

@Override
public PubKey getClientPubKey() {
return this.pubKey;
}

@Override
public MsgQueueConsensusSettings getConsensusSettings() {
return this.consensusSettings;
}

@Override
public MsgQueueNetworkSettings getMsgQueueNetworkSettings() {
return this.consensusSettings.getNetworkSettings();
}
}

+ 0
- 69
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueClientIncomingConfig.java View File

@@ -1,69 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueClientIncomingConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:50
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.crypto.PubKey;

import java.lang.reflect.Method;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueClientIncomingConfig implements MsgQueueClientIncomingSettings {

private int clientId;

private PubKey pubKey;

private MsgQueueConsensusSettings consensusSettings;

public MsgQueueClientIncomingConfig setConsensusSettings(MsgQueueConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
return this;
}

public MsgQueueClientIncomingConfig setClientId(int clientId) {
this.clientId = clientId;
return this;
}

public MsgQueueClientIncomingConfig setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
return this;
}

@Override
public int getClientId() {
return this.clientId;
}

@Override
public String getProviderName() {
return MsgQueueConsensusProvider.NAME;
}

@Override
public MsgQueueConsensusSettings getConsensusSettings() {
return this.consensusSettings;
}

@Override
public PubKey getPubKey() {
return pubKey;
}
}

+ 0
- 65
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueConsensusConfig.java View File

@@ -1,65 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueConsensusConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:26
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.mq.settings.*;
import com.jd.blockchain.crypto.PubKey;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
* 设置消息队列的信息
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueConsensusConfig implements MsgQueueConsensusSettings {

private List<NodeSettings> nodeSettingsList = new ArrayList<>();

private MsgQueueNetworkSettings networkSettings;

private MsgQueueBlockSettings blockSettings;

public MsgQueueConsensusConfig addNodeSettings(MsgQueueNodeSettings nodeSettings) {
nodeSettingsList.add(nodeSettings);
return this;
}

public MsgQueueConsensusConfig setNetworkSettings(MsgQueueNetworkSettings networkSettings) {
this.networkSettings = networkSettings;
return this;
}

public MsgQueueConsensusConfig setBlockSettings(MsgQueueBlockSettings blockSettings) {
this.blockSettings = blockSettings;
return this;
}

@Override
public NodeSettings[] getNodes() {
return nodeSettingsList.toArray(new NodeSettings[nodeSettingsList.size()]);
}

@Override
public MsgQueueNetworkSettings getNetworkSettings() {
return networkSettings;
}

@Override
public MsgQueueBlockSettings getBlockSettings() {
return blockSettings;
}
}

+ 0
- 71
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueNetworkConfig.java View File

@@ -1,71 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueNetworkConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午4:55
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;

import java.lang.reflect.Method;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueNetworkConfig implements MsgQueueNetworkSettings {

private String server;

private String txTopic;

private String blTopic;

private String msgTopic;

public MsgQueueNetworkConfig setServer(String server) {
this.server = server;
return this;
}

public MsgQueueNetworkConfig setTxTopic(String txTopic) {
this.txTopic = txTopic;
return this;
}

public MsgQueueNetworkConfig setBlTopic(String blTopic) {
this.blTopic = blTopic;
return this;
}

public MsgQueueNetworkConfig setMsgTopic(String msgTopic) {
this.msgTopic = msgTopic;
return this;
}

@Override
public String getServer() {
return server;
}

@Override
public String getTxTopic() {
return txTopic;
}

@Override
public String getBlTopic() {
return blTopic;
}

@Override
public String getMsgTopic() {
return msgTopic;
}
}

+ 0
- 46
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueNodeConfig.java View File

@@ -1,46 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueNodeConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:33
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.crypto.PubKey;

/**
* peer节点IP
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueNodeConfig implements MsgQueueNodeSettings {

private String address;

private PubKey pubKey;

public MsgQueueNodeConfig setAddress(String address) {
this.address = address;
return this;
}

public MsgQueueNodeConfig setPubKey(PubKey pubKey) {
this.pubKey = pubKey;
return this;
}

@Override
public String getAddress() {
return this.address;
}

@Override
public PubKey getPubKey() {
return this.pubKey;
}
}

+ 0
- 72
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueServerConfig.java View File

@@ -1,72 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueServerConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:32
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.consensus.mq.settings.MsgQueueBlockSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueServerSettings;

/**
* peer节点配置
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueServerConfig implements MsgQueueServerSettings {

private MsgQueueBlockSettings blockSettings;

private MsgQueueConsensusSettings consensusSettings;

private MsgQueueNodeSettings nodeSettings;

private String realmName;

public MsgQueueServerConfig setRealmName(String realmName) {
this.realmName = realmName;
return this;
}

public MsgQueueServerConfig setBlockSettings(MsgQueueBlockSettings blockSettings) {
this.blockSettings = blockSettings;
return this;
}

public MsgQueueServerConfig setConsensusSettings(MsgQueueConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
return setBlockSettings(consensusSettings.getBlockSettings());
}

public MsgQueueServerConfig setNodeSettings(MsgQueueNodeSettings nodeSettings) {
this.nodeSettings = nodeSettings;
return this;
}

@Override
public String getRealmName() {
return this.realmName;
}

@Override
public MsgQueueNodeSettings getReplicaSettings() {
return nodeSettings;
}

@Override
public MsgQueueBlockSettings getBlockSettings() {
return blockSettings;
}

@Override
public MsgQueueConsensusSettings getConsensusSettings() {
return consensusSettings;
}
}

+ 0
- 105
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/config/MsgQueueSettingsFactory.java View File

@@ -1,105 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueSettingsFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:49
* Description:
*/
package com.jd.blockchain.consensus.mq.config;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consensus.SettingsFactory;
import com.jd.blockchain.consensus.mq.MsgQueueConsensusSettingsBuilder;
import com.jd.blockchain.consensus.mq.settings.MsgQueueBlockSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.utils.io.BytesEncoder;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueSettingsFactory implements SettingsFactory {

static {
DataContractRegistry.register(NodeSettings.class);

DataContractRegistry.register(MsgQueueNodeSettings.class);

DataContractRegistry.register(ConsensusSettings.class);

DataContractRegistry.register(MsgQueueConsensusSettings.class);

DataContractRegistry.register(MsgQueueNetworkSettings.class);

DataContractRegistry.register(MsgQueueBlockSettings.class);

DataContractRegistry.register(MsgQueueClientIncomingSettings.class);

DataContractRegistry.register(ClientIncomingSettings.class);
}

private static final MsgQueueConsensusSettingsEncoder MQCS_ENCODER = new MsgQueueConsensusSettingsEncoder();

private static final MsgQueueClientIncomingSettingsEncoder MQCIS_ENCODER = new MsgQueueClientIncomingSettingsEncoder();

private static final MsgQueueConsensusSettingsBuilder BUILDER = new MsgQueueConsensusSettingsBuilder();

@Override
public MsgQueueConsensusSettingsBuilder getConsensusSettingsBuilder() {
return BUILDER;
}

@Override
public BytesEncoder<ConsensusSettings> getConsensusSettingsEncoder() {
return MQCS_ENCODER;
}

@Override
public BytesEncoder<ClientIncomingSettings> getIncomingSettingsEncoder() {
return MQCIS_ENCODER;
}

private static class MsgQueueConsensusSettingsEncoder implements BytesEncoder<ConsensusSettings>{

@Override
public byte[] encode(ConsensusSettings data) {
if (data instanceof MsgQueueConsensusSettings) {
return BinaryProtocol.encode(data, MsgQueueConsensusSettings.class);
}
throw new IllegalArgumentException("Settings data isn't supported! Accept MsgQueueConsensusSettings only!");
}

@Override
public MsgQueueConsensusSettings decode(byte[] bytes) {
return BinaryProtocol.decodeAs(bytes, MsgQueueConsensusSettings.class);
}
}

private static class MsgQueueClientIncomingSettingsEncoder implements BytesEncoder<ClientIncomingSettings>{

@Override
public byte[] encode(ClientIncomingSettings data) {
if (data instanceof MsgQueueClientIncomingSettings) {
return BinaryProtocol.encode(data, MsgQueueClientIncomingSettings.class);
}
throw new IllegalArgumentException("Settings data isn't supported! Accept MsgQueueClientIncomingSettings only!");
}

@Override
public MsgQueueClientIncomingSettings decode(byte[] bytes) {
return BinaryProtocol.decodeAs(bytes, MsgQueueClientIncomingSettings.class);
}

}
}

+ 0
- 44
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/AbstractConsumer.java View File

@@ -1,44 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.consumer.AbstractConsumer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/29 下午12:31
* Description:
*/
package com.jd.blockchain.consensus.mq.consumer;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.event.EventProducer;
import com.jd.blockchain.consensus.mq.exchange.BytesEventFactory;
import com.jd.blockchain.consensus.mq.exchange.BytesEventProducer;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

/**
*
* @author shaozhuguang
* @create 2018/12/29
* @since 1.0.0
*/

public abstract class AbstractConsumer implements MsgQueueConsumer {

protected EventProducer eventProducer;

protected void initEventHandler(EventHandler eventHandler) {
Disruptor<EventEntity<byte[]>> disruptor =
new Disruptor<>(new BytesEventFactory(),
BytesEventFactory.BUFFER_SIZE, r -> {
return new Thread(r);
}, ProducerType.SINGLE, new BlockingWaitStrategy());

disruptor.handleEventsWith(eventHandler);
disruptor.start();
RingBuffer<EventEntity<byte[]>> ringBuffer = disruptor.getRingBuffer();
this.eventProducer = new BytesEventProducer(ringBuffer);
}
}

+ 0
- 28
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/MsgQueueConsumer.java View File

@@ -1,28 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: MsgQueueConsumer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:38
* Description:
*/
package com.jd.blockchain.consensus.mq.consumer;

import com.lmax.disruptor.EventHandler;

import java.io.Closeable;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public interface MsgQueueConsumer extends Closeable {

void connect(EventHandler eventHandler) throws Exception;

void start() throws Exception;
}


+ 0
- 76
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/NatsConsumer.java View File

@@ -1,76 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.nats.RabbitConsumer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:40
* Description:
*/
package com.jd.blockchain.consensus.mq.consumer;

import com.jd.blockchain.utils.ConsoleUtils;
import com.lmax.disruptor.EventHandler;
import io.nats.client.*;

import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class NatsConsumer extends AbstractConsumer implements MsgQueueConsumer {

private final ExecutorService msgListener = Executors.newSingleThreadExecutor();

private Connection nc;

private Subscription sub;

private String server;

private String topic;

public NatsConsumer(String server, String topic) {
this.server = server;
this.topic = topic;
}

@Override
public void connect(EventHandler eventHandler) throws Exception {
initEventHandler(eventHandler);
Options options = new Options.Builder().server(server).noReconnect().build();
this.nc = Nats.connect(options);
this.sub = nc.subscribe(topic);
this.nc.flush(Duration.ZERO);
ConsoleUtils.info("[*] NatsConsumer[%s, %s] connect success !!!", this.server, this.topic);
}

@Override
public void start() {
msgListener.execute(() -> {
for (;;) {
try {
Message msg = this.sub.nextMessage(Duration.ZERO);
eventProducer.publish(msg.getData());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

@Override
public void close() throws IOException {
try {
nc.close();
} catch (Exception e) {
throw new IOException(e);
}
}
}

+ 0
- 92
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/consumer/RabbitConsumer.java View File

@@ -1,92 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.nats.RabbitConsumer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:40
* Description:
*/
package com.jd.blockchain.consensus.mq.consumer;

import com.jd.blockchain.consensus.mq.factory.RabbitFactory;
import com.jd.blockchain.utils.ConsoleUtils;
import com.lmax.disruptor.EventHandler;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class RabbitConsumer extends AbstractConsumer implements MsgQueueConsumer {

private Connection connection;

private Channel channel;

private String exchangeName;

private String server;

private String queueName;

public RabbitConsumer(String server, String topic) {
this.server = server;
this.exchangeName = topic;
}

private void rabbitConsumerHandle() throws Exception {
rabbitConsumerHandleByQueue();
}

private void rabbitConsumerHandleByQueue() throws IOException {
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) {
// 此处将收到的消息加入队列即可
try {
eventProducer.publish(body);
channel.basicAck(envelope.getDeliveryTag(), false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
this.channel.basicConsume(this.queueName, false, consumer);
}

@Override
public void connect(EventHandler eventHandler) throws Exception {
initEventHandler(eventHandler);
ConnectionFactory factory = RabbitFactory.initConnectionFactory(server);
connection = factory.newConnection();
channel = connection.createChannel();

channel.exchangeDeclare(this.exchangeName, "fanout");
queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, this.exchangeName, "");
channel.basicQos(8);

ConsoleUtils.info("[*] RabbitConsumer[%s, %s] connect success !!!", this.server, this.exchangeName);
}

@Override
public void start() throws Exception {
rabbitConsumerHandle();
}

@Override
public void close() throws IOException {
try {
this.channel.close();
this.connection.close();
} catch (Exception e) {
throw new IOException(e);
}
}
}

+ 0
- 64
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/BlockEvent.java View File

@@ -1,64 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: BlockEvent
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/20 上午11:32
* Description:
*/
package com.jd.blockchain.consensus.mq.event;

import com.jd.blockchain.consensus.mq.util.MessageConvertUtil;

import java.util.HashMap;
import java.util.Map;

/**
*
* @author shaozhuguang
* @create 2018/11/20
* @since 1.0.0
*/

public class BlockEvent {

private Map<String, String> txMap = new HashMap<>();

public Map<String, String> getTxMap() {
return txMap;
}

public void setTxMap(Map<String, String> txMap) {
this.txMap = txMap;
}

public void put(String txKey, String txResp) {
txMap.put(txKey, txResp);
}

public void put(String txKey, byte[] txResp) {
put(txKey, MessageConvertUtil.base64Encode(txResp));
}

public String getTxResp(String txKey) {
return txMap.get(txKey);
}

public byte[] getTxRespBytes(String txKey) {
String txResp = getTxResp(txKey);
if (txResp != null && txResp.length() > 0) {
// 字符串转字节数组
return MessageConvertUtil.base64Decode(txResp);
}
return null;
}

public boolean containTxResp(String txKey) {
return txMap.containsKey(txKey);
}

public boolean isEmpty() {
if (txMap == null) return true;
return txMap.isEmpty();
}
}

+ 0
- 44
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/MessageEvent.java View File

@@ -1,44 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.peer.consensus.MessageEvent
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/23 上午11:45
* Description:
*/
package com.jd.blockchain.consensus.mq.event;

/**
*
* @author shaozhuguang
* @create 2018/11/23
* @since 1.0.0
*/

public class MessageEvent {

String messageKey;

byte[] message;

public MessageEvent(String messageKey, byte[] message) {
this.messageKey = messageKey;
this.message = message;
}

public String getMessageKey() {
return messageKey;
}

public void setMessageKey(String messageKey) {
this.messageKey = messageKey;
}

public byte[] getMessage() {
return message;
}

public void setMessage(byte[] message) {
this.message = message;
}
}

+ 0
- 58
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/event/TxBlockedEvent.java View File

@@ -1,58 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: BlockEvent
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/20 上午11:32
* Description:
*/
package com.jd.blockchain.consensus.mq.event;


import com.jd.blockchain.consensus.mq.util.MessageConvertUtil;

/**
*
* @author shaozhuguang
* @create 2018/11/20
* @since 1.0.0
*/

public class TxBlockedEvent {

private String txKey;

private String transaction;

public TxBlockedEvent() {
}

public TxBlockedEvent(String txKey, String transaction) {
this.txKey = txKey;
this.transaction = transaction;
}

public void setTxKey(String txKey) {
this.txKey = txKey;
}

public void setTransaction(String transaction) {
this.transaction = transaction;
}

public String getTxKey() {
return txKey;
}

public String getTransaction() {
return transaction;
}

public byte[] txResponseBytes() {
if (transaction != null && transaction.length() > 0) {
// 字符串转字节数组
return MessageConvertUtil.base64Decode(transaction);
}
return null;
}
}

+ 0
- 30
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/BytesEventFactory.java View File

@@ -1,30 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.rabbitmq.nats.consensus.disruptor.ExchangeEventFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 上午10:48
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

import com.jd.blockchain.consensus.event.EventEntity;
import com.lmax.disruptor.EventFactory;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class BytesEventFactory implements EventFactory<EventEntity<byte[]>> {

public static final int BUFFER_SIZE = 256 * 1024;
// public static final int BUFFER_SIZE = 8 * 1024;

@Override
public EventEntity<byte[]> newInstance() {
return new EventEntity<>();
}
}

+ 0
- 40
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/BytesEventProducer.java View File

@@ -1,40 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.rabbitmq.nats.consensus.disruptor.ExchangeEventProducer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 上午10:50
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.event.EventProducer;
import com.lmax.disruptor.RingBuffer;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class BytesEventProducer implements EventProducer<byte[]> {

private final RingBuffer<EventEntity<byte[]>> ringBuffer;

public BytesEventProducer(RingBuffer<EventEntity<byte[]>> ringBuffer) {
this.ringBuffer = ringBuffer;
}

@Override
public void publish(byte[] entity) {
long sequence = ringBuffer.next();
try {
EventEntity<byte[]> event = ringBuffer.get(sequence);
event.setEntity(entity);
} finally {
this.ringBuffer.publish(sequence);
}
}
}

+ 0
- 31
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEntityFactory.java View File

@@ -1,31 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.ExchangeEntityFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午4:08
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class ExchangeEntityFactory {

public static ExchangeEventInnerEntity newBlockInstance() {
return new ExchangeEventInnerEntity(ExchangeType.BLOCK);
}

public static ExchangeEventInnerEntity newEmptyInstance() {
return new ExchangeEventInnerEntity(ExchangeType.EMPTY);
}

public static ExchangeEventInnerEntity newTransactionInstance(byte[] content) {
return new ExchangeEventInnerEntity(ExchangeType.TRANSACTION, content);
}
}

+ 0
- 30
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventFactory.java View File

@@ -1,30 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.rabbitmq.nats.consensus.disruptor.ExchangeEventFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 上午10:48
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

import com.jd.blockchain.consensus.event.EventEntity;
import com.lmax.disruptor.EventFactory;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class ExchangeEventFactory implements EventFactory<EventEntity<ExchangeEventInnerEntity>> {

public static final int BUFFER_SIZE = 256 * 1024;
// public static final int BUFFER_SIZE = 8 * 1024;

@Override
public EventEntity<ExchangeEventInnerEntity> newInstance() {
return new EventEntity<>();
}
}

+ 0
- 53
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventInnerEntity.java View File

@@ -1,53 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.ExchangeEventInnerEntity
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午4:04
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class ExchangeEventInnerEntity {

private ExchangeType type;

private byte[] content;

public ExchangeEventInnerEntity() {
}

public ExchangeEventInnerEntity(ExchangeType type) {
this.type = type;
}

public ExchangeEventInnerEntity(ExchangeType type, byte[] content) {
this.type = type;
this.content = content;
}



public ExchangeType getType() {
return type;
}

public void setType(ExchangeType type) {
this.type = type;
}

public byte[] getContent() {
return content;
}

public void setContent(byte[] content) {
this.content = content;
}
}

+ 0
- 40
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeEventProducer.java View File

@@ -1,40 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.rabbitmq.nats.consensus.disruptor.ExchangeEventProducer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 上午10:50
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.event.EventProducer;
import com.lmax.disruptor.RingBuffer;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class ExchangeEventProducer implements EventProducer<ExchangeEventInnerEntity> {

private final RingBuffer<EventEntity<ExchangeEventInnerEntity>> ringBuffer;

public ExchangeEventProducer(RingBuffer<EventEntity<ExchangeEventInnerEntity>> ringBuffer) {
this.ringBuffer = ringBuffer;
}

@Override
public void publish(ExchangeEventInnerEntity entity) {
long sequence = ringBuffer.next();
try {
EventEntity<ExchangeEventInnerEntity> event = ringBuffer.get(sequence);
event.setEntity(entity);
} finally {
this.ringBuffer.publish(sequence);
}
}
}

+ 0
- 23
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/exchange/ExchangeType.java View File

@@ -1,23 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.nats.ExchangeType
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午3:34
* Description:
*/
package com.jd.blockchain.consensus.mq.exchange;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public enum ExchangeType {
BLOCK,
EMPTY,
TRANSACTION,
;
}

+ 0
- 23
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/MsgQueueConfig.java View File

@@ -1,23 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.factory.MsgQueueConfig
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午5:16
* Description:
*/
package com.jd.blockchain.consensus.mq.factory;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public final class MsgQueueConfig {

public static final String NATS_PREFIX = "nats";

public static final String RABBIT_PREFIX = "rabbit";
}

+ 0
- 52
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/MsgQueueFactory.java View File

@@ -1,52 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: MsgQueueFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:13
* Description:
*/
package com.jd.blockchain.consensus.mq.factory;


import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;

import static com.jd.blockchain.consensus.mq.factory.MsgQueueConfig.NATS_PREFIX;
import static com.jd.blockchain.consensus.mq.factory.MsgQueueConfig.RABBIT_PREFIX;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class MsgQueueFactory {

public static MsgQueueProducer newProducer(String server, String topic) {
try {
if (server.startsWith(NATS_PREFIX)) {
return NatsFactory.newProducer(server, topic);
} else if (server.startsWith(RABBIT_PREFIX)) {
return RabbitFactory.newProducer(server, topic);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}

public static MsgQueueConsumer newConsumer(String server, String topic) {
try {
if (server.startsWith(NATS_PREFIX)) {
return NatsFactory.newConsumer(server, topic);
} else if (server.startsWith(RABBIT_PREFIX)) {
return RabbitFactory.newConsumer(server, topic);
}
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

+ 0
- 32
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/NatsFactory.java View File

@@ -1,32 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: NatsFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:15
* Description:
*/
package com.jd.blockchain.consensus.mq.factory;

import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.consumer.NatsConsumer;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.producer.NatsProducer;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class NatsFactory {

public static MsgQueueProducer newProducer(String server, String topic) throws Exception {
return new NatsProducer(server, topic);
}

public static MsgQueueConsumer newConsumer(String server, String topic) throws Exception {
return new NatsConsumer(server, topic);
}
}

+ 0
- 52
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/factory/RabbitFactory.java View File

@@ -1,52 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.nats.RabbitFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:15
* Description:
*/
package com.jd.blockchain.consensus.mq.factory;

import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.consumer.RabbitConsumer;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.producer.RabbitProducer;
import com.rabbitmq.client.ConnectionFactory;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class RabbitFactory {

public static MsgQueueProducer newProducer(String server, String topic) throws Exception {
return new RabbitProducer(server, topic);
}

public static MsgQueueConsumer newConsumer(String server, String topic) throws Exception {
return new RabbitConsumer(server, topic);
}

public static ConnectionFactory initConnectionFactory(String server) {
ConnectionFactory factory = new ConnectionFactory();
// 解析server,生成host+port,默认格式:rabbit://localhost:5672
try {
String[] hostAndPort = server.split("//")[1].split(":");
if (hostAndPort == null || hostAndPort.length == 0) {
factory.setHost("localhost");
} else if (hostAndPort.length == 1) {
factory.setHost(hostAndPort[0]);
} else {
factory.setHost(hostAndPort[0]);
factory.setPort(Integer.parseInt(hostAndPort[1]));
}
} catch (Exception e) {
factory.setHost("localhost");
}
return factory;
}
}

+ 0
- 36
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/MsgQueueProducer.java View File

@@ -1,36 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: MsgQueueProducer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:37
* Description:
*/
package com.jd.blockchain.consensus.mq.producer;

import java.io.Closeable;
import java.util.List;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public interface MsgQueueProducer extends Closeable {

void connect() throws Exception;

void publish(byte[] message) throws Exception;

void publishString(String message) throws Exception;

void publishStringList(List<String> messages) throws Exception;

void publishStringArray(String[] messages) throws Exception;

void publishBytesArray(byte[][] message) throws Exception;

void publishBytesList(List<byte[]> messages) throws Exception;
}

+ 0
- 100
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/NatsProducer.java View File

@@ -1,100 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: NatsProducer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:39
* Description:
*/
package com.jd.blockchain.consensus.mq.producer;

import io.nats.client.Connection;
import io.nats.client.Nats;
import io.nats.client.Options;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

import com.jd.blockchain.utils.ConsoleUtils;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class NatsProducer implements MsgQueueProducer {

// 主要操作:发送MQ请求
private Connection nc;

private String server;

// 主题
private String topic;

public NatsProducer() {

}

public NatsProducer(String server, String topic) {
this.topic = topic;
this.server = server;
}

@Override
public void connect() throws Exception{
Options o = new Options.Builder().server(server).noReconnect().build();
this.nc = Nats.connect(o);
ConsoleUtils.info("[*] NatsProducer[%s, %s] connect success !!!", this.server, this.topic);
}

@Override
public void publish(byte[] message) {
nc.publish(topic, message);
}

@Override
public void publishString(String message) {
publish(message.getBytes(StandardCharsets.UTF_8));
}

@Override
public void publishStringList(List<String> messages) {
for (String message : messages) {
publishString(message);
}
}

@Override
public void publishStringArray(String[] messages) {
for (String message : messages) {
publishString(message);
}
}

@Override
public void publishBytesArray(byte[][] message) {
for (byte[] bytes : message) {
publish(bytes);
}
}

@Override
public void publishBytesList(List<byte[]> messages) {
for (byte[] message : messages) {
publish(message);
}
}

@Override
public void close() throws IOException {
try {
nc.close();
} catch (Exception e) {
throw new IOException(e);
}
}
}

+ 0
- 106
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/producer/RabbitProducer.java View File

@@ -1,106 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.nats.RabbitProducer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/5 下午10:39
* Description:
*/
package com.jd.blockchain.consensus.mq.producer;

import com.jd.blockchain.consensus.mq.factory.RabbitFactory;
import com.jd.blockchain.utils.ConsoleUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
*
* @author shaozhuguang
* @create 2018/11/5
* @since 1.0.0
*/

public class RabbitProducer implements MsgQueueProducer {

// 主要操作时发送JMQ请求
private Channel channel;

private Connection connection;

private String exchangeName;

private String server;

public RabbitProducer() {

}

public RabbitProducer(String server, String topic) throws Exception {
this.exchangeName = topic;
this.server = server;
}

@Override
public void connect() throws Exception {
ConnectionFactory factory = RabbitFactory.initConnectionFactory(server);
connection = factory.newConnection();
channel = connection.createChannel();
channel.exchangeDeclare(this.exchangeName, "fanout");
ConsoleUtils.info("[*] RabbitProducer[%s, %s] connect success !!!", this.server, this.exchangeName);
}

@Override
public void publish(byte[] message) throws Exception {
channel.basicPublish(this.exchangeName, "", null, message);
}

@Override
public void publishString(String message) throws Exception {
publish(message.getBytes(StandardCharsets.UTF_8));
}

@Override
public void publishStringList(List<String> messages) throws Exception {
for (String message : messages) {
publishString(message);
}
}

@Override
public void publishStringArray(String[] messages) throws Exception {
for (String message : messages) {
publishString(message);
}
}

@Override
public void publishBytesArray(byte[][] message) throws Exception {
for (byte[] bytes : message) {
publish(bytes);
}
}

@Override
public void publishBytesList(List<byte[]> messages) throws Exception {
for (byte[] message : messages) {
publish(message);
}
}

@Override
public void close() throws IOException {
try {
channel.close();
connection.close();
} catch (Exception e) {
throw new IOException(e);
}
}


}

+ 0
- 297
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/DefaultMsgQueueMessageDispatcher.java View File

@@ -1,297 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.server.DefaultMsgQueueMessageDispatcher
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 上午11:05
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.event.EventProducer;
import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.exchange.ExchangeEntityFactory;
import com.jd.blockchain.consensus.mq.exchange.ExchangeEventFactory;
import com.jd.blockchain.consensus.mq.exchange.ExchangeEventInnerEntity;
import com.jd.blockchain.consensus.mq.exchange.ExchangeEventProducer;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.io.IOException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public class DefaultMsgQueueMessageDispatcher implements MsgQueueMessageDispatcher, EventHandler<EventEntity<byte[]>> {

private static final byte[] blockCommitBytes = new byte[]{0x00};

private final BlockingQueue<byte[]> dataQueue = new ArrayBlockingQueue<>(1024 * 16);

private final ExecutorService dataExecutor = Executors.newSingleThreadExecutor();

private final ScheduledThreadPoolExecutor timeHandleExecutor = new ScheduledThreadPoolExecutor(2);

private final AtomicLong blockIndex = new AtomicLong();

private long syncIndex = 0L;

private MsgQueueProducer txProducer;

private MsgQueueConsumer txConsumer;

private EventProducer eventProducer;

private EventHandler eventHandler;

private final int TX_SIZE_PER_BLOCK;

private final long MAX_DELAY_MILLISECONDS_PER_BLOCK;

private boolean isRunning;

private boolean isConnected;

public DefaultMsgQueueMessageDispatcher(int txSizePerBlock, long maxDelayMilliSecondsPerBlock) {
this.TX_SIZE_PER_BLOCK = txSizePerBlock;
this.MAX_DELAY_MILLISECONDS_PER_BLOCK = maxDelayMilliSecondsPerBlock;
}

public DefaultMsgQueueMessageDispatcher setTxProducer(MsgQueueProducer txProducer) {
this.txProducer = txProducer;
return this;
}

public DefaultMsgQueueMessageDispatcher setTxConsumer(MsgQueueConsumer txConsumer) {
this.txConsumer = txConsumer;
return this;
}

public DefaultMsgQueueMessageDispatcher setEventHandler(EventHandler eventHandler) {
this.eventHandler = eventHandler;
return this;
}

public void init() {
handleDisruptor(eventHandler);
}

private void handleDisruptor(EventHandler eventHandler) {
Disruptor<EventEntity<ExchangeEventInnerEntity>> disruptor =
new Disruptor<>(new ExchangeEventFactory(),
ExchangeEventFactory.BUFFER_SIZE, r -> {
return new Thread(r);
}, ProducerType.SINGLE, new BlockingWaitStrategy());

disruptor.handleEventsWith(eventHandler);
disruptor.start();
RingBuffer<EventEntity<ExchangeEventInnerEntity>> ringBuffer = disruptor.getRingBuffer();

this.eventProducer = new ExchangeEventProducer(ringBuffer);
}

public synchronized void connect() throws Exception {
if (!isConnected) {
txProducer.connect();
txConsumer.connect(this);
isConnected = true;
}
}

@Override
public synchronized void stop() throws Exception {
isRunning = false;
close();
}

@Override
public void run() {
this.isRunning = true;
try {
txConsumer.start();
} catch (Exception e) {

}
// handleData();
// listen();
}

// private void listen() {
// while (isRunning) {
// try {
// byte[] data = this.txConsumer.start();
// dataQueue.put(data);
// // 收到数据后由队列处理
//// handleData(data);
// } catch (Exception e) {
// // 日志打印
// ConsoleUtils.info("ERROR dispatcher start data exception {%s}", e.getMessage());
// }
// }
// }

// private void handleData() {
// dataExecutor.execute(() -> {
// byte[] data;
// for (;;) {
// try {
// data = dataQueue.take();
// if (data.length == 1) {
// // 结块标识优先处理
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// } else {
// if (syncIndex == 0) { // 收到第一个交易
// // 需要判断是否需要进行定时任务
// if (MAX_DELAY_MILLISECONDS_PER_BLOCK > 0) {
// this.timeHandleExecutor.schedule(
// timeBlockTask(this.blockIndex.get()),
// MAX_DELAY_MILLISECONDS_PER_BLOCK, TimeUnit.MILLISECONDS);
// }
// }
// syncIndex++;
// eventProducer.publish(ExchangeEntityFactory.newTransactionInstance(data));
// if (syncIndex == TX_SIZE_PER_BLOCK) {
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// }
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// });
// for (;;) {
// try {
// final byte[] data = dataQueue.take();
// dataExecutor.execute(() -> {
// if (data.length == 1) {
// // 结块标识优先处理
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// } else {
// if (syncIndex == 0) { // 收到第一个交易
// // 需要判断是否需要进行定时任务
// if (MAX_DELAY_MILLISECONDS_PER_BLOCK > 0) {
// this.timeHandleExecutor.schedule(
// timeBlockTask(this.blockIndex.get()),
// MAX_DELAY_MILLISECONDS_PER_BLOCK, TimeUnit.MILLISECONDS);
// }
// }
// syncIndex++;
// eventProducer.publish(ExchangeEntityFactory.newTransactionInstance(data));
// if (syncIndex == TX_SIZE_PER_BLOCK) {
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// }
// }
// }
// );
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// }

// private void handleData(final byte[] data) {
// dataExecutor.execute(() -> {
// try {
// if (data.length == 1) {
// // 结块标识优先处理
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// } else {
// if (syncIndex == 0) { // 收到第一个交易
// // 需要判断是否需要进行定时任务
// if (MAX_DELAY_MILLISECONDS_PER_BLOCK > 0) {
// this.timeHandleExecutor.schedule(
// timeBlockTask(this.blockIndex.get()),
// MAX_DELAY_MILLISECONDS_PER_BLOCK, TimeUnit.MILLISECONDS);
// }
// }
// syncIndex++;
// eventProducer.publish(ExchangeEntityFactory.newTransactionInstance(data));
// if (syncIndex == TX_SIZE_PER_BLOCK) {
// syncIndex = 0L;
// this.blockIndex.getAndIncrement();
// eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
// }
// }
// } catch (Exception e) {
// // 记录日志
// ConsoleUtils.info("ERROR TransactionDispatcher process queue data exception {%s}", e.getMessage());
// }
// });
//
// }

private Runnable timeBlockTask(final long currentBlockIndex) {
return () -> {
final boolean isEqualBlock = this.blockIndex.compareAndSet(
currentBlockIndex, currentBlockIndex + 1);
if (isEqualBlock) {
try {
txProducer.publish(blockCommitBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}

@Override
public void close() throws IOException {
this.txProducer.close();
this.txConsumer.close();
}

@Override
public void onEvent(EventEntity<byte[]> event, long sequence, boolean endOfBatch) throws Exception {
try {
byte[] data = event.getEntity();
// System.out.printf("Thread [%s, $s] on event !!!\r\n",
// Thread.currentThread().getId(), Thread.currentThread().getName());
if (data.length == 1) {
// 结块标识优先处理
syncIndex = 0L;
this.blockIndex.getAndIncrement();
eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
} else {
if (syncIndex == 0) { // 收到第一个交易
// 需要判断是否需要进行定时任务
if (MAX_DELAY_MILLISECONDS_PER_BLOCK > 0) {
this.timeHandleExecutor.schedule(
timeBlockTask(this.blockIndex.get()),
MAX_DELAY_MILLISECONDS_PER_BLOCK, TimeUnit.MILLISECONDS);
}
}
syncIndex++;
eventProducer.publish(ExchangeEntityFactory.newTransactionInstance(data));
if (syncIndex == TX_SIZE_PER_BLOCK) {
syncIndex = 0L;
this.blockIndex.getAndIncrement();
eventProducer.publish(ExchangeEntityFactory.newBlockInstance());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

+ 0
- 126
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/ExtendMsgQueueMessageExecutor.java View File

@@ -1,126 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.server.DefaultMsgQueueMessageDispatcher
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 上午11:05
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.service.MessageHandle;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.lmax.disruptor.EventHandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public class ExtendMsgQueueMessageExecutor implements MsgQueueMessageDispatcher, EventHandler<EventEntity<byte[]>> {

private static final Logger LOGGER = LoggerFactory.getLogger(ExtendMsgQueueMessageExecutor.class);

private final ExecutorService dataExecutor = Executors.newSingleThreadExecutor();

private MsgQueueProducer msgProducer;

private MsgQueueConsumer msgConsumer;

private MessageHandle messageHandle;

private boolean isRunning;

private boolean isConnected;

public ExtendMsgQueueMessageExecutor setMsgProducer(MsgQueueProducer msgProducer) {
this.msgProducer = msgProducer;
return this;
}

public ExtendMsgQueueMessageExecutor setMsgConsumer(MsgQueueConsumer msgConsumer) {
this.msgConsumer = msgConsumer;
return this;
}

public ExtendMsgQueueMessageExecutor setMessageHandle(MessageHandle messageHandle) {
this.messageHandle = messageHandle;
return this;
}

@Override
public void init() {
// do nothing
}

public synchronized void connect() throws Exception {
if (!isConnected) {
msgProducer.connect();
msgConsumer.connect(this);
msgConsumer.start();
isConnected = true;
}
}

@Override
public synchronized void stop() throws Exception {
isRunning = false;
close();
}

@Override
public void run() {
this.isRunning = true;
// this.msgConsumer.start();
// listen();
}

// private void listen() {
// while (isRunning) {
// try {
// byte[] data = this.msgConsumer.start();
// // 收到数据后由队列处理
// handleData(data);
// } catch (Exception e) {
// // 日志打印
// LOGGER.error("extend message handle exception {}", e.getMessage());
// }
// }
// }

private void handleData(byte[] data) {
dataExecutor.execute(() -> {
try {
AsyncFuture<byte[]> result = messageHandle.processUnordered(data);
msgProducer.publish(result.get());
} catch (Exception e) {
LOGGER.error("process Unordered message exception {}", e.getMessage());
}
});
}

@Override
public void close() throws IOException {
isConnected = false;
this.msgProducer.close();
this.msgConsumer.close();
}

@Override
public void onEvent(EventEntity<byte[]> event, long sequence, boolean endOfBatch) throws Exception {
byte[] data = event.getEntity();
handleData(data);
}
}

+ 0
- 70
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueConsensusManageService.java View File

@@ -1,70 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.server.MsgQueueConsensusManageService
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 下午1:46
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import java.util.Arrays;

import com.jd.blockchain.consensus.ClientIdentification;
import com.jd.blockchain.consensus.ConsensusManageService;
import com.jd.blockchain.consensus.ConsensusSecurityException;
import com.jd.blockchain.consensus.mq.config.MsgQueueClientIncomingConfig;
import com.jd.blockchain.consensus.mq.settings.MsgQueueClientIncomingSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureFunction;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueConsensusManageService implements ConsensusManageService {

private MsgQueueConsensusSettings consensusSettings;

public MsgQueueConsensusManageService setConsensusSettings(MsgQueueConsensusSettings consensusSettings) {
this.consensusSettings = consensusSettings;
return this;
}

@Override
public MsgQueueClientIncomingSettings authClientIncoming(ClientIdentification authId) throws ConsensusSecurityException {
boolean isLegal = isLegal(authId);
if (isLegal) {
MsgQueueClientIncomingSettings mqcis = new MsgQueueClientIncomingConfig()
.setPubKey(authId.getPubKey())
.setClientId(clientId(authId.getIdentityInfo()))
.setConsensusSettings(this.consensusSettings)
;
return mqcis;
}
return null;
}

private int clientId(byte[] identityInfo) {
// todo

return 0;
}

public boolean isLegal(ClientIdentification authId) {
boolean isLegal = false;
PubKey pubKey = authId.getPubKey();
byte[] identityInfo = authId.getIdentityInfo();
byte[] address = pubKey.toBytes(); // 使用公钥地址作为认证信息
if (Arrays.equals(address, identityInfo)) {
SignatureFunction signatureFunction = Crypto.getSignatureFunction(pubKey.getAlgorithm());
isLegal = signatureFunction.verify(authId.getSignature(), pubKey, identityInfo);
}
return isLegal;
}
}

+ 0
- 28
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueMessageDispatcher.java View File

@@ -1,28 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.server.MsgQueueMessageDispatcher
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:30
* Description:
*/
package com.jd.blockchain.consensus.mq.server;


import java.io.Closeable;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public interface MsgQueueMessageDispatcher extends Runnable, Closeable {

void init();

void connect() throws Exception;

void stop() throws Exception;
}

+ 0
- 182
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueMessageExecutor.java View File

@@ -1,182 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.server.MsgQueueMessageExecutor
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午2:10
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import com.jd.blockchain.consensus.event.EventEntity;
import com.jd.blockchain.consensus.mq.event.MessageEvent;
import com.jd.blockchain.consensus.mq.event.TxBlockedEvent;
import com.jd.blockchain.consensus.mq.exchange.ExchangeEventInnerEntity;
import com.jd.blockchain.consensus.mq.exchange.ExchangeType;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.util.MessageConvertUtil;
import com.jd.blockchain.consensus.service.MessageHandle;
import com.jd.blockchain.consensus.service.StateMachineReplicate;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.utils.concurrent.AsyncFuture;
import com.lmax.disruptor.EventHandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public class MsgQueueMessageExecutor implements EventHandler<EventEntity<ExchangeEventInnerEntity>> {

private static final Logger LOGGER = LoggerFactory.getLogger(MsgQueueMessageExecutor.class);

// todo 暂不处理队列溢出导致的OOM
private final ExecutorService blockEventExecutor = Executors.newFixedThreadPool(10);

private MsgQueueProducer blProducer;

private List<MessageEvent> exchangeEvents = new ArrayList<>();

private String realmName;

private MessageHandle messageHandle;

private final AtomicInteger messageId = new AtomicInteger();

private int txSizePerBlock = 1000;

private StateMachineReplicate stateMachineReplicator;

public MsgQueueMessageExecutor setRealmName(String realmName) {
this.realmName = realmName;
return this;
}

public MsgQueueMessageExecutor setBlProducer(MsgQueueProducer blProducer) {
this.blProducer = blProducer;
return this;
}

public MsgQueueMessageExecutor setTxSizePerBlock(int txSizePerBlock) {
this.txSizePerBlock = txSizePerBlock;
return this;
}

public MsgQueueMessageExecutor setMessageHandle(MessageHandle messageHandle) {
this.messageHandle = messageHandle;
return this;
}

public MsgQueueMessageExecutor setStateMachineReplicator(StateMachineReplicate stateMachineReplicator) {
this.stateMachineReplicator = stateMachineReplicator;
return this;
}

public MsgQueueMessageExecutor init() {
try {
long latestStateId = stateMachineReplicator.getLatestStateID(realmName);
// 设置基础消息ID
messageId.set(((int)latestStateId + 1) * txSizePerBlock);
blProducer.connect();
} catch (Exception e) {
throw new RuntimeException(e);
}
return this;
}

@Override
public void onEvent(EventEntity<ExchangeEventInnerEntity> event, long sequence, boolean endOfBatch) throws Exception {
ExchangeEventInnerEntity entity = event.getEntity();
if (entity != null) {
if (entity.getType() == ExchangeType.BLOCK || entity.getType() == ExchangeType.EMPTY) {
if (!exchangeEvents.isEmpty()) {
process(exchangeEvents);
exchangeEvents.clear();
}
} else {
byte[] bytes = event.getEntity().getContent();
String key = bytes2Key(bytes);
exchangeEvents.add(new MessageEvent(key, bytes));
}
}
}

private void process(List<MessageEvent> messageEvents) {
if (messageEvents != null && !messageEvents.isEmpty()) {
try {
Map<String, AsyncFuture<byte[]>> txResponseMap = execute(messageEvents);
if (txResponseMap != null && !txResponseMap.isEmpty()) {
// byte[] asyncFuture;
for (Map.Entry<String, AsyncFuture<byte[]>> entry : txResponseMap.entrySet()) {
final String txKey = entry.getKey();
final AsyncFuture<byte[]> asyncFuture = entry.getValue();
// asyncFuture = entry.getValue().get();

blockEventExecutor.execute(() -> {
TxBlockedEvent txBlockedEvent = new TxBlockedEvent(txKey,
MessageConvertUtil.base64Encode(asyncFuture.get()));
byte[] serializeBytes = MessageConvertUtil.serializeTxBlockedEvent(txBlockedEvent);
// 通过消息队列发送该消息
try {
this.blProducer.publish(serializeBytes);
} catch (Exception e) {
LOGGER.error("publish block event message exception {}", e.getMessage());
}
});
}
}
} catch (Exception e) {
// 打印日志
LOGGER.error("process message exception {}", e.getMessage());
}
}
}

private Map<String, AsyncFuture<byte[]>> execute(List<MessageEvent> messageEvents) {
// System.out.printf("Thread[%s %s] execute messageEvents !!! \r\n",
// Thread.currentThread().getId(), Thread.currentThread().getName());
Map<String, AsyncFuture<byte[]>> asyncFutureMap = new HashMap<>();
// 使用MessageHandle处理
// long startTime = System.currentTimeMillis();
// int txSize = messageEvents.size();
String batchId = messageHandle.beginBatch(realmName);
try {
for (MessageEvent messageEvent : messageEvents) {
String txKey = messageEvent.getMessageKey();
byte[] txContent = messageEvent.getMessage();
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(messageId.getAndIncrement(), txContent, realmName, batchId);
asyncFutureMap.put(txKey, asyncFuture);
}
messageHandle.completeBatch(realmName, batchId);
messageHandle.commitBatch(realmName, batchId);
// long totalTime = System.currentTimeMillis() - startTime;
// String content = String.format("batch[%s] process, time = {%s}ms, TPS = %.2f \r\n",
// batchId, totalTime, txSize * 1000.0D / totalTime);
// System.out.println(content);
// logQueue.put(content);
// 提交之后需要获取对应的结果
} catch (Exception e) {
// todo 需要处理应答码 404
messageHandle.rollbackBatch(realmName, batchId, TransactionState.CONSENSUS_ERROR.CODE);
}
return asyncFutureMap;
}


private String bytes2Key(byte[] bytes) {
return MessageConvertUtil.messageKey(bytes);
}
}

+ 0
- 196
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueNodeServer.java View File

@@ -1,196 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.server.MsgQueueNodeServer
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 上午11:20
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider;
import com.jd.blockchain.consensus.mq.consumer.MsgQueueConsumer;
import com.jd.blockchain.consensus.mq.factory.MsgQueueFactory;
import com.jd.blockchain.consensus.mq.producer.MsgQueueProducer;
import com.jd.blockchain.consensus.mq.settings.MsgQueueBlockSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueServerSettings;
import com.jd.blockchain.consensus.service.MessageHandle;
import com.jd.blockchain.consensus.service.NodeServer;
import com.jd.blockchain.consensus.service.StateMachineReplicate;

import java.util.concurrent.Executors;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public class MsgQueueNodeServer implements NodeServer {

private DefaultMsgQueueMessageDispatcher dispatcher;

private ExtendMsgQueueMessageExecutor extendExecutor;

private MessageHandle messageHandle;

private StateMachineReplicate stateMachineReplicator;

private MsgQueueMessageExecutor messageExecutor;

private MsgQueueNetworkSettings networkSettings;

private MsgQueueConsensusManageService manageService;

private int txSizePerBlock = 1000;

private long maxDelayMilliSecondsPerBlock = 1000;

private MsgQueueServerSettings serverSettings;

private boolean isRunning;

public MsgQueueNodeServer setMessageHandle(MessageHandle messageHandle) {
this.messageHandle = messageHandle;
return this;
}

public MsgQueueNodeServer setStateMachineReplicator(StateMachineReplicate stateMachineReplicator) {
this.stateMachineReplicator = stateMachineReplicator;
return this;
}

public MsgQueueNodeServer setTxSizePerBlock(int txSizePerBlock) {
this.txSizePerBlock = txSizePerBlock;
return this;
}

public MsgQueueNodeServer setMaxDelayMilliSecondsPerBlock(long maxDelayMilliSecondsPerBlock) {
this.maxDelayMilliSecondsPerBlock = maxDelayMilliSecondsPerBlock;
return this;
}

public MsgQueueNodeServer setMsgQueueNetworkSettings(MsgQueueNetworkSettings networkSettings) {
this.networkSettings = networkSettings;
return this;
}

public MsgQueueNodeServer setServerSettings(MsgQueueServerSettings serverSettings) {
this.serverSettings = serverSettings;
this.manageService = new MsgQueueConsensusManageService()
.setConsensusSettings(serverSettings.getConsensusSettings());
return this;
}

public MsgQueueNodeServer init() {
String realmName = this.serverSettings.getRealmName();
MsgQueueBlockSettings blockSettings = this.serverSettings.getBlockSettings();
MsgQueueConsensusSettings consensusSettings = this.serverSettings.getConsensusSettings();

this.setTxSizePerBlock(blockSettings.getTxSizePerBlock())
.setMaxDelayMilliSecondsPerBlock(blockSettings.getMaxDelayMilliSecondsPerBlock())
.setMsgQueueNetworkSettings(consensusSettings.getNetworkSettings())
;

String server = networkSettings.getServer(),
txTopic = networkSettings.getTxTopic(),
blTopic = networkSettings.getBlTopic(),
msgTopic = networkSettings.getMsgTopic();

MsgQueueProducer blProducer = MsgQueueFactory.newProducer(server, blTopic),
txProducer = MsgQueueFactory.newProducer(server, txTopic),
msgProducer = MsgQueueFactory.newProducer(server, msgTopic);

MsgQueueConsumer txConsumer = MsgQueueFactory.newConsumer(server, txTopic),
msgConsumer = MsgQueueFactory.newConsumer(server, msgTopic);

initMessageExecutor(blProducer, realmName);

initDispatcher(txProducer, txConsumer);

initExtendExecutor(msgProducer, msgConsumer);

return this;
}

@Override
public String getProviderName() {
return MsgQueueConsensusProvider.NAME;
}

@Override
public MsgQueueConsensusManageService getManageService() {
return this.manageService;
}

@Override
public MsgQueueServerSettings getSettings() {
return serverSettings;
}

@Override
public boolean isRunning() {
return isRunning;
}

@Override
public synchronized void start() {
if (!isRunning) {
try {
dispatcher.connect();
Executors.newSingleThreadExecutor().execute(dispatcher);
extendExecutor.connect();
Executors.newSingleThreadExecutor().execute(extendExecutor);
isRunning = true;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

@Override
public synchronized void stop() {
if (isRunning) {
try {
dispatcher.stop();
extendExecutor.stop();
isRunning = false;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

private void initMessageExecutor(MsgQueueProducer blProducer, final String realmName) {
messageExecutor = new MsgQueueMessageExecutor()
.setRealmName(realmName)
.setMessageHandle(messageHandle)
.setBlProducer(blProducer)
.setStateMachineReplicator(stateMachineReplicator)
.setTxSizePerBlock(txSizePerBlock)
.init()
;
}

private void initDispatcher(MsgQueueProducer txProducer, MsgQueueConsumer txConsumer) {
dispatcher = new DefaultMsgQueueMessageDispatcher(txSizePerBlock, maxDelayMilliSecondsPerBlock)
.setTxProducer(txProducer)
.setTxConsumer(txConsumer)
.setEventHandler(messageExecutor)
;
dispatcher.init();
}


private void initExtendExecutor(MsgQueueProducer msgProducer, MsgQueueConsumer msgConsumer) {
extendExecutor = new ExtendMsgQueueMessageExecutor()
.setMessageHandle(messageHandle)
.setMsgConsumer(msgConsumer)
.setMsgProducer(msgProducer)
;
extendExecutor.init();
}
}

+ 0
- 61
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/server/MsgQueueNodeServerFactory.java View File

@@ -1,61 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.server.MsgQueueNodeServerFactory
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:30
* Description:
*/
package com.jd.blockchain.consensus.mq.server;

import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.mq.config.MsgQueueNodeConfig;
import com.jd.blockchain.consensus.mq.config.MsgQueueServerConfig;
import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueServerSettings;
import com.jd.blockchain.consensus.service.*;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/

public class MsgQueueNodeServerFactory implements NodeServerFactory {

@Override
public MsgQueueServerSettings buildServerSettings(String realmName, ConsensusSettings consensusSetting, String currentNodeAddress) {

if (!(consensusSetting instanceof MsgQueueConsensusSettings)) {
throw new IllegalArgumentException("ConsensusSettings data isn't supported! Accept MsgQueueConsensusSettings only!");
}

MsgQueueNodeSettings nodeSettings = new MsgQueueNodeConfig().setAddress(currentNodeAddress);

MsgQueueServerSettings serverSettings = new MsgQueueServerConfig()
.setRealmName(realmName)
.setNodeSettings(nodeSettings)
.setConsensusSettings((MsgQueueConsensusSettings) consensusSetting)
;
return serverSettings;


}

@Override
public MsgQueueNodeServer setupServer(ServerSettings serverSettings, MessageHandle messageHandler, StateMachineReplicate stateMachineReplicator) {
if (!(serverSettings instanceof MsgQueueServerSettings)) {
throw new IllegalArgumentException("ServerSettings data isn't supported! Accept MsgQueueServerSettings only!");
}

MsgQueueNodeServer nodeServer = new MsgQueueNodeServer()
.setServerSettings((MsgQueueServerSettings) serverSettings)
.setMessageHandle(messageHandler)
.setStateMachineReplicator(stateMachineReplicator)
.init()
;
return nodeServer;
}
}

+ 0
- 30
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueBlockSettings.java View File

@@ -1,30 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueBlockSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:28
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/
@DataContract(code = DataCodes.CONSENSUS_MSGQUEUE_BLOCK_SETTINGS)
public interface MsgQueueBlockSettings {

@DataField(order = 0, primitiveType = PrimitiveType.INT32)
int getTxSizePerBlock();

@DataField(order = 1, primitiveType = PrimitiveType.INT64)
long getMaxDelayMilliSecondsPerBlock();
}

+ 0
- 30
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueClientIncomingSettings.java View File

@@ -1,30 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueClientIncomingSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:35
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consensus.ClientIncomingSettings;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.PubKey;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/
@DataContract(code = DataCodes.CONSENSUS_MSGQUEUE_CLI_INCOMING_SETTINGS)
public interface MsgQueueClientIncomingSettings extends ClientIncomingSettings {

@DataField(order = 1, primitiveType=PrimitiveType.BYTES)
PubKey getPubKey();
}

+ 0
- 23
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueClientSettings.java View File

@@ -1,23 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueClientSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:30
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.consensus.client.ClientSettings;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public interface MsgQueueClientSettings extends ClientSettings {

MsgQueueNetworkSettings getMsgQueueNetworkSettings();
}

+ 0
- 33
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueConsensusSettings.java View File

@@ -1,33 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueConsensusSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:37
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.mq.config.MsgQueueBlockConfig;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.Property;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/
@DataContract(code = DataCodes.CONSENSUS_MSGQUEUE_SETTINGS)
public interface MsgQueueConsensusSettings extends ConsensusSettings {

@DataField(order = 0, refContract = true)
MsgQueueNetworkSettings getNetworkSettings();

@DataField(order = 1, refContract = true)
MsgQueueBlockSettings getBlockSettings();
}

+ 0
- 36
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueNetworkSettings.java View File

@@ -1,36 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.mq.config.MsgQueueNetworkSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/12 上午11:43
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;

/**
*
* @author shaozhuguang
* @create 2018/12/12
* @since 1.0.0
*/
@DataContract(code = DataCodes.CONSENSUS_MSGQUEUE_NETWORK_SETTINGS)
public interface MsgQueueNetworkSettings {

@DataField(order = 0, primitiveType = PrimitiveType.TEXT)
String getServer();

@DataField(order = 1, primitiveType = PrimitiveType.TEXT)
String getTxTopic();

@DataField(order = 2, primitiveType = PrimitiveType.TEXT)
String getBlTopic();

@DataField(order = 3, primitiveType = PrimitiveType.TEXT)
String getMsgTopic();
}

+ 0
- 25
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueNodeSettings.java View File

@@ -1,25 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:50
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.consensus.NodeSettings;
import com.jd.blockchain.consts.DataCodes;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

@DataContract(code=DataCodes.CONSENSUS_MSGQUEUE_NODE_SETTINGS)
public interface MsgQueueNodeSettings extends NodeSettings {

}

+ 0
- 25
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/settings/MsgQueueServerSettings.java View File

@@ -1,25 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.consensus.mq.config.MsgQueueServerSettings
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/12/13 下午4:39
* Description:
*/
package com.jd.blockchain.consensus.mq.settings;

import com.jd.blockchain.consensus.service.ServerSettings;

/**
*
* @author shaozhuguang
* @create 2018/12/13
* @since 1.0.0
*/

public interface MsgQueueServerSettings extends ServerSettings {

MsgQueueBlockSettings getBlockSettings();

MsgQueueConsensusSettings getConsensusSettings();
}

+ 0
- 95
core/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/util/MessageConvertUtil.java View File

@@ -1,95 +0,0 @@
/**
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved
* FileName: com.jd.blockchain.sdk.mq.event.MessageConvertUtil
* Author: shaozhuguang
* Department: 区块链研发部
* Date: 2018/11/21 下午7:28
* Description:
*/
package com.jd.blockchain.consensus.mq.util;

import com.alibaba.fastjson.JSON;
import com.jd.blockchain.consensus.mq.event.BlockEvent;
import com.jd.blockchain.consensus.mq.event.TxBlockedEvent;
import com.jd.blockchain.utils.security.ShaUtils;

import org.springframework.util.Base64Utils;


/**
*
* @author shaozhuguang
* @create 2018/11/21
* @since 1.0.0
*/

public class MessageConvertUtil {

public static final String defaultCharsetName = "UTF-8";

public static String base64Encode(byte[] src) {
return Base64Utils.encodeToString(src);
}

public static byte[] base64Decode(String src) {
return Base64Utils.decodeFromString(src);
}

public static String messageKey(byte[] src) {
return base64Encode(ShaUtils.hash_256(src));
}

public static BlockEvent convertBytes2BlockEvent(byte[] serializeBytes) {
String text;
try{
text = new String(serializeBytes, defaultCharsetName);
} catch (Exception e) {
throw new RuntimeException(e);
}
return convertString2BlockEvent(text);
}

public static BlockEvent convertString2BlockEvent(String serializeString) {
return JSON.parseObject(serializeString, BlockEvent.class);
}

public static TxBlockedEvent convertBytes2TxBlockedEvent(byte[] serializeBytes) {
String text;
try{
text = new String(serializeBytes, defaultCharsetName);
} catch (Exception e) {
throw new RuntimeException(e);
}
return convertString2TxBlockedEvent(text);
}

public static TxBlockedEvent convertString2TxBlockedEvent(String serializeString) {
return JSON.parseObject(serializeString, TxBlockedEvent.class);
}

public static byte[] serializeBlockEvent(BlockEvent blockEvent) {
String serializeString = serializeEvent(blockEvent);
byte[] serializeBytes;
try {
serializeBytes = serializeString.getBytes(defaultCharsetName);
} catch (Exception e) {
throw new RuntimeException(e);
}
return serializeBytes;
}

public static byte[] serializeTxBlockedEvent(TxBlockedEvent txBlockedEvent) {
String serializeString = JSON.toJSONString(txBlockedEvent);
byte[] serializeBytes;
try {
serializeBytes = serializeString.getBytes(defaultCharsetName);
} catch (Exception e) {
throw new RuntimeException(e);
}
return serializeBytes;
}

public static String serializeEvent(BlockEvent blockEvent) {
return JSON.toJSONString(blockEvent);
}
}

+ 0
- 17
core/consensus/pom.xml View File

@@ -1,17 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-core</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-core</artifactId>
<packaging>pom</packaging>

<modules>
<module>consensus-bftsmart</module>
<module>consensus-mq</module>
</modules>
</project>

+ 0
- 27
core/contract/README.MD View File

@@ -1,27 +0,0 @@
### 合约相关说明
1. 编译合约入口:ContractCompilerCmdTest.java;
2. 账本调用合约测试入口:ContractEventSendOperationHandleTest.java;

### 单元测试注意事项
使用ContractEventSendOperationHandleTest.java进行单元测试,注意事项:
1. 设置合约使用PUB_CLASS_PATH、CORE_CLASS_PATH位置(sys-contract.properties);
PUB包在根目录中的contract-libs文件夹;core包需要编译来生成。具体如下:
- 进入contract-jar模块,执行maven命令:
```
mvn clean assembly:assembly
```
- 生成的core包位于模块的target中的contract-jar-xxx所在的coreLib中;
- 将此coreLib目录作为CORE_CLASS_PATH指向的目录。
2. 编译生成合约压缩包,即执行:ContractCompilerCmdTest.java对应的mainTestOk();
在编译之前,修改sys-contract.properties文件的变量CONTRACT_FROM_PATH(合约源文件位置)、CONTRACT_SAVE_TO_PATH(合约保存位置)。
3. 在合约保存位置中可看到生成的压缩包:xxx.contract;然后执行 ContractEventSendOperationHandleTest.java测试用例test1()即可。

### 20180910版本改造
1. 在contract-jar中添加了mvn assembly处理逻辑,将合约用到的lib包全部放置其target/xxx/pubLib文件夹中,执行:
```
mvn clean assembly:assembly
```
2. 修改了sys-contract.properties文件,新增了CONTRACT_CLASS_LIBS参数;
- 将CONTRACT_CLASS_PATH专用于存储路径
- CONTRACT_CLASS_LIBS来存放所有的jar包
3. 删减了contract-libs文件夹中需要动态生成的jar。

+ 0
- 43
core/contract/contract-jvm/pom.xml View File

@@ -1,43 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-core</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>contract-jvm</artifactId>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-framework</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>runtime-context</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>runtime-modular</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 0
- 105
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java View File

@@ -1,105 +0,0 @@
package com.jd.blockchain.contract.jvm;

import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.EventProcessingAware;
import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEncoding;
import com.jd.blockchain.ledger.BytesValueList;
import com.jd.blockchain.utils.Bytes;

/**
* @author huanghaiquan
*
*/
public abstract class AbstractContractCode implements ContractCode {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractContractCode.class);
private Bytes address;
private long version;

private ContractDefinition contractDefinition;

public AbstractContractCode(Bytes address, long version, ContractDefinition contractDefinition) {
this.address = address;
this.version = version;
this.contractDefinition = contractDefinition;
}

public ContractDefinition getContractDefinition() {
return contractDefinition;
}

@Override
public Bytes getAddress() {
return address;
}

@Override
public long getVersion() {
return version;
}

@Override
public BytesValue processEvent(ContractEventContext eventContext) {
EventProcessingAware evtProcAwire = null;
Object retn = null;
Method handleMethod = null;
Exception error = null;
try {
// 执行预处理;
Object contractInstance = getContractInstance();
if (contractInstance instanceof EventProcessingAware) {
evtProcAwire = (EventProcessingAware) contractInstance;
}

if (evtProcAwire != null) {
evtProcAwire.beforeEvent(eventContext);
}

// 反序列化参数;
handleMethod = contractDefinition.getType().getHandleMethod(eventContext.getEvent());

if (handleMethod == null) {
throw new ContractException(
String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(),
contractDefinition.getType().getName(), eventContext.getEvent()));
}
BytesValueList bytesValues = eventContext.getArgs();
Object[] args = BytesValueEncoding.decode(bytesValues, handleMethod.getParameterTypes());
retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args);
} catch (Exception e) {
error = e;
}

if (evtProcAwire != null) {
try {
evtProcAwire.postEvent(eventContext, error);
} catch (Exception e) {
String errorMessage = "Error occurred while posting contract event! --" + e.getMessage();
LOGGER.error(errorMessage, e);
throw new ContractException(errorMessage, e);
}
}
if (error != null) {
// Rethrow error;
throw new ContractException(String.format("Error occurred while processing event[%s] of contract[%s]! --%s",
eventContext.getEvent(), address.toString(), error.getMessage()), error);
}

BytesValue retnBytes = BytesValueEncoding.encodeSingle(retn, handleMethod.getReturnType());
return retnBytes;
}

protected abstract Object getContractInstance();

}

+ 0
- 24
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/ContractDefinition.java View File

@@ -1,24 +0,0 @@
package com.jd.blockchain.contract.jvm;

import com.jd.blockchain.contract.ContractType;

public class ContractDefinition {

private ContractType type;

private Class<?> mainClass;

public Class<?> getMainClass() {
return mainClass;
}

public ContractType getType() {
return type;
}

public ContractDefinition(ContractType type, Class<?> mainClass) {
this.type = type;
this.mainClass = mainClass;
}

}

+ 0
- 25
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java View File

@@ -1,25 +0,0 @@
package com.jd.blockchain.contract.jvm;

import com.jd.blockchain.contract.ContractType;
import com.jd.blockchain.utils.Bytes;

public class InstantiatedContractCode<T> extends AbstractContractCode {

private T instance;

public InstantiatedContractCode(Bytes address, long version, Class<T> delaredInterface, T instance) {
super(address, version, resolveContractDefinition(delaredInterface, instance.getClass()));
this.instance = instance;
}

private static ContractDefinition resolveContractDefinition(Class<?> declaredIntf, Class<?> implementedClass) {
ContractType contractType = ContractType.resolve(declaredIntf);
return new ContractDefinition(contractType, implementedClass);
}

@Override
protected T getContractInstance() {
return instance;
}

}

+ 0
- 41
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java View File

@@ -1,41 +0,0 @@
package com.jd.blockchain.contract.jvm;

import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.runtime.RuntimeContext;
import com.jd.blockchain.utils.Bytes;

public class JVMContractEngine implements ContractEngine {

private RuntimeContext runtimeContext = RuntimeContext.get();
private String getCodeName(Bytes address, long version) {
return address.toBase58() + "_" + version;
}
@Override
public ContractCode getContract(Bytes address, long version) {
String codeName = getCodeName(address, version);
Module module = runtimeContext.getDynamicModule(codeName);
if (module == null) {
return null;
}
return new JavaContractCode(address, version, module);
}

@Override
public ContractCode setupContract(Bytes address, long version, byte[] code) {
//is there the contractCode before setup? if yes ,then return;
ContractCode contractCode = getContract(address,version);
if(contractCode != null){
return contractCode;
}
String codeName = getCodeName(address, version);
Module module = runtimeContext.createDynamicModule(codeName,code);
if (module == null) {
return null;
}
return new JavaContractCode(address, version, module);
}
}

+ 0
- 20
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractServiceProvider.java View File

@@ -1,20 +0,0 @@
package com.jd.blockchain.contract.jvm;

import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.contract.engine.ContractServiceProvider;

public class JVMContractServiceProvider implements ContractServiceProvider {
@Override
public String getName() {
return JVMContractServiceProvider.class.getName();
}

@Override
public ContractEngine getEngine() {
return InnerEngine.INSTANCE;
}

private static class InnerEngine {
private static final ContractEngine INSTANCE = new JVMContractEngine();
}
}

+ 0
- 108
core/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java View File

@@ -1,108 +0,0 @@
package com.jd.blockchain.contract.jvm;

import java.util.concurrent.Callable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jd.blockchain.contract.Contract;
import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.ContractType;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.utils.Bytes;

/**
* 基于 java jar 包并且以模块化方式独立加载的合约代码;
*
* @author huanghaiquan
*
*/
public class JavaContractCode extends AbstractContractCode {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class);
private Module codeModule;
private Bytes address;
private long version;

public JavaContractCode(Bytes address, long version, Module codeModule) {
super(address, version, resolveContractDefinition(codeModule));
this.address = address;
this.version = version;
this.codeModule = codeModule;
}

protected static ContractDefinition resolveContractDefinition(Module codeModule) {
String mainClassName = codeModule.getMainClass();
Class<?> mainClass = codeModule.loadClass(mainClassName);
Class<?>[] interfaces = mainClass.getInterfaces();
Class<?> contractInterface = null;
for (Class<?> itf : interfaces) {
Contract annoContract = itf.getAnnotation(Contract.class);
if (annoContract != null) {
if (contractInterface == null) {
contractInterface = itf;
} else {
throw new ContractException(
"One contract definition is only allowed to implement one contract type!");
}
}
}
if (contractInterface == null) {
throw new ContractException("No contract type is implemented!");
}
ContractType type = ContractType.resolve(contractInterface);
return new ContractDefinition(type, mainClass);
}

@Override
public Bytes getAddress() {
return address;
}

@Override
public long getVersion() {
return version;
}

@Override
public BytesValue processEvent(ContractEventContext eventContext) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Start processing event{} of contract{}...", eventContext.getEvent(), address.toString());
}
try {
return codeModule.call(new ContractExecution(eventContext));
} catch (Exception ex) {
LOGGER.error(String.format("Error occurred while processing event[%s] of contract[%s]! --%s",
eventContext.getEvent(), address.toString(), ex.getMessage()), ex);
throw ex;
} finally {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("End processing event{} of contract{}. ", eventContext.getEvent(), address.toString());
}
}
}

protected Object getContractInstance() {
try {
// 每一次调用都通过反射创建合约的实例;
return getContractDefinition().getMainClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}

private class ContractExecution implements Callable<BytesValue> {
private ContractEventContext eventContext;

public ContractExecution(ContractEventContext contractEventContext) {
this.eventContext = contractEventContext;
}

@Override
public BytesValue call() throws Exception {
return JavaContractCode.super.processEvent(eventContext);
}
}

}

+ 0
- 274
core/contract/contract-maven-plugin/ReadME.MD View File

@@ -1,274 +0,0 @@
# 合约编译插件使用教程

### 1、maven引入

在pom.xml文件中引入合约编译插件:
```xml
<plugin>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-maven-plugin</artifactId>
<version>1.0.0.RELEASE</version>
<executions>
<execution>
<id>make-contract</id>
<phase>package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>com.jd.chain.contracts.ContractTestInfImpl</mainClass>
</manifest>
</archive>
<finalName>contract</finalName>
</configuration>
</plugin>

```

需要说明的几点如下:
+ 1)version:请根据实际JDChain发布版本确认,不同版本会有区别;
+ 2)executions->execution->id:该值请随意指定;
+ 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息);
+ 4)executions->execution->goals->goal:必须使用compile;
+ 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置;
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-JDChain-Contract.jar文件,只有该文件是可以发布到JDChain的合约包;


### 2、执行命令
使用mvn执行命令,下面两种方式均可:

方式一:只执行contract插件命令
```shell
mvn clean compile contract:compile
```

方式二:直接执行打包命令:
```shell
mvn clean package
```


### 3、合约编写要求
合约的执行结果会对整条链产生比较深刻的影响,为了使用户能够更好、更合理的使用合约,目前JDChain约定合约编写规则包括以下几点:

(违反其中任何一点都可能导致合约编译失败,但即使合约编译通过也不能保证合约可百分百运行正常)

+ 1)合约工程必须引入com.jd.blockchain:sdk-pack:该包中有合约正常编写需要使用的基本类;
+ 2)com.jd.blockchain:sdk-pack的scope必须定义为provided;
+ 3)合约发布必须通过合约编译插件进行打包:合约编译插件不但会对Jar包进行校验,同时也会加入JDChain独有的特征,只有具有该特征的Jar才能正常发布;
+ 4)合约中严禁使用随机数、IO、NIO等操作;
+ 5)合约打包时,请使用<scope>provided</scope>排除常用的工具包,例如FastJson、apache下的一些工具包等;
+ 6)合约必须有一个接口和该接口的实现类,详细要求如下:
- a. 接口必须有@Contract注解;
- b. 接口的可调用方法上必须有@ContractEvent注解,且每个注解中的name属性不能重复;
- c. 合约方法支持入参和返回值,其主要包括所有基本类型;



### 4、合约案例

#### 4.1、代码实例
以下是一个可创建银行账户,指定具体金额,并可以转账的合约代码(逻辑较简单,仅供参考):

合约接口代码如下:
```java
package com.jd.chain.contract;


@Contract
public interface TransferContract {

@ContractEvent(name = "create")
String create(String address, String account, long money);

@ContractEvent(name = "transfer")
String transfer(String address, String from, String to, long money);

@ContractEvent(name = "read")
long read(String address, String account);

@ContractEvent(name = "readAll")
String readAll(String address, String account);
}

```

合约实现类代码如下:
```java
package com.jd.chain.contract;

import com.alibaba.fastjson.JSON;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;

public class TransferContractImpl implements EventProcessingAware, TransferContract {

private ContractEventContext eventContext;

private HashDigest ledgerHash;

@Override
public String create(String address, String account, long money) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
// 肯定有返回值,但若不存在则返回version=-1
if (kvDataEntries != null && kvDataEntries.length > 0) {
long currVersion = kvDataEntries[0].getVersion();
if (currVersion > -1) {
throw new IllegalStateException(String.format("%s -> %s already have created !!!", address, account));
}
eventContext.getLedger().dataAccount(address).setInt64(account, money, -1L);
} else {
throw new IllegalStateException(String.format("Ledger[%s] inner Error !!!", ledgerHash.toBase58()));
}
return String.format("DataAccountAddress[%s] -> Create(By Contract Operation) Account = %s and Money = %s Success!!! \r\n",
address, account, money);
}

@Override
public String transfer(String address, String from, String to, long money) {
// 首先查询余额
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to);
if (kvDataEntries == null || kvDataEntries.length != 2) {
throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to));
} else {
// 判断from账号中钱数量是否足够
long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L;
for (KVDataEntry kvDataEntry : kvDataEntries) {
if (kvDataEntry.getKey().equals(from)) {
fromMoney = (long) kvDataEntry.getValue();
fromVersion = kvDataEntry.getVersion();
} else {
toMoney = (long) kvDataEntry.getValue();
toVersion = kvDataEntry.getVersion();
}
}
if (fromMoney < money) {
throw new IllegalStateException(String.format("%s -> %s not have enough money !!!", address, from));
}
long fromNewMoney = fromMoney - money;
long toNewMoney = toMoney + money;
// 重新设置
eventContext.getLedger().dataAccount(address).setInt64(from, fromNewMoney, fromVersion);
eventContext.getLedger().dataAccount(address).setInt64(to, toNewMoney, toVersion);
}

return String.format("DataAccountAddress[%s] transfer from [%s] to [%s] and [money = %s] Success !!!", address, from, to, money);
}

@Override
public long read(String address, String account) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
return -1;
}
return (long)kvDataEntries[0].getValue();
}

@Override
public String readAll(String address, String account) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
// 获取最新的版本号
if (kvDataEntries == null || kvDataEntries.length == 0) {
return "";
}
long newestVersion = kvDataEntries[0].getVersion();
if (newestVersion == -1) {
return "";
}
KVDataVO[] kvDataVOS = new KVDataVO[1];
long[] versions = new long[(int)newestVersion + 1];
for (int i = 0; i < versions.length; i++) {
versions[i] = i;
}
KVDataVO kvDataVO = new KVDataVO(account, versions);

kvDataVOS[0] = kvDataVO;

KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS);

KVDataEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO);

return JSON.toJSONString(allEntries);
}

@Override
public void beforeEvent(ContractEventContext eventContext) {
this.eventContext = eventContext;
this.ledgerHash = eventContext.getCurrentLedgerHash();
}

@Override
public void postEvent(ContractEventContext eventContext, Exception error) {

}
}
```


#### 4.2、pom.xml文件实例

```xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.jd.chain</groupId>
<version>1.0.0.RELEASE</version>
<modelVersion>4.0.0</modelVersion>

<artifactId>contract-samples</artifactId>

<name>contract-samples</name>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>sdk-pack</artifactId>
<version>1.0.0.RELEASE</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.32</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-maven-plugin</artifactId>
<version>1.0.0.RELEASE</version>
<executions>
<execution>
<id>make-contract</id>
<phase>package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>com.jd.chain.contract.TransferContractImpl</mainClass>
</manifest>
</archive>
<finalName>contract</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>

```

+ 0
- 1
core/contract/contract-maven-plugin/conf/jd-com.priv View File

@@ -1 +0,0 @@
177gjsuHdbf3PU68Sm1ZU2aMcyB7sLWj94xwBUoUKvTgHq7qGUfg6ynDB62hocYYXSRXD4X

+ 0
- 1
core/contract/contract-maven-plugin/conf/jd-com.pub View File

@@ -1 +0,0 @@
endPsK36imXrY66pru6ttZ8dZ3TynWekmdqoM1K7ZRRoRBBiYVzM

+ 0
- 1
core/contract/contract-maven-plugin/conf/ownerPassword.txt View File

@@ -1 +0,0 @@
abc

+ 0
- 74
core/contract/contract-maven-plugin/pom.xml View File

@@ -1,74 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-core</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>contract-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-model</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>utils-common</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>sdk-client</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>tools-keygen</artifactId>
<version>${project.version}</version>
</dependency>


<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
</dependency>

<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
</dependency>

<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.4</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5</version>
</plugin>
</plugins>
</build>
</project>

+ 0
- 19
core/contract/contract-maven-plugin/readme.txt View File

@@ -1,19 +0,0 @@
说明
1.编译:mvn clean install

快速自测:
1.ContractRemoteAutoMojoTest类用于快速自测发布和执行,快速自测是在测试链的环境中发布和执行合约;
2.修改sys-contract.properties文件中的相关信息;
3.合约发布之后,会在控制台生成合约地址,待5秒钟之后,会执行此合约。sys-contract.properties的contractArgs参数可修改,查看其不同效果;
###
contract's address=5SmEqUsnLY4APVfS32xYDpRPuz55Rsuupdt1
execute the contract,result=true
exeContract(),SUCCESS
###
4.在peer节点的控制台可以看到输出的结果信息。

通过maven插件中通过ContractAllAutoMojo做简单的编译、发布和执行测试,对应单元测试类ContractAllAutoMojoTest;





+ 0
- 178
core/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java View File

@@ -1,178 +0,0 @@
package com.jd.blockchain;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.sdk.BlockchainService;
import com.jd.blockchain.sdk.client.GatewayServiceFactory;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.net.NetworkAddress;

/**
* @Author zhaogw
* @Date 2018/11/2 10:18
*/
public enum ContractDeployExeUtil {
instance;
private BlockchainService bcsrv;
private Bytes contractAddress;

public BlockchainKeypair getKeyPair(String pubPath, String prvPath, String rawPassword){
PubKey pub = null;
PrivKey prv = null;
try {
prv = KeyGenUtils.readPrivKey(prvPath, KeyGenUtils.encodePassword(rawPassword));
pub = KeyGenUtils.readPubKey(pubPath);

} catch (Exception e) {
e.printStackTrace();
}

return new BlockchainKeypair(pub, prv);
}

public PubKey getPubKey(String pubPath){
PubKey pub = null;
try {
if(pubPath == null){
BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate();
pub = contractKeyPair.getPubKey();
}else {
pub = KeyGenUtils.readPubKey(pubPath);
}

} catch (Exception e) {
e.printStackTrace();
}

return pub;
}
public byte[] getChainCode(String path){
byte[] chainCode = null;
File file = null;
InputStream input = null;
try {
file = new File(path);
input = new FileInputStream(file);
chainCode = new byte[input.available()];
input.read(chainCode);

} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(input!=null){
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return chainCode;
}

private void register(){
DataContractRegistry.register(TransactionContent.class);
DataContractRegistry.register(TransactionContentBody.class);
DataContractRegistry.register(TransactionRequest.class);
DataContractRegistry.register(NodeRequest.class);
DataContractRegistry.register(EndpointRequest.class);
DataContractRegistry.register(TransactionResponse.class);
DataContractRegistry.register(DataAccountKVSetOperation.class);
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class);
DataContractRegistry.register(Operation.class);
DataContractRegistry.register(ContractCodeDeployOperation.class);
DataContractRegistry.register(ContractEventSendOperation.class);
DataContractRegistry.register(DataAccountRegisterOperation.class);
DataContractRegistry.register(UserRegisterOperation.class);
DataContractRegistry.register(ParticipantRegisterOperation.class);
DataContractRegistry.register(ParticipantStateUpdateOperation.class);
}

public BlockchainService initBcsrv(String host, int port) {
if(bcsrv!=null){
return bcsrv;
}
NetworkAddress addr = new NetworkAddress(host, port);
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(addr);
bcsrv = gwsrvFact.getBlockchainService();
return bcsrv;
}

public boolean deploy(HashDigest ledgerHash, BlockchainIdentity contractIdentity, BlockchainKeypair ownerKey, byte[] chainCode){
register();

TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash);
txTpl.contracts().deploy(contractIdentity, chainCode);
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(ownerKey);
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();

// 验证结果;
contractAddress = contractIdentity.getAddress();
this.setContractAddress(contractAddress);
System.out.println("contract's address="+contractAddress);
return txResp.isSuccess();
}
public boolean deploy(String host, int port, HashDigest ledgerHash, BlockchainKeypair ownerKey, byte[] chainCode){
register();

BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity();
initBcsrv(host,port);
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode);
}

// 根据用户指定的公钥生成合约地址
public boolean deploy(String host, int port, String ledger,String ownerPubPath, String ownerPrvPath,
String ownerPassword, String chainCodePath,String pubPath){
PubKey pubKey = getPubKey(pubPath);
BlockchainIdentity contractIdentity = new BlockchainIdentityData(pubKey);
byte[] chainCode = getChainCode(chainCodePath);

BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword);
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger));
initBcsrv(host,port);
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode);
}

// 暂不支持从插件执行合约;此外,由于合约参数调用的格式发生变化,故此方法被废弃;by: huanghaiquan at 2019-04-30;
// public boolean exeContract(String ledger,String ownerPubPath, String ownerPrvPath,
// String ownerPassword,String event,String contractArgs){
// BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword);
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger));
//
// // 定义交易,传输最简单的数字、字符串、提取合约中的地址;
// TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash);
// txTpl.contractEvents().send(getContractAddress(),event,contractArgs.getBytes());
//
// // 签名;
// PreparedTransaction ptx = txTpl.prepare();
// ptx.sign(ownerKey);
//
// // 提交并等待共识返回;
// TransactionResponse txResp = ptx.commit();
//
// // 验证结果;
// return txResp.isSuccess();
// }

public Bytes getContractAddress() {
return contractAddress;
}

public void setContractAddress(Bytes contractAddress) {
this.contractAddress = contractAddress;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save