Jdchain is an open-source blockchain platform of JD science and Technology Co., Ltd. the goal is to realize a general blockchain framework system for enterprise application scenarios, which can serve as enterprise level infrastructure and provide efficient, flexible and secure solutions for business innovation. The reason why jdchain is chosen for research is that jdchain is one of the few bottom layers and a blockchain platform implemented by java
Project address: https://github.com/blockchain...
Document address: http://ledger.jd.com/setup.html
Deployment components
- peer: master node of blockchain, participating in consensus, ledger operation, etc
- gateway: communication with Peer node, responsible for blockchain browser and message delivery
- Client: use SDK and gateway link to initiate transaction through gateway
Foolproof deployment
Get deployment package
There are two ways to get the deployment package: first, directly from Download official website . 2. Pull the source code from github and build it by yourself. The deployment package will be generated under the deployment directory. Note that if the package is built on Windows system, the startup script in the package will have the problem of escaping characters when running under linux system. You need to set lineEnding to unix in assembly.xml. For specific settings Check me out.
Decompression deployment
Deployment reference: Deploy JDChain from scratch
Effect preview
Blockchain deployment tool
Blockchain browser
Problems encountered in deployment:
The official documents are quite detailed, but many details are not specified. The general experience and development environment are relatively simple. It is possible to deploy four nodes of peer on one host. At this time, we should pay attention to the port layout, because the current consensus algorithm of jdchain is open-source bftsmart Implementation, the consensus port cannot be continuous on the same host, or port conflicts will occur. The blogger has encountered this problem. The following is the detailed troubleshooting process: exceptions are thrown when using SDK to create users. The gateway can connect normally, and there is no problem with secret key authentication:
Caused by: java.lang.IndexOutOfBoundsException: The accessing index is out of BytesSlice's bounds! at com.jd.blockchain.utils.io.BytesSlice.checkBoundary(BytesSlice.java:174) at com.jd.blockchain.utils.io.BytesSlice.getInt(BytesSlice.java:97) at com.jd.blockchain.utils.io.BytesSlice.getInt(BytesSlice.java:86) at com.jd.blockchain.binaryproto.impl.HeaderEncoder.resolveCode(HeaderEncoder.java:71) at com.jd.blockchain.binaryproto.BinaryProtocol.decode(BinaryProtocol.java:41) at com.jd.blockchain.sdk.converters.BinarySerializeResponseConverter.getResponse(BinarySerializeResponseConverter.java:33) at com.jd.blockchain.utils.http.agent.HttpServiceAgent.invoke(HttpServiceAgent.java:587) ... 7 more
Exception in gateway
11:57:05.537 ERROR com.jd.blockchain.gateway.web.GatewayGlobalExceptionHandler 34 json - Unexpected exception occurred! --[RequestURL=[POST] http://192.168.1.190:8081/rpc/tx][class java.lang.IllegalStateException]Returned object not currently part of this pool java.lang.IllegalStateException: Returned object not currently part of this pool at org.apache.commons.pool2.impl.GenericObjectPool.returnObject(GenericObjectPool.java:530) ~[commons-pool2-2.5.0.jar!/:2.5.0] at com.jd.blockchain.consensus.bftsmart.client.BftsmartMessageService.sendOrderedMessage(BftsmartMessageService.java:46) ~[consensus-bftsmart-1.1.1.RELEASE.jar!/:1.1.1.RELEASE] at com.jd.blockchain.consensus.bftsmart.client.BftsmartMessageService.sendOrdered(BftsmartMessageService.java:22) ~[consensus-bftsmart-1.1.1.RELEASE.jar!/:1.1.1.RELEASE] at com.jd.blockchain.sdk.service.NodeSigningAppender.process(NodeSigningAppender.java:84) ~[sdk-base-1.1.1.RELEASE.jar!/:1.1.1.RELEASE] at com.jd.blockchain.sdk.service.PeerServiceProxy.process(PeerServiceProxy.java:89) ~[sdk-base-1.1.1.RELEASE.jar!/:1.1.1.RELEASE] at com.jd.blockchain.gateway.web.TxProcessingController.process(TxProcessingController.java:70) ~[gateway-1.1.1.RELEASE.jar!/:1.1.1.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_231] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_231] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_231] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_231]
Finally, it is found that the exception is caused by the failure of creating AsynchServiceProxy in the gateway. This part of the implementation uses Apache Commons pool2. The implementation is as follows:
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); } }
This code BinarySerializeUtils.deserialize(bftsmartClientSettings.getTopology()) returned null and did not get bftsmart's network topology correctly. Then look at the peer node. It is found that only node 0 succeeds, and other exceptions are thrown as follows. It is preliminarily judged that the copy service of bftsmart failed to start due to port Occupation:
11:36:48.479 ERROR bftsmart.tom.ServiceReplica 247 init - null java.net.BindException: Address is already in use at sun.nio.ch.Net.bind0(Native Method) ~[?:1.8.0_231] at sun.nio.ch.Net.bind(Net.java:433) ~[?:1.8.0_231] at sun.nio.ch.Net.bind(Net.java:425) ~[?:1.8.0_231] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) ~[?:1.8.0_231] at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:130) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:558) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1358) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:501) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:486) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:1019) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:254) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:366) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-all-4.1.29.Final.jar:4.1.29.Final] at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_231]
According to bftsmart's official documents, if you are running on the same host, you cannot use the sequential port number, that is, the consensus port of the peer that was arranged at the beginning, 6000, 6001, 6002 and 6003 are not available. The reasons are as follows: if you deploy / execute some (or all) copies in the same computer (127.0.0.1), config/hosts.config cannot have the sequential port number (for example, 1 0000,10001,10002,10003). This is because each replica is bound to two ports: one for receiving messages from the client and the other for receiving messages from other replicas (select by getting the next port number). More generally, if port number P is assigned to replica R, it attempts to bind port P (bound to the received client request) and port P + 1 (bound to another replica). If this guideline is not enforced, the replica may not be able to bind all required ports.
- Document address: https://github.com/bft-smart/...
epilogue
Jdchain is a complete blockchain project implemented in java, which is a great boon for java developers to study blockchain. Moreover, the project has been iterative since its open source, and is friendly in terms of documentation and community support. Although the introduction is very simple, there are still many things to study to go deep into the back of this project. The main plan of the building is to make clear the interaction between the SDK and the gateway, and then study the latest consensus implementation (based on RabbitMQ), then the application of the smart contract, and finally the in-depth code implementation. There may be other content output about jdchain later. At last, I hope to contribute some codes, provide some cases and answer some questions to the community after mastering all of them. Do your best for open source