diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index d411efcbe..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Java Gradle CircleCI 2.0 configuration file -# -# Check https://circleci.com/docs/2.0/language-java/ for more details -# -version: 2 -jobs: - build: - working_directory: ~/web3sdk - branches: - only: - - master - - /release-2.*/ - tags: - only: - - /v2.*/ - docker: - # specify the version you desire here - - image: circleci/openjdk:8-jdk - environment: - POSTGRES_USER: root - environment: - # Customize the JVM maximum heap limit - JVM_OPTS: -Xmx3200m - TERM: dumb - - steps: - - - checkout - - # Download and cache dependencies - - restore_cache: - keys: - - v1-dependencies-{{ checksum "build.gradle" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - # build blockchian by build_chain.sh - - run: - name: fisco-bcos - command: | - sudo apt-get update - sudo apt install -y openssl curl - curl -LO https://raw.githubusercontent.com/FISCO-BCOS/FISCO-BCOS/master/tools/build_chain.sh && chmod u+x build_chain.sh - bash <(curl -s https://raw.githubusercontent.com/FISCO-BCOS/FISCO-BCOS/master/tools/ci/download_bin.sh) -b master - ./bin/fisco-bcos -v - ./build_chain.sh -e bin/fisco-bcos -l "127.0.0.1:4" -p 30300,20200,8545 - cd nodes/127.0.0.1 - ./start_all.sh - - - run: gradle dependencies - - - save_cache: - paths: - - ~/web3sdk/.gradle - key: v1-dependencies-{{ checksum "build.gradle" }} - - # run integration test for sdk - - run: - name: sdk - command: | - cp nodes/127.0.0.1/sdk/* src/test/resources/ - gradle test - - run: - name: Upload Coverage - command: | - gradle jacocoTestReport - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 08692442a..2470caf72 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ gradle.properties /src/test/resources/node.key /src/test/java/org/fisco/bcos/temp build.gradle.bak +/.settings/ +.project diff --git a/.travis.yml b/.travis.yml index e7cb23123..ffa404f33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,18 @@ # safelist branches: - only: - - master - - /release-2.*/ -tags: - only: - - /v2.*/ + only: + - /.*/ + +matrix: + fast_finish: true + include: + - os: linux + dist: xenial + sudo: required language: java jdk: - - oraclejdk8 + - openjdk8 before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock @@ -23,9 +26,16 @@ cache: before_install: - gradle wrapper -script: - - ./gradlew build -x test - - ./gradlew jacocoTestReport - -after_success: - - bash <(curl -s https://codecov.io/bash) \ No newline at end of file +script: | + curl -LO https://raw.githubusercontent.com/FISCO-BCOS/FISCO-BCOS/release-2.0.0-rc3/tools/build_chain.sh && chmod u+x build_chain.sh + bash <(curl -s https://raw.githubusercontent.com/FISCO-BCOS/FISCO-BCOS/master/tools/ci/download_bin.sh) -b release-2.0.0-rc3 + echo "127.0.0.1:4 agency1 1,2,3" > ipconf + ./build_chain.sh -e bin/fisco-bcos -f ipconf -p 30300,20200,8545 -v 2.0.0-rc3 + ./nodes/127.0.0.1/start_all.sh + ./nodes/127.0.0.1/fisco-bcos -v + cp nodes/127.0.0.1/sdk/* src/integration-test/resources/ + mv src/integration-test/resources/applicationContext-sample.xml src/integration-test/resources/applicationContext.xml + ./gradlew verifyGoogleJavaFormat + ./gradlew build + ./gradlew test + ./gradlew integrationTest \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 05c335580..25b71fda9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,18 @@ Go to [issues page](https://github.com/FISCO-BCOS/web3sdk/issues) 7. Wait the community to review the code 8. Merged !!!! +## Code formatting + +The code formatting tool are described by the [google-java-format-gradle-plugin](https://github.com/sherter/google-java-format-gradle-plugin). + +Execute the task `googleJavaFormat` to format all *.java files in the project +``` +./gradlew goJF +``` +Execute the task `verifyGoogleJavaFormat` to verify that all *.java files are formatted properly +``` +./gradlew verGJF +``` ## Continous integration diff --git a/Changelog.md b/Changelog.md index ebd674941..55b83706a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,8 +1,28 @@ +### v2.0.0-rc3 + +(2019-05-28) + +增加 +1. 提供CRUDService类,包含操作用户表的CRUD接口。 +2. 提供加载账号文件的工具管理类PEMManager和P12Manager,可以分别加载PEM格式和PKCS12格式的账戶文件。 +3. 增加集成测试,覆盖web3j api和precompile api。 + +更新 +1. 优化日志格式,调整日志输出内容,可以更详细显示交易流程信息。 +2. 优化选择节点块高最大的节点发送交易。 +3. 支持多群组区块链前置配置。 +4. SDK配置文件中,机构属性字段修改为agencyName。 + +* Compatibility + +1. 兼容rc1,rc2, rc3的节点 + + ### v2.0.0-rc2 (2019-04-25) -* Add +* 增加 1. 可并行合约开发框架ParallelContract.sol 2. 并行预编译转账合约DagTransferPrecompiled的压测程序 @@ -10,7 +30,7 @@ 4. CRUD合约的压测程序 5. 回滚合约的压测程序 -* Update +* 更新 1. 在交易编码中加入chainID和groupID,以支持rc2节点的交易格式 2. sol转java,在java文件中增加了abi字段。 @@ -23,15 +43,19 @@ (2019-03-18) -* Add +* 增加 1. 提供多群组支持 2. 提供Spring Boot配置以及demo项目 3. 提供模块化的单元测试,新增使用示例 4. 增加Precompiled Service接口,实现对区块链相关配置的管理,及实现特定预编译合约的功能 -* Update +* 更新 1. 同步以太坊最新代码,支持动态数组返回,支持最新0.5.x合约 2. 优化合约编译流程,无需下载solcj即可直接编译合约生成abi bin和java合约文件 3. 升级Web3j,修改Web3j接口名 + +* Compatibility + +1. 兼容rc1的节点 \ No newline at end of file diff --git a/build.gradle b/build.gradle index e25f65362..89389943d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,13 @@ +plugins { + id 'com.github.sherter.google-java-format' version '0.8' +} apply plugin: 'maven' apply plugin: 'idea' apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'signing' -apply plugin:'application' -apply plugin: 'jacoco' +apply plugin: 'application' sourceCompatibility = 1.8 @@ -15,13 +17,23 @@ targetCompatibility = 1.8 // In this section you declare where to find the dependencies of your project repositories { - maven { - url "http://maven.aliyun.com/nexus/content/groups/public/" - } - maven { url 'https://dl.bintray.com/ethereum/maven/' } + maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } + maven { url 'https://dl.bintray.com/ethereum/maven/' } mavenCentral() } +googleJavaFormat { + options style: 'AOSP' + source = sourceSets*.allJava + include '**/*.java' + exclude '**/temp/*.java' +} + +verifyGoogleJavaFormat { + source = sourceSets*.allJava + include '**/*.java' + exclude '**/temp/*.java' +} def spring_version="4.3.18.RELEASE" @@ -44,39 +56,44 @@ List alibaba = [ // In this section you declare the dependencies for your production and test code dependencies { -// compile files('lib/solcJ-all-0.4.25-gm.jar') - //compile 'org.ethereum:solcJ-all:0.5.2' - compile 'org.ethereum:solcJ-all:0.4.25' - compile logger,spring,alibaba - compile 'org.apache.commons:commons-lang3:3.1' - compile "com.fasterxml.jackson.core:jackson-databind:2.9.6" - compile 'io.netty:netty-all:4.1.32.Final' + // compile files('lib/solcJ-all-0.4.25-gm.jar') + // compile 'org.ethereum:solcJ-all:0.5.2' + compile 'org.ethereum:solcJ-all:0.4.25' + compile logger,spring,alibaba + compile 'org.apache.commons:commons-lang3:3.1' + compile 'com.fasterxml.jackson.core:jackson-databind:2.9.6' + compile 'io.netty:netty-all:4.1.32.Final' compile 'io.netty:netty-tcnative:2.0.20.Final' compile 'io.netty:netty-tcnative-boringssl-static:2.0.20.Final' compile 'com.google.guava:guava:19.0' compile 'commons-configuration:commons-configuration:1.10' - - // web3j - compile 'org.apache.httpcomponents:httpclient:4.5.5', + // web3j + compile 'org.apache.httpcomponents:httpclient:4.5.5', 'org.bouncycastle:bcprov-jdk15on:1.54', 'com.lambdaworks:scrypt:1.4.0', 'com.squareup:javapoet:1.7.0', 'io.reactivex:rxjava:1.2.4', - "io.reactivex.rxjava2:rxjava:2.2.2", - 'com.github.jnr:jnr-unixsocket:0.15', - 'info.picocli:picocli:3.6.0', - "org.java-websocket:Java-WebSocket:1.3.8", - "org.apache.commons:commons-collections4:4.0", - "commons-io:commons-io:2.4", - 'com.github.stefanbirkner:system-rules:1.18.0', - 'junit:junit:4.12', - 'org.mockito:mockito-core:2.23.0' + 'io.reactivex.rxjava2:rxjava:2.2.2', + 'com.github.jnr:jnr-unixsocket:0.15', + 'info.picocli:picocli:3.6.0', + 'org.java-websocket:Java-WebSocket:1.3.8', + 'org.apache.commons:commons-collections4:4.0', + 'commons-io:commons-io:2.4', + 'com.github.stefanbirkner:system-rules:1.18.0', + 'junit:junit:4.12', + 'org.mockito:mockito-core:2.23.0' + compile 'de.vandermeer:asciitable:0.3.2' } -archivesBaseName = 'web3sdk' -group = 'org.fisco-bcos' -version = '2.0.2' +//archivesBaseName = 'web3sdk' +//group = 'org.fisco-bcos' +//version = '2.0.2' +configurations { + integrationTestCompile.extendsFrom testCompile + integrationTestRuntime.extendsFrom testRuntime +} + // for old sdk sourceSets { main { @@ -88,8 +105,29 @@ sourceSets { srcDir 'src/test/resources' } } + integrationTest { + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/integration-test/java') + } + resources.srcDir file('src/integration-test/resources') + } } +task integrationTest(type: Test) { + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath + outputs.upToDateWhen { false } +} + +check.dependsOn integrationTest +integrationTest.mustRunAfter test + +check.dependsOn.remove(test) +check.dependsOn.remove(integrationTest) +check.dependsOn.remove(verifyGoogleJavaFormat) + // 1 dist jar jar { destinationDir file('dist/apps') @@ -186,14 +224,4 @@ test { // } // } //} - -jacocoTestReport { - reports { - xml.enabled true - html.enabled false - } -} - -check.dependsOn jacocoTestReport - mainClassName = System.getProperty("exec.mainClass") ?: "org.fisco.bcos.channel.test.amop.Channel2Client" \ No newline at end of file diff --git a/doc/CONTRIBUTING_CN.md b/doc/CONTRIBUTING_CN.md index 876975aac..89888f60d 100644 --- a/doc/CONTRIBUTING_CN.md +++ b/doc/CONTRIBUTING_CN.md @@ -40,6 +40,19 @@ 7. 等待社区review这个PR 8. PR合入,特性开发完成! +## 代码格式化 + +代码格式化gradle插件[google-java-format-gradle-plugin](https://github.com/sherter/google-java-format-gradle-plugin). + +执行任务 `googleJavaFormat`格式化java文件。 +``` +./gradlew goJF +``` +执行任务 `verifyGoogleJavaFormat`验证java文件是否格式化完成 +``` +./gradlew verGJF +``` + ## 持续集成(CI) 持续集成框架 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 144d3ccb3..9d01c9d3f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip diff --git a/release_note.txt b/release_note.txt index a4b58387a..56c2ea320 100644 --- a/release_note.txt +++ b/release_note.txt @@ -1 +1 @@ -v2.0.0-rc2 +v2.0.0-rc3 diff --git a/src/test/java/org/fisco/bcos/channel/test/TestBase.java b/src/integration-test/java/org/fisco/bcos/TestBase.java similarity index 50% rename from src/test/java/org/fisco/bcos/channel/test/TestBase.java rename to src/integration-test/java/org/fisco/bcos/TestBase.java index 397da0701..c122de28f 100644 --- a/src/test/java/org/fisco/bcos/channel/test/TestBase.java +++ b/src/integration-test/java/org/fisco/bcos/TestBase.java @@ -1,9 +1,13 @@ -package org.fisco.bcos.channel.test; +package org.fisco.bcos; + +import java.math.BigInteger; import org.fisco.bcos.channel.client.Service; +import org.fisco.bcos.channel.test.guomi.Ok; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; +import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; import org.junit.AfterClass; import org.junit.BeforeClass; import org.springframework.context.ApplicationContext; @@ -11,28 +15,34 @@ public class TestBase { public static ApplicationContext context = null; - // 初始化交易签名私钥 - public Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + public static Credentials credentials = + Credentials.create("d0fee0a4e3c545a9394965042f8f891b6e5482c212a7428ec175d6aed121353a"); protected static Web3j web3j; + protected static BigInteger gasPrice = new BigInteger("30000000"); + protected static BigInteger gasLimit = new BigInteger("30000000"); + protected static String address; + protected static BigInteger blockNumber; + protected static String blockHash; + protected static String txHash; @BeforeClass public static void setUpBeforeClass() throws Exception { - // 获取spring配置文件,生成上下文 - context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - // ((ClassPathXmlApplicationContext) context).start(); + + context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); Service service = context.getBean(Service.class); service.run(); - System.out.println("start..."); - System.out.println("==================================================================="); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); channelEthereumService.setChannelService(service); web3j = Web3j.build(channelEthereumService, service.getGroupId()); - // EthBlockNumber ethBlockNumber = web3.ethBlockNumber().send(); + + Ok ok = Ok.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send(); + address = ok.getContractAddress(); + blockNumber = ok.getTransactionReceipt().get().getBlockNumber(); + blockHash = ok.getTransactionReceipt().get().getBlockHash(); + txHash = ok.getTransactionReceipt().get().getTransactionHash(); } @AfterClass diff --git a/src/integration-test/java/org/fisco/bcos/contract/Ok.java b/src/integration-test/java/org/fisco/bcos/contract/Ok.java new file mode 100644 index 000000000..afedf165d --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/contract/Ok.java @@ -0,0 +1,217 @@ +package org.fisco.bcos.contract; + +import io.reactivex.Flowable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.fisco.bcos.channel.client.TransactionSucCallback; +import org.fisco.bcos.web3j.abi.EventEncoder; +import org.fisco.bcos.web3j.abi.TypeReference; +import org.fisco.bcos.web3j.abi.datatypes.Event; +import org.fisco.bcos.web3j.abi.datatypes.Function; +import org.fisco.bcos.web3j.abi.datatypes.Type; +import org.fisco.bcos.web3j.abi.datatypes.generated.Uint256; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameter; +import org.fisco.bcos.web3j.protocol.core.RemoteCall; +import org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter; +import org.fisco.bcos.web3j.protocol.core.methods.response.Log; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.Contract; +import org.fisco.bcos.web3j.tx.TransactionManager; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; + +/** + * Auto generated code. + * + *

Do not modify! + * + *

Please use the web3j command line tools, + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. + * + *

Generated with web3j version none. + */ +public class Ok extends Contract { + private static final String BINARY = + "608060405234801561001057600080fd5b5060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060006002600101819055506103bf806100c26000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806366c99139146100515780636d4ce63c1461007e575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100a9565b005b34801561008a57600080fd5b506100936102e1565b6040518082815260200191505060405180910390f35b8060006001015410806100c757506002600101548160026001015401105b156100d1576102de565b8060006001015403600060010181905550806002600101600082825401925050819055507fc77b710b83d1dc3f3fafeccd08a6c469beb873b2f0975b50d1698e46b3ee5b4c816040518082815260200191505060405180910390a160046080604051908101604052806040805190810160405280600881526020017f323031373034313300000000000000000000000000000000000000000000000081525081526020016000800160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152509080600181540180825580915050906001820390600052602060002090600402016000909192909190915060008201518160000190805190602001906102419291906102ee565b5060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301555050505b50565b6000600260010154905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032f57805160ff191683800117855561035d565b8280016001018555821561035d579182015b8281111561035c578251825591602001919060010190610341565b5b50905061036a919061036e565b5090565b61039091905b8082111561038c576000816000905550600101610374565b5090565b905600a165627a7a72305820fb983c66bee66788f407721b23b10a8aae3dc9ef8f1b09e08ec6a6c0b0ec70100029"; + + public static final String FUNC_TRANS = "trans"; + + public static final String FUNC_GET = "get"; + + public static final Event TRANSEVENT_EVENT = + new Event("TransEvent", Arrays.>asList(new TypeReference() {}));; + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall trans(BigInteger num) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void trans(BigInteger num, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall get() { + final Function function = + new Function( + FUNC_GET, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public List getTransEventEvents(TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(TRANSEVENT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + TransEventEventResponse typedResponse = new TransEventEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.num = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable transEventEventFlowable(BcosFilter filter) { + return web3j + .logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public TransEventEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(TRANSEVENT_EVENT, log); + TransEventEventResponse typedResponse = new TransEventEventResponse(); + typedResponse.log = log; + typedResponse.num = + (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable transEventEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSEVENT_EVENT)); + return transEventEventFlowable(filter); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, credentials, contractGasProvider); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(Ok.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return deployRemoteCall(Ok.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(Ok.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall(Ok.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class TransEventEventResponse { + public Log log; + + public BigInteger num; + } +} diff --git a/src/integration-test/java/org/fisco/bcos/contract/OkTest.java b/src/integration-test/java/org/fisco/bcos/contract/OkTest.java new file mode 100644 index 000000000..20a7f69e5 --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/contract/OkTest.java @@ -0,0 +1,31 @@ +package org.fisco.bcos.contract; + +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import java.util.concurrent.TimeUnit; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; +import org.junit.Test; + +public class OkTest extends TestBase { + + @Test + public void testOkContract() throws Exception { + + Ok ok = Ok.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send(); + + if (ok != null) { + TransactionReceipt receipt = ok.trans(new BigInteger("4")).send(); + assertTrue(receipt.getBlockNumber().intValue() > 0); + assertTrue(receipt.getTransactionIndex().intValue() >= 0); + assertTrue(receipt.getGasUsed().intValue() > 0); + BigInteger oldBalance = ok.get().sendAsync().get(60000, TimeUnit.MILLISECONDS); + ok.trans(new BigInteger("4")).sendAsync().get(60000, TimeUnit.MILLISECONDS); + BigInteger newBalance = ok.get().sendAsync().get(60000, TimeUnit.MILLISECONDS); + assertTrue(newBalance.intValue() == oldBalance.intValue() + 4); + } + } +} diff --git a/src/integration-test/java/org/fisco/bcos/precompile/CRUDServiceTest.java b/src/integration-test/java/org/fisco/bcos/precompile/CRUDServiceTest.java new file mode 100644 index 000000000..ce4b2fb27 --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/precompile/CRUDServiceTest.java @@ -0,0 +1,82 @@ +package org.fisco.bcos.precompile; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.precompile.crud.CRUDSerivce; +import org.fisco.bcos.web3j.precompile.crud.Condition; +import org.fisco.bcos.web3j.precompile.crud.Entry; +import org.fisco.bcos.web3j.precompile.crud.Table; +import org.junit.Test; + +public class CRUDServiceTest extends TestBase { + + + CRUDSerivce crudSerivce = new CRUDSerivce(web3j, credentials); + + @SuppressWarnings("unchecked") + @Test + public void curdTest() throws Exception { + + String tableName = "t_test" + new Random().nextInt(100000); + String key = "name"; + String valueFields = "item_id, item_name"; + Table table = new Table(tableName, key, valueFields); + + // create table + int resultCreate = crudSerivce.createTable(table); + assertEquals(resultCreate, 0); + + // insert records + int insertResult = 0; + int num = 5; + for(int i = 1; i <= num; i++) + { + Entry insertEntry = table.getEntry(); + insertEntry.put("item_id", "1"); + insertEntry.put("item_name", "apple"+i); + table.setKey("fruit"); + insertResult += crudSerivce.insert(table, insertEntry); + } + assertEquals(insertResult, num); + + // select records + Condition condition1 = table.getCondition(); + condition1.EQ("item_id", "1"); + condition1.Limit(1); + + List> resultSelect1 = crudSerivce.select(table, condition1); + assertEquals(resultSelect1.get(0).get("name"), "fruit"); + assertEquals(resultSelect1.get(0).get("item_id"), "1"); + assertEquals(resultSelect1.get(0).get("item_name"), "apple1"); + + // update records + Entry updateEntry = table.getEntry(); + updateEntry.put("item_id", "1"); + updateEntry.put("item_name", "orange"); + Condition updateCondition = table.getCondition(); + updateCondition.EQ("item_id", "1"); + int updateResult = crudSerivce.update(table, updateEntry, updateCondition); + assertEquals(updateResult, num); + + // select records + Condition condition2 = table.getCondition(); + condition2.EQ("item_id", "1"); + condition2.Limit(1);; + List> resultSelect2 = crudSerivce.select(table, condition2); + assertEquals(resultSelect2.get(0).get("name"), "fruit"); + assertEquals(resultSelect2.get(0).get("item_id"), "1"); + assertEquals(resultSelect2.get(0).get("item_name"), "orange"); + + // remove records + Condition removeCondition = table.getCondition(); + removeCondition.EQ("item_id", "1"); + int removeResult = crudSerivce.remove(table, removeCondition); + assertEquals(removeResult, num); + } + +} diff --git a/src/test/java/org/fisco/bcos/channel/test/precompile/CnsServiceTest.java b/src/integration-test/java/org/fisco/bcos/precompile/CnsServiceTest.java similarity index 97% rename from src/test/java/org/fisco/bcos/channel/test/precompile/CnsServiceTest.java rename to src/integration-test/java/org/fisco/bcos/precompile/CnsServiceTest.java index ffefe498c..8c04d300f 100644 --- a/src/test/java/org/fisco/bcos/channel/test/precompile/CnsServiceTest.java +++ b/src/integration-test/java/org/fisco/bcos/precompile/CnsServiceTest.java @@ -1,10 +1,11 @@ -package org.fisco.bcos.channel.test.precompile; +package org.fisco.bcos.precompile; import static org.junit.Assert.assertEquals; import java.math.BigInteger; import java.security.SecureRandom; -import org.fisco.bcos.channel.test.TestBase; + +import org.fisco.bcos.TestBase; import org.fisco.bcos.channel.test.contract.Ok; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.precompile.cns.CnsService; diff --git a/src/integration-test/java/org/fisco/bcos/precompile/Common.java b/src/integration-test/java/org/fisco/bcos/precompile/Common.java new file mode 100644 index 000000000..a040d3512 --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/precompile/Common.java @@ -0,0 +1,8 @@ +package org.fisco.bcos.precompile; + +public class Common { + + public static String SUSSCESS = "{\"code\":0,\"msg\":\"success\"}"; + public static String TABLE_NAME = "t_test"; + public static String TX_ORIGIN = "0xf1585b8d0e08a0a00fff662e24d67ba95a438256"; +} diff --git a/src/integration-test/java/org/fisco/bcos/precompile/ConsensusServiceTest.java b/src/integration-test/java/org/fisco/bcos/precompile/ConsensusServiceTest.java new file mode 100644 index 000000000..06323926e --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/precompile/ConsensusServiceTest.java @@ -0,0 +1,33 @@ +package org.fisco.bcos.precompile; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.precompile.consensus.ConsensusService; +import org.junit.Ignore; + +public class ConsensusServiceTest extends TestBase { + + + private ConsensusService consensusService = new ConsensusService(web3j, credentials); + + @Ignore + public void addSealerAndObserverTest() throws Exception { + + List sealerList1 = web3j.getSealerList().send().getSealerList(); + String nodeId = sealerList1.get(sealerList1.size() -1); + + String addObserverResult = consensusService.addObserver(nodeId); + assertEquals(addObserverResult, Common.SUSSCESS); + + String removeNodeResult = consensusService.removeNode(nodeId); + assertEquals(removeNodeResult, Common.SUSSCESS); + + String addSealerResult = consensusService.addSealer(nodeId); + assertEquals(addSealerResult, Common.SUSSCESS); + + } + +} diff --git a/src/integration-test/java/org/fisco/bcos/precompile/PermissionServiceTest.java b/src/integration-test/java/org/fisco/bcos/precompile/PermissionServiceTest.java new file mode 100644 index 000000000..4f79d8250 --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/precompile/PermissionServiceTest.java @@ -0,0 +1,63 @@ +package org.fisco.bcos.precompile; + +import static org.junit.Assert.assertEquals; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.precompile.exception.PrecompileMessageException; +import org.fisco.bcos.web3j.precompile.permission.PermissionService; +import org.junit.Test; + +public class PermissionServiceTest extends TestBase { + + + PermissionService permissionService = new PermissionService(web3j, credentials); + + @Test(expected= PrecompileMessageException.class) + public void userTableManager() throws Exception { + + String grantUserTableManagerResult = permissionService.grantUserTableManager("tt", Common.TX_ORIGIN); + + } + + @Test + public void deployAndCreateManager() throws Exception { + + String grantDeployAndCreateManagerResult = permissionService.grantDeployAndCreateManager(Common.TX_ORIGIN); + assertEquals(grantDeployAndCreateManagerResult, Common.SUSSCESS); + + String revokeDeployAndCreateManagerResult = permissionService.revokeDeployAndCreateManager(Common.TX_ORIGIN); + assertEquals(revokeDeployAndCreateManagerResult, Common.SUSSCESS); + + } + + @Test + public void nodeManager() throws Exception { + + String grantNodeManagerResult = permissionService.grantNodeManager(Common.TX_ORIGIN); + assertEquals(grantNodeManagerResult, Common.SUSSCESS); + + String revokeNodeManagerResult = permissionService.revokeNodeManager(Common.TX_ORIGIN); + assertEquals(revokeNodeManagerResult, Common.SUSSCESS); + } + + @Test + public void cnsManager() throws Exception { + + String grantCNSManagerResult = permissionService.grantCNSManager(Common.TX_ORIGIN); + assertEquals(grantCNSManagerResult, Common.SUSSCESS); + + String revokeCNSManagerResult = permissionService.revokeCNSManager(Common.TX_ORIGIN); + assertEquals(revokeCNSManagerResult, Common.SUSSCESS); + } + + @Test + public void sysConfigManager() throws Exception { + + String grantSysConfigManagerResult = permissionService.grantSysConfigManager(Common.TX_ORIGIN); + assertEquals(grantSysConfigManagerResult, Common.SUSSCESS); + + String revokeSysConfigManagerResult = permissionService.revokeSysConfigManager(Common.TX_ORIGIN); + assertEquals(revokeSysConfigManagerResult, Common.SUSSCESS); + + } +} diff --git a/src/integration-test/java/org/fisco/bcos/precompile/SystemConfigServiceTest.java b/src/integration-test/java/org/fisco/bcos/precompile/SystemConfigServiceTest.java new file mode 100644 index 000000000..f64de589b --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/precompile/SystemConfigServiceTest.java @@ -0,0 +1,30 @@ +package org.fisco.bcos.precompile; + +import static org.junit.Assert.assertEquals; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.precompile.config.EnumKey; +import org.fisco.bcos.web3j.precompile.config.SystemConfigService; +import org.junit.Test; + +public class SystemConfigServiceTest extends TestBase { + + + SystemConfigService systemConfigSerivce = new SystemConfigService(web3j, credentials); + + @Test + public void setValueByKey() throws Exception { + + String txCountLimit1 = "5000"; + systemConfigSerivce.setValueByKey(EnumKey.tx_count_limit.toString(), txCountLimit1); + String txCountLimit2 = web3j.getSystemConfigByKey(EnumKey.tx_count_limit.toString()).send().getSystemConfigByKey(); + assertEquals(txCountLimit1, txCountLimit2); + + String txGasLimit1 = "50000000"; + systemConfigSerivce.setValueByKey(EnumKey.tx_gas_limit.toString(), txGasLimit1); + String txGasLimit2 = web3j.getSystemConfigByKey(EnumKey.tx_gas_limit.toString()).send().getSystemConfigByKey(); + assertEquals(txGasLimit1, txGasLimit2); + + } + +} diff --git a/src/integration-test/java/org/fisco/bcos/web3j/Web3jApITest.java b/src/integration-test/java/org/fisco/bcos/web3j/Web3jApITest.java new file mode 100644 index 000000000..b18509e0d --- /dev/null +++ b/src/integration-test/java/org/fisco/bcos/web3j/Web3jApITest.java @@ -0,0 +1,191 @@ +package org.fisco.bcos.web3j; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.concurrent.ExecutionException; + +import org.fisco.bcos.TestBase; +import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameter; +import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameterName; +import org.fisco.bcos.web3j.protocol.core.methods.response.BcosBlock; +import org.fisco.bcos.web3j.protocol.core.methods.response.BcosTransaction; +import org.fisco.bcos.web3j.protocol.core.methods.response.BcosTransactionReceipt; +import org.fisco.bcos.web3j.protocol.core.methods.response.BlockHash; +import org.fisco.bcos.web3j.protocol.core.methods.response.BlockNumber; +import org.fisco.bcos.web3j.protocol.core.methods.response.Code; +import org.fisco.bcos.web3j.protocol.core.methods.response.GroupList; +import org.fisco.bcos.web3j.protocol.core.methods.response.GroupPeers; +import org.fisco.bcos.web3j.protocol.core.methods.response.NodeIDList; +import org.fisco.bcos.web3j.protocol.core.methods.response.NodeVersion; +import org.fisco.bcos.web3j.protocol.core.methods.response.ObserverList; +import org.fisco.bcos.web3j.protocol.core.methods.response.PbftView; +import org.fisco.bcos.web3j.protocol.core.methods.response.Peers; +import org.fisco.bcos.web3j.protocol.core.methods.response.PendingTransactions; +import org.fisco.bcos.web3j.protocol.core.methods.response.PendingTxSize; +import org.fisco.bcos.web3j.protocol.core.methods.response.SealerList; +import org.fisco.bcos.web3j.protocol.core.methods.response.SystemConfig; +import org.fisco.bcos.web3j.protocol.core.methods.response.TotalTransactionCount; +import org.fisco.bcos.web3j.protocol.core.methods.response.Transaction; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.junit.Test; + +public class Web3jApITest extends TestBase { + + @Test + public void getNodeVersion() throws IOException { + NodeVersion nodeVersion = web3j.getNodeVersion().send(); + assertNotNull(nodeVersion.getNodeVersion().getBuildTime()); + assertNotNull(nodeVersion.getNodeVersion().getBuildType()); + assertNotNull(nodeVersion.getNodeVersion().getGitBranch()); + assertNotNull(nodeVersion.getNodeVersion().getGitCommit()); + assertNotNull(nodeVersion.getNodeVersion().getVersion()); + } + + @Test + public void getBlockNumber() throws IOException, InterruptedException, ExecutionException { + BlockNumber blockNumber = web3j.getBlockNumber().send(); + assertNotNull(blockNumber.getBlockNumber()); + blockNumber = web3j.getBlockNumber().sendAsync().get(); + assertNotNull(blockNumber.getBlockNumber()); + } + + @Test + public void getBlockNumberCache() throws IOException { + BigInteger blockNumberCache = web3j.getBlockNumberCache(); + assertNotNull(blockNumberCache); + } + + @Test + public void pbftView() throws Exception { + PbftView pbftView = web3j.getPbftView().send(); + assertNotNull(pbftView.getPbftView()); + } + + @Test + public void getConsensusStatus() throws Exception { + String consensusStatus = web3j.getConsensusStatus().sendForReturnString(); + assertNotNull(consensusStatus); + } + + @Test + public void getSyncStatus() throws Exception { + String syncStatus = web3j.getSyncStatus().sendForReturnString(); + assertNotNull(syncStatus); + } + + @Test + public void peers() throws Exception { + Peers peers = web3j.getPeers().send(); + assertNotNull(peers.getPeers()); + } + + @Test + public void groupPeers() throws Exception { + GroupPeers groupPeers = web3j.getGroupPeers().send(); + assertNotNull(groupPeers.getGroupPeers()); + } + + @Test + public void groupList() throws Exception { + GroupList groupList = web3j.getGroupList().send(); + assertNotNull(groupList.getGroupList()); + } + + @Test + public void getSealerList() throws Exception { + SealerList sealerList = web3j.getSealerList().send(); + assertNotNull(sealerList.getSealerList()); + } + + @Test + public void getObserverList() throws Exception { + ObserverList observerList = web3j.getObserverList().send(); + assertNotNull(observerList.getObserverList()); + } + + @Test + public void getNodeIDList() throws Exception { + NodeIDList nodeIDList = web3j.getNodeIDList().send(); + assertNotNull(nodeIDList.getNodeIDList()); + } + + @Test + public void getSystemConfigByKey() throws Exception { + SystemConfig txCountLimit = web3j.getSystemConfigByKey("tx_count_limit").send(); + SystemConfig txGasLimit = web3j.getSystemConfigByKey("tx_gas_limit").send(); + assertNotNull(txCountLimit.getSystemConfigByKey()); + assertNotNull(txGasLimit.getSystemConfigByKey()); + } + + @Test + public void getCode() throws Exception { + Code code = web3j.getCode(address, DefaultBlockParameterName.LATEST).send(); + assertNotNull(code.getCode()); + } + + @Test + public void getTotalTransactionCount() throws Exception { + TotalTransactionCount count = web3j.getTotalTransactionCount().send(); + assertNotNull(count.getTotalTransactionCount()); + } + + @Test + public void getBlockByHash() throws Exception { + BcosBlock bcosBlock = web3j.getBlockByHash(blockHash, true).send(); + assertNotNull(bcosBlock.getBlock()); + } + + @Test + public void getBlockByNumber() throws Exception { + BcosBlock bcosBlock = web3j.getBlockByNumber(DefaultBlockParameter.valueOf(blockNumber), true).send(); + assertNotNull(bcosBlock.getBlock()); + } + + @Test + public void getBlockHashByNumber() throws Exception { + BlockHash blockHash = web3j.getBlockHashByNumber(DefaultBlockParameter.valueOf(blockNumber)).send(); + assertNotNull(blockHash.getBlockHashByNumber()); + } + + @Test + public void getTransactionByHash() throws Exception { + BcosTransaction bcosTransaction = web3j.getTransactionByHash(blockHash).send(); + assertNotNull(bcosTransaction.getTransaction()); + } + + @Test + public void getTransactionByBlockNumberAndIndex() throws IOException { + BcosTransaction bcosTransaction = web3j.getTransactionByBlockNumberAndIndex(DefaultBlockParameter.valueOf(blockNumber), new BigInteger("0")).send(); + Transaction transaction = bcosTransaction.getTransaction().get(); + assertNotNull(transaction); + } + + @Test + public void getTransactionByBlockHashAndIndex() throws IOException { + BcosTransaction bcosTransaction = web3j.getTransactionByBlockHashAndIndex(blockHash, new BigInteger("0")).send(); + Transaction transaction = bcosTransaction.getTransaction().get(); + assertNotNull(transaction); + } + + @Test + public void getTransactionReceipt() throws IOException { + BcosTransactionReceipt bcosTransactionReceipt = web3j.getTransactionReceipt(txHash).send(); + TransactionReceipt transactionReceipt = bcosTransactionReceipt.getTransactionReceipt().get(); + assertNotNull(transactionReceipt); + } + + @Test + public void getPendingTransaction() throws IOException { + PendingTransactions pendingTransactions = web3j.getPendingTransaction().send(); + assertNotNull(pendingTransactions.getPendingTransactions()); + } + + @Test + public void getPendingTxSize() throws IOException { + PendingTxSize pendingTxSize = web3j.getPendingTxSize().send(); + assertNotNull(pendingTxSize.getPendingTxSize()); + } + +} diff --git a/src/test/resources/applicationContext.xml b/src/integration-test/resources/applicationContext-sample.xml similarity index 97% rename from src/test/resources/applicationContext.xml rename to src/integration-test/resources/applicationContext-sample.xml index d2b52e245..8dea7eeb3 100644 --- a/src/test/resources/applicationContext.xml +++ b/src/integration-test/resources/applicationContext-sample.xml @@ -43,7 +43,7 @@ - + diff --git a/src/integration-test/resources/log4j.properties b/src/integration-test/resources/log4j.properties new file mode 100644 index 000000000..b3b3284d2 --- /dev/null +++ b/src/integration-test/resources/log4j.properties @@ -0,0 +1,49 @@ +### set log levels ### +log4j.rootLogger = INFO, info, error + +### output the TRACE level log information to the =./log/trace.log ### +log4j.appender.trace = org.apache.log4j.DailyRollingFileAppender +log4j.appender.trace.File = ./log/trace.log +log4j.appender.trace.Append = true +log4j.appender.trace.Threshold = TRACE +log4j.appender.trace.filter.traceFilter = org.apache.log4j.varia.LevelRangeFilter +log4j.appender.trace.filter.traceFilter.levelMin = TRACE +log4j.appender.trace.filter.traceFilter.levelMax = TRACE +log4j.appender.trace.layout = org.apache.log4j.PatternLayout +log4j.appender.trace.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n + +### output the DEBUG level log information to the =./log/debug.log ### +log4j.appender.debug = org.apache.log4j.DailyRollingFileAppender +log4j.appender.debug.File = ./log/debug.log +log4j.appender.debug.Append = true +log4j.appender.debug.Threshold = DEBUG +log4j.appender.debug.filter.debugFilter = org.apache.log4j.varia.LevelRangeFilter +log4j.appender.debug.filter.debugFilter.levelMin = DEBUG +log4j.appender.debug.filter.debugFilter.levelMax = DEBUG +log4j.appender.debug.layout = org.apache.log4j.PatternLayout +log4j.appender.debug.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n + +### output the INFO level log information to the =./log/info.log ### +log4j.appender.info = org.apache.log4j.DailyRollingFileAppender +log4j.appender.info.File = ./log/info.log +log4j.appender.info.Append = true +log4j.appender.info.Threshold = INFO +log4j.appender.info.filter.infoFilter = org.apache.log4j.varia.LevelRangeFilter +log4j.appender.info.filter.infoFilter.levelMin = INFO +log4j.appender.info.filter.infoFilter.levelMax = INFO +log4j.appender.info.layout = org.apache.log4j.PatternLayout +log4j.appender.info.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n + +### output the ERROR level log information to the=./log/error.log ### +log4j.appender.error = org.apache.log4j.DailyRollingFileAppender +log4j.appender.error.File = ./log/error.log +log4j.appender.error.Append = true +log4j.appender.error.Threshold = ERROR +log4j.appender.error.layout = org.apache.log4j.PatternLayout +log4j.appender.error.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n + +###output the log information to the console ### +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n diff --git a/src/main/java/org/fisco/bcos/channel/client/BcosResponseCallback.java b/src/main/java/org/fisco/bcos/channel/client/BcosResponseCallback.java new file mode 100644 index 000000000..941f04709 --- /dev/null +++ b/src/main/java/org/fisco/bcos/channel/client/BcosResponseCallback.java @@ -0,0 +1,34 @@ +package org.fisco.bcos.channel.client; + +import io.netty.util.Timeout; +import org.fisco.bcos.channel.dto.BcosResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class BcosResponseCallback { + private static Logger logger = LoggerFactory.getLogger(BcosResponseCallback.class); + + private Timeout timeout; + + public abstract void onResponse(BcosResponse response); + + public void onTimeout() { + logger.error("Processing bcos message timeout:{}"); + + BcosResponse response = new BcosResponse(); + response.setErrorCode(102); + response.setErrorMessage("Processing bcos message timeout"); + + response.setContent(""); + + onResponse(response); + } + + public Timeout getTimeout() { + return timeout; + } + + public void setTimeout(Timeout timeout) { + this.timeout = timeout; + } +} diff --git a/src/main/java/org/fisco/bcos/channel/client/ChannelPushCallback.java b/src/main/java/org/fisco/bcos/channel/client/ChannelPushCallback.java index b70d073a3..4a7f39fd6 100644 --- a/src/main/java/org/fisco/bcos/channel/client/ChannelPushCallback.java +++ b/src/main/java/org/fisco/bcos/channel/client/ChannelPushCallback.java @@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory; public abstract class ChannelPushCallback { - public abstract void onPush(ChannelPush push); + public abstract void onPush(ChannelPush push); - static Logger logger = LoggerFactory.getLogger(ChannelPushCallback.class); + static Logger logger = LoggerFactory.getLogger(ChannelPushCallback.class); } diff --git a/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback.java b/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback.java index 533be1883..20994579b 100644 --- a/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback.java +++ b/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback.java @@ -14,233 +14,237 @@ import org.slf4j.LoggerFactory; public abstract class ChannelResponseCallback { - private static Logger logger = LoggerFactory.getLogger(ChannelResponseCallback.class); - - public abstract void onResponseMessage(ChannelResponse response); - - public final void onResponse(ChannelResponse response) { - if (response.getErrorCode() == 99) { - logger.error("Local node error,try the next local node"); - retrySendMessage(1); // 1表示客户端错误 - } else if (response.getErrorCode() == 100) { - logger.error("Remote node error,try the next remote node"); - retrySendMessage(2); // 2表示服务端错误,错误码可重用 - } else { - try { - onResponseMessage(response); - } catch (Exception e) { - logger.error("c:", e); - } - - if (message.getSeq() != null) { - service.getSeq2Callback().remove(message.getSeq()); - } - - if (timeout != null) { - timeout.cancel(); - } - } - } - - public final void onTimeout() { - logger.error("send message timeout:{}", message.getSeq()); - - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(102); - response.setMessageID(message.getSeq()); - response.setErrorMessage("send message timeout"); - response.setContent(""); - - try { - onResponseMessage(response); - } catch (Exception e) { - logger.error("timeout processing error:", e); - } - - service.getSeq2Callback().remove(message.getSeq()); - timeout.cancel(); - } - - public void retrySendMessage(Integer errorType) { - Integer errorCode = 0; - try { - if (errorType == 1 || errorType == 0) { - message.setFromNode(""); - - // 选取客户端节点 - logger.debug("Number of local nodes:{}", fromConnectionInfos.size()); - if (fromConnectionInfos.size() > 0) { - Random random = new SecureRandom(); - Integer index = random.nextInt(fromConnectionInfos.size()); - - logger.debug("selected:{}", index); - - setFromConnection(fromConnectionInfos.get(index)); - message.setFromNode(getFromConnection().getNodeID()); - - Boolean res = fromConnectionInfos.remove(fromConnectionInfos.get(index)); - logger.debug( - "Number of local nodes after processing:{} {}", res, fromConnectionInfos.size()); - } - - if (message.getFromNode().isEmpty()) { - // 所有节点已尝试,无法再重试了 - logger.error("All local nodes are unavailable"); - - errorCode = 99; - throw new Exception("All local nodes are unavailable"); + private static Logger logger = LoggerFactory.getLogger(ChannelResponseCallback.class); + + public abstract void onResponseMessage(ChannelResponse response); + + public final void onResponse(ChannelResponse response) { + if (response.getErrorCode() == 99) { + logger.error("Local node error,try the next local node"); + retrySendMessage(1); // 1表示客户端错误 + } else if (response.getErrorCode() == 100) { + logger.error("Remote node error,try the next remote node"); + retrySendMessage(2); // 2表示服务端错误,错误码可重用 + } else { + try { + onResponseMessage(response); + } catch (Exception e) { + logger.error("c:", e); + } + + if (message.getSeq() != null) { + service.getSeq2Callback().remove(message.getSeq()); + } + + if (timeout != null) { + timeout.cancel(); + } } - } - - if (errorType == 2 || errorType == 0) { - message.setToNode(""); - // 选取服务端节点 - logger.debug("Number of peer nodes:{}", toConnectionInfos.size()); - if (toConnectionInfos.size() > 0) { - Random random = new SecureRandom(); - Integer index = random.nextInt(toConnectionInfos.size()); - - logger.debug("selected:{}", index); - - setToConnection(toConnectionInfos.get(index)); - message.setToNode(getToConnection().getNodeID()); + } - Boolean res = toConnectionInfos.remove(toConnectionInfos.get(index)); - logger.debug( - "Number of peer nodes after processing:{} {}", res, toConnectionInfos.size()); - } + public final void onTimeout() { + logger.error("send message timeout:{}", message.getSeq()); - if (message.getToNode().isEmpty()) { - // 所有节点已尝试,无法再重试了 - logger.error("All peer nodes are unavailable"); + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(102); + response.setMessageID(message.getSeq()); + response.setErrorMessage("send message timeout"); + response.setContent(""); - errorCode = 103; - throw new Exception("All peer nodes are unavailable"); + try { + onResponseMessage(response); + } catch (Exception e) { + logger.error("timeout processing error:", e); } - } - - logger.debug("try from {} send to:{}", message.getFromNode(), message.getToNode()); - - message.setFromNode(fromConnection.getNodeID()); - - ChannelHandlerContext ctx = - fromChannelConnections.getNetworkConnectionByHost( - getFromConnection().getHost(), getFromConnection().getPort()); - if (ctx != null && ctx.channel().isActive()) { - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); - - logger.debug( - "send message to " - + fromConnection.getHost() - + ":" - + String.valueOf(fromConnection.getPort()) - + " success"); - } else { - logger.error("sending node unavailable"); - - retrySendMessage(1); - } - } catch (Exception e) { - logger.error("send message exception ", e); - - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(errorCode); - response.setErrorMessage(e.getMessage()); - - try { - onResponseMessage(response); - } catch (Exception ee) { - logger.error("onResponseMessage error:", ee); - } - - // 彻底失败后,删掉这个seq - if (message.getSeq() != null) { service.getSeq2Callback().remove(message.getSeq()); - } - - if (timeout != null) { timeout.cancel(); - } + } - return; + public void retrySendMessage(Integer errorType) { + Integer errorCode = 0; + try { + if (errorType == 1 || errorType == 0) { + message.setFromNode(""); + + // 选取客户端节点 + logger.debug("Number of local nodes:{}", fromConnectionInfos.size()); + if (fromConnectionInfos.size() > 0) { + Random random = new SecureRandom(); + Integer index = random.nextInt(fromConnectionInfos.size()); + + logger.debug("selected:{}", index); + + setFromConnection(fromConnectionInfos.get(index)); + message.setFromNode(getFromConnection().getNodeID()); + + Boolean res = fromConnectionInfos.remove(fromConnectionInfos.get(index)); + logger.debug( + "Number of local nodes after processing:{} {}", + res, + fromConnectionInfos.size()); + } + + if (message.getFromNode().isEmpty()) { + // 所有节点已尝试,无法再重试了 + logger.error("All local nodes are unavailable"); + + errorCode = 99; + throw new Exception("All local nodes are unavailable"); + } + } + + if (errorType == 2 || errorType == 0) { + message.setToNode(""); + // 选取服务端节点 + logger.debug("Number of peer nodes:{}", toConnectionInfos.size()); + if (toConnectionInfos.size() > 0) { + Random random = new SecureRandom(); + Integer index = random.nextInt(toConnectionInfos.size()); + + logger.debug("selected:{}", index); + + setToConnection(toConnectionInfos.get(index)); + message.setToNode(getToConnection().getNodeID()); + + Boolean res = toConnectionInfos.remove(toConnectionInfos.get(index)); + logger.debug( + "Number of peer nodes after processing:{} {}", + res, + toConnectionInfos.size()); + } + + if (message.getToNode().isEmpty()) { + // 所有节点已尝试,无法再重试了 + logger.error("All peer nodes are unavailable"); + + errorCode = 103; + throw new Exception("All peer nodes are unavailable"); + } + } + + logger.debug("try from {} send to:{}", message.getFromNode(), message.getToNode()); + + message.setFromNode(fromConnection.getNodeID()); + + ChannelHandlerContext ctx = + fromChannelConnections.getNetworkConnectionByHost( + getFromConnection().getHost(), getFromConnection().getPort()); + + if (ctx != null && ctx.channel().isActive()) { + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); + + logger.debug( + "send message to " + + fromConnection.getHost() + + ":" + + String.valueOf(fromConnection.getPort()) + + " success"); + } else { + logger.error("sending node unavailable"); + + retrySendMessage(1); + } + } catch (Exception e) { + logger.error("send message exception ", e); + + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(errorCode); + response.setErrorMessage(e.getMessage()); + + try { + onResponseMessage(response); + } catch (Exception ee) { + logger.error("onResponseMessage error:", ee); + } + + // 彻底失败后,删掉这个seq + if (message.getSeq() != null) { + service.getSeq2Callback().remove(message.getSeq()); + } + + if (timeout != null) { + timeout.cancel(); + } + + return; + } } - } - public ConnectionInfo getFromConnection() { - return fromConnection; - } + public ConnectionInfo getFromConnection() { + return fromConnection; + } - public void setFromConnection(ConnectionInfo fromConnection) { - this.fromConnection = fromConnection; - } + public void setFromConnection(ConnectionInfo fromConnection) { + this.fromConnection = fromConnection; + } - public ConnectionInfo getToConnection() { - return toConnection; - } + public ConnectionInfo getToConnection() { + return toConnection; + } - public void setToConnection(ConnectionInfo toConnection) { - this.toConnection = toConnection; - } + public void setToConnection(ConnectionInfo toConnection) { + this.toConnection = toConnection; + } - public List getFromConnectionInfos() { - return fromConnectionInfos; - } + public List getFromConnectionInfos() { + return fromConnectionInfos; + } - public void setFromConnectionInfos(List fromConnectionInfos) { - this.fromConnectionInfos = fromConnectionInfos; - } + public void setFromConnectionInfos(List fromConnectionInfos) { + this.fromConnectionInfos = fromConnectionInfos; + } - public ChannelConnections getFromChannelConnections() { - return fromChannelConnections; - } + public ChannelConnections getFromChannelConnections() { + return fromChannelConnections; + } - public void setFromChannelConnections(ChannelConnections fromConnectionConnections) { - this.fromChannelConnections = fromConnectionConnections; - } + public void setFromChannelConnections(ChannelConnections fromConnectionConnections) { + this.fromChannelConnections = fromConnectionConnections; + } - public List getToConnectionInfos() { - return toConnectionInfos; - } + public List getToConnectionInfos() { + return toConnectionInfos; + } - public void setToConnectionInfos(List connectionInfos) { - this.toConnectionInfos = connectionInfos; - } + public void setToConnectionInfos(List connectionInfos) { + this.toConnectionInfos = connectionInfos; + } - public ChannelMessage getRequest() { - return message; - } + public ChannelMessage getRequest() { + return message; + } - public void setRequest(ChannelMessage message) { - this.message = message; - } + public void setRequest(ChannelMessage message) { + this.message = message; + } - public Service getService() { - return service; - } + public Service getService() { + return service; + } - public void setService(Service service) { - this.service = service; - } + public void setService(Service service) { + this.service = service; + } - public Timeout getTimeout() { - return timeout; - } + public Timeout getTimeout() { + return timeout; + } - public void setTimeout(Timeout timeout) { - this.timeout = timeout; - } + public void setTimeout(Timeout timeout) { + this.timeout = timeout; + } - private ConnectionInfo fromConnection; - private ConnectionInfo toConnection; - private List fromConnectionInfos; - private ChannelConnections fromChannelConnections; - private List toConnectionInfos; - private ChannelMessage message; - private Service service; - private Timeout timeout; + private ConnectionInfo fromConnection; + private ConnectionInfo toConnection; + private List fromConnectionInfos; + private ChannelConnections fromChannelConnections; + private List toConnectionInfos; + private ChannelMessage message; + private Service service; + private Timeout timeout; } diff --git a/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback2.java b/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback2.java index 861f4eb0c..9a0d9e0d9 100644 --- a/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback2.java +++ b/src/main/java/org/fisco/bcos/channel/client/ChannelResponseCallback2.java @@ -14,176 +14,176 @@ import org.slf4j.LoggerFactory; public abstract class ChannelResponseCallback2 { - private static Logger logger = LoggerFactory.getLogger(ChannelResponseCallback2.class); - private ConnectionInfo fromConnection; - private List fromConnectionInfos; - private ChannelConnections fromChannelConnections; - private ChannelMessage2 message; - private Service service; - private Timeout timeout; - - public abstract void onResponseMessage(ChannelResponse response); - - public final void onResponse(ChannelResponse response) { - if (response.getErrorCode() == 99) { - logger.error("Local node error,try the next local nodec"); - - retrySendMessage(); // 1表示客户端错误 - } else { - try { - onResponseMessage(response); - } catch (Exception e) { - logger.error("response package processing error:", e); - } - - if (message.getSeq() != null) { - service.getSeq2Callback().remove(message.getSeq()); - } - - if (timeout != null) { - timeout.cancel(); - } + private static Logger logger = LoggerFactory.getLogger(ChannelResponseCallback2.class); + private ConnectionInfo fromConnection; + private List fromConnectionInfos; + private ChannelConnections fromChannelConnections; + private ChannelMessage2 message; + private Service service; + private Timeout timeout; + + public abstract void onResponseMessage(ChannelResponse response); + + public final void onResponse(ChannelResponse response) { + if (response.getErrorCode() == 99) { + logger.error("Local node error,try the next local nodec"); + + retrySendMessage(); // 1表示客户端错误 + } else { + try { + onResponseMessage(response); + } catch (Exception e) { + logger.error("response package processing error:", e); + } + + if (message.getSeq() != null) { + service.getSeq2Callback().remove(message.getSeq()); + } + + if (timeout != null) { + timeout.cancel(); + } + } } - } - public final void onTimeout() { - logger.error("send message timeout:{}", message.getSeq()); + public final void onTimeout() { + logger.error("send message timeout:{}", message.getSeq()); - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(102); - response.setMessageID(message.getSeq()); - response.setErrorMessage("send message timeout"); - response.setContent(""); + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(102); + response.setMessageID(message.getSeq()); + response.setErrorMessage("send message timeout"); + response.setContent(""); - try { - onResponseMessage(response); - } catch (Exception e) { - logger.error("timeout processing error:", e); - } + try { + onResponseMessage(response); + } catch (Exception e) { + logger.error("timeout processing error:", e); + } - service.getSeq2Callback().remove(message.getSeq()); - timeout.cancel(); - } - - public void retrySendMessage() { - Integer errorCode = 0; - try { - // 选取客户端节点 - logger.debug("Number of local nodes:{}", fromConnectionInfos.size()); - - setFromConnection(null); - if (fromConnectionInfos.size() > 0) { - Random random = new SecureRandom(); - Integer index = random.nextInt(fromConnectionInfos.size()); - - logger.debug("selected:{}", index); - - setFromConnection(fromConnectionInfos.get(index)); - - fromConnectionInfos.remove(fromConnectionInfos.get(index)); - } - - if (getFromConnection() == null) { - // 所有节点已尝试,无法再重试了 - logger.error("Failed to send message,all retry failed"); - - errorCode = 99; - throw new Exception("Failed to send message,all retry failed"); - } - - ChannelHandlerContext ctx = - fromChannelConnections.getNetworkConnectionByHost( - getFromConnection().getHost(), getFromConnection().getPort()); - - if (ctx != null && ctx.channel().isActive()) { - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); - - logger.debug( - "send message to " - + fromConnection.getHost() - + ":" - + String.valueOf(fromConnection.getPort()) - + " 成功"); - } else { - logger.error("sending node unavailable"); - - retrySendMessage(); - } - } catch (Exception e) { - logger.error("send message exception ", e); - - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(errorCode); - response.setErrorMessage(e.getMessage()); - - try { - onResponseMessage(response); - } catch (Exception ee) { - logger.error("onResponseMessage error:", ee); - } - - // 彻底失败后,删掉这个seq - if (message.getSeq() != null) { service.getSeq2Callback().remove(message.getSeq()); - } - - if (timeout != null) { timeout.cancel(); - } + } - return; + public void retrySendMessage() { + Integer errorCode = 0; + try { + // 选取客户端节点 + logger.debug("Number of local nodes:{}", fromConnectionInfos.size()); + + setFromConnection(null); + if (fromConnectionInfos.size() > 0) { + Random random = new SecureRandom(); + Integer index = random.nextInt(fromConnectionInfos.size()); + + logger.debug("selected:{}", index); + + setFromConnection(fromConnectionInfos.get(index)); + + fromConnectionInfos.remove(fromConnectionInfos.get(index)); + } + + if (getFromConnection() == null) { + // 所有节点已尝试,无法再重试了 + logger.error("Failed to send message,all retry failed"); + + errorCode = 99; + throw new Exception("Failed to send message,all retry failed"); + } + + ChannelHandlerContext ctx = + fromChannelConnections.getNetworkConnectionByHost( + getFromConnection().getHost(), getFromConnection().getPort()); + + if (ctx != null && ctx.channel().isActive()) { + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); + + logger.debug( + "send message to " + + fromConnection.getHost() + + ":" + + String.valueOf(fromConnection.getPort()) + + " 成功"); + } else { + logger.error("sending node unavailable"); + + retrySendMessage(); + } + } catch (Exception e) { + logger.error("send message exception ", e); + + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(errorCode); + response.setErrorMessage(e.getMessage()); + + try { + onResponseMessage(response); + } catch (Exception ee) { + logger.error("onResponseMessage error:", ee); + } + + // 彻底失败后,删掉这个seq + if (message.getSeq() != null) { + service.getSeq2Callback().remove(message.getSeq()); + } + + if (timeout != null) { + timeout.cancel(); + } + + return; + } } - } - public ConnectionInfo getFromConnection() { - return fromConnection; - } + public ConnectionInfo getFromConnection() { + return fromConnection; + } - public void setFromConnection(ConnectionInfo fromConnection) { - this.fromConnection = fromConnection; - } + public void setFromConnection(ConnectionInfo fromConnection) { + this.fromConnection = fromConnection; + } - public List getFromConnectionInfos() { - return fromConnectionInfos; - } + public List getFromConnectionInfos() { + return fromConnectionInfos; + } - public void setFromConnectionInfos(List fromConnectionInfos) { - this.fromConnectionInfos = fromConnectionInfos; - } + public void setFromConnectionInfos(List fromConnectionInfos) { + this.fromConnectionInfos = fromConnectionInfos; + } - public ChannelConnections getFromChannelConnections() { - return fromChannelConnections; - } + public ChannelConnections getFromChannelConnections() { + return fromChannelConnections; + } - public void setFromChannelConnections(ChannelConnections fromConnectionConnections) { - this.fromChannelConnections = fromConnectionConnections; - } + public void setFromChannelConnections(ChannelConnections fromConnectionConnections) { + this.fromChannelConnections = fromConnectionConnections; + } - public ChannelMessage2 getRequest() { - return message; - } + public ChannelMessage2 getRequest() { + return message; + } - public void setRequest(ChannelMessage2 message) { - this.message = message; - } + public void setRequest(ChannelMessage2 message) { + this.message = message; + } - public Service getService() { - return service; - } + public Service getService() { + return service; + } - public void setService(Service service) { - this.service = service; - } + public void setService(Service service) { + this.service = service; + } - public Timeout getTimeout() { - return timeout; - } + public Timeout getTimeout() { + return timeout; + } - public void setTimeout(Timeout timeout) { - this.timeout = timeout; - } + public void setTimeout(Timeout timeout) { + this.timeout = timeout; + } } diff --git a/src/main/java/org/fisco/bcos/channel/client/FiscoResponseCallback.java b/src/main/java/org/fisco/bcos/channel/client/FiscoResponseCallback.java deleted file mode 100644 index 86d771c8f..000000000 --- a/src/main/java/org/fisco/bcos/channel/client/FiscoResponseCallback.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.fisco.bcos.channel.client; - -import io.netty.util.Timeout; -import org.fisco.bcos.channel.dto.FiscoResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class FiscoResponseCallback { - private static Logger logger = LoggerFactory.getLogger(FiscoResponseCallback.class); - - private Timeout timeout; - - public abstract void onResponse(FiscoResponse response); - - public void onTimeout() { - logger.error("Processing fisco message timeout:{}"); - - FiscoResponse response = new FiscoResponse(); - response.setErrorCode(102); - response.setErrorMessage("Processing fisco message timeout"); - - response.setContent(""); - - onResponse(response); - } - - public Timeout getTimeout() { - return timeout; - } - - public void setTimeout(Timeout timeout) { - this.timeout = timeout; - } -} diff --git a/src/main/java/org/fisco/bcos/channel/client/P12Manager.java b/src/main/java/org/fisco/bcos/channel/client/P12Manager.java new file mode 100644 index 000000000..9b2161ad4 --- /dev/null +++ b/src/main/java/org/fisco/bcos/channel/client/P12Manager.java @@ -0,0 +1,142 @@ +package org.fisco.bcos.channel.client; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.util.Collections; +import org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.fisco.bcos.web3j.crypto.ECKeyPair; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +public class P12Manager { + private String p12File; + private final String NAME = "key"; + private String password; + private KeyStore keyStore; + PKCS12KeyStoreSpi p12KeyStore; + + public P12Manager() { + Security.setProperty("crypto.policy", "unlimited"); + Security.addProvider(new BouncyCastleProvider()); + } + + public void load() + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, + NoSuchProviderException { + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + keyStore = KeyStore.getInstance("PKCS12", "BC"); + Resource keyStoreResource = resolver.getResource(p12File); + + keyStore.load(keyStoreResource.getInputStream(), password.toCharArray()); + } + + public void load(InputStream in, String password) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + p12KeyStore.engineLoad(in, password.toCharArray()); + } + + public PrivateKey getPrivateKey(String password) + throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException { + return (PrivateKey) keyStore.getKey(NAME, password.toCharArray()); + } + + public PublicKey getPublicKey(String password) + throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, + InvalidKeySpecException, NoSuchProviderException { + ECPrivateKey privateKey = (ECPrivateKey) getPrivateKey(password); + + ECParameterSpec params = privateKey.getParams(); + + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = + org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); + org.bouncycastle.math.ec.ECPoint q = bcSpec.getG().multiply(privateKey.getS()); + org.bouncycastle.math.ec.ECPoint bcW = bcSpec.getCurve().decodePoint(q.getEncoded(false)); + ECPoint w = + new ECPoint( + bcW.getAffineXCoord().toBigInteger(), bcW.getAffineYCoord().toBigInteger()); + ECPublicKeySpec keySpec = new ECPublicKeySpec(w, tryFindNamedCurveSpec(params)); + return (PublicKey) + KeyFactory.getInstance( + "EC", + org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) + .generatePublic(keySpec); + } + + @SuppressWarnings("unchecked") + public static ECParameterSpec tryFindNamedCurveSpec(ECParameterSpec params) { + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = + org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); + for (Object name : Collections.list(org.bouncycastle.jce.ECNamedCurveTable.getNames())) { + org.bouncycastle.jce.spec.ECNamedCurveParameterSpec bcNamedSpec = + org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec((String) name); + if (bcNamedSpec.getN().equals(bcSpec.getN()) + && bcNamedSpec.getH().equals(bcSpec.getH()) + && bcNamedSpec.getCurve().equals(bcSpec.getCurve()) + && bcNamedSpec.getG().equals(bcSpec.getG())) { + return new org.bouncycastle.jce.spec.ECNamedCurveSpec( + bcNamedSpec.getName(), + bcNamedSpec.getCurve(), + bcNamedSpec.getG(), + bcNamedSpec.getN(), + bcNamedSpec.getH(), + bcNamedSpec.getSeed()); + } + } + return params; + } + + public Certificate getCertificate() throws KeyStoreException { + return keyStore.getCertificate(NAME); + } + + public PublicKey getPublicKeyFromCertificate() throws KeyStoreException { + Certificate certificate = getCertificate(); + return certificate.getPublicKey(); + } + + public ECKeyPair getECKeyPair(String password) + throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, + InvalidKeySpecException, NoSuchProviderException { + PrivateKey privateKey = getPrivateKey(password); + PublicKey publicKey = getPublicKey(password); + + KeyPair keyPair = new KeyPair(publicKey, privateKey); + + return ECKeyPair.create(keyPair); + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getP12File() { + return p12File; + } + + public void setP12File(String p12File) { + this.p12File = p12File; + } +} diff --git a/src/main/java/org/fisco/bcos/channel/client/PEMManager.java b/src/main/java/org/fisco/bcos/channel/client/PEMManager.java new file mode 100644 index 000000000..f86b8ffe9 --- /dev/null +++ b/src/main/java/org/fisco/bcos/channel/client/PEMManager.java @@ -0,0 +1,136 @@ +package org.fisco.bcos.channel.client; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Collections; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.fisco.bcos.web3j.crypto.ECKeyPair; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +public class PEMManager { + private PemObject pem; + private String pemFile; + + public PEMManager() { + Security.setProperty("crypto.policy", "unlimited"); + Security.addProvider(new BouncyCastleProvider()); + } + + public void load() + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, + NoSuchProviderException, InvalidKeySpecException { + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource pemResources = resolver.getResource(pemFile); + + load(pemResources.getInputStream()); + } + + public void load(InputStream in) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, + InvalidKeySpecException, NoSuchProviderException { + PemReader pemReader = new PemReader(new InputStreamReader(in)); + + pem = pemReader.readPemObject(); + if (pem == null) { + throw new IOException("The file does not represent a pem account."); + } + pemReader.close(); + } + + public PrivateKey getPrivateKey() + throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException { + // PrivateKey key = KeyFactory.getInstance("EC", + // org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME).generatePrivate(new + // X509EncodedKeySpec(pem.getContent())); + + PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(pem.getContent()); + KeyFactory keyFacotry = + KeyFactory.getInstance( + "EC", org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME); + return keyFacotry.generatePrivate(encodedKeySpec); + } + + public PublicKey getPublicKey() + throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException { + ECPrivateKey privateKey = (ECPrivateKey) getPrivateKey(); + + ECParameterSpec params = privateKey.getParams(); + + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = + org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); + org.bouncycastle.math.ec.ECPoint q = bcSpec.getG().multiply(privateKey.getS()); + org.bouncycastle.math.ec.ECPoint bcW = bcSpec.getCurve().decodePoint(q.getEncoded(false)); + ECPoint w = + new ECPoint( + bcW.getAffineXCoord().toBigInteger(), bcW.getAffineYCoord().toBigInteger()); + ECPublicKeySpec keySpec = new ECPublicKeySpec(w, tryFindNamedCurveSpec(params)); + return (PublicKey) + KeyFactory.getInstance( + "EC", + org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) + .generatePublic(keySpec); + } + + public ECKeyPair getECKeyPair() + throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, + InvalidKeySpecException, NoSuchProviderException { + PrivateKey privateKey = getPrivateKey(); + PublicKey publicKey = getPublicKey(); + + KeyPair keyPair = new KeyPair(publicKey, privateKey); + + return ECKeyPair.create(keyPair); + } + + @SuppressWarnings("unchecked") + public static ECParameterSpec tryFindNamedCurveSpec(ECParameterSpec params) { + org.bouncycastle.jce.spec.ECParameterSpec bcSpec = + org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); + for (Object name : Collections.list(org.bouncycastle.jce.ECNamedCurveTable.getNames())) { + org.bouncycastle.jce.spec.ECNamedCurveParameterSpec bcNamedSpec = + org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec((String) name); + if (bcNamedSpec.getN().equals(bcSpec.getN()) + && bcNamedSpec.getH().equals(bcSpec.getH()) + && bcNamedSpec.getCurve().equals(bcSpec.getCurve()) + && bcNamedSpec.getG().equals(bcSpec.getG())) { + return new org.bouncycastle.jce.spec.ECNamedCurveSpec( + bcNamedSpec.getName(), + bcNamedSpec.getCurve(), + bcNamedSpec.getG(), + bcNamedSpec.getN(), + bcNamedSpec.getH(), + bcNamedSpec.getSeed()); + } + } + return params; + } + + public String getPemFile() { + return pemFile; + } + + public void setPemFile(String pemFile) { + this.pemFile = pemFile; + } +} diff --git a/src/main/java/org/fisco/bcos/channel/client/Service.java b/src/main/java/org/fisco/bcos/channel/client/Service.java index 31fa326d2..fdbbab936 100644 --- a/src/main/java/org/fisco/bcos/channel/client/Service.java +++ b/src/main/java/org/fisco/bcos/channel/client/Service.java @@ -9,6 +9,7 @@ import io.netty.util.Timer; import io.netty.util.TimerTask; import java.math.BigInteger; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -18,740 +19,832 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import org.fisco.bcos.channel.dto.*; +import org.fisco.bcos.channel.dto.BcosMessage; +import org.fisco.bcos.channel.dto.BcosRequest; +import org.fisco.bcos.channel.dto.BcosResponse; +import org.fisco.bcos.channel.dto.ChannelMessage; +import org.fisco.bcos.channel.dto.ChannelMessage2; +import org.fisco.bcos.channel.dto.ChannelPush; +import org.fisco.bcos.channel.dto.ChannelPush2; +import org.fisco.bcos.channel.dto.ChannelRequest; +import org.fisco.bcos.channel.dto.ChannelResponse; import org.fisco.bcos.channel.handler.ChannelConnections; import org.fisco.bcos.channel.handler.ConnectionCallback; import org.fisco.bcos.channel.handler.ConnectionInfo; import org.fisco.bcos.channel.handler.GroupChannelConnectionsConfig; +import org.fisco.bcos.channel.handler.Message; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class Service { - private static Logger logger = LoggerFactory.getLogger(Service.class); - private Integer connectSeconds = 30; - private Integer connectSleepPerMillis = 1; - private String orgID; - private GroupChannelConnectionsConfig allChannelConnections; - private ChannelPushCallback pushCallback; - private Map seq2Callback = new ConcurrentHashMap(); - private int groupId; - private static ObjectMapper objectMapper = new ObjectMapper(); - private BigInteger number = BigInteger.valueOf(0); - - /** add transaction seq callback */ - private Map seq2TransactionCallback = new ConcurrentHashMap(); - - private Timer timeoutHandler = new HashedWheelTimer(); - private ThreadPoolTaskExecutor threadPool; - - private Set topics = new HashSet(); - - public void setTopics(Set topics) { - try { - this.topics = topics; - } catch (Exception e) { - logger.error("system error", e); - } - } - - public Integer getConnectSeconds() { - return connectSeconds; - } - - public void setConnectSeconds(Integer connectSeconds) { - this.connectSeconds = connectSeconds; - } - - public Integer getConnectSleepPerMillis() { - return connectSleepPerMillis; - } - - public void setConnectSleepPerMillis(Integer connectSleepPerMillis) { - this.connectSleepPerMillis = connectSleepPerMillis; - } - - public String getOrgID() { - return orgID; - } - - public void setOrgID(String orgID) { - this.orgID = orgID; - } - - public ChannelPushCallback getPushCallback() { - return pushCallback; - } - - public void setPushCallback(ChannelPushCallback pushCallback) { - this.pushCallback = pushCallback; - } - - public GroupChannelConnectionsConfig getAllChannelConnections() { - return allChannelConnections; - } - - public void setAllChannelConnections(GroupChannelConnectionsConfig allChannelConnections) { - this.allChannelConnections = allChannelConnections; - } - - public void run() throws Exception { - logger.debug("init ChannelService"); - int flag = 0; - for (ChannelConnections channelConnections : allChannelConnections.getAllChannelConnections()) { - - if (channelConnections.getGroupId() == groupId) { - flag = 1; + private static Logger logger = LoggerFactory.getLogger(Service.class); + private Integer connectSeconds = 30; + private Integer connectSleepPerMillis = 1; + private String orgID; + private String agencyName; + private GroupChannelConnectionsConfig allChannelConnections; + private ChannelPushCallback pushCallback; + private Map seq2Callback = new ConcurrentHashMap(); + private int groupId; + private static ObjectMapper objectMapper = new ObjectMapper(); + private BigInteger number = BigInteger.valueOf(0); + private ConcurrentHashMap nodeToBlockNumberMap = new ConcurrentHashMap<>(); + /** add transaction seq callback */ + private Map seq2TransactionCallback = new ConcurrentHashMap(); + + private Timer timeoutHandler = new HashedWheelTimer(); + private ThreadPoolTaskExecutor threadPool; + + private Set topics = new HashSet(); + + public void setTopics(Set topics) { try { - ConnectionCallback connectionCallback = new ConnectionCallback(topics); - connectionCallback.setChannelService(this); - - channelConnections.setCallback(connectionCallback); - channelConnections.init(); - channelConnections.setThreadPool(threadPool); - channelConnections.startConnect(); - - int sleepTime = 0; - boolean running = false; - while (true) { - Map networkConnection = - channelConnections.getNetworkConnections(); - for (String key : networkConnection.keySet()) { - if (networkConnection.get(key) != null - && networkConnection.get(key).channel().isActive()) { - running = true; - break; - } + this.topics = topics; + } catch (Exception e) { + logger.error("system error", e); + } + } + + public ConcurrentHashMap getNodeToBlockNumberMap() { + return nodeToBlockNumberMap; + } + + public void setNodeToBlockNumberMap(ConcurrentHashMap nodeToBlockNumberMap) { + this.nodeToBlockNumberMap = nodeToBlockNumberMap; + } + + public boolean flushTopics(List topics) { + + try { + Message message = new Message(); + message.setResult(0); + message.setType((short) 0x32); // topic设置topic消息0x32 + message.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); + + message.setData(objectMapper.writeValueAsBytes(topics.toArray())); + + ChannelConnections fromChannelConnections = + allChannelConnections + .getAllChannelConnections() + .stream() + .filter(x -> x.getGroupId() == groupId) + .findFirst() + .get(); + + if (fromChannelConnections == null) { + logger.error("not found and connections which orgId is:{}", orgID); + return false; } - if (running || sleepTime > connectSeconds * 1000) { - break; - } else { - Thread.sleep(connectSleepPerMillis); - sleepTime += connectSleepPerMillis; + for (String key : fromChannelConnections.getNetworkConnections().keySet()) { + ChannelHandlerContext ctx = fromChannelConnections.getNetworkConnections().get(key); + + if (ctx != null && ctx.channel().isActive()) { + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + ctx.writeAndFlush(out); + + String host = + ((SocketChannel) ctx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + logger.info( + "try to flush seq:{} topics:{} to host:{} port :{}", + message.getSeq(), + topics, + host, + port); + } } - } - - if (!running) { - logger.error("connectSeconds = " + connectSeconds); - logger.error( - "cannot not connect to node success, please checkout the node and the sdk config!"); - throw new Exception( - "Init ChannelService fail!Please Refer To Link Below:https://github.com/FISCO-BCOS/web3sdk/wiki/web3sdk-debug"); - } - } catch (InterruptedException e) { - logger.error("system error ", e); - Thread.currentThread().interrupt(); + + return true; } catch (Exception e) { - logger.error("system error ", e); - throw e; + logger.error("flushTopics exception", e); } - } + + return false; } - if (flag == 0) { - throw new Exception("Please set the right groupId"); + + public Set getTopics() { + return this.topics; } - } - public FiscoResponse sendEthereumMessage(FiscoRequest request) { - class Callback extends FiscoResponseCallback { - Callback() { - try { - semaphore.acquire(1); + public Integer getConnectSeconds() { + return connectSeconds; + } - } catch (InterruptedException e) { - logger.error("error :", e); - Thread.currentThread().interrupt(); - } - } + public void setConnectSeconds(Integer connectSeconds) { + this.connectSeconds = connectSeconds; + } - @Override - public void onResponse(FiscoResponse response) { - fiscoResponse = response; + public Integer getConnectSleepPerMillis() { + return connectSleepPerMillis; + } - if (fiscoResponse != null && fiscoResponse.getContent() != null) { - logger.debug("response: {}", response.getContent()); - } else { - logger.error("fisco error"); - } + public void setConnectSleepPerMillis(Integer connectSleepPerMillis) { + this.connectSleepPerMillis = connectSleepPerMillis; + } + + public String getOrgID() { + return orgID; + } + + public void setOrgID(String orgID) { + this.orgID = orgID; + } + + public String getAgencyName() { + return agencyName; + } + + public void setAgencyName(String agencyName) { + this.agencyName = agencyName; + } + + public ChannelPushCallback getPushCallback() { + return pushCallback; + } - semaphore.release(); - } + public void setPushCallback(ChannelPushCallback pushCallback) { + this.pushCallback = pushCallback; + } - public FiscoResponse fiscoResponse; - public Semaphore semaphore = new Semaphore(1, true); - }; + public GroupChannelConnectionsConfig getAllChannelConnections() { + return allChannelConnections; + } - Callback callback = new Callback(); + public void setAllChannelConnections(GroupChannelConnectionsConfig allChannelConnections) { + this.allChannelConnections = allChannelConnections; + } + + public void run() throws Exception { + logger.debug("init ChannelService"); + int flag = 0; + for (ChannelConnections channelConnections : + allChannelConnections.getAllChannelConnections()) { + + if (channelConnections.getGroupId() == groupId) { + flag = 1; + try { + ConnectionCallback connectionCallback = new ConnectionCallback(topics); + connectionCallback.setChannelService(this); + + channelConnections.setCallback(connectionCallback); + channelConnections.init(); + channelConnections.setThreadPool(threadPool); + channelConnections.startConnect(); + + int sleepTime = 0; + boolean running = false; + while (true) { + Map networkConnection = + channelConnections.getNetworkConnections(); + for (String key : networkConnection.keySet()) { + if (networkConnection.get(key) != null + && networkConnection.get(key).channel().isActive()) { + running = true; + break; + } + } + + if (running || sleepTime > connectSeconds * 1000) { + break; + } else { + Thread.sleep(connectSleepPerMillis); + sleepTime += connectSleepPerMillis; + } + } - asyncSendEthereumMessage(request, callback); - try { - callback.semaphore.acquire(1); - } catch (InterruptedException e) { - logger.error("system error:", e); - Thread.currentThread().interrupt(); + if (!running) { + logger.error("connectSeconds = " + connectSeconds); + logger.error( + "can not connect to nodes success, please checkout the node status and the sdk config!"); + throw new Exception( + "Can not connect to nodes success, please checkout the node status and the sdk config!"); + } + } catch (InterruptedException e) { + logger.error("system error ", e); + Thread.currentThread().interrupt(); + } catch (Exception e) { + logger.error("system error ", e); + throw e; + } + } + } + if (flag == 0) { + throw new Exception("Please set the right groupId"); + } } - return callback.fiscoResponse; - } + public BcosResponse sendEthereumMessage(BcosRequest request) { + class Callback extends BcosResponseCallback { + Callback() { + try { + semaphore.acquire(1); + + } catch (InterruptedException e) { + logger.error("error :", e); + Thread.currentThread().interrupt(); + } + } + + @Override + public void onResponse(BcosResponse response) { + fiscoResponse = response; + + if (fiscoResponse != null && fiscoResponse.getContent() != null) { + logger.debug("response: {}", response.getContent()); + } else { + logger.error("fisco error"); + } + + semaphore.release(); + } - public FiscoResponse sendEthereumMessage( - FiscoRequest request, TransactionSucCallback transactionSucCallback) { - class Callback extends FiscoResponseCallback { - public FiscoResponse ethereumResponse; - public Semaphore semaphore = new Semaphore(1, true); + public BcosResponse fiscoResponse; + public Semaphore semaphore = new Semaphore(1, true); + }; - Callback() { + Callback callback = new Callback(); + + asyncSendEthereumMessage(request, callback); try { - semaphore.acquire(1); + callback.semaphore.acquire(1); } catch (InterruptedException e) { - logger.error("error:", e); - Thread.currentThread().interrupt(); + logger.error("system error:", e); + Thread.currentThread().interrupt(); } - } - - @Override - public void onResponse(FiscoResponse response) { - ethereumResponse = response; - - logger.info("response: {}", response.getContent()); - - semaphore.release(); - } - } - - Callback callback = new Callback(); - asyncSendEthereumMessage(request, callback, transactionSucCallback); - try { - callback.semaphore.acquire(1); - } catch (InterruptedException e) { - logger.error("system error:", e); - Thread.currentThread().interrupt(); - } - - return callback.ethereumResponse; - } - - public void asyncSendEthereumMessage( - FiscoRequest request, - FiscoResponseCallback fiscoResponseCallback, - TransactionSucCallback transactionSucCallback) { - this.asyncSendEthereumMessage(request, fiscoResponseCallback); - if (request.getTimeout() > 0) { - final TransactionSucCallback callbackInner = transactionSucCallback; - callbackInner.setTimeout( - timeoutHandler.newTimeout( - new TimerTask() { - @Override - public void run(Timeout timeout) throws Exception { - // 处理超时逻辑 - callbackInner.onTimeout(); - // timeout时清除map的数据,所以尽管后面有回包数据,也会找不到seq->callback的关系 - seq2TransactionCallback.remove(request.getMessageID()); + + return callback.fiscoResponse; + } + + public BcosResponse sendEthereumMessage( + BcosRequest request, TransactionSucCallback transactionSucCallback) { + class Callback extends BcosResponseCallback { + public BcosResponse ethereumResponse; + public Semaphore semaphore = new Semaphore(1, true); + + Callback() { + try { + semaphore.acquire(1); + } catch (InterruptedException e) { + logger.error("error:", e); + Thread.currentThread().interrupt(); } - }, - request.getTimeout(), - TimeUnit.MILLISECONDS)); - this.seq2TransactionCallback.put(request.getMessageID(), callbackInner); - } else { - this.seq2TransactionCallback.put(request.getMessageID(), transactionSucCallback); - } - } - - public ChannelResponse sendChannelMessage2(ChannelRequest request) { - class Callback extends ChannelResponseCallback2 { - Callback() { - try { - semaphore.acquire(1); + } + + @Override + public void onResponse(BcosResponse response) { + ethereumResponse = response; + semaphore.release(); + } + } + Callback callback = new Callback(); + asyncSendEthereumMessage(request, callback, transactionSucCallback); + try { + callback.semaphore.acquire(1); } catch (InterruptedException e) { - logger.error("error:", e); - Thread.currentThread().interrupt(); + logger.error("system error:", e); + Thread.currentThread().interrupt(); + } + + return callback.ethereumResponse; + } + + public void asyncSendEthereumMessage( + BcosRequest request, + BcosResponseCallback fiscoResponseCallback, + TransactionSucCallback transactionSucCallback) { + this.asyncSendEthereumMessage(request, fiscoResponseCallback); + if (request.getTimeout() > 0) { + final TransactionSucCallback callbackInner = transactionSucCallback; + callbackInner.setTimeout( + timeoutHandler.newTimeout( + new TimerTask() { + @Override + public void run(Timeout timeout) throws Exception { + // 处理超时逻辑 + callbackInner.onTimeout(); + // timeout时清除map的数据,所以尽管后面有回包数据,也会找不到seq->callback的关系 + seq2TransactionCallback.remove(request.getMessageID()); + } + }, + request.getTimeout(), + TimeUnit.MILLISECONDS)); + this.seq2TransactionCallback.put(request.getMessageID(), callbackInner); + } else { + this.seq2TransactionCallback.put(request.getMessageID(), transactionSucCallback); } - } + } - @Override - public void onResponseMessage(ChannelResponse response) { - channelResponse = response; + public ChannelResponse sendChannelMessage2(ChannelRequest request) { + class Callback extends ChannelResponseCallback2 { + Callback() { + try { + semaphore.acquire(1); - logger.debug("response: {}", response.getContent()); - - semaphore.release(); - } + } catch (InterruptedException e) { + logger.error("error:", e); + Thread.currentThread().interrupt(); + } + } - public ChannelResponse channelResponse; - public Semaphore semaphore = new Semaphore(1, true); - }; + @Override + public void onResponseMessage(ChannelResponse response) { + channelResponse = response; - Callback callback = new Callback(); + logger.debug("response: {}", response.getContent()); - asyncSendChannelMessage2(request, callback); - try { - callback.semaphore.acquire(1); - } catch (InterruptedException e) { - logger.error("system error:", e); - Thread.currentThread().interrupt(); - } + semaphore.release(); + } - return callback.channelResponse; - } + public ChannelResponse channelResponse; + public Semaphore semaphore = new Semaphore(1, true); + }; - public void asyncSendEthereumMessage(FiscoRequest request, FiscoResponseCallback callback) { - logger.debug("fisco message: " + request.getMessageID()); + Callback callback = new Callback(); - Boolean sended = false; - - FiscoMessage fiscoMessage = new FiscoMessage(); - - fiscoMessage.setSeq(request.getMessageID()); - fiscoMessage.setResult(0); - fiscoMessage.setType((short) 0x12); - fiscoMessage.setData(request.getContent().getBytes()); - - // 选取发送节点 - try { - - ChannelConnections fromChannelConnections = - allChannelConnections - .getAllChannelConnections() - .stream() - .filter(x -> x.getGroupId() == groupId) - .findFirst() - .get(); - - if (fromChannelConnections == null) { - // 没有找到对应的链 - // 返回错误 - logger.error("not found:{}", orgID); - - throw new Exception("not found orgID"); - } - - ChannelHandlerContext ctx = fromChannelConnections.randomNetworkConnection(); - - ByteBuf out = ctx.alloc().buffer(); - fiscoMessage.writeHeader(out); - fiscoMessage.writeExtra(out); - - seq2Callback.put(request.getMessageID(), callback); - - if (request.getTimeout() > 0) { - final FiscoResponseCallback callbackInner = callback; // ethereum名字可能会搞混,换成channel - callback.setTimeout( - timeoutHandler.newTimeout( - new TimerTask() { - FiscoResponseCallback _callback = callbackInner; - - @Override - public void run(Timeout timeout) throws Exception { - // 处理超时逻辑 - _callback.onTimeout(); - } - }, - request.getTimeout(), - TimeUnit.MILLISECONDS)); - } - - ctx.writeAndFlush(out); - - logger.debug( - "send fisco message to " - + ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress() - + ":" - + ((SocketChannel) ctx.channel()).remoteAddress().getPort() - + " success"); - - sended = true; - } catch (Exception e) { - logger.error("system error: " + e.getMessage()); - - FiscoResponse response = new FiscoResponse(); - response.setErrorCode(-1); - response.setErrorMessage( - e.getMessage() - + " requset send failed! Please Refer To Link Below:https://github.com/FISCO-BCOS/web3sdk/wiki/web3sdk-debug"); - response.setContent(""); - response.setMessageID(request.getMessageID()); - - if (callback.getTimeout() != null) { - callback.getTimeout().cancel(); - } - callback.onResponse(response); - } - } - - public void asyncSendChannelMessage2(ChannelRequest request, ChannelResponseCallback2 callback) { - try { - logger.debug("ChannelRequest: " + request.getMessageID()); - callback.setService(this); - - ChannelMessage2 channelMessage = new ChannelMessage2(); - - channelMessage.setSeq(request.getMessageID()); - channelMessage.setResult(0); - channelMessage.setType((short) 0x30); // 链上链下请求0x30 - channelMessage.setData(request.getContent().getBytes()); - channelMessage.setTopic(request.getToTopic()); - - try { - List fromConnectionInfos = new ArrayList(); - - // 设置发送节点 - ChannelConnections fromChannelConnections = - allChannelConnections - .getAllChannelConnections() - .stream() - .filter(x -> x.getGroupId() == groupId) - .findFirst() - .get(); - if (fromChannelConnections == null) { - // 没有找到对应的链 - // 返回错误 - logger.error("not found orgID:{}", orgID); - - throw new Exception("not found orgID"); + asyncSendChannelMessage2(request, callback); + try { + callback.semaphore.acquire(1); + } catch (InterruptedException e) { + logger.error("system error:", e); + Thread.currentThread().interrupt(); } - fromConnectionInfos.addAll(fromChannelConnections.getConnections()); - logger.debug( - "FromOrg:{} nodes:{}", - request.getFromOrg(), - fromChannelConnections.getConnections().size()); - callback.setFromChannelConnections(fromChannelConnections); - callback.setFromConnectionInfos(fromConnectionInfos); + return callback.channelResponse; + } - // 设置消息内容 - callback.setRequest(channelMessage); + public void asyncSendEthereumMessage(BcosRequest request, BcosResponseCallback callback) { + Boolean sended = false; - seq2Callback.put(request.getMessageID(), callback); + BcosMessage bcosMessage = new BcosMessage(); - if (request.getTimeout() > 0) { - final ChannelResponseCallback2 callbackInner = callback; - callback.setTimeout( - timeoutHandler.newTimeout( - new TimerTask() { - ChannelResponseCallback2 _callback = callbackInner; - - @Override - public void run(Timeout timeout) throws Exception { - // 处理超时逻辑 - _callback.onTimeout(); - } - }, - request.getTimeout(), - TimeUnit.MILLISECONDS)); - } + bcosMessage.setSeq(request.getMessageID()); + bcosMessage.setResult(0); + bcosMessage.setType((short) 0x12); + bcosMessage.setData(request.getContent().getBytes()); + // select node + try { + ChannelConnections channelConnections = + allChannelConnections + .getAllChannelConnections() + .stream() + .filter(x -> x.getGroupId() == groupId) + .findFirst() + .get(); + + if (channelConnections == null) { + if (orgID != null) { + logger.error("not found:{}", orgID); + throw new Exception("not found orgID"); + } else { + logger.error("not found:{}", agencyName); + throw new Exception("not found agencyName"); + } + } + ChannelHandlerContext ctx = + channelConnections.randomNetworkConnection(nodeToBlockNumberMap); + + ByteBuf out = ctx.alloc().buffer(); + bcosMessage.writeHeader(out); + bcosMessage.writeExtra(out); + + seq2Callback.put(request.getMessageID(), callback); + + if (request.getTimeout() > 0) { + final BcosResponseCallback callbackInner = callback; + callback.setTimeout( + timeoutHandler.newTimeout( + new TimerTask() { + BcosResponseCallback _callback = callbackInner; + + @Override + public void run(Timeout timeout) throws Exception { + // handle timer + _callback.onTimeout(); + } + }, + request.getTimeout(), + TimeUnit.MILLISECONDS)); + } - callback.retrySendMessage(); - } catch (Exception e) { - logger.error("send message fail:", e); - - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(100); - response.setMessageID(request.getMessageID()); - response.setErrorMessage(e.getMessage()); - response.setContent(""); - - callback.onResponse(response); - return; - } - } catch (Exception e) { - logger.error("system error", e); - } - } - - public void sendResponseMessage( - ChannelResponse response, - ConnectionInfo info, - ChannelHandlerContext ctx, - String fromNode, - String toNode, - String seq) { - try { - ChannelMessage responseMessage = new ChannelMessage(); - - responseMessage.setData(response.getContent().getBytes()); - responseMessage.setResult(response.getErrorCode()); - responseMessage.setSeq(seq); - responseMessage.setType((short) 0x21); // 链上链下回包0x21 - responseMessage.setToNode(fromNode); - responseMessage.setFromNode(toNode); - - ByteBuf out = ctx.alloc().buffer(); - responseMessage.writeHeader(out); - responseMessage.writeExtra(out); - - ctx.writeAndFlush(out); - - logger.debug("response seq:{} length:{}", response.getMessageID(), out.readableBytes()); - } catch (Exception e) { - logger.error("system error", e); - } - } - - // 链上链下二期回包 - public void sendResponseMessage2( - ChannelResponse response, ChannelHandlerContext ctx, String seq, String topic) { - try { - ChannelMessage2 responseMessage = new ChannelMessage2(); - - responseMessage.setData(response.getContent().getBytes()); - responseMessage.setResult(response.getErrorCode()); - responseMessage.setSeq(seq); - responseMessage.setType((short) 0x31); // 链上链下二期回包0x31 - responseMessage.setTopic(topic); - - ByteBuf out = ctx.alloc().buffer(); - responseMessage.writeHeader(out); - responseMessage.writeExtra(out); - - ctx.writeAndFlush(out); - - logger.debug("response seq:{} length:{}", response.getMessageID(), out.readableBytes()); - } catch (Exception e) { - logger.error("system error:", e); - } - } - - public void onReceiveChannelMessage(ChannelHandlerContext ctx, ChannelMessage message) { - ChannelResponseCallback callback = (ChannelResponseCallback) seq2Callback.get(message.getSeq()); - logger.debug("onReceiveChannelMessage seq:{}", message.getSeq()); - - if (message.getType() == 0x20) { // 链上链下请求 - logger.debug("channel Message PUSH"); - if (callback != null) { - // 清空callback再处理 - logger.debug("seq already existed,clean:{}", message.getSeq()); - seq2Callback.remove(message.getSeq()); - } - - try { - ChannelPush push = new ChannelPush(); - - if (pushCallback != null) { - push.setService(this); - push.setCtx(ctx); - push.setMessageID(message.getSeq()); - push.setFromNode(message.getFromNode()); - push.setToNode(message.getToNode()); - push.setSeq(message.getSeq()); - push.setMessageID(message.getSeq()); - - push.setContent(new String(message.getData(), 0, message.getData().length)); - - pushCallback.onPush(push); - } else { - logger.error("can not push,unset push callback"); + ctx.writeAndFlush(out); + sended = true; + SocketChannel socketChannel = (SocketChannel) ctx.channel(); + InetSocketAddress socketAddress = socketChannel.remoteAddress(); + logger.debug( + "selected node {}:{} bcos request, seq:{}", + socketAddress.getAddress().getHostAddress(), + socketAddress.getPort(), + bcosMessage.getSeq()); + + } catch (Exception e) { + logger.error("system error: " + e); + + BcosResponse response = new BcosResponse(); + response.setErrorCode(-1); + response.setErrorMessage( + e.getMessage() + + " Requset send failed! Can not connect to nodes success, please checkout the node status and the sdk config!"); + response.setContent(""); + response.setMessageID(request.getMessageID()); + + if (callback.getTimeout() != null) { + callback.getTimeout().cancel(); + } + callback.onResponse(response); } - } catch (Exception e) { - logger.error("pushCallback error:", e); - } - } else if (message.getType() == 0x21) { // 链上链下回包 - logger.debug("channel response:{}", message.getSeq()); - if (callback != null) { - logger.debug("found callback response"); - - ChannelResponse response = new ChannelResponse(); - if (message.getResult() != 0) { - response.setErrorCode(message.getResult()); - response.setErrorMessage("response error"); + } + + public void asyncSendChannelMessage2( + ChannelRequest request, ChannelResponseCallback2 callback) { + try { + logger.debug("ChannelRequest: " + request.getMessageID()); + callback.setService(this); + + ChannelMessage2 channelMessage = new ChannelMessage2(); + + channelMessage.setSeq(request.getMessageID()); + channelMessage.setResult(0); + channelMessage.setType((short) 0x30); // 链上链下请求0x30 + channelMessage.setData(request.getContent().getBytes()); + channelMessage.setTopic(request.getToTopic()); + + try { + List fromConnectionInfos = new ArrayList(); + + // 设置发送节点 + ChannelConnections fromChannelConnections = + allChannelConnections + .getAllChannelConnections() + .stream() + .filter(x -> x.getGroupId() == groupId) + .findFirst() + .get(); + if (fromChannelConnections == null) { + // 没有找到对应的链 + // 返回错误 + if (orgID != null) { + logger.error("not found:{}", orgID); + throw new Exception("not found orgID"); + } else { + logger.error("not found:{}", agencyName); + throw new Exception("not found agencyName"); + } + } + fromConnectionInfos.addAll(fromChannelConnections.getConnections()); + logger.debug( + "FromOrg:{} nodes:{}", + request.getFromOrg(), + fromChannelConnections.getConnections().size()); + + callback.setFromChannelConnections(fromChannelConnections); + callback.setFromConnectionInfos(fromConnectionInfos); + + // 设置消息内容 + callback.setRequest(channelMessage); + + seq2Callback.put(request.getMessageID(), callback); + + if (request.getTimeout() > 0) { + final ChannelResponseCallback2 callbackInner = callback; + callback.setTimeout( + timeoutHandler.newTimeout( + new TimerTask() { + ChannelResponseCallback2 _callback = callbackInner; + + @Override + public void run(Timeout timeout) throws Exception { + // 处理超时逻辑 + _callback.onTimeout(); + } + }, + request.getTimeout(), + TimeUnit.MILLISECONDS)); + } + + callback.retrySendMessage(); + } catch (Exception e) { + logger.error("send message fail:", e); + + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(100); + response.setMessageID(request.getMessageID()); + response.setErrorMessage(e.getMessage()); + response.setContent(""); + + callback.onResponse(response); + return; + } + } catch (Exception e) { + logger.error("system error", e); } + } + + public void sendResponseMessage( + ChannelResponse response, + ConnectionInfo info, + ChannelHandlerContext ctx, + String fromNode, + String toNode, + String seq) { + try { + ChannelMessage responseMessage = new ChannelMessage(); + + responseMessage.setData(response.getContent().getBytes()); + responseMessage.setResult(response.getErrorCode()); + responseMessage.setSeq(seq); + responseMessage.setType((short) 0x21); // 链上链下回包0x21 + responseMessage.setToNode(fromNode); + responseMessage.setFromNode(toNode); + + ByteBuf out = ctx.alloc().buffer(); + responseMessage.writeHeader(out); + responseMessage.writeExtra(out); - response.setErrorCode(message.getResult()); - response.setMessageID(message.getSeq()); - if (message.getData() != null) { - response.setContent(new String(message.getData())); + ctx.writeAndFlush(out); + + logger.debug("response seq:{} length:{}", response.getMessageID(), out.readableBytes()); + } catch (Exception e) { + logger.error("system error", e); } + } + + // 链上链下二期回包 + public void sendResponseMessage2( + ChannelResponse response, ChannelHandlerContext ctx, String seq, String topic) { + try { + ChannelMessage2 responseMessage = new ChannelMessage2(); + + responseMessage.setData(response.getContent().getBytes()); + responseMessage.setResult(response.getErrorCode()); + responseMessage.setSeq(seq); + responseMessage.setType((short) 0x31); // 链上链下二期回包0x31 + responseMessage.setTopic(topic); + + ByteBuf out = ctx.alloc().buffer(); + responseMessage.writeHeader(out); + responseMessage.writeExtra(out); - callback.onResponse(response); - } else { - logger.error("can not found response callback,timeout:{}", message.getData()); - return; - } + ctx.writeAndFlush(out); + + logger.debug("response seq:{} length:{}", response.getMessageID(), out.readableBytes()); + } catch (Exception e) { + logger.error("system error:", e); + } } - } - public void onReceiveEthereumMessage(ChannelHandlerContext ctx, FiscoMessage message) { - FiscoResponseCallback callback = - (FiscoResponseCallback) seq2Callback.get(message.getSeq()); - logger.debug("FiscoResponse seq:{}", message.getSeq()); + public void onReceiveChannelMessage(ChannelHandlerContext ctx, ChannelMessage message) { + ChannelResponseCallback callback = + (ChannelResponseCallback) seq2Callback.get(message.getSeq()); + logger.debug("onReceiveChannelMessage seq:{}", message.getSeq()); + + if (message.getType() == 0x20) { // 链上链下请求 + logger.debug("channel Message PUSH"); + if (callback != null) { + // 清空callback再处理 + logger.debug("seq already existed,clean:{}", message.getSeq()); + seq2Callback.remove(message.getSeq()); + } - if (callback != null) { - logger.debug("found callback FiscoResponse"); + try { + ChannelPush push = new ChannelPush(); - if (callback.getTimeout() != null) { - callback.getTimeout().cancel(); - } + if (pushCallback != null) { + push.setService(this); + push.setCtx(ctx); + push.setMessageID(message.getSeq()); + push.setFromNode(message.getFromNode()); + push.setToNode(message.getToNode()); + push.setSeq(message.getSeq()); + push.setMessageID(message.getSeq()); - FiscoResponse response = new FiscoResponse(); - if (message.getResult() != 0) { - response.setErrorMessage("FiscoResponse error"); - } + push.setContent(new String(message.getData(), 0, message.getData().length)); - response.setErrorCode(message.getResult()); - response.setMessageID(message.getSeq()); - response.setContent(new String(message.getData())); + pushCallback.onPush(push); + } else { + logger.error("can not push,unset push callback"); + } + } catch (Exception e) { + logger.error("pushCallback error:", e); + } + } else if (message.getType() == 0x21) { // 链上链下回包 + logger.debug("channel response:{}", message.getSeq()); + if (callback != null) { + logger.debug("found callback response"); + + ChannelResponse response = new ChannelResponse(); + if (message.getResult() != 0) { + response.setErrorCode(message.getResult()); + response.setErrorMessage("response error"); + } - callback.onResponse(response); + response.setErrorCode(message.getResult()); + response.setMessageID(message.getSeq()); + if (message.getData() != null) { + response.setContent(new String(message.getData())); + } - seq2Callback.remove(message.getSeq()); - } else { - logger.debug("no callback push message"); + callback.onResponse(response); + } else { + logger.error("can not found response callback,timeout:{}", message.getData()); + return; + } + } } - } - public void onReceiveChannelMessage2(ChannelHandlerContext ctx, ChannelMessage2 message) { - ChannelResponseCallback2 callback = - (ChannelResponseCallback2) seq2Callback.get(message.getSeq()); - logger.debug("ChannelResponse seq:{}", message.getSeq()); + public void onReceiveEthereumMessage(ChannelHandlerContext ctx, BcosMessage message) { + BcosResponseCallback callback = (BcosResponseCallback) seq2Callback.get(message.getSeq()); - if (message.getType() == 0x30) { // 链上链下请求 - logger.debug("channel PUSH"); - if (callback != null) { - // 清空callback再处理 - logger.debug("seq already existed,clear:{}", message.getSeq()); - seq2Callback.remove(message.getSeq()); - } + if (callback != null) { - try { - ChannelPush2 push = new ChannelPush2(); + if (callback.getTimeout() != null) { + callback.getTimeout().cancel(); + } - if (pushCallback != null) { - // pushCallback.setInfo(info); - push.setSeq(message.getSeq()); - push.setService(this); - push.setCtx(ctx); - push.setTopic(message.getTopic()); + BcosResponse response = new BcosResponse(); + if (message.getResult() != 0) { + response.setErrorMessage("BcosResponse error"); + } - push.setSeq(message.getSeq()); - push.setMessageID(message.getSeq()); - push.setContent(new String(message.getData(), 0, message.getData().length)); + response.setErrorCode(message.getResult()); + response.setMessageID(message.getSeq()); + response.setContent(new String(message.getData())); - pushCallback.onPush(push); - } else { - logger.error("can not push,unset push callback"); - } - } catch (Exception e) { - logger.error("push error:", e); - } - } else if (message.getType() == 0x31) { // 链上链下回包 - logger.debug("channel message:{}", message.getSeq()); - if (callback != null) { - logger.debug("found callback response"); - - ChannelResponse response = new ChannelResponse(); - if (message.getResult() != 0) { - response.setErrorCode(message.getResult()); - response.setErrorMessage("response errors"); - } + callback.onResponse(response); - response.setErrorCode(message.getResult()); - response.setMessageID(message.getSeq()); - if (message.getData() != null) { - response.setContent(new String(message.getData())); + seq2Callback.remove(message.getSeq()); + } else { + logger.debug("no callback push message"); } - - callback.onResponse(response); - } else { - logger.error("can not found response callback,timeout:{}", message.getData()); - return; - } } - } - public void onReceiveBlockNotify(ChannelHandlerContext ctx, ChannelMessage2 message) { - try { - String data = new String(message.getData()); - logger.debug("Receive block notify: {}", data); - String[] split = data.split(","); - if (split.length != 2) { - logger.error("Block notify format error: {}", data); - return; - } + public void onReceiveChannelMessage2(ChannelHandlerContext ctx, ChannelMessage2 message) { + ChannelResponseCallback2 callback = + (ChannelResponseCallback2) seq2Callback.get(message.getSeq()); + logger.debug("ChannelResponse seq:{}", message.getSeq()); + + if (message.getType() == 0x30) { // 链上链下请求 + logger.debug("channel PUSH"); + if (callback != null) { + // 清空callback再处理 + logger.debug("seq already existed,clear:{}", message.getSeq()); + seq2Callback.remove(message.getSeq()); + } + + try { + ChannelPush2 push = new ChannelPush2(); - Integer groupID = Integer.parseInt(split[0]); + if (pushCallback != null) { + // pushCallback.setInfo(info); + push.setSeq(message.getSeq()); + push.setService(this); + push.setCtx(ctx); + push.setTopic(message.getTopic()); - if (!groupID.equals(getGroupId())) { - logger.error("Received groupID[{}] not match groupID[{}]", groupID, getGroupId()); + push.setSeq(message.getSeq()); + push.setMessageID(message.getSeq()); + push.setContent(new String(message.getData(), 0, message.getData().length)); - return; - } + pushCallback.onPush(push); + } else { + logger.error("can not push,unset push callback"); + } + } catch (Exception e) { + logger.error("push error:", e); + } + } else if (message.getType() == 0x31) { // 链上链下回包 + logger.debug("channel message:{}", message.getSeq()); + if (callback != null) { + logger.debug("found callback response"); + + ChannelResponse response = new ChannelResponse(); + if (message.getResult() != 0) { + response.setErrorCode(message.getResult()); + response.setErrorMessage("response errors"); + } - Integer number = Integer.parseInt(split[1]); + response.setErrorCode(message.getResult()); + response.setMessageID(message.getSeq()); + if (message.getData() != null) { + response.setContent(new String(message.getData())); + } - if (number.compareTo(getNumber().intValue()) > 0) { - setNumber(BigInteger.valueOf((long) number)); - } - } catch (Exception e) { - logger.error("Block notify error", e); + callback.onResponse(response); + } else { + logger.error("can not found response callback,timeout:{}", message.getData()); + return; + } + } } - } - public void onReceiveTransactionMessage(ChannelHandlerContext ctx, FiscoMessage message) { - TransactionSucCallback callback = - (TransactionSucCallback) seq2TransactionCallback.get(message.getSeq()); - logger.info("receive transaction success seq:{}", message.getSeq()); + public void onReceiveBlockNotify(ChannelHandlerContext ctx, ChannelMessage2 message) { + try { + String data = new String(message.getData()); + logger.info("Receive block notify: {}", data); + String[] split = data.split(","); + if (split.length != 2) { + logger.error("Block notify format error: {}", data); + return; + } + Integer groupID = Integer.parseInt(split[0]); + + if (!groupID.equals(getGroupId())) { + logger.error("Received groupID[{}] not match groupID[{}]", groupID, getGroupId()); - if (callback != null) { - logger.info("found callback transaction callback"); + return; + } + SocketChannel socketChannel = (SocketChannel) ctx.channel(); + String hostAddress = socketChannel.remoteAddress().getAddress().getHostAddress(); + int port = socketChannel.remoteAddress().getPort(); + Integer number = Integer.parseInt(split[1]); + + nodeToBlockNumberMap.put(hostAddress + port, number); + // get max blockNumber to set blocklimit + Integer maxBlockNumber = number; + for (String key : nodeToBlockNumberMap.keySet()) { + int blockNumber = nodeToBlockNumberMap.get(key); + if (blockNumber >= maxBlockNumber) { + maxBlockNumber = blockNumber; + } + } + if (maxBlockNumber > getNumber().intValue()) { + setNumber(BigInteger.valueOf((long) maxBlockNumber)); + } + } catch (Exception e) { + logger.error("Block notify error", e); + } + } - if (callback.getTimeout() != null) { - // 停止定时器,防止多响应一次 - callback.getTimeout().cancel(); - } + public void onReceiveTransactionMessage(ChannelHandlerContext ctx, BcosMessage message) { + TransactionSucCallback callback = + (TransactionSucCallback) seq2TransactionCallback.get(message.getSeq()); - try { - TransactionReceipt receipt = - objectMapper.readValue(message.getData(), TransactionReceipt.class); + if (callback != null) { + if (callback.getTimeout() != null) { + // stop timer,avoid response more once + callback.getTimeout().cancel(); + } - callback.onResponse(receipt); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("Decode receipt error: " + e.getLocalizedMessage()); + try { + TransactionReceipt receipt = + objectMapper.readValue(message.getData(), TransactionReceipt.class); - callback.onResponse(receipt); - } + callback.onResponse(receipt); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("Decode receipt error: " + e.getLocalizedMessage()); + + callback.onResponse(receipt); + } - seq2TransactionCallback.remove(message.getSeq()); - } else { - logger.info("callback is null"); + seq2TransactionCallback.remove(message.getSeq()); + } } - } - public String newSeq() { - return UUID.randomUUID().toString().replaceAll("-", ""); - } + public String newSeq() { + String seq = UUID.randomUUID().toString().replaceAll("-", ""); + logger.info("New Seq" + seq); + return seq; + } - public Map getSeq2Callback() { - return seq2Callback; - } + public Map getSeq2Callback() { + return seq2Callback; + } - public void setSeq2Callback(Map seq2Callback) { - this.seq2Callback = seq2Callback; - } + public void setSeq2Callback(Map seq2Callback) { + this.seq2Callback = seq2Callback; + } - public ThreadPoolTaskExecutor getThreadPool() { - return threadPool; - } + public ThreadPoolTaskExecutor getThreadPool() { + return threadPool; + } - public void setThreadPool(ThreadPoolTaskExecutor threadPool) { - this.threadPool = threadPool; - } + public void setThreadPool(ThreadPoolTaskExecutor threadPool) { + this.threadPool = threadPool; + } - public int getGroupId() { - return groupId; - } + public int getGroupId() { + return groupId; + } - public void setGroupId(int groupId) { - this.groupId = groupId; - } + public void setGroupId(int groupId) { + this.groupId = groupId; + } - public BigInteger getNumber() { - return number; - } + public BigInteger getNumber() { + return number; + } - public void setNumber(BigInteger number) { - this.number = number; - } + public void setNumber(BigInteger number) { + this.number = number; + } } diff --git a/src/main/java/org/fisco/bcos/channel/client/TransactionSucCallback.java b/src/main/java/org/fisco/bcos/channel/client/TransactionSucCallback.java index 3ddc55277..2734c783f 100644 --- a/src/main/java/org/fisco/bcos/channel/client/TransactionSucCallback.java +++ b/src/main/java/org/fisco/bcos/channel/client/TransactionSucCallback.java @@ -7,25 +7,25 @@ /** Created by suyuhui on 17/8/17. */ public abstract class TransactionSucCallback { - private static Logger logger = LoggerFactory.getLogger(TransactionSucCallback.class); + private static Logger logger = LoggerFactory.getLogger(TransactionSucCallback.class); - public abstract void onResponse(TransactionReceipt response); + public abstract void onResponse(TransactionReceipt response); - public void onTimeout() { - logger.error("transactionSuc timeout"); + public void onTimeout() { + logger.error("transactionSuc timeout"); - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("Receipt timeout"); - onResponse(receipt); - } + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("Transaction receipt timeout."); + onResponse(receipt); + } - public Timeout getTimeout() { - return timeout; - } + public Timeout getTimeout() { + return timeout; + } - public void setTimeout(Timeout timeout) { - this.timeout = timeout; - } + public void setTimeout(Timeout timeout) { + this.timeout = timeout; + } - private Timeout timeout; + private Timeout timeout; } diff --git a/src/main/java/org/fisco/bcos/channel/dto/BcosMessage.java b/src/main/java/org/fisco/bcos/channel/dto/BcosMessage.java new file mode 100644 index 000000000..d9f1d58fa --- /dev/null +++ b/src/main/java/org/fisco/bcos/channel/dto/BcosMessage.java @@ -0,0 +1,28 @@ +package org.fisco.bcos.channel.dto; + +import io.netty.buffer.ByteBuf; +import org.fisco.bcos.channel.handler.Message; + +public class BcosMessage extends Message { + private static final long serialVersionUID = 3763237749437810546L; + + public BcosMessage() {} + + public BcosMessage(Message msg) { + length = msg.getLength(); + type = msg.getType(); + seq = msg.getSeq(); + result = msg.getResult(); + } + + @Override + public void readExtra(ByteBuf in) { + data = new byte[length - Message.HEADER_LENGTH]; + in.readBytes(data, 0, length - Message.HEADER_LENGTH); + } + + @Override + public void writeExtra(ByteBuf out) { + out.writeBytes(data); + } +} diff --git a/src/main/java/org/fisco/bcos/channel/dto/BcosRequest.java b/src/main/java/org/fisco/bcos/channel/dto/BcosRequest.java new file mode 100644 index 000000000..062ceefe0 --- /dev/null +++ b/src/main/java/org/fisco/bcos/channel/dto/BcosRequest.java @@ -0,0 +1,78 @@ +package org.fisco.bcos.channel.dto; + +public class BcosRequest { + private String keyID; // chain ID + private String orgApp; // org identification + private String version; + private String bankNO; // institution identification + private String appName; // application kinds + + private String messageID; + private Integer timeout = 0; // ms + + private String content; + + public String getKeyID() { + return keyID; + } + + public void setKeyID(String keyID) { + this.keyID = keyID; + } + + public String getOrgApp() { + return orgApp; + } + + public void setOrgApp(String orgApp) { + this.orgApp = orgApp; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getBankNO() { + return bankNO; + } + + public void setBankNO(String bankNO) { + this.bankNO = bankNO; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getMessageID() { + return messageID; + } + + public void setMessageID(String messageID) { + this.messageID = messageID; + } + + public Integer getTimeout() { + return timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/src/main/java/org/fisco/bcos/channel/dto/FiscoResponse.java b/src/main/java/org/fisco/bcos/channel/dto/BcosResponse.java similarity index 96% rename from src/main/java/org/fisco/bcos/channel/dto/FiscoResponse.java rename to src/main/java/org/fisco/bcos/channel/dto/BcosResponse.java index 9e3a7896a..d0029a672 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/FiscoResponse.java +++ b/src/main/java/org/fisco/bcos/channel/dto/BcosResponse.java @@ -1,6 +1,6 @@ package org.fisco.bcos.channel.dto; -public class FiscoResponse { +public class BcosResponse { private Integer errorCode; private String errorMessage; @@ -38,5 +38,4 @@ public String getContent() { public void setContent(String content) { this.content = content; } - } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage.java index 1bb0642be..065f31a56 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage.java @@ -6,71 +6,71 @@ import org.slf4j.LoggerFactory; public class ChannelMessage extends Message { - private static Logger logger = LoggerFactory.getLogger(ChannelMessage.class); - - private static final long serialVersionUID = -7276897518418560354L; - - public ChannelMessage() {} - - public ChannelMessage(Message msg) { - length = msg.getLength(); - type = msg.getType(); - seq = msg.getSeq(); - result = msg.getResult(); - } - - @Override - public void readExtra(ByteBuf in) { - logger.debug("readExtra channel package: {}", result); - if (result == 0) { - byte[] toNodeBytes = new byte[128]; - in.readBytes(toNodeBytes, 0, 128); - toNode = new String(toNodeBytes); - logger.debug("toNode: {}", toNode); - - byte[] fromNodeBytes = new byte[128]; - in.readBytes(fromNodeBytes, 0, 128); - fromNode = new String(fromNodeBytes); - logger.debug("fromNode: {}", fromNode); - - data = new byte[length - Message.HEADER_LENGTH - 128 - 128]; - in.readBytes(data, 0, length - Message.HEADER_LENGTH - 128 - 128); - logger.debug("data: {} {}", data.length, data); + private static Logger logger = LoggerFactory.getLogger(ChannelMessage.class); + + private static final long serialVersionUID = -7276897518418560354L; + + public ChannelMessage() {} + + public ChannelMessage(Message msg) { + length = msg.getLength(); + type = msg.getType(); + seq = msg.getSeq(); + result = msg.getResult(); } - } - @Override - public void writeHeader(ByteBuf out) { - // 先计算总长度 - length = Message.HEADER_LENGTH + toNode.length() + fromNode.length() + data.length; + @Override + public void readExtra(ByteBuf in) { + logger.debug("readExtra channel package: {}", result); + if (result == 0) { + byte[] toNodeBytes = new byte[128]; + in.readBytes(toNodeBytes, 0, 128); + toNode = new String(toNodeBytes); + logger.debug("toNode: {}", toNode); + + byte[] fromNodeBytes = new byte[128]; + in.readBytes(fromNodeBytes, 0, 128); + fromNode = new String(fromNodeBytes); + logger.debug("fromNode: {}", fromNode); + + data = new byte[length - Message.HEADER_LENGTH - 128 - 128]; + in.readBytes(data, 0, length - Message.HEADER_LENGTH - 128 - 128); + logger.debug("data: {} {}", data.length, data); + } + } - super.writeHeader(out); - } + @Override + public void writeHeader(ByteBuf out) { + // 先计算总长度 + length = Message.HEADER_LENGTH + toNode.length() + fromNode.length() + data.length; - @Override - public void writeExtra(ByteBuf out) { - out.writeBytes(toNode.getBytes()); - out.writeBytes(fromNode.getBytes()); + super.writeHeader(out); + } - out.writeBytes(data); - } + @Override + public void writeExtra(ByteBuf out) { + out.writeBytes(toNode.getBytes()); + out.writeBytes(fromNode.getBytes()); - public String getToNode() { - return toNode; - } + out.writeBytes(data); + } - public void setToNode(String toNode) { - this.toNode = toNode; - } + public String getToNode() { + return toNode; + } - public String getFromNode() { - return fromNode; - } + public void setToNode(String toNode) { + this.toNode = toNode; + } - public void setFromNode(String fromNode) { - this.fromNode = fromNode; - } + public String getFromNode() { + return fromNode; + } + + public void setFromNode(String fromNode) { + this.fromNode = fromNode; + } - private String toNode; - private String fromNode; + private String toNode; + private String fromNode; } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage2.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage2.java index b69362915..de9a8f4e5 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage2.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelMessage2.java @@ -6,58 +6,56 @@ import org.slf4j.LoggerFactory; public class ChannelMessage2 extends Message { - private static Logger logger = LoggerFactory.getLogger(ChannelMessage2.class); + private static Logger logger = LoggerFactory.getLogger(ChannelMessage2.class); - private static final long serialVersionUID = -7276897518418560354L; + private static final long serialVersionUID = -7276897518418560354L; - public ChannelMessage2() {} + public ChannelMessage2() {} - public ChannelMessage2(Message msg) { - length = msg.getLength(); - type = msg.getType(); - seq = msg.getSeq(); - result = msg.getResult(); - } + public ChannelMessage2(Message msg) { + length = msg.getLength(); + type = msg.getType(); + seq = msg.getSeq(); + result = msg.getResult(); + } - @Override - public void readExtra(ByteBuf in) { - logger.debug("readExtra channel2 package: {}", result); - if (result == 0) { - Short topicLength = in.readUnsignedByte(); + @Override + public void readExtra(ByteBuf in) { + if (result == 0) { + Short topicLength = in.readUnsignedByte(); - byte[] topicBytes = new byte[topicLength - 1]; - in.readBytes(topicBytes, 0, topicLength - 1); - topic = new String(topicBytes); + byte[] topicBytes = new byte[topicLength - 1]; + in.readBytes(topicBytes, 0, topicLength - 1); + topic = new String(topicBytes); - data = new byte[length - Message.HEADER_LENGTH - topicLength]; - in.readBytes(data, 0, length - Message.HEADER_LENGTH - topicLength); - logger.debug("data: {} {}", data.length, data); + data = new byte[length - Message.HEADER_LENGTH - topicLength]; + in.readBytes(data, 0, length - Message.HEADER_LENGTH - topicLength); + } } - } - @Override - public void writeHeader(ByteBuf out) { - // 先计算总长度 - length = Message.HEADER_LENGTH + 1 + topic.length() + data.length; + @Override + public void writeHeader(ByteBuf out) { + // total length + length = Message.HEADER_LENGTH + 1 + topic.length() + data.length; - super.writeHeader(out); - } + super.writeHeader(out); + } - @Override - public void writeExtra(ByteBuf out) { - out.writeByte(1 + topic.length()); - out.writeBytes(topic.getBytes()); + @Override + public void writeExtra(ByteBuf out) { + out.writeByte(1 + topic.length()); + out.writeBytes(topic.getBytes()); - out.writeBytes(data); - } + out.writeBytes(data); + } - public String getTopic() { - return topic; - } + public String getTopic() { + return topic; + } - public void setTopic(String toTopic) { - this.topic = toTopic; - } + public void setTopic(String toTopic) { + this.topic = toTopic; + } - private String topic; + private String topic; } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelPush.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelPush.java index f6edfa816..f56749784 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelPush.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelPush.java @@ -7,164 +7,164 @@ import org.slf4j.LoggerFactory; public class ChannelPush { - static Logger logger = LoggerFactory.getLogger(ChannelPush.class); + static Logger logger = LoggerFactory.getLogger(ChannelPush.class); - public String getKeyID() { - return keyID; - } + public String getKeyID() { + return keyID; + } - public void setKeyID(String keyID) { - this.keyID = keyID; - } + public void setKeyID(String keyID) { + this.keyID = keyID; + } - public String getOrgApp() { - return orgApp; - } + public String getOrgApp() { + return orgApp; + } - public void setOrgApp(String orgApp) { - this.orgApp = orgApp; - } + public void setOrgApp(String orgApp) { + this.orgApp = orgApp; + } - public String getVersion() { - return version; - } + public String getVersion() { + return version; + } - public void setVersion(String version) { - this.version = version; - } + public void setVersion(String version) { + this.version = version; + } - public String getBankNO() { - return bankNO; - } + public String getBankNO() { + return bankNO; + } - public void setBankNO(String bankNO) { - this.bankNO = bankNO; - } + public void setBankNO(String bankNO) { + this.bankNO = bankNO; + } - public String getAppName() { - return appName; - } + public String getAppName() { + return appName; + } - public void setAppName(String appName) { - this.appName = appName; - } + public void setAppName(String appName) { + this.appName = appName; + } - public String getMessageID() { - return messageID; - } + public String getMessageID() { + return messageID; + } - public void setMessageID(String messageID) { - this.messageID = messageID; - } + public void setMessageID(String messageID) { + this.messageID = messageID; + } - public String getToOrg() { - return toOrg; - } + public String getToOrg() { + return toOrg; + } - public void setToOrg(String toOrg) { - this.toOrg = toOrg; - } + public void setToOrg(String toOrg) { + this.toOrg = toOrg; + } - public Integer getTimeout() { - return timeout; - } + public Integer getTimeout() { + return timeout; + } - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } - public Integer getTtl() { - return ttl; - } + public Integer getTtl() { + return ttl; + } - public void setTtl(Integer ttl) { - this.ttl = ttl; - } + public void setTtl(Integer ttl) { + this.ttl = ttl; + } - public String getContent() { - return content; - } + public String getContent() { + return content; + } - public void setContent(String content) { - this.content = content; - } + public void setContent(String content) { + this.content = content; + } - public void sendResponse(ChannelResponse response) { - logger.debug("send ChannelResponse seq:{}", response.getMessageID()); + public void sendResponse(ChannelResponse response) { + logger.debug("send ChannelResponse seq:{}", response.getMessageID()); - response.setMessageID(seq); + response.setMessageID(seq); - service.sendResponseMessage(response, info, ctx, fromNode, toNode, seq); - } + service.sendResponseMessage(response, info, ctx, fromNode, toNode, seq); + } - private String keyID; // 链ID - private String orgApp; // 来源标识 - private String version; // 版本 - private String bankNO; // 机构标识 - private String appName; // 应用类型 + private String keyID; // 链ID + private String orgApp; // 来源标识 + private String version; // 版本 + private String bankNO; // 机构标识 + private String appName; // 应用类型 - private String messageID; // 消息的唯一标识id - private String toOrg; // 目标机构标识 + private String messageID; // 消息的唯一标识id + private String toOrg; // 目标机构标识 - private Integer timeout; // 超时时间(毫秒) - private Integer ttl; // TTL + private Integer timeout; // 超时时间(毫秒) + private Integer ttl; // TTL - private String content; // 请求包体 + private String content; // 请求包体 - // 回包用字段 + // 回包用字段 - public Service getService() { - return service; - } + public Service getService() { + return service; + } - public void setService(Service service) { - this.service = service; - } + public void setService(Service service) { + this.service = service; + } - public ConnectionInfo getInfo() { - return info; - } + public ConnectionInfo getInfo() { + return info; + } - public void setInfo(ConnectionInfo info) { - this.info = info; - } + public void setInfo(ConnectionInfo info) { + this.info = info; + } - public ChannelHandlerContext getCtx() { - return ctx; - } + public ChannelHandlerContext getCtx() { + return ctx; + } - public void setCtx(ChannelHandlerContext ctx) { - this.ctx = ctx; - } + public void setCtx(ChannelHandlerContext ctx) { + this.ctx = ctx; + } - public String getFromNode() { - return fromNode; - } + public String getFromNode() { + return fromNode; + } - public void setFromNode(String fromNode) { - this.fromNode = fromNode; - } + public void setFromNode(String fromNode) { + this.fromNode = fromNode; + } - public String getToNode() { - return toNode; - } + public String getToNode() { + return toNode; + } - public void setToNode(String toNode) { - this.toNode = toNode; - } + public void setToNode(String toNode) { + this.toNode = toNode; + } - public String getSeq() { - return seq; - } + public String getSeq() { + return seq; + } - public void setSeq(String seq) { - this.seq = seq; - } + public void setSeq(String seq) { + this.seq = seq; + } - private Service service; - private ConnectionInfo info; - private ChannelHandlerContext ctx; - private String fromNode; - private String toNode; - private String seq; + private Service service; + private ConnectionInfo info; + private ChannelHandlerContext ctx; + private String fromNode; + private String toNode; + private String seq; } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelPush2.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelPush2.java index cacfa43ad..82f5eac66 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelPush2.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelPush2.java @@ -6,62 +6,62 @@ import org.slf4j.LoggerFactory; public class ChannelPush2 extends ChannelPush { - static Logger logger = LoggerFactory.getLogger(ChannelPush2.class); + static Logger logger = LoggerFactory.getLogger(ChannelPush2.class); - public String getContent() { - return content; - } + public String getContent() { + return content; + } - public void setContent(String content) { - this.content = content; - } + public void setContent(String content) { + this.content = content; + } - public String getTopic() { - return topic; - } + public String getTopic() { + return topic; + } - public void setTopic(String topic) { - this.topic = topic; - } + public void setTopic(String topic) { + this.topic = topic; + } - public void sendResponse(ChannelResponse response) { - logger.debug("send ChannelResponse seq:{}", response.getMessageID()); + public void sendResponse(ChannelResponse response) { + logger.debug("send ChannelResponse seq:{}", response.getMessageID()); - response.setMessageID(seq); + response.setMessageID(seq); - service.sendResponseMessage2(response, ctx, seq, topic); - } + service.sendResponseMessage2(response, ctx, seq, topic); + } - private String content; // 请求包体 - private String topic; + private String content; // 请求包体 + private String topic; - // 回包用字段 + // 回包用字段 - public Service getService() { - return service; - } + public Service getService() { + return service; + } - public void setService(Service service) { - this.service = service; - } + public void setService(Service service) { + this.service = service; + } - public ChannelHandlerContext getCtx() { - return ctx; - } + public ChannelHandlerContext getCtx() { + return ctx; + } - public void setCtx(ChannelHandlerContext ctx) { - this.ctx = ctx; - } + public void setCtx(ChannelHandlerContext ctx) { + this.ctx = ctx; + } - public String getSeq() { - return seq; - } + public String getSeq() { + return seq; + } - public void setSeq(String seq) { - this.seq = seq; - } + public void setSeq(String seq) { + this.seq = seq; + } - private Service service; - private ChannelHandlerContext ctx; - private String seq; + private Service service; + private ChannelHandlerContext ctx; + private String seq; } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelRequest.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelRequest.java index a7e997846..168fd767f 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelRequest.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelRequest.java @@ -2,106 +2,106 @@ public class ChannelRequest { - public String getFromOrg() { - return fromOrg; - } + public String getFromOrg() { + return fromOrg; + } - public void setFromOrg(String keyID) { - this.fromOrg = keyID; - } + public void setFromOrg(String keyID) { + this.fromOrg = keyID; + } - public String getOrgApp() { - return orgApp; - } + public String getOrgApp() { + return orgApp; + } - public void setOrgApp(String orgApp) { - this.orgApp = orgApp; - } + public void setOrgApp(String orgApp) { + this.orgApp = orgApp; + } - public String getVersion() { - return version; - } + public String getVersion() { + return version; + } - public void setVersion(String version) { - this.version = version; - } + public void setVersion(String version) { + this.version = version; + } - public String getBankNO() { - return bankNO; - } + public String getBankNO() { + return bankNO; + } - public void setBankNO(String bankNO) { - this.bankNO = bankNO; - } + public void setBankNO(String bankNO) { + this.bankNO = bankNO; + } - public String getAppName() { - return appName; - } + public String getAppName() { + return appName; + } - public void setAppName(String appName) { - this.appName = appName; - } + public void setAppName(String appName) { + this.appName = appName; + } - public String getMessageID() { - return messageID; - } + public String getMessageID() { + return messageID; + } - public void setMessageID(String messageID) { - this.messageID = messageID; - } + public void setMessageID(String messageID) { + this.messageID = messageID; + } - public String getToOrg() { - return toOrg; - } + public String getToOrg() { + return toOrg; + } - public void setToOrg(String toOrg) { - this.toOrg = toOrg; - } + public void setToOrg(String toOrg) { + this.toOrg = toOrg; + } - public String getToTopic() { - return toTopic; - } + public String getToTopic() { + return toTopic; + } - public void setToTopic(String toTopic) { - this.toTopic = toTopic; - } + public void setToTopic(String toTopic) { + this.toTopic = toTopic; + } - public Integer getTimeout() { - return timeout; - } + public Integer getTimeout() { + return timeout; + } - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } - public Integer getTtl() { - return ttl; - } + public Integer getTtl() { + return ttl; + } - public void setTtl(Integer ttl) { - this.ttl = ttl; - } + public void setTtl(Integer ttl) { + this.ttl = ttl; + } - public String getContent() { - return content; - } + public String getContent() { + return content; + } - public void setContent(String content) { - this.content = content; - } + public void setContent(String content) { + this.content = content; + } - private String fromOrg; // 链ID - private String orgApp; // 来源标识 - private String version; // 版本 - private String bankNO; // 机构标识 - private String appName; // 应用类型 + private String fromOrg; // 链ID + private String orgApp; // 来源标识 + private String version; // 版本 + private String bankNO; // 机构标识 + private String appName; // 应用类型 - private String messageID; // 消息的唯一标识id - private String toOrg; // 目标机构标识 - private String toTopic; // 目标topic + private String messageID; // 消息的唯一标识id + private String toOrg; // 目标机构标识 + private String toTopic; // 目标topic - private Integer timeout = 0; // 超时时间(毫秒) - private Integer ttl; // TTL 限制重试的次数 + private Integer timeout = 0; // 超时时间(毫秒) + private Integer ttl; // TTL 限制重试的次数 - private String content; // 请求包体 + private String content; // 请求包体 } diff --git a/src/main/java/org/fisco/bcos/channel/dto/ChannelResponse.java b/src/main/java/org/fisco/bcos/channel/dto/ChannelResponse.java index d16b024a7..8af065342 100644 --- a/src/main/java/org/fisco/bcos/channel/dto/ChannelResponse.java +++ b/src/main/java/org/fisco/bcos/channel/dto/ChannelResponse.java @@ -1,42 +1,42 @@ package org.fisco.bcos.channel.dto; public class ChannelResponse { - public Integer getErrorCode() { - return errorCode; - } + public Integer getErrorCode() { + return errorCode; + } - public void setErrorCode(Integer errorCode) { - this.errorCode = errorCode; - } + public void setErrorCode(Integer errorCode) { + this.errorCode = errorCode; + } - public String getErrorMessage() { - return errorMessage; - } + public String getErrorMessage() { + return errorMessage; + } - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } - public String getMessageID() { - return messageID; - } + public String getMessageID() { + return messageID; + } - public void setMessageID(String messageID) { - this.messageID = messageID; - } + public void setMessageID(String messageID) { + this.messageID = messageID; + } - public String getContent() { - return content; - } + public String getContent() { + return content; + } - public void setContent(String content) { - this.content = content; - } + public void setContent(String content) { + this.content = content; + } - private Integer errorCode; // 错误码 - private String errorMessage; // 错误信息 + private Integer errorCode; // 错误码 + private String errorMessage; // 错误信息 - private String messageID; // 消息唯一ID + private String messageID; // 消息唯一ID - private String content; // 响应包体 + private String content; // 响应包体 } diff --git a/src/main/java/org/fisco/bcos/channel/dto/FiscoMessage.java b/src/main/java/org/fisco/bcos/channel/dto/FiscoMessage.java deleted file mode 100644 index 9c6ee0dbb..000000000 --- a/src/main/java/org/fisco/bcos/channel/dto/FiscoMessage.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.fisco.bcos.channel.dto; - -import io.netty.buffer.ByteBuf; -import org.fisco.bcos.channel.handler.Message; - -public class FiscoMessage extends Message { - private static final long serialVersionUID = 3763237749437810546L; - - public FiscoMessage() {} - - public FiscoMessage(Message msg) { - length = msg.getLength(); - type = msg.getType(); - seq = msg.getSeq(); - result = msg.getResult(); - } - - @Override - public void readExtra(ByteBuf in) { - data = new byte[length - Message.HEADER_LENGTH]; - in.readBytes(data, 0, length - Message.HEADER_LENGTH); - } - - @Override - public void writeExtra(ByteBuf out) { - out.writeBytes(data); - } -} diff --git a/src/main/java/org/fisco/bcos/channel/dto/FiscoRequest.java b/src/main/java/org/fisco/bcos/channel/dto/FiscoRequest.java deleted file mode 100644 index 93c38ddea..000000000 --- a/src/main/java/org/fisco/bcos/channel/dto/FiscoRequest.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.fisco.bcos.channel.dto; - -public class FiscoRequest { - private String keyID; // chain ID - private String orgApp; // org identification - private String version; - private String bankNO; // institution identification - private String appName; // application kinds - - private String messageID; - private Integer timeout = 0; // ms - - private String content; - - public String getKeyID() { - return keyID; - } - - public void setKeyID(String keyID) { - this.keyID = keyID; - } - - public String getOrgApp() { - return orgApp; - } - - public void setOrgApp(String orgApp) { - this.orgApp = orgApp; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getBankNO() { - return bankNO; - } - - public void setBankNO(String bankNO) { - this.bankNO = bankNO; - } - - public String getAppName() { - return appName; - } - - public void setAppName(String appName) { - this.appName = appName; - } - - public String getMessageID() { - return messageID; - } - - public void setMessageID(String messageID) { - this.messageID = messageID; - } - - public Integer getTimeout() { - return timeout; - } - - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - -} diff --git a/src/main/java/org/fisco/bcos/channel/handler/ChannelConnections.java b/src/main/java/org/fisco/bcos/channel/handler/ChannelConnections.java index 32aad6898..bcc204ef9 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/ChannelConnections.java +++ b/src/main/java/org/fisco/bcos/channel/handler/ChannelConnections.java @@ -3,7 +3,11 @@ import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; -import io.netty.channel.*; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -17,11 +21,18 @@ import io.netty.handler.timeout.IdleStateHandler; import java.io.InputStream; import java.security.SecureRandom; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; -import org.fisco.bcos.channel.dto.FiscoMessage; +import org.fisco.bcos.channel.dto.BcosMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; @@ -30,380 +41,435 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class ChannelConnections { - private static Logger logger = LoggerFactory.getLogger(ChannelConnections.class); - - private Callback callback; - private List connectionsStr; - private String caCertPath = "classpath:ca.crt"; - private String nodeCaPath = "classpath:node.crt"; - private String nodeKeyPath = "classpath:node.key"; - private List connections = new ArrayList(); - private Boolean running = false; - private ThreadPoolTaskExecutor threadPool; - private long idleTimeout = (long) 10000; - private long heartBeatDelay = (long) 2000; - public Map networkConnections = new HashMap(); - private int groupId; - private Bootstrap bootstrap = new Bootstrap(); - ServerBootstrap serverBootstrap = new ServerBootstrap(); - - public int getGroupId() { - return groupId; - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - public String getNodeCaPath() { - return nodeCaPath; - } - - public void setNodeCaPath(String nodeCaPath) { - this.nodeCaPath = nodeCaPath; - } - - public String getNodeKeyPath() { - return nodeKeyPath; - } - - public void setNodeKeyPath(String nodeKeyPath) { - this.nodeKeyPath = nodeKeyPath; - } - - public interface Callback { - void onConnect(ChannelHandlerContext ctx); - - void onDisconnect(ChannelHandlerContext ctx); - - void onMessage(ChannelHandlerContext ctx, ByteBuf message); - } - - public Callback getCallback() { - return callback; - } + private static Logger logger = LoggerFactory.getLogger(ChannelConnections.class); + + private Callback callback; + private List connectionsStr; + private String caCertPath = "classpath:ca.crt"; + private String nodeCaPath = "classpath:node.crt"; + private String nodeKeyPath = "classpath:node.key"; + private List connections = new ArrayList(); + private Boolean running = false; + private ThreadPoolTaskExecutor threadPool; + private long idleTimeout = (long) 10000; + private long heartBeatDelay = (long) 2000; + public Map networkConnections = + new HashMap(); + private int groupId; + private Bootstrap bootstrap = new Bootstrap(); + ServerBootstrap serverBootstrap = new ServerBootstrap(); + + public int getGroupId() { + return groupId; + } - public void setCallback(Callback callback) { - this.callback = callback; - } + public void setGroupId(int groupId) { + this.groupId = groupId; + } - public List getConnectionsStr() { - return connectionsStr; - } + public String getNodeCaPath() { + return nodeCaPath; + } - public void setConnectionsStr(List connectionsStr) { - this.connectionsStr = connectionsStr; - } + public void setNodeCaPath(String nodeCaPath) { + this.nodeCaPath = nodeCaPath; + } - public List getConnections() { - return connections; - } + public String getNodeKeyPath() { + return nodeKeyPath; + } - public void setConnections(List connections) { - this.connections = connections; - } + public void setNodeKeyPath(String nodeKeyPath) { + this.nodeKeyPath = nodeKeyPath; + } - public ThreadPoolTaskExecutor getThreadPool() { - return threadPool; - } + public interface Callback { + void onConnect(ChannelHandlerContext ctx); - public void setThreadPool(ThreadPoolTaskExecutor threadPool) { - this.threadPool = threadPool; - } + void onDisconnect(ChannelHandlerContext ctx); - public long getIdleTimeout() { - return idleTimeout; - } + void onMessage(ChannelHandlerContext ctx, ByteBuf message); + } - public void setIdleTimeout(long idleTimeout) { - this.idleTimeout = idleTimeout; - } + public Callback getCallback() { + return callback; + } - public long getHeartBeatDelay() { - return heartBeatDelay; - } + public void setCallback(Callback callback) { + this.callback = callback; + } - public void setHeartBeatDelay(long heartBeatDelay) { - this.heartBeatDelay = heartBeatDelay; - } + public List getConnectionsStr() { + return connectionsStr; + } - public String getCaCertPath() { - return caCertPath; - } - - public void setCaCertPath(String caCertPath) { - this.caCertPath = caCertPath; - } - - public ChannelHandlerContext randomNetworkConnection() throws Exception { - List activeConnections = new ArrayList(); + public void setConnectionsStr(List connectionsStr) { + this.connectionsStr = connectionsStr; + } - for (String key : networkConnections.keySet()) { - if (networkConnections.get(key) != null && networkConnections.get(key).channel().isActive()) { - activeConnections.add(networkConnections.get(key)); - } + public List getConnections() { + return connections; } - if (activeConnections.isEmpty()) { - logger.error("activeConnections isEmpty"); - throw new Exception("activeConnections isEmpty"); + public void setConnections(List connections) { + this.connections = connections; } - Random random = new SecureRandom(); - Integer index = random.nextInt(activeConnections.size()); + public ThreadPoolTaskExecutor getThreadPool() { + return threadPool; + } - logger.debug("selected:{}", index); + public void setThreadPool(ThreadPoolTaskExecutor threadPool) { + this.threadPool = threadPool; + } - return activeConnections.get(index); - } + public long getIdleTimeout() { + return idleTimeout; + } - public ConnectionInfo getConnectionInfo(String host, Integer port) { - for (ConnectionInfo info : connections) { - if (info.getHost().equals(host) && info.getPort().equals(port)) { - return info; - } + public void setIdleTimeout(long idleTimeout) { + this.idleTimeout = idleTimeout; } - return null; - } + public long getHeartBeatDelay() { + return heartBeatDelay; + } - public Map getNetworkConnections() { - return networkConnections; - } + public void setHeartBeatDelay(long heartBeatDelay) { + this.heartBeatDelay = heartBeatDelay; + } - public ChannelHandlerContext getNetworkConnectionByHost(String host, Integer port) { - String endpoint = host + ":" + port; + public String getCaCertPath() { + return caCertPath; + } - return networkConnections.get(endpoint); - } + public void setCaCertPath(String caCertPath) { + this.caCertPath = caCertPath; + } - public void setNetworkConnectionByHost(String host, Integer port, ChannelHandlerContext ctx) { - String endpoint = host + ":" + port; + public ChannelHandlerContext randomNetworkConnection( + ConcurrentHashMap nodeToBlockNumberMap) throws Exception { + List activeConnections = new ArrayList(); - networkConnections.put(endpoint, ctx); - } + for (String key : networkConnections.keySet()) { + if (networkConnections.get(key) != null + && networkConnections.get(key).channel().isActive()) { + activeConnections.add(networkConnections.get(key)); + } + } + + if (activeConnections.isEmpty()) { + logger.error("activeConnections isEmpty"); + throw new Exception("activeConnections isEmpty"); + } + // select maxBlockNumber node + List maxBlockNumberConnections = + new ArrayList(); + long maxBlockNumber = 0; + if (nodeToBlockNumberMap != null) { + for (String key : nodeToBlockNumberMap.keySet()) { + int blockNumber = nodeToBlockNumberMap.get(key); + if (blockNumber >= maxBlockNumber) { + if (blockNumber > maxBlockNumber) { + maxBlockNumberConnections.clear(); + } + + Optional optionalCtx = + activeConnections + .stream() + .filter( + x -> + key.equals( + ((SocketChannel) x.channel()) + .remoteAddress() + .getAddress() + .getHostAddress() + + ((SocketChannel) x.channel()) + .remoteAddress() + .getPort())) + .findFirst(); + if (optionalCtx.isPresent()) { + ChannelHandlerContext channelHandlerContext = optionalCtx.get(); + maxBlockNumberConnections.add(channelHandlerContext); + maxBlockNumber = blockNumber; + } + } + } + } + Random random = new SecureRandom(); + int selectNodeIndex = 0; + ChannelHandlerContext selectedNodeChannelHandlerContext = null; + if (!maxBlockNumberConnections.isEmpty()) { + selectNodeIndex = random.nextInt(maxBlockNumberConnections.size()); + selectedNodeChannelHandlerContext = maxBlockNumberConnections.get(selectNodeIndex); + } else { + selectNodeIndex = random.nextInt(activeConnections.size()); + selectedNodeChannelHandlerContext = activeConnections.get(selectNodeIndex); + } + return selectedNodeChannelHandlerContext; + } - public void removeNetworkConnectionByHost(String host, Integer port) { - String endpoint = host + ":" + port; + public ConnectionInfo getConnectionInfo(String host, Integer port) { + for (ConnectionInfo info : connections) { + if (info.getHost().equals(host) && info.getPort().equals(port)) { + return info; + } + } - networkConnections.remove(endpoint); - } + return null; + } - public void startListen(Integer port) throws SSLException { - if (running) { - logger.debug("running"); - return; + public Map getNetworkConnections() { + return networkConnections; } - logger.debug("init connections listen"); + public ChannelHandlerContext getNetworkConnectionByHost(String host, Integer port) { + String endpoint = host + ":" + port; - EventLoopGroup bossGroup = new NioEventLoopGroup(); - EventLoopGroup workerGroup = new NioEventLoopGroup(); + return networkConnections.get(endpoint); + } - final ChannelConnections selfService = this; - final ThreadPoolTaskExecutor selfThreadPool = threadPool; + public void setNetworkConnectionByHost(String host, Integer port, ChannelHandlerContext ctx) { + String endpoint = host + ":" + port; - SslContext sslCtx = initSslContextForListening(); - logger.debug("listening sslcontext init success"); - try { - serverBootstrap - .group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .option(ChannelOption.SO_BACKLOG, 100) - .handler(new LoggingHandler(LogLevel.INFO)) - .childHandler( - new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - /* - * 每次连接使用新的handler - * 连接信息从socketChannel中获取 - */ - ChannelHandler handler = new ChannelHandler(); - handler.setConnections(selfService); - handler.setIsServer(true); - handler.setThreadPool(selfThreadPool); + networkConnections.put(endpoint, ctx); + } - ch.pipeline() - .addLast( - sslCtx.newHandler(ch.alloc()), - new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, -4, 0), - new IdleStateHandler( - idleTimeout, idleTimeout, idleTimeout, TimeUnit.MILLISECONDS), - handler); - } - }); + public void removeNetworkConnectionByHost(String host, Integer port) { + String endpoint = host + ":" + port; - ChannelFuture future = serverBootstrap.bind(port); - future.get(); + networkConnections.remove(endpoint); + } - running = true; - } catch (Exception e) { - logger.error("error ", e); + public void startListen(Integer port) throws SSLException { + if (running) { + logger.debug("running"); + return; + } + + logger.debug("init connections listen"); + + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + final ChannelConnections selfService = this; + final ThreadPoolTaskExecutor selfThreadPool = threadPool; + + SslContext sslCtx = initSslContextForListening(); + logger.debug("listening sslcontext init success"); + try { + serverBootstrap + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 100) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler( + new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) throws Exception { + /* + * 每次连接使用新的handler + * 连接信息从socketChannel中获取 + */ + ChannelHandler handler = new ChannelHandler(); + handler.setConnections(selfService); + handler.setIsServer(true); + handler.setThreadPool(selfThreadPool); + + ch.pipeline() + .addLast( + sslCtx.newHandler(ch.alloc()), + new LengthFieldBasedFrameDecoder( + Integer.MAX_VALUE, 0, 4, -4, 0), + new IdleStateHandler( + idleTimeout, + idleTimeout, + idleTimeout, + TimeUnit.MILLISECONDS), + handler); + } + }); + + ChannelFuture future = serverBootstrap.bind(port); + future.get(); + + running = true; + } catch (Exception e) { + logger.error("error ", e); + } } - } - public void init() { - logger.debug("init connections"); - // 初始化connections - for (String conn : connectionsStr) { - ConnectionInfo connection = new ConnectionInfo(); + public void init() { + logger.debug("init connections"); + // 初始化connections + for (String conn : connectionsStr) { + ConnectionInfo connection = new ConnectionInfo(); - String[] split2 = conn.split(":"); + String[] split2 = conn.split(":"); - connection.setHost(split2[0]); - connection.setPort(Integer.parseInt(split2[1])); + connection.setHost(split2[0]); + connection.setPort(Integer.parseInt(split2[1])); - networkConnections.put(conn, null); + networkConnections.put(conn, null); - logger.debug("add direct node :[" + "]:[" + split2[1] + "]"); + logger.debug("add direct node :[" + "]:[" + split2[1] + "]"); - connection.setConfig(true); - connections.add(connection); + connection.setConfig(true); + connections.add(connection); + } } - } - public void startConnect() throws SSLException { - if (running) { - logger.debug("running"); - return; + public void startConnect() throws SSLException { + if (running) { + logger.debug("running"); + return; + } + + logger.debug("init connections connect"); + // 初始化netty + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + bootstrap.group(workerGroup); + bootstrap.channel(NioSocketChannel.class); + bootstrap.option(ChannelOption.SO_KEEPALIVE, true); + + final ChannelConnections selfService = this; + final ThreadPoolTaskExecutor selfThreadPool = threadPool; + + SslContext sslCtx = initSslContextForConnect(); + logger.debug(" connect sslcontext init success"); + + bootstrap.handler( + new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) throws Exception { + /* + * 每次连接使用新的handler 连接信息从socketChannel中获取 + */ + ChannelHandler handler = new ChannelHandler(); + handler.setConnections(selfService); + handler.setIsServer(false); + handler.setThreadPool(selfThreadPool); + + ch.pipeline() + .addLast( + sslCtx.newHandler(ch.alloc()), + new LengthFieldBasedFrameDecoder( + Integer.MAX_VALUE, 0, 4, -4, 0), + new IdleStateHandler( + idleTimeout, + idleTimeout, + idleTimeout, + TimeUnit.MILLISECONDS), + handler); + } + }); + + running = true; + + Thread loop = + new Thread() { + public void run() { + try { + while (true) { + if (!running) { + return; + } + + // 尝试重连 + + reconnect(); + Thread.sleep(heartBeatDelay); + } + } catch (InterruptedException e) { + logger.error("error", e); + Thread.currentThread().interrupt(); + } + } + }; + + loop.start(); } - logger.debug("init connections connect"); - // 初始化netty - EventLoopGroup workerGroup = new NioEventLoopGroup(); - - bootstrap.group(workerGroup); - bootstrap.channel(NioSocketChannel.class); - bootstrap.option(ChannelOption.SO_KEEPALIVE, true); - - final ChannelConnections selfService = this; - final ThreadPoolTaskExecutor selfThreadPool = threadPool; + private SslContext initSslContextForConnect() throws SSLException { + SslContext sslCtx; + try { + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource caResource = resolver.getResource(getCaCertPath()); + InputStream caInputStream = caResource.getInputStream(); + Resource keystorecaResource = resolver.getResource(getNodeCaPath()); + Resource keystorekeyResource = resolver.getResource(getNodeKeyPath()); + sslCtx = + SslContextBuilder.forClient() + .trustManager(caInputStream) + .keyManager( + keystorecaResource.getInputStream(), + keystorekeyResource.getInputStream()) + .sslProvider(SslProvider.JDK) + .build(); + } catch (Exception e) { + logger.debug("SSLCONTEXT ***********" + e.getMessage()); + throw new SSLException( + "Failed to initialize the client-side SSLContext: " + e.getMessage()); + } + return sslCtx; + } - SslContext sslCtx = initSslContextForConnect(); - logger.debug(" connect sslcontext init success"); + private SslContext initSslContextForListening() throws SSLException { + SslContext sslCtx; + try { + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource caResource = resolver.getResource(getCaCertPath()); + InputStream caInputStream = caResource.getInputStream(); + Resource keystorecaResource = resolver.getResource(getNodeCaPath()); + Resource keystorekeyResource = resolver.getResource(getNodeKeyPath()); + sslCtx = + SslContextBuilder.forServer( + keystorecaResource.getInputStream(), + keystorekeyResource.getInputStream()) + .trustManager(caInputStream) + .sslProvider(SslProvider.JDK) + .build(); + } catch (Exception e) { + logger.debug("SSLCONTEXT ***********" + e.getMessage()); + throw new SSLException( + "Failed to initialize the client-side SSLContext, please checkout ca.crt File!", + e); + } + return sslCtx; + } - bootstrap.handler( - new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - /* - * 每次连接使用新的handler 连接信息从socketChannel中获取 - */ - ChannelHandler handler = new ChannelHandler(); - handler.setConnections(selfService); - handler.setIsServer(false); - handler.setThreadPool(selfThreadPool); + public void reconnect() { + for (Entry ctx : networkConnections.entrySet()) { + if (ctx.getValue() == null || !ctx.getValue().channel().isActive()) { + String[] split = ctx.getKey().split(":"); - ch.pipeline() - .addLast( - sslCtx.newHandler(ch.alloc()), - new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, -4, 0), - new IdleStateHandler( - idleTimeout, idleTimeout, idleTimeout, TimeUnit.MILLISECONDS), - handler); - } - }); + String host = split[0]; + Integer port = Integer.parseInt(split[1]); + logger.debug("try connect to: {}:{}", host, port); - running = true; + bootstrap.connect(host, port); + logger.debug("connect to: {}:{} success", host, port); + } else { + logger.trace("send heart beat to {}", ctx.getKey()); + // 连接还在,发送心跳 + BcosMessage fiscoMessage = new BcosMessage(); - Thread loop = - new Thread() { - public void run() { - try { - while (true) { - if (!running) { - return; - } + fiscoMessage.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); + fiscoMessage.setResult(0); + fiscoMessage.setType((short) 0x13); + fiscoMessage.setData("0".getBytes()); - // 尝试重连 + ByteBuf out = ctx.getValue().alloc().buffer(); + fiscoMessage.writeHeader(out); + fiscoMessage.writeExtra(out); - reconnect(); - Thread.sleep(heartBeatDelay); - } - } catch (InterruptedException e) { - logger.error("error", e); - Thread.currentThread().interrupt(); + ctx.getValue().writeAndFlush(out); } - } - }; - - loop.start(); - } - - private SslContext initSslContextForConnect() throws SSLException { - SslContext sslCtx; - try { - ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - Resource caResource = resolver.getResource(getCaCertPath()); - InputStream caInputStream = caResource.getInputStream(); - Resource keystorecaResource = resolver.getResource(getNodeCaPath()); - Resource keystorekeyResource = resolver.getResource(getNodeKeyPath()); - sslCtx = - SslContextBuilder.forClient() - .trustManager(caInputStream) - .keyManager(keystorecaResource.getInputStream(), keystorekeyResource.getInputStream()) - .sslProvider(SslProvider.JDK) - .build(); - } catch (Exception e) { - logger.debug("SSLCONTEXT ***********" + e.getMessage()); - throw new SSLException("Failed to initialize the client-side SSLContext: " + e.getMessage()); - } - return sslCtx; - } - - private SslContext initSslContextForListening() throws SSLException { - SslContext sslCtx; - try { - ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - Resource caResource = resolver.getResource(getCaCertPath()); - InputStream caInputStream = caResource.getInputStream(); - Resource keystorecaResource = resolver.getResource(getNodeCaPath()); - Resource keystorekeyResource = resolver.getResource(getNodeKeyPath()); - sslCtx = - SslContextBuilder.forServer( - keystorecaResource.getInputStream(), keystorekeyResource.getInputStream()) - .trustManager(caInputStream) - .build(); - } catch (Exception e) { - logger.debug("SSLCONTEXT ***********" + e.getMessage()); - throw new SSLException( - "Failed to initialize the client-side SSLContext, please checkout ca.crt File!", e); - } - return sslCtx; - } - - public void reconnect() { - for (Entry ctx : networkConnections.entrySet()) { - if (ctx.getValue() == null || !ctx.getValue().channel().isActive()) { - String[] split = ctx.getKey().split(":"); - - String host = split[0]; - Integer port = Integer.parseInt(split[1]); - logger.debug("try connect to: {}:{}", host, port); - - bootstrap.connect(host, port); - logger.debug("connect to: {}:{} success", host, port); - } else { - logger.trace("send heart beat to {}", ctx.getKey()); - // 连接还在,发送心跳 - FiscoMessage fiscoMessage = new FiscoMessage(); - - fiscoMessage.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); - fiscoMessage.setResult(0); - fiscoMessage.setType((short) 0x13); - fiscoMessage.setData("0".getBytes()); - - ByteBuf out = ctx.getValue().alloc().buffer(); - fiscoMessage.writeHeader(out); - fiscoMessage.writeExtra(out); - - ctx.getValue().writeAndFlush(out); - } - } - } - - public void onReceiveMessage(ChannelHandlerContext ctx, ByteBuf message) { - callback.onMessage(ctx, message); - } + } + } + + public void onReceiveMessage(ChannelHandlerContext ctx, ByteBuf message) { + callback.onMessage(ctx, message); + } } diff --git a/src/main/java/org/fisco/bcos/channel/handler/ChannelHandler.java b/src/main/java/org/fisco/bcos/channel/handler/ChannelHandler.java index 39ab4bb01..290ac3a71 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/ChannelHandler.java +++ b/src/main/java/org/fisco/bcos/channel/handler/ChannelHandler.java @@ -11,203 +11,206 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class ChannelHandler extends SimpleChannelInboundHandler { - private static Logger logger = LoggerFactory.getLogger(ChannelHandler.class); - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); - - if (evt instanceof IdleStateEvent) { - IdleStateEvent e = (IdleStateEvent) evt; - switch (e.state()) { - case READER_IDLE: - case WRITER_IDLE: - case ALL_IDLE: - logger.error( - "event:{} connect{}:{} long time Inactive,disconnect", e.state(), host, port); - channelInactive(ctx); - ctx.disconnect(); - ctx.close(); - break; - default: - break; - } - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - try { - // 已连上,获取ip信息 - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); - - logger.debug( - "success,connected[" - + host - + "]:[" - + String.valueOf(port) - + "]," - + String.valueOf(ctx.channel().isActive())); - - if (isServer) { - logger.debug("server accept new connect: {}:{}", host, port); - // 将此新连接增加到connections - ConnectionInfo info = new ConnectionInfo(); - info.setHost(host); - info.setPort(port); - - connections.getConnections().add(info); - connections.setNetworkConnectionByHost(info.getHost(), info.getPort(), ctx); - connections.getCallback().onConnect(ctx); - } else { - // 更新ctx信息 - ChannelHandlerContext connection = connections.getNetworkConnectionByHost(host, port); - if (connection != null && connection.channel().isActive()) { - logger.debug("connect available, close reconnect: {}:{}", host, port); - - ctx.channel().disconnect(); - ctx.channel().close(); - } else { - logger.debug("client connect success {}:{}", host, port); - connections.setNetworkConnectionByHost(host, port, ctx); - connections.getCallback().onConnect(ctx); + private static Logger logger = LoggerFactory.getLogger(ChannelHandler.class); + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + if (evt instanceof IdleStateEvent) { + IdleStateEvent e = (IdleStateEvent) evt; + switch (e.state()) { + case READER_IDLE: + case WRITER_IDLE: + case ALL_IDLE: + logger.error( + "event:{} connect{}:{} long time Inactive,disconnect", + e.state(), + host, + port); + channelInactive(ctx); + ctx.disconnect(); + ctx.close(); + break; + default: + break; + } } - } - } catch (Exception e) { - logger.error("error", e); } - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - try { - logger.debug("disconnect"); - // 已断连,获取ip信息 - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); - - logger.debug( - "disconnect " - + host - + ":" - + String.valueOf(port) - + " ," - + String.valueOf(ctx.channel().isActive())); - - if (isServer) { - // server模式下,移除该connectionInfo - for (Integer i = 0; i < connections.getConnections().size(); ++i) { - ConnectionInfo info = connections.getConnections().get(i); - - if (info.getHost().equals(host) && info.getPort().equals(port)) { - connections.getConnections().remove(i); - } - } - // 移除该networkConnection - connections.removeNetworkConnectionByHost(host, port); - } else { - // 无需将连接置为null - // connections.setNetworkConnection(host, port, null); - } - - connections.getCallback().onDisconnect(ctx); - } catch (Exception e) { - logger.error("error ", e); + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + try { + // connected,get ip info + String host = + ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + logger.debug( + "success,connected[" + + host + + "]:[" + + String.valueOf(port) + + "]," + + String.valueOf(ctx.channel().isActive())); + + if (isServer) { + logger.debug("server accept new connect: {}:{}", host, port); + // add the connection to the connections + ConnectionInfo info = new ConnectionInfo(); + info.setHost(host); + info.setPort(port); + + connections.getConnections().add(info); + connections.setNetworkConnectionByHost(info.getHost(), info.getPort(), ctx); + connections.getCallback().onConnect(ctx); + } else { + // 更新ctx信息 + ChannelHandlerContext connection = + connections.getNetworkConnectionByHost(host, port); + if (connection != null && connection.channel().isActive()) { + logger.debug("connect available, close reconnect: {}:{}", host, port); + + ctx.channel().disconnect(); + ctx.channel().close(); + } else { + logger.debug("client connect success {}:{}", host, port); + connections.setNetworkConnectionByHost(host, port, ctx); + connections.getCallback().onConnect(ctx); + } + } + } catch (Exception e) { + logger.error("error", e); + } } - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); - - final ChannelHandlerContext ctxF = ctx; - final ByteBuf in = (ByteBuf) msg; - - logger.trace("receive,from" + host + ":" + port + " in:" + in.readableBytes()); - logger.trace("threadPool:{}", threadPool == null); - - try { - if (threadPool == null) { - connections.onReceiveMessage(ctx, in); - } else { - threadPool.execute( - new Runnable() { - @Override - public void run() { - connections.onReceiveMessage(ctxF, in); - } - }); - } - } catch (RejectedExecutionException e) { - logger.error("threadPool is full,reject to request", e); + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + try { + logger.debug("disconnect"); + // lost the connection, get ip info + String host = + ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + logger.debug( + "disconnect " + + host + + ":" + + String.valueOf(port) + + " ," + + String.valueOf(ctx.channel().isActive())); + + if (isServer) { + // server mode,remove the connection + for (Integer i = 0; i < connections.getConnections().size(); ++i) { + ConnectionInfo info = connections.getConnections().get(i); + + if (info.getHost().equals(host) && info.getPort().equals(port)) { + connections.getConnections().remove(i); + } + } + + // remove the networkConnection + connections.removeNetworkConnectionByHost(host, port); + } else { + // set the connection disabled + // connections.setNetworkConnection(host, port, null); + } + + connections.getCallback().onDisconnect(ctx); + } catch (Exception e) { + logger.error("error ", e); + } } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.error("network error ", cause); - // 已断连,获取ip信息 - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); - - logger.debug( - "disconnect " - + host - + ":" - + String.valueOf(port) - + " ," - + String.valueOf(ctx.channel().isActive())); - - if (isServer) { - // server模式下,移除该connection - connections.removeNetworkConnectionByHost(host, port); - } else { - // 将该连接置为不可用 - // connections.setNetworkConnection(host, port, null); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + final ChannelHandlerContext ctxF = ctx; + final ByteBuf in = (ByteBuf) msg; + try { + if (threadPool == null) { + connections.onReceiveMessage(ctx, in); + } else { + threadPool.execute( + new Runnable() { + @Override + public void run() { + connections.onReceiveMessage(ctxF, in); + } + }); + } + + } catch (RejectedExecutionException e) { + logger.error("threadPool is full, reject to request", e); + } } - ctx.disconnect(); - ctx.close(); - } + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.error("network error ", cause); + // lost the connection,get ip info + String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); + + logger.debug( + "disconnect " + + host + + ":" + + String.valueOf(port) + + " ," + + String.valueOf(ctx.channel().isActive())); + + if (isServer) { + // server mode,remove the connection + connections.removeNetworkConnectionByHost(host, port); + } else { + // set the connection disabled + // connections.setNetworkConnection(host, port, null); + } + + ctx.disconnect(); + ctx.close(); + } - @Override - protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - channelRead(ctx, in); - } + @Override + protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + channelRead(ctx, in); + } - public void checkAvailable(ChannelHandlerContext ctx) {} + public void checkAvailable(ChannelHandlerContext ctx) {} - public ChannelConnections getConnections() { - return connections; - } + public ChannelConnections getConnections() { + return connections; + } - public void setConnections(ChannelConnections connections) { - this.connections = connections; - } + public void setConnections(ChannelConnections connections) { + this.connections = connections; + } - public Boolean getIsServer() { - return isServer; - } + public Boolean getIsServer() { + return isServer; + } - public void setIsServer(Boolean isServer) { - this.isServer = isServer; - } + public void setIsServer(Boolean isServer) { + this.isServer = isServer; + } - public ThreadPoolTaskExecutor getThreadPool() { - return threadPool; - } + public ThreadPoolTaskExecutor getThreadPool() { + return threadPool; + } - public void setThreadPool(ThreadPoolTaskExecutor threadPool) { - this.threadPool = threadPool; + public void setThreadPool(ThreadPoolTaskExecutor threadPool) { + this.threadPool = threadPool; - logger.debug("set threadPool:{}", threadPool == null); - } + logger.debug("set threadPool:{}", threadPool == null); + } - private ChannelConnections connections; - private Boolean isServer = false; - private ThreadPoolTaskExecutor threadPool; + private ChannelConnections connections; + private Boolean isServer = false; + private ThreadPoolTaskExecutor threadPool; } diff --git a/src/main/java/org/fisco/bcos/channel/handler/ConnectionCallback.java b/src/main/java/org/fisco/bcos/channel/handler/ConnectionCallback.java index f2e71cfb0..3edcd4dd6 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/ConnectionCallback.java +++ b/src/main/java/org/fisco/bcos/channel/handler/ConnectionCallback.java @@ -1,152 +1,203 @@ package org.fisco.bcos.channel.handler; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.SocketChannel; import java.io.UnsupportedEncodingException; import java.math.BigInteger; +import java.net.InetSocketAddress; +import java.util.Arrays; import java.util.Set; import java.util.UUID; +import org.fisco.bcos.channel.client.BcosResponseCallback; import org.fisco.bcos.channel.client.Service; +import org.fisco.bcos.channel.dto.BcosMessage; +import org.fisco.bcos.channel.dto.BcosResponse; import org.fisco.bcos.channel.dto.ChannelMessage; import org.fisco.bcos.channel.dto.ChannelMessage2; -import org.fisco.bcos.channel.dto.FiscoMessage; +import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; +import org.fisco.bcos.web3j.protocol.core.Request; +import org.fisco.bcos.web3j.protocol.core.methods.response.BlockNumber; +import org.fisco.bcos.web3j.protocol.exceptions.MessageDecodingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ConnectionCallback implements ChannelConnections.Callback { - private static Logger logger = LoggerFactory.getLogger(ConnectionCallback.class); + private static Logger logger = LoggerFactory.getLogger(ConnectionCallback.class); - private ObjectMapper objectMapper = new ObjectMapper(); - private Service channelService; - private Set topics; + private ObjectMapper objectMapper = new ObjectMapper(); + private Service channelService; + private Set topics; - public Service getChannelService() { - return channelService; - } - - public void setChannelService(Service channelService) { - this.channelService = channelService; - } - - public ConnectionCallback(Set topics) { - this.topics = topics; - } - - public void setTopics(Set topics) { - try { - this.topics = topics; - } catch (Exception e) { - logger.error("system error", e); + public Service getChannelService() { + return channelService; } - } - - @Override - public void onConnect(ChannelHandlerContext ctx) { - try { - channelService.setNumber(BigInteger.ONE); - - Message message = new Message(); - message.setResult(0); - message.setType((short) 0x32); - message.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); - - logger.debug("connection established,send topic to the connection:{}", message.getSeq()); - topics.add("_block_notify_" + String.valueOf(channelService.getGroupId())); - message.setData(objectMapper.writeValueAsBytes(topics.toArray())); - - logger.debug("topics: {}", new String(message.getData())); - - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); - } catch (Exception e) { - logger.error("error:", e); + public void setChannelService(Service channelService) { + this.channelService = channelService; } - } - @Override - public void onDisconnect(ChannelHandlerContext ctx) {} - - @Override - public void onMessage(ChannelHandlerContext ctx, ByteBuf message) { - try { - Message msg = new Message(); - msg.readHeader(message); + public ConnectionCallback(Set topics) { + this.topics = topics; + } - logger.trace("receive Message type: {}", msg.getType()); + public void setTopics(Set topics) { + try { + this.topics = topics; + } catch (Exception e) { + logger.error("system error", e); + } + } - if (msg.getType() == 0x20 || msg.getType() == 0x21) { - logger.debug("channel message"); + @Override + public void onConnect(ChannelHandlerContext ctx) { + try { + channelService.setNumber(BigInteger.ONE); - ChannelMessage channelMessage = new ChannelMessage(msg); - channelMessage.readExtra(message); + Message message = new Message(); + message.setResult(0); + message.setType((short) 0x32); + message.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); - channelService.onReceiveChannelMessage(ctx, channelMessage); - } else if (msg.getType() == 0x30 || msg.getType() == 0x31) { - logger.debug("channel2 message"); + logger.debug( + "connection established,send topic to the connection:{}", message.getSeq()); - ChannelMessage2 channelMessage = new ChannelMessage2(msg); - channelMessage.readExtra(message); + topics.add("_block_notify_" + String.valueOf(channelService.getGroupId())); + message.setData(objectMapper.writeValueAsBytes(topics.toArray())); - channelService.onReceiveChannelMessage2(ctx, channelMessage); - } else if (msg.getType() == 0x12) { - logger.debug("fisco message"); + logger.debug("topics: {}", new String(message.getData())); - FiscoMessage fiscoMessage = new FiscoMessage(msg); - fiscoMessage.readExtra(message); + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); - channelService.onReceiveEthereumMessage(ctx, fiscoMessage); - } else if (msg.getType() == 0x13) { - msg.readExtra(message); + ctx.writeAndFlush(out); - String content = "1"; - try { - content = new String(msg.getData(), "utf-8"); - } catch (UnsupportedEncodingException e) { - logger.error("heartbeat packet cannot be parsed"); + queryBlockNumberForSelectNodes(ctx); } catch (Exception e) { - logger.error("heartbeat packet Exception"); + logger.error("error:", e); } + } - if (content.equals("0")) { - logger.trace("heartbeat packet,send heartbeat packet back"); - Message response = new Message(); - - response.setSeq(msg.getSeq()); - response.setResult(0); - response.setType((short) 0x13); - response.setData("1".getBytes()); + private void queryBlockNumberForSelectNodes(ChannelHandlerContext ctx) + throws JsonProcessingException { + BcosMessage bcosMessage = new BcosMessage(); + bcosMessage.setType((short) 0x12); + String seq = UUID.randomUUID().toString().replaceAll("-", ""); + bcosMessage.setSeq(seq); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(channelService); + Request request = + new Request<>( + "getBlockNumber", + Arrays.asList(channelService.getGroupId()), + channelEthereumService, + BlockNumber.class); + ObjectMapper objectMapper = new ObjectMapper(); + bcosMessage.setData(objectMapper.writeValueAsBytes(request)); + ByteBuf byteBuf = ctx.alloc().buffer(); + bcosMessage.writeHeader(byteBuf); + bcosMessage.writeExtra(byteBuf); + ctx.writeAndFlush(byteBuf); + + channelService + .getSeq2Callback() + .put( + seq, + new BcosResponseCallback() { + + @Override + public void onResponse(BcosResponse response) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + BlockNumber blockNumber = + objectMapper.readValue( + response.getContent(), BlockNumber.class); + SocketChannel socketChannel = (SocketChannel) ctx.channel(); + InetSocketAddress socketAddress = socketChannel.remoteAddress(); + channelService + .getNodeToBlockNumberMap() + .put( + socketAddress.getAddress().getHostAddress() + + socketAddress.getPort(), + blockNumber.getBlockNumber().intValue()); + } catch (Exception e) { + throw new MessageDecodingException(response.getContent()); + } + } + }); + } - ByteBuf out = ctx.alloc().buffer(); - response.writeHeader(out); - response.writeExtra(out); + @Override + public void onDisconnect(ChannelHandlerContext ctx) {} - ctx.writeAndFlush(out); - } else if (content.equals("1")) { - logger.trace("heartbeat response"); + @Override + public void onMessage(ChannelHandlerContext ctx, ByteBuf message) { + try { + Message msg = new Message(); + msg.readHeader(message); + + if (msg.getType() == 0x20 || msg.getType() == 0x21) { + ChannelMessage channelMessage = new ChannelMessage(msg); + channelMessage.readExtra(message); + + channelService.onReceiveChannelMessage(ctx, channelMessage); + } else if (msg.getType() == 0x30 || msg.getType() == 0x31) { + ChannelMessage2 channelMessage = new ChannelMessage2(msg); + channelMessage.readExtra(message); + + channelService.onReceiveChannelMessage2(ctx, channelMessage); + } else if (msg.getType() == 0x12) { + BcosMessage fiscoMessage = new BcosMessage(msg); + fiscoMessage.readExtra(message); + + channelService.onReceiveEthereumMessage(ctx, fiscoMessage); + } else if (msg.getType() == 0x13) { + msg.readExtra(message); + + String content = "1"; + try { + content = new String(msg.getData(), "utf-8"); + } catch (UnsupportedEncodingException e) { + logger.error("heartbeat packet cannot be parsed"); + } catch (Exception e) { + logger.error("heartbeat packet Exception"); + } + + if ("0".equals(content)) { + logger.trace("heartbeat packet,send heartbeat packet back"); + Message response = new Message(); + + response.setSeq(msg.getSeq()); + response.setResult(0); + response.setType((short) 0x13); + response.setData("1".getBytes()); + + ByteBuf out = ctx.alloc().buffer(); + response.writeHeader(out); + response.writeExtra(out); + + ctx.writeAndFlush(out); + } else if ("1".equals(content)) { + logger.trace("heartbeat response"); + } + } else if (msg.getType() == 0x1000) { + BcosMessage fiscoMessage = new BcosMessage(msg); + fiscoMessage.readExtra(message); + channelService.onReceiveTransactionMessage(ctx, fiscoMessage); + } else if (msg.getType() == 0x1001) { + // new block notify + ChannelMessage2 channelMessage = new ChannelMessage2(msg); + channelMessage.readExtra(message); + + channelService.onReceiveBlockNotify(ctx, channelMessage); + } else { + logger.error("unknown message type:{}", msg.getType()); + } + } finally { + message.release(); } - } else if (msg.getType() == 0x1000) { - FiscoMessage fiscoMessage = new FiscoMessage(msg); - logger.trace("TransactionReceipt notify: {}", fiscoMessage.getSeq()); - - fiscoMessage.readExtra(message); - channelService.onReceiveTransactionMessage(ctx, fiscoMessage); - } else if (msg.getType() == 0x1001) { - // new block notify - ChannelMessage2 channelMessage = new ChannelMessage2(msg); - channelMessage.readExtra(message); - - logger.trace("New block notify"); - channelService.onReceiveBlockNotify(ctx, channelMessage); - } else { - logger.error("unknown message type:{}", msg.getType()); - } - } finally { - message.release(); } - } } diff --git a/src/main/java/org/fisco/bcos/channel/handler/ConnectionInfo.java b/src/main/java/org/fisco/bcos/channel/handler/ConnectionInfo.java index dd4f61803..9e3ed7536 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/ConnectionInfo.java +++ b/src/main/java/org/fisco/bcos/channel/handler/ConnectionInfo.java @@ -4,50 +4,50 @@ import java.util.List; public class ConnectionInfo { - public String getNodeID() { - return nodeID; - } + public String getNodeID() { + return nodeID; + } - public void setNodeID(String nodeID) { - this.nodeID = nodeID; - } + public void setNodeID(String nodeID) { + this.nodeID = nodeID; + } - public String getHost() { - return host; - } + public String getHost() { + return host; + } - public void setHost(String host) { - this.host = host; - } + public void setHost(String host) { + this.host = host; + } - public Integer getPort() { - return port; - } + public Integer getPort() { + return port; + } - public void setPort(Integer port) { - this.port = port; - } + public void setPort(Integer port) { + this.port = port; + } - public Boolean getConfig() { - return config; - } + public Boolean getConfig() { + return config; + } - public void setConfig(Boolean config) { - this.config = config; - } + public void setConfig(Boolean config) { + this.config = config; + } - public List getTopics() { - return topics; - } + public List getTopics() { + return topics; + } - public void setTopics(List topics) { - this.topics = topics; - } + public void setTopics(List topics) { + this.topics = topics; + } - private String nodeID = ""; - private String host = ""; - private Integer port = 0; - private Boolean config = false; + private String nodeID = ""; + private String host = ""; + private Integer port = 0; + private Boolean config = false; - private List topics = new ArrayList(); + private List topics = new ArrayList(); } diff --git a/src/main/java/org/fisco/bcos/channel/handler/Decoder.java b/src/main/java/org/fisco/bcos/channel/handler/Decoder.java index 1bae71686..1d2bf85e6 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/Decoder.java +++ b/src/main/java/org/fisco/bcos/channel/handler/Decoder.java @@ -8,43 +8,44 @@ import org.slf4j.LoggerFactory; public class Decoder extends ByteToMessageDecoder { - private static Logger logger = LoggerFactory.getLogger(Decoder.class); - - private Integer dataLength = 0; - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - logger.debug("decode:" + in.readableBytes()); - - while (true) { - if (dataLength > 0) { - if (in.readableBytes() < dataLength - 4) { - return; + private static Logger logger = LoggerFactory.getLogger(Decoder.class); + + private Integer dataLength = 0; + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) + throws Exception { + logger.debug("decode:" + in.readableBytes()); + + while (true) { + if (dataLength > 0) { + if (in.readableBytes() < dataLength - 4) { + return; + } + + Short type = in.readShort(); + ByteBuf data = in.readBytes(dataLength - 6); + + Message message = new Message(); + message.setLength(dataLength); + message.setType(type); + message.setData(data.array()); + + logger.debug( + "new message: " + + String.valueOf(message.getLength()) + + "," + + String.valueOf(message.getType())); + out.add(message); + dataLength = 0; + } else { + if (in.readableBytes() < 4) { + return; + } + + dataLength = in.readInt(); + logger.debug("dataLength " + String.valueOf(dataLength)); + } } - - Short type = in.readShort(); - ByteBuf data = in.readBytes(dataLength - 6); - - Message message = new Message(); - message.setLength(dataLength); - message.setType(type); - message.setData(data.array()); - - logger.debug( - "new message: " - + String.valueOf(message.getLength()) - + "," - + String.valueOf(message.getType())); - out.add(message); - dataLength = 0; - } else { - if (in.readableBytes() < 4) { - return; - } - - dataLength = in.readInt(); - logger.debug("dataLength " + String.valueOf(dataLength)); - } } - } } diff --git a/src/main/java/org/fisco/bcos/channel/handler/Encoder.java b/src/main/java/org/fisco/bcos/channel/handler/Encoder.java index f4335a285..cf1d2e6ec 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/Encoder.java +++ b/src/main/java/org/fisco/bcos/channel/handler/Encoder.java @@ -7,14 +7,14 @@ import org.slf4j.LoggerFactory; public class Encoder extends MessageToByteEncoder { - private static Logger logger = LoggerFactory.getLogger(Encoder.class); + private static Logger logger = LoggerFactory.getLogger(Encoder.class); - @Override - protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception { - logger.debug("encode:" + msg.getLength() + "," + msg.getData()); + @Override + protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception { + logger.debug("encode:" + msg.getLength() + "," + msg.getData()); - out.writeIntLE(msg.getLength()); - out.writeShortLE(msg.getType()); - out.writeBytes(msg.getData()); - } + out.writeIntLE(msg.getLength()); + out.writeShortLE(msg.getType()); + out.writeBytes(msg.getData()); + } } diff --git a/src/main/java/org/fisco/bcos/channel/handler/GroupChannelConnectionsConfig.java b/src/main/java/org/fisco/bcos/channel/handler/GroupChannelConnectionsConfig.java index 94b96562b..306f7c9d1 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/GroupChannelConnectionsConfig.java +++ b/src/main/java/org/fisco/bcos/channel/handler/GroupChannelConnectionsConfig.java @@ -3,13 +3,13 @@ import java.util.List; public class GroupChannelConnectionsConfig { - private List allChannelConnections; + private List allChannelConnections; - public List getAllChannelConnections() { - return allChannelConnections; - } + public List getAllChannelConnections() { + return allChannelConnections; + } - public void setAllChannelConnections(List allChannelConnections) { - this.allChannelConnections = allChannelConnections; - } + public void setAllChannelConnections(List allChannelConnections) { + this.allChannelConnections = allChannelConnections; + } } diff --git a/src/main/java/org/fisco/bcos/channel/handler/Message.java b/src/main/java/org/fisco/bcos/channel/handler/Message.java index f6f0e1b95..18dc5bb9b 100644 --- a/src/main/java/org/fisco/bcos/channel/handler/Message.java +++ b/src/main/java/org/fisco/bcos/channel/handler/Message.java @@ -7,90 +7,90 @@ import org.slf4j.LoggerFactory; public class Message implements Serializable { - private static Logger logger = LoggerFactory.getLogger(Message.class); + private static Logger logger = LoggerFactory.getLogger(Message.class); - private static final long serialVersionUID = -7276897518418560354L; + private static final long serialVersionUID = -7276897518418560354L; - public static final int HEADER_LENGTH = 4 + 2 + 32 + 4; + public static final int HEADER_LENGTH = 4 + 2 + 32 + 4; - public void readHeader(ByteBuf in) { + public void readHeader(ByteBuf in) { - length = in.readInt(); - type = in.readShort(); - byte[] dst = new byte[32]; - in.readBytes(dst); - try { - seq = new String(dst, "utf-8"); - } catch (UnsupportedEncodingException e) { + length = in.readInt(); + type = in.readShort(); + byte[] dst = new byte[32]; + in.readBytes(dst); + try { + seq = new String(dst, "utf-8"); + } catch (UnsupportedEncodingException e) { + } + result = in.readInt(); } - result = in.readInt(); - } - - public void readExtra(ByteBuf in) { - data = new byte[length - HEADER_LENGTH]; - in.readBytes(data, 0, length - HEADER_LENGTH); - } - - public void writeHeader(ByteBuf out) { - // 先计算总长度 - if (length.equals(0)) { - length = HEADER_LENGTH + data.length; + + public void readExtra(ByteBuf in) { + data = new byte[length - HEADER_LENGTH]; + in.readBytes(data, 0, length - HEADER_LENGTH); + } + + public void writeHeader(ByteBuf out) { + // 先计算总长度 + if (length.equals(0)) { + length = HEADER_LENGTH + data.length; + } + + out.writeInt(length); + out.writeShort(type); + out.writeBytes(seq.getBytes(), 0, 32); + out.writeInt(result); + } + + public void writeExtra(ByteBuf out) { + out.writeBytes(data); + } + + public Integer getLength() { + return length; + } + + public void setLength(Integer length) { + this.length = length; + } + + public Short getType() { + return type; + } + + public void setType(Short type) { + this.type = type; + } + + public String getSeq() { + return seq; + } + + public void setSeq(String seq) { + this.seq = seq; + } + + public Integer getResult() { + return result; + } + + public void setResult(Integer result) { + this.result = result; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + this.length = data.length + HEADER_LENGTH; } - out.writeInt(length); - out.writeShort(type); - out.writeBytes(seq.getBytes(), 0, 32); - out.writeInt(result); - } - - public void writeExtra(ByteBuf out) { - out.writeBytes(data); - } - - public Integer getLength() { - return length; - } - - public void setLength(Integer length) { - this.length = length; - } - - public Short getType() { - return type; - } - - public void setType(Short type) { - this.type = type; - } - - public String getSeq() { - return seq; - } - - public void setSeq(String seq) { - this.seq = seq; - } - - public Integer getResult() { - return result; - } - - public void setResult(Integer result) { - this.result = result; - } - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - this.length = data.length + HEADER_LENGTH; - } - - protected Integer length = 0; - protected Short type = 0; - protected String seq = ""; - protected Integer result = 0; - protected byte[] data; + protected Integer length = 0; + protected Short type = 0; + protected String seq = ""; + protected Integer result = 0; + protected byte[] data; } diff --git a/src/main/java/org/fisco/bcos/channel/proxy/ConnectionPair.java b/src/main/java/org/fisco/bcos/channel/proxy/ConnectionPair.java index bc31a033b..2f56e1e71 100644 --- a/src/main/java/org/fisco/bcos/channel/proxy/ConnectionPair.java +++ b/src/main/java/org/fisco/bcos/channel/proxy/ConnectionPair.java @@ -16,166 +16,165 @@ import org.slf4j.LoggerFactory; class ConnectionPair { - private static Logger logger = LoggerFactory.getLogger(ConnectionPair.class); - - public ChannelHandlerContext localConnection; // SDK connect - public ChannelHandlerContext remoteConnection; // node connect - public Timeout timeout; - - private Message message; - private ConnectionInfo remoteConnectionInfo; - private List remoteConnectionInfos; - private ChannelConnections remoteChannelConnections; - private Server server; - - public Message getMessage() { - return message; - } - - public void setMessage(Message message) { - this.message = message; - } - - public ConnectionInfo getRemoteConnectionInfo() { - return remoteConnectionInfo; - } - - public void setRemoteConnectionInfo(ConnectionInfo remoteConnectionInfo) { - this.remoteConnectionInfo = remoteConnectionInfo; - } - - public List getRemoteConnectionInfos() { - return remoteConnectionInfos; - } - - public void setRemoteConnectionInfos(List remoteConnectionInfos) { - this.remoteConnectionInfos = remoteConnectionInfos; - } - - public ChannelConnections getRemoteChannelConnections() { - return remoteChannelConnections; - } - - public void setRemoteChannelConnections(ChannelConnections remoteChannelConnections) { - this.remoteChannelConnections = remoteChannelConnections; - } - - public Server getServer() { - return server; - } - - public void setServer(Server server) { - this.server = server; - } - - public void init() { - final ConnectionPair self = this; - final String seq = message.getSeq(); - - timeout = - server - .getTimeoutHandler() - .newTimeout( - new TimerTask() { - private ConnectionPair selfServer = self; - private String selfSeq = seq; - - @Override - public void run(Timeout timeout) throws Exception { - // 处理超时逻辑 - logger.trace("clean timeout session:{}", selfSeq); - - selfServer.server.getSeq2Connections().remove(selfSeq); - } - }, - 30000, - TimeUnit.MILLISECONDS); - } - - public void retrySendRemoteMessage() { - Integer errorCode = 0; - try { - // 选取客户端节点 - logger.debug("remoteConnection size :{}", remoteConnectionInfos.size()); - - remoteConnectionInfo = null; - if (remoteConnectionInfos.size() > 0) { - Random random = new SecureRandom(); - Integer index = random.nextInt(remoteConnectionInfos.size()); - - logger.debug("selected:{}", index); - - remoteConnectionInfo = remoteConnectionInfos.get(index); - - remoteConnectionInfos.remove(remoteConnectionInfos.get(index)); - } - - if (remoteConnectionInfo == null) { - // 所有节点已尝试,无法再重试了 - logger.error("remoteConnectionInfo null"); - - errorCode = 99; - throw new Exception("remoteConnectionInfo null"); - } - - ChannelHandlerContext ctx = - remoteChannelConnections.getNetworkConnectionByHost( - remoteConnectionInfo.getHost(), remoteConnectionInfo.getPort()); - remoteConnection = ctx; - - if (ctx != null && ctx.channel().isActive()) { - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); - - logger.debug( - "send message to " - + remoteConnectionInfo.getHost() - + ":" - + String.valueOf(remoteConnectionInfo.getPort()) - + " success"); - } else { - logger.error("local node inactive"); - retrySendRemoteMessage(); - } - } catch (Exception e) { - logger.error("send message error", e); - - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(errorCode); - response.setErrorMessage(e.getMessage()); - - // 找不到连接,错误 - logger.error("connection error 99"); - - if (message.getType() == 0x20 || message.getType() == 0x21) { - message.setType((short) 0x21); - } else if (message.getType() == 0x30 || message.getType() == 0x31) { - message.setType((short) 0x31); - } else { - // ethereum消息,不用改类型 - } - - message.setResult(99); - - ByteBuf out = localConnection.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - localConnection.writeAndFlush(out); - - // 彻底失败后,删掉这个seq - if (message.getSeq() != null) { - server.getSeq2Connections().remove(message.getSeq()); - } - - if (timeout != null) { - timeout.cancel(); - } - - return; + private static Logger logger = LoggerFactory.getLogger(ConnectionPair.class); + + public ChannelHandlerContext localConnection; // SDK connect + public ChannelHandlerContext remoteConnection; // node connect + public Timeout timeout; + + private Message message; + private ConnectionInfo remoteConnectionInfo; + private List remoteConnectionInfos; + private ChannelConnections remoteChannelConnections; + private Server server; + + public Message getMessage() { + return message; + } + + public void setMessage(Message message) { + this.message = message; + } + + public ConnectionInfo getRemoteConnectionInfo() { + return remoteConnectionInfo; + } + + public void setRemoteConnectionInfo(ConnectionInfo remoteConnectionInfo) { + this.remoteConnectionInfo = remoteConnectionInfo; + } + + public List getRemoteConnectionInfos() { + return remoteConnectionInfos; + } + + public void setRemoteConnectionInfos(List remoteConnectionInfos) { + this.remoteConnectionInfos = remoteConnectionInfos; + } + + public ChannelConnections getRemoteChannelConnections() { + return remoteChannelConnections; + } + + public void setRemoteChannelConnections(ChannelConnections remoteChannelConnections) { + this.remoteChannelConnections = remoteChannelConnections; + } + + public Server getServer() { + return server; + } + + public void setServer(Server server) { + this.server = server; + } + + public void init() { + final ConnectionPair self = this; + final String seq = message.getSeq(); + + timeout = + server.getTimeoutHandler() + .newTimeout( + new TimerTask() { + private ConnectionPair selfServer = self; + private String selfSeq = seq; + + @Override + public void run(Timeout timeout) throws Exception { + // 处理超时逻辑 + logger.trace("clean timeout session:{}", selfSeq); + + selfServer.server.getSeq2Connections().remove(selfSeq); + } + }, + 30000, + TimeUnit.MILLISECONDS); + } + + public void retrySendRemoteMessage() { + Integer errorCode = 0; + try { + // 选取客户端节点 + logger.debug("remoteConnection size :{}", remoteConnectionInfos.size()); + + remoteConnectionInfo = null; + if (remoteConnectionInfos.size() > 0) { + Random random = new SecureRandom(); + Integer index = random.nextInt(remoteConnectionInfos.size()); + + logger.debug("selected:{}", index); + + remoteConnectionInfo = remoteConnectionInfos.get(index); + + remoteConnectionInfos.remove(remoteConnectionInfos.get(index)); + } + + if (remoteConnectionInfo == null) { + // 所有节点已尝试,无法再重试了 + logger.error("remoteConnectionInfo null"); + + errorCode = 99; + throw new Exception("remoteConnectionInfo null"); + } + + ChannelHandlerContext ctx = + remoteChannelConnections.getNetworkConnectionByHost( + remoteConnectionInfo.getHost(), remoteConnectionInfo.getPort()); + remoteConnection = ctx; + + if (ctx != null && ctx.channel().isActive()) { + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); + + logger.debug( + "send message to " + + remoteConnectionInfo.getHost() + + ":" + + String.valueOf(remoteConnectionInfo.getPort()) + + " success"); + } else { + logger.error("local node inactive"); + retrySendRemoteMessage(); + } + } catch (Exception e) { + logger.error("send message error", e); + + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(errorCode); + response.setErrorMessage(e.getMessage()); + + // 找不到连接,错误 + logger.error("connection error 99"); + + if (message.getType() == 0x20 || message.getType() == 0x21) { + message.setType((short) 0x21); + } else if (message.getType() == 0x30 || message.getType() == 0x31) { + message.setType((short) 0x31); + } else { + // ethereum消息,不用改类型 + } + + message.setResult(99); + + ByteBuf out = localConnection.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + localConnection.writeAndFlush(out); + + // 彻底失败后,删掉这个seq + if (message.getSeq() != null) { + server.getSeq2Connections().remove(message.getSeq()); + } + + if (timeout != null) { + timeout.cancel(); + } + + return; + } } - } } diff --git a/src/main/java/org/fisco/bcos/channel/proxy/ResponseCallback.java b/src/main/java/org/fisco/bcos/channel/proxy/ResponseCallback.java index 0220fe7e2..8fd4e774f 100644 --- a/src/main/java/org/fisco/bcos/channel/proxy/ResponseCallback.java +++ b/src/main/java/org/fisco/bcos/channel/proxy/ResponseCallback.java @@ -3,5 +3,5 @@ import org.fisco.bcos.channel.handler.Message; public interface ResponseCallback { - public void onResponse(Message response); + public void onResponse(Message response); } diff --git a/src/main/java/org/fisco/bcos/channel/proxy/Server.java b/src/main/java/org/fisco/bcos/channel/proxy/Server.java index 2d3f5407a..517cc60d3 100644 --- a/src/main/java/org/fisco/bcos/channel/proxy/Server.java +++ b/src/main/java/org/fisco/bcos/channel/proxy/Server.java @@ -8,7 +8,13 @@ import io.netty.util.Timer; import java.io.UnsupportedEncodingException; import java.security.SecureRandom; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import javax.net.ssl.SSLException; import org.fisco.bcos.channel.handler.ChannelConnections; @@ -19,533 +25,553 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class Server { - private static Logger logger = LoggerFactory.getLogger(Server.class); + private static Logger logger = LoggerFactory.getLogger(Server.class); - class ConnectionCallback implements ChannelConnections.Callback { - public Server getServer() { - return server; - } - - public void setServer(Server server) { - this.server = server; - } - - public Boolean getFromRemote() { - return fromRemote; - } - - public void setFromRemote(Boolean fromRemote) { - this.fromRemote = fromRemote; - } - - @Override - public void onMessage(ChannelHandlerContext ctx, ByteBuf message) { - try { - Message msg = new Message(); - msg.readHeader(message); - msg.readExtra(message); - - logger.debug("receive Message type: {}", msg.getType()); - - if (msg.getType() == 0x20 || msg.getType() == 0x21) { - logger.debug("channel "); - } else if (msg.getType() == 0x30 || msg.getType() == 0x31) { - logger.debug("channel2"); - } else if (msg.getType() == 0x32) { - logger.debug("topic"); - - onTopic(ctx, msg); - return; - } else if (msg.getType() == 0x12) { - logger.debug("ethereum"); - } else if (msg.getType() == 0x13) { - onHeartBeat(ctx, msg); - return; - } else if (msg.getType() == 0x1000) { - logger.debug("transaction message call back."); - } else { - logger.error("unknown message:{}", msg.getType()); + class ConnectionCallback implements ChannelConnections.Callback { + public Server getServer() { + return server; } - if (fromRemote) { - logger.debug("remote message"); - server.onRemoteMessage(ctx, msg); - } else { - logger.debug("local message"); - server.onLocalMessage(ctx, msg); + public void setServer(Server server) { + this.server = server; } - } finally { - message.release(); - } - } - @Override - public void onConnect(ChannelHandlerContext ctx) { - // 成功连接到新节点,发送topic - if (fromRemote) { - try { - logger.debug("endpoint connection established,send topic"); - broadcastTopic(ctx); - } catch (Exception e) { - logger.error("error ", e); + public Boolean getFromRemote() { + return fromRemote; } - } - } - @Override - public void onDisconnect(ChannelHandlerContext ctx) { - // 有sdk断开,需更新topic - if (!fromRemote) { - // 需要清除该连接的信息 - logger.debug("SDK disconnect,update and broadcast topic"); - - broadcastTopic(); - } - } - - private Server server; - private Boolean fromRemote = false; - } - - public ChannelConnections getLocalConnections() { - return localConnections; - } + public void setFromRemote(Boolean fromRemote) { + this.fromRemote = fromRemote; + } - public void setLocalConnections(ChannelConnections localConnections) { - this.localConnections = localConnections; - } + @Override + public void onMessage(ChannelHandlerContext ctx, ByteBuf message) { + try { + Message msg = new Message(); + msg.readHeader(message); + msg.readExtra(message); + + logger.debug("receive Message type: {}", msg.getType()); + + if (msg.getType() == 0x20 || msg.getType() == 0x21) { + logger.debug("channel "); + } else if (msg.getType() == 0x30 || msg.getType() == 0x31) { + logger.debug("channel2"); + } else if (msg.getType() == 0x32) { + logger.debug("topic"); + + onTopic(ctx, msg); + return; + } else if (msg.getType() == 0x12) { + logger.debug("ethereum"); + } else if (msg.getType() == 0x13) { + onHeartBeat(ctx, msg); + return; + } else if (msg.getType() == 0x1000) { + logger.debug("transaction message call back."); + } else { + logger.error("unknown message:{}", msg.getType()); + } + + if (fromRemote) { + logger.debug("remote message"); + server.onRemoteMessage(ctx, msg); + } else { + logger.debug("local message"); + server.onLocalMessage(ctx, msg); + } + } finally { + message.release(); + } + } - public ChannelConnections getRemoteConnections() { - return remoteConnections; - } + @Override + public void onConnect(ChannelHandlerContext ctx) { + // 成功连接到新节点,发送topic + if (fromRemote) { + try { + logger.debug("endpoint connection established,send topic"); + broadcastTopic(ctx); + } catch (Exception e) { + logger.error("error ", e); + } + } + } - public void setRemoteConnections(ChannelConnections connections) { - this.remoteConnections = connections; - } + @Override + public void onDisconnect(ChannelHandlerContext ctx) { + // 有sdk断开,需更新topic + if (!fromRemote) { + // 需要清除该连接的信息 + logger.debug("SDK disconnect,update and broadcast topic"); - public Map getSeq2Connections() { - return seq2Connections; - } + broadcastTopic(); + } + } - public void setSeq2Connections(Map seq2Connections) { - this.seq2Connections = seq2Connections; - } + private Server server; + private Boolean fromRemote = false; + } - public Integer getBindPort() { - return bindPort; - } + public ChannelConnections getLocalConnections() { + return localConnections; + } - public void setBindPort(Integer bindPort) { - this.bindPort = bindPort; - } + public void setLocalConnections(ChannelConnections localConnections) { + this.localConnections = localConnections; + } - public Timer getTimeoutHandler() { - return timeoutHandler; - } + public ChannelConnections getRemoteConnections() { + return remoteConnections; + } - public void setTimeoutHandler(Timer timeoutHandler) { - this.timeoutHandler = timeoutHandler; - } + public void setRemoteConnections(ChannelConnections connections) { + this.remoteConnections = connections; + } - public void run() throws SSLException { - logger.debug("init ProxyServer"); + public Map getSeq2Connections() { + return seq2Connections; + } - try { - ConnectionCallback localConnectionCallback = new ConnectionCallback(); - localConnectionCallback.setServer(this); - localConnectionCallback.setFromRemote(false); + public void setSeq2Connections(Map seq2Connections) { + this.seq2Connections = seq2Connections; + } - ConnectionCallback remoteConnectionCallback = new ConnectionCallback(); - remoteConnectionCallback.setServer(this); - remoteConnectionCallback.setFromRemote(true); + public Integer getBindPort() { + return bindPort; + } - localConnections.setCallback(localConnectionCallback); - localConnections.startListen(bindPort); + public void setBindPort(Integer bindPort) { + this.bindPort = bindPort; + } - remoteConnections.setCallback(remoteConnectionCallback); - remoteConnections.init(); - remoteConnections.setThreadPool(threadPool); - remoteConnections.startConnect(); - } catch (Exception e) { - logger.error("error ", e); + public Timer getTimeoutHandler() { + return timeoutHandler; + } - throw e; + public void setTimeoutHandler(Timer timeoutHandler) { + this.timeoutHandler = timeoutHandler; } - } - - public void broadcastTopic() { - broadcastTopic(null); - } - - public void broadcastTopic(ChannelHandlerContext ctx) { - try { - Message message = new Message(); - message.setResult(0); - message.setType((short) 0x32); // topic设置topic消息0x32 - message.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); - - // 综合所有的topics - Set allTopics = new HashSet(); - for (ConnectionInfo connectionInfo : localConnections.getConnections()) { - // 有效的连接,才增加到全局topic - ChannelHandlerContext localCtx = - localConnections.getNetworkConnectionByHost( - connectionInfo.getHost(), connectionInfo.getPort()); - - if (localCtx != null && localCtx.channel().isActive()) { - logger.debug( - "node:{}:{} follow topics: {}", - connectionInfo.getHost(), - connectionInfo.getPort(), - connectionInfo.getTopics()); - allTopics.addAll(connectionInfo.getTopics()); - } - } - message.setData(objectMapper.writeValueAsBytes(allTopics.toArray())); + public void run() throws SSLException { + logger.debug("init ProxyServer"); - logger.debug("all topics: {}", new String(message.getData())); + try { + ConnectionCallback localConnectionCallback = new ConnectionCallback(); + localConnectionCallback.setServer(this); + localConnectionCallback.setFromRemote(false); - if (ctx == null) { - // 广播到所有远端节点 - for (String key : remoteConnections.getNetworkConnections().keySet()) { - ChannelHandlerContext remoteCtx = remoteConnections.getNetworkConnections().get(key); + ConnectionCallback remoteConnectionCallback = new ConnectionCallback(); + remoteConnectionCallback.setServer(this); + remoteConnectionCallback.setFromRemote(true); - if (remoteCtx != null && remoteCtx.channel().isActive()) { - ByteBuf out = remoteCtx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); + localConnections.setCallback(localConnectionCallback); + localConnections.startListen(bindPort); - if (remoteCtx != null && remoteCtx.channel().isActive()) { - logger.debug( - "send topic {}:{}", - ((SocketChannel) remoteCtx.channel()) - .remoteAddress() - .getAddress() - .getHostAddress(), - ((SocketChannel) remoteCtx.channel()).remoteAddress().getPort()); + remoteConnections.setCallback(remoteConnectionCallback); + remoteConnections.init(); + remoteConnections.setThreadPool(threadPool); + remoteConnections.startConnect(); + } catch (Exception e) { + logger.error("error ", e); - remoteCtx.writeAndFlush(out); - } - } + throw e; } - } else { - // 发送到指定远端节点 - logger.debug( - "topic send to {}:{}", - ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(), - ((SocketChannel) ctx.channel()).remoteAddress().getPort()); - - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); - } - } catch (Exception e) { - logger.error("error ", e); } - } - - public void onLocalMessage(ChannelHandlerContext ctx, Message message) { - try { - logger.debug("sdk request: " + message.getSeq()); - ChannelHandlerContext remoteCtx = null; - - ConnectionPair pair = seq2Connections.get(message.getSeq()); - - if (pair != null) { - // 已有这个seq,发往远端的响应 - logger.debug("seq existed"); - - // 发送到远端的响应 - remoteCtx = pair.remoteConnection; - - if (message.getType() != 0x31) { - pair.localConnection = ctx; - } + public void broadcastTopic() { + broadcastTopic(null); + } - ByteBuf out = remoteCtx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - logger.debug( - "msg send to:{}:{}", - ((SocketChannel) remoteCtx.channel()).remoteAddress().getAddress().getHostAddress(), - ((SocketChannel) remoteCtx.channel()).remoteAddress().getPort()); - remoteCtx.writeAndFlush(out); - } else { - pair = new ConnectionPair(); - pair.localConnection = ctx; - pair.setServer(this); - pair.setMessage(message); - - // 没有这个seq,可能是新发请求或者新收到的push - // 本地发往远程的消息,如果是链上链下,需要按给定的nodeID发 - if (message.getType() == 0x20 || message.getType() == 0x21) { - // 获取nodeID - logger.debug("channel message v1"); - if (message.getData().length < 256) { - logger.error( - "wrong channel message, length less than 256:{}", message.getData().length); - } - - // 获取nodeID对应的连接,检查可用性 - String nodeID = new String(message.getData(), 128, 128); - - logger.debug("forward:{}", nodeID, message.getData()); - for (ConnectionInfo conn : remoteConnections.getConnections()) { - if (conn.getNodeID().equals(nodeID)) { - remoteCtx = - remoteConnections.getNetworkConnectionByHost(conn.getHost(), conn.getPort()); - pair.remoteConnection = remoteCtx; - - break; + public void broadcastTopic(ChannelHandlerContext ctx) { + try { + Message message = new Message(); + message.setResult(0); + message.setType((short) 0x32); // topic设置topic消息0x32 + message.setSeq(UUID.randomUUID().toString().replaceAll("-", "")); + + // 综合所有的topics + Set allTopics = new HashSet(); + for (ConnectionInfo connectionInfo : localConnections.getConnections()) { + // 有效的连接,才增加到全局topic + ChannelHandlerContext localCtx = + localConnections.getNetworkConnectionByHost( + connectionInfo.getHost(), connectionInfo.getPort()); + + if (localCtx != null && localCtx.channel().isActive()) { + logger.debug( + "node:{}:{} follow topics: {}", + connectionInfo.getHost(), + connectionInfo.getPort(), + connectionInfo.getTopics()); + allTopics.addAll(connectionInfo.getTopics()); + } } - } - - if (remoteCtx == null || !remoteCtx.channel().isActive()) { - // 找不到连接,错误 - logger.error("connect exception,error 99"); - if (message.getType() == 0x20 || message.getType() == 0x21) { - message.setType((short) 0x21); + message.setData(objectMapper.writeValueAsBytes(allTopics.toArray())); + + logger.debug("all topics: {}", new String(message.getData())); + + if (ctx == null) { + // 广播到所有远端节点 + for (String key : remoteConnections.getNetworkConnections().keySet()) { + ChannelHandlerContext remoteCtx = + remoteConnections.getNetworkConnections().get(key); + + if (remoteCtx != null && remoteCtx.channel().isActive()) { + ByteBuf out = remoteCtx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + if (remoteCtx != null && remoteCtx.channel().isActive()) { + logger.debug( + "send topic {}:{}", + ((SocketChannel) remoteCtx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) remoteCtx.channel()) + .remoteAddress() + .getPort()); + + remoteCtx.writeAndFlush(out); + } + } + } } else { - message.setType((short) 0x31); + // 发送到指定远端节点 + logger.debug( + "topic send to {}:{}", + ((SocketChannel) ctx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) ctx.channel()).remoteAddress().getPort()); + + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); } + } catch (Exception e) { + logger.error("error ", e); + } + } - message.setResult(99); - - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); - - ctx.writeAndFlush(out); + public void onLocalMessage(ChannelHandlerContext ctx, Message message) { + try { + logger.debug("sdk request: " + message.getSeq()); - return; - } + ChannelHandlerContext remoteCtx = null; - ByteBuf out = remoteCtx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); + ConnectionPair pair = seq2Connections.get(message.getSeq()); - logger.debug( - "send to:{}:{}", - ((SocketChannel) remoteCtx.channel()).remoteAddress().getAddress().getHostAddress(), - ((SocketChannel) remoteCtx.channel()).remoteAddress().getPort()); - remoteCtx.writeAndFlush(out); - pair.init(); - } else { - logger.debug("other type message,ConnectionPair"); + if (pair != null) { + // 已有这个seq,发往远端的响应 + logger.debug("seq existed"); - pair.setRemoteChannelConnections(remoteConnections); + // 发送到远端的响应 + remoteCtx = pair.remoteConnection; - List remoteConnectionInfos = new ArrayList(); - remoteConnectionInfos.addAll(remoteConnections.getConnections()); - pair.setRemoteConnectionInfos(remoteConnectionInfos); + if (message.getType() != 0x31) { + pair.localConnection = ctx; + } - seq2Connections.put(message.getSeq(), pair); + ByteBuf out = remoteCtx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); - pair.init(); - pair.retrySendRemoteMessage(); + logger.debug( + "msg send to:{}:{}", + ((SocketChannel) remoteCtx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) remoteCtx.channel()).remoteAddress().getPort()); + remoteCtx.writeAndFlush(out); + } else { + pair = new ConnectionPair(); + pair.localConnection = ctx; + pair.setServer(this); + pair.setMessage(message); + + // 没有这个seq,可能是新发请求或者新收到的push + // 本地发往远程的消息,如果是链上链下,需要按给定的nodeID发 + if (message.getType() == 0x20 || message.getType() == 0x21) { + // 获取nodeID + logger.debug("channel message v1"); + if (message.getData().length < 256) { + logger.error( + "wrong channel message, length less than 256:{}", + message.getData().length); + } + + // 获取nodeID对应的连接,检查可用性 + String nodeID = new String(message.getData(), 128, 128); + + logger.debug("forward:{}", nodeID, message.getData()); + for (ConnectionInfo conn : remoteConnections.getConnections()) { + if (conn.getNodeID().equals(nodeID)) { + remoteCtx = + remoteConnections.getNetworkConnectionByHost( + conn.getHost(), conn.getPort()); + pair.remoteConnection = remoteCtx; + + break; + } + } + + if (remoteCtx == null || !remoteCtx.channel().isActive()) { + // 找不到连接,错误 + logger.error("connect exception,error 99"); + + if (message.getType() == 0x20 || message.getType() == 0x21) { + message.setType((short) 0x21); + } else { + message.setType((short) 0x31); + } + + message.setResult(99); + + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); + + return; + } + + ByteBuf out = remoteCtx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + logger.debug( + "send to:{}:{}", + ((SocketChannel) remoteCtx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) remoteCtx.channel()).remoteAddress().getPort()); + remoteCtx.writeAndFlush(out); + pair.init(); + } else { + logger.debug("other type message,ConnectionPair"); + + pair.setRemoteChannelConnections(remoteConnections); + + List remoteConnectionInfos = new ArrayList(); + remoteConnectionInfos.addAll(remoteConnections.getConnections()); + pair.setRemoteConnectionInfos(remoteConnectionInfos); + + seq2Connections.put(message.getSeq(), pair); + + pair.init(); + pair.retrySendRemoteMessage(); + } + } + } catch (Exception e) { + logger.error("error ", e); } - } - } catch (Exception e) { - logger.error("error ", e); } - } - public void onRemoteMessage(ChannelHandlerContext ctx, Message message) { - try { - logger.debug("processing : " + message.getSeq()); + public void onRemoteMessage(ChannelHandlerContext ctx, Message message) { + try { + logger.debug("processing : " + message.getSeq()); + + ChannelHandlerContext localCtx = null; + + ConnectionPair pair = seq2Connections.get(message.getSeq()); + + if (message.getType() == 0x30) { + // 链上链下二期,需要找到关注该topic的连接 + Short length = (short) message.getData()[0]; + String topic = new String(message.getData(), 1, length - 1); + + Set topicCtxs = new HashSet(); + for (ConnectionInfo connectionInfo : localConnections.getConnections()) { + if (connectionInfo.getTopics().contains(topic)) { + ChannelHandlerContext topicCtx = + localConnections.getNetworkConnectionByHost( + connectionInfo.getHost(), connectionInfo.getPort()); + + if (topicCtx != null && topicCtx.channel().isActive()) { + topicCtxs.add(topicCtx); + } + } + } + + logger.debug("send topic:{} sum{} follow topic", topic, topicCtxs.size()); + + if (topicCtxs.isEmpty()) { + // 找不到连接,错误 + logger.error("connection not found,error 99"); + + message.setType((short) 0x31); + message.setResult(99); + + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); + + ctx.writeAndFlush(out); + + return; + } + + // 随机下发 + Random random = new SecureRandom(); + Integer index = random.nextInt(topicCtxs.size()); + ChannelHandlerContext target = (ChannelHandlerContext) topicCtxs.toArray()[index]; + + logger.debug( + "send to {}:{}", + ((SocketChannel) target.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) target.channel()).remoteAddress().getPort()); + + localCtx = target; + + if (pair == null) { + pair = new ConnectionPair(); + pair.localConnection = localCtx; + pair.remoteConnection = ctx; + pair.setServer(this); + pair.setMessage(message); + + seq2Connections.put(message.getSeq(), pair); + pair.init(); + } else { + pair.remoteConnection = ctx; + } + } else { + if (pair != null) { + // 已有这个seq,可能是发送响应或者收到回包消息 + logger.debug("seq existed"); - ChannelHandlerContext localCtx = null; + // 收到来自远端的回包 + localCtx = pair.localConnection; - ConnectionPair pair = seq2Connections.get(message.getSeq()); + if (message.getResult() != 0 && message.getType() == 0x31) { + // 链上链下二期错误时,执行retry + logger.error("endpoint error:{},retry", message.getResult()); - if (message.getType() == 0x30) { - // 链上链下二期,需要找到关注该topic的连接 - Short length = (short) message.getData()[0]; - String topic = new String(message.getData(), 1, length - 1); + pair.retrySendRemoteMessage(); + return; + } - Set topicCtxs = new HashSet(); - for (ConnectionInfo connectionInfo : localConnections.getConnections()) { - if (connectionInfo.getTopics().contains(topic)) { - ChannelHandlerContext topicCtx = - localConnections.getNetworkConnectionByHost( - connectionInfo.getHost(), connectionInfo.getPort()); + pair.remoteConnection = ctx; + } else { + // 没有这个seq,可能是新发请求或者新收到的push - if (topicCtx != null && topicCtx.channel().isActive()) { - topicCtxs.add(topicCtx); + // 其他消息(链上链下一期),随机发 + localCtx = localConnections.randomNetworkConnection(null); + } } - } - } - - logger.debug("send topic:{} sum{} follow topic", topic, topicCtxs.size()); - - if (topicCtxs.isEmpty()) { - // 找不到连接,错误 - logger.error("connection not found,error 99"); - - message.setType((short) 0x31); - message.setResult(99); - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); + if (localCtx == null || !localCtx.channel().isActive()) { + // 找不到连接,错误 + logger.error("connect unavailable,error 99"); - ctx.writeAndFlush(out); + if (message.getType() == 0x20 || message.getType() == 0x21) { + message.setType((short) 0x21); + } else { + message.setType((short) 0x31); + } - return; - } - - // 随机下发 - Random random = new SecureRandom(); - Integer index = random.nextInt(topicCtxs.size()); - ChannelHandlerContext target = (ChannelHandlerContext) topicCtxs.toArray()[index]; - - logger.debug( - "send to {}:{}", - ((SocketChannel) target.channel()).remoteAddress().getAddress().getHostAddress(), - ((SocketChannel) target.channel()).remoteAddress().getPort()); - - localCtx = target; - - if (pair == null) { - pair = new ConnectionPair(); - pair.localConnection = localCtx; - pair.remoteConnection = ctx; - pair.setServer(this); - pair.setMessage(message); - - seq2Connections.put(message.getSeq(), pair); - pair.init(); - } else { - pair.remoteConnection = ctx; - } - } else { - if (pair != null) { - // 已有这个seq,可能是发送响应或者收到回包消息 - logger.debug("seq existed"); + message.setResult(99); - // 收到来自远端的回包 - localCtx = pair.localConnection; + ByteBuf out = ctx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); - if (message.getResult() != 0 && message.getType() == 0x31) { - // 链上链下二期错误时,执行retry - logger.error("endpoint error:{},retry", message.getResult()); + ctx.writeAndFlush(out); - pair.retrySendRemoteMessage(); - return; - } + return; + } - pair.remoteConnection = ctx; - } else { - // 没有这个seq,可能是新发请求或者新收到的push + ByteBuf out = localCtx.alloc().buffer(); + message.writeHeader(out); + message.writeExtra(out); - // 其他消息(链上链下一期),随机发 - localCtx = localConnections.randomNetworkConnection(); + logger.debug( + "send to:{}:{}", + ((SocketChannel) localCtx.channel()) + .remoteAddress() + .getAddress() + .getHostAddress(), + ((SocketChannel) localCtx.channel()).remoteAddress().getPort()); + localCtx.writeAndFlush(out); + } catch (Exception e) { + logger.error("error ", e); } - } - - if (localCtx == null || !localCtx.channel().isActive()) { - // 找不到连接,错误 - logger.error("connect unavailable,error 99"); + } - if (message.getType() == 0x20 || message.getType() == 0x21) { - message.setType((short) 0x21); - } else { - message.setType((short) 0x31); + public void onHeartBeat(ChannelHandlerContext ctx, Message message) { + String content = "1"; + try { + content = new String(message.getData(), "utf-8"); + } catch (UnsupportedEncodingException e) { + logger.error("unexpected heartbeat "); + } catch (Exception e) { + logger.error("heartbeat error"); } - message.setResult(99); + if (content.equals("0")) { + Message response = new Message(); - ByteBuf out = ctx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); + response.setSeq(message.getSeq()); + response.setResult(0); + response.setType((short) 0x13); + response.setData("1".getBytes()); - ctx.writeAndFlush(out); - - return; - } - - ByteBuf out = localCtx.alloc().buffer(); - message.writeHeader(out); - message.writeExtra(out); + ByteBuf out = ctx.alloc().buffer(); + response.writeHeader(out); + response.writeExtra(out); - logger.debug( - "send to:{}:{}", - ((SocketChannel) localCtx.channel()).remoteAddress().getAddress().getHostAddress(), - ((SocketChannel) localCtx.channel()).remoteAddress().getPort()); - localCtx.writeAndFlush(out); - } catch (Exception e) { - logger.error("error ", e); - } - } - - public void onHeartBeat(ChannelHandlerContext ctx, Message message) { - String content = "1"; - try { - content = new String(message.getData(), "utf-8"); - } catch (UnsupportedEncodingException e) { - logger.error("unexpected heartbeat "); - } catch (Exception e) { - logger.error("heartbeat error"); + ctx.writeAndFlush(out); + } else if (content.equals("1")) { + } } - if (content.equals("0")) { - Message response = new Message(); + public void onTopic(ChannelHandlerContext ctx, Message message) { + logger.debug("SDK topics message: {} {}", message.getSeq(), new String(message.getData())); + String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); + Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); // + ConnectionInfo info = localConnections.getConnectionInfo(host, port); - response.setSeq(message.getSeq()); - response.setResult(0); - response.setType((short) 0x13); - response.setData("1".getBytes()); + if (info != null) { + try { + List topics = objectMapper.readValue(message.getData(), List.class); - ByteBuf out = ctx.alloc().buffer(); - response.writeHeader(out); - response.writeExtra(out); + info.setTopics(topics); - ctx.writeAndFlush(out); - } else if (content.equals("1")) { + broadcastTopic(); + } catch (Exception e) { + logger.error("parse topic error", e); + } + } } - } - public void onTopic(ChannelHandlerContext ctx, Message message) { - logger.debug("SDK topics message: {} {}", message.getSeq(), new String(message.getData())); - String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress(); - Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort(); // - ConnectionInfo info = localConnections.getConnectionInfo(host, port); + public ThreadPoolTaskExecutor getThreadPool() { + return threadPool; + } - if (info != null) { - try { - List topics = objectMapper.readValue(message.getData(), List.class); + public void setThreadPool(ThreadPoolTaskExecutor threadPool) { + this.threadPool = threadPool; + } - info.setTopics(topics); + // private String orgID; + private ChannelConnections localConnections = new ChannelConnections(); + private ChannelConnections remoteConnections; + private Map seq2Connections = + new ConcurrentHashMap(); + private Integer bindPort = 8830; + private ObjectMapper objectMapper = new ObjectMapper(); + private Timer timeoutHandler = new HashedWheelTimer(); - broadcastTopic(); - } catch (Exception e) { - logger.error("parse topic error", e); - } - } - } - - public ThreadPoolTaskExecutor getThreadPool() { - return threadPool; - } - - public void setThreadPool(ThreadPoolTaskExecutor threadPool) { - this.threadPool = threadPool; - } - - // private String orgID; - private ChannelConnections localConnections = new ChannelConnections(); - private ChannelConnections remoteConnections; - private Map seq2Connections = - new ConcurrentHashMap(); - private Integer bindPort = 8830; - private ObjectMapper objectMapper = new ObjectMapper(); - private Timer timeoutHandler = new HashedWheelTimer(); - - private ThreadPoolTaskExecutor threadPool; + private ThreadPoolTaskExecutor threadPool; } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/EventEncoder.java b/src/main/java/org/fisco/bcos/web3j/abi/EventEncoder.java index 4280c0b20..d0d18206d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/EventEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/EventEncoder.java @@ -13,31 +13,31 @@ */ public class EventEncoder { - private EventEncoder() {} + private EventEncoder() {} - public static String encode(Event event) { + public static String encode(Event event) { - String methodSignature = buildMethodSignature(event.getName(), event.getParameters()); + String methodSignature = buildMethodSignature(event.getName(), event.getParameters()); - return buildEventSignature(methodSignature); - } + return buildEventSignature(methodSignature); + } - static String buildMethodSignature( - String methodName, List> parameters) { + static String buildMethodSignature( + String methodName, List> parameters) { - StringBuilder result = new StringBuilder(); - result.append(methodName); - result.append("("); - String params = - parameters.stream().map(p -> Utils.getTypeName(p)).collect(Collectors.joining(",")); - result.append(params); - result.append(")"); - return result.toString(); - } + StringBuilder result = new StringBuilder(); + result.append(methodName); + result.append("("); + String params = + parameters.stream().map(p -> Utils.getTypeName(p)).collect(Collectors.joining(",")); + result.append(params); + result.append(")"); + return result.toString(); + } - public static String buildEventSignature(String methodSignature) { - byte[] input = methodSignature.getBytes(); - byte[] hash = Hash.sha3(input); - return Numeric.toHexString(hash); - } + public static String buildEventSignature(String methodSignature) { + byte[] input = methodSignature.getBytes(); + byte[] hash = Hash.sha3(input); + return Numeric.toHexString(hash); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/EventValues.java b/src/main/java/org/fisco/bcos/web3j/abi/EventValues.java index bb1b46476..8c40bca85 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/EventValues.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/EventValues.java @@ -5,19 +5,19 @@ /** Persisted solidity event parameters. */ public class EventValues { - private final List indexedValues; - private final List nonIndexedValues; + private final List indexedValues; + private final List nonIndexedValues; - public EventValues(List indexedValues, List nonIndexedValues) { - this.indexedValues = indexedValues; - this.nonIndexedValues = nonIndexedValues; - } + public EventValues(List indexedValues, List nonIndexedValues) { + this.indexedValues = indexedValues; + this.nonIndexedValues = nonIndexedValues; + } - public List getIndexedValues() { - return indexedValues; - } + public List getIndexedValues() { + return indexedValues; + } - public List getNonIndexedValues() { - return nonIndexedValues; - } + public List getNonIndexedValues() { + return nonIndexedValues; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/FunctionEncoder.java b/src/main/java/org/fisco/bcos/web3j/abi/FunctionEncoder.java index 359f53cf5..6399ca8cc 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/FunctionEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/FunctionEncoder.java @@ -16,71 +16,72 @@ */ public class FunctionEncoder { - private FunctionEncoder() {} + private FunctionEncoder() {} - public static String encode(Function function) { - List parameters = function.getInputParameters(); + public static String encode(Function function) { + List parameters = function.getInputParameters(); - String methodSignature = buildMethodSignature(function.getName(), parameters); - String methodId = buildMethodId(methodSignature); + String methodSignature = buildMethodSignature(function.getName(), parameters); + String methodId = buildMethodId(methodSignature); - StringBuilder result = new StringBuilder(); - result.append(methodId); + StringBuilder result = new StringBuilder(); + result.append(methodId); - return encodeParameters(parameters, result); - } + return encodeParameters(parameters, result); + } - public static String encodeConstructor(List parameters) { - return encodeParameters(parameters, new StringBuilder()); - } + public static String encodeConstructor(List parameters) { + return encodeParameters(parameters, new StringBuilder()); + } - private static String encodeParameters(List parameters, StringBuilder result) { - int dynamicDataOffset = getLength(parameters) * Type.MAX_BYTE_LENGTH; - StringBuilder dynamicData = new StringBuilder(); + private static String encodeParameters(List parameters, StringBuilder result) { + int dynamicDataOffset = getLength(parameters) * Type.MAX_BYTE_LENGTH; + StringBuilder dynamicData = new StringBuilder(); - for (Type parameter : parameters) { - String encodedValue = TypeEncoder.encode(parameter); + for (Type parameter : parameters) { + String encodedValue = TypeEncoder.encode(parameter); - if (TypeEncoder.isDynamic(parameter)) { - String encodedDataOffset = - TypeEncoder.encodeNumeric(new Uint(BigInteger.valueOf(dynamicDataOffset))); - result.append(encodedDataOffset); - dynamicData.append(encodedValue); - dynamicDataOffset += encodedValue.length() >> 1; - } else { - result.append(encodedValue); - } - } - result.append(dynamicData); + if (TypeEncoder.isDynamic(parameter)) { + String encodedDataOffset = + TypeEncoder.encodeNumeric(new Uint(BigInteger.valueOf(dynamicDataOffset))); + result.append(encodedDataOffset); + dynamicData.append(encodedValue); + dynamicDataOffset += encodedValue.length() >> 1; + } else { + result.append(encodedValue); + } + } + result.append(dynamicData); - return result.toString(); - } + return result.toString(); + } - private static int getLength(List parameters) { - int count = 0; - for (Type type : parameters) { - if (type instanceof StaticArray) { - count += ((StaticArray) type).getValue().size(); - } else { - count++; - } + private static int getLength(List parameters) { + int count = 0; + for (Type type : parameters) { + if (type instanceof StaticArray) { + count += ((StaticArray) type).getValue().size(); + } else { + count++; + } + } + return count; } - return count; - } - static String buildMethodSignature(String methodName, List parameters) { - StringBuilder result = new StringBuilder(); - result.append(methodName); - result.append("("); - String params = parameters.stream().map(Type::getTypeAsString).collect(Collectors.joining(",")); - result.append(params); - result.append(")"); - return result.toString(); - } + static String buildMethodSignature(String methodName, List parameters) { + StringBuilder result = new StringBuilder(); + result.append(methodName); + result.append("("); + String params = + parameters.stream().map(Type::getTypeAsString).collect(Collectors.joining(",")); + result.append(params); + result.append(")"); + return result.toString(); + } - static String buildMethodId(String methodSignature) { - byte[] input = methodSignature.getBytes(); - byte[] hash = Hash.sha3(input); - return Numeric.toHexString(hash).substring(0, 10); - } + static String buildMethodId(String methodSignature) { + byte[] input = methodSignature.getBytes(); + byte[] hash = Hash.sha3(input); + return Numeric.toHexString(hash).substring(0, 10); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoder.java b/src/main/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoder.java index 332e5cfa8..492fe301e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoder.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoder.java @@ -18,115 +18,122 @@ /** Decodes values returned by function or event calls. */ public class FunctionReturnDecoder { - private FunctionReturnDecoder() {} + private FunctionReturnDecoder() {} - /** - * Decode ABI encoded return values from smart contract function call. - * - * @param rawInput ABI encoded input - * @param outputParameters list of return types as {@link TypeReference} - * @return {@link List} of values returned by function, {@link Collections#emptyList()} if invalid - * response - */ - public static List decode(String rawInput, List> outputParameters) { - String input = Numeric.cleanHexPrefix(rawInput); + /** + * Decode ABI encoded return values from smart contract function call. + * + * @param rawInput ABI encoded input + * @param outputParameters list of return types as {@link TypeReference} + * @return {@link List} of values returned by function, {@link Collections#emptyList()} if + * invalid response + */ + public static List decode(String rawInput, List> outputParameters) { + String input = Numeric.cleanHexPrefix(rawInput); - if (Strings.isEmpty(input)) { - return Collections.emptyList(); - } else { - return build(input, outputParameters); + if (Strings.isEmpty(input)) { + return Collections.emptyList(); + } else { + return build(input, outputParameters); + } } - } - /** - * Decodes an indexed parameter associated with an event. Indexed parameters are individually - * encoded, unlike non-indexed parameters which are encoded as per ABI-encoded function parameters - * and return values. - * - *

If any of the following types are indexed, the Keccak-256 hashes of the values are returned - * instead. These are returned as a bytes32 value. - * - *

    - *
  • Arrays - *
  • Strings - *
  • Bytes - *
- * - *

See the Solidity - * documentation for further information. - * - * @param rawInput ABI encoded input - * @param typeReference of expected result type - * @param type of TypeReference - * @return the decode value - */ - @SuppressWarnings("unchecked") - public static Type decodeIndexedValue( - String rawInput, TypeReference typeReference) { - String input = Numeric.cleanHexPrefix(rawInput); + /** + * Decodes an indexed parameter associated with an event. Indexed parameters are individually + * encoded, unlike non-indexed parameters which are encoded as per ABI-encoded function + * parameters and return values. + * + *

If any of the following types are indexed, the Keccak-256 hashes of the values are + * returned instead. These are returned as a bytes32 value. + * + *

    + *
  • Arrays + *
  • Strings + *
  • Bytes + *
+ * + *

See the Solidity + * documentation for further information. + * + * @param rawInput ABI encoded input + * @param typeReference of expected result type + * @param type of TypeReference + * @return the decode value + */ + @SuppressWarnings("unchecked") + public static Type decodeIndexedValue( + String rawInput, TypeReference typeReference) { + String input = Numeric.cleanHexPrefix(rawInput); - try { - Class type = typeReference.getClassType(); + try { + Class type = typeReference.getClassType(); - if (Bytes.class.isAssignableFrom(type)) { - return TypeDecoder.decodeBytes(input, (Class) Class.forName(type.getName())); - } else if (Array.class.isAssignableFrom(type) - || BytesType.class.isAssignableFrom(type) - || Utf8String.class.isAssignableFrom(type)) { - return TypeDecoder.decodeBytes(input, Bytes32.class); - } else { - return TypeDecoder.decode(input, type); - } - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException("Invalid class reference provided", e); + if (Bytes.class.isAssignableFrom(type)) { + return TypeDecoder.decodeBytes(input, (Class) Class.forName(type.getName())); + } else if (Array.class.isAssignableFrom(type) + || BytesType.class.isAssignableFrom(type) + || Utf8String.class.isAssignableFrom(type)) { + return TypeDecoder.decodeBytes(input, Bytes32.class); + } else { + return TypeDecoder.decode(input, type); + } + } catch (ClassNotFoundException e) { + throw new UnsupportedOperationException("Invalid class reference provided", e); + } } - } - private static List build(String input, List> outputParameters) { - List results = new ArrayList<>(outputParameters.size()); + private static List build(String input, List> outputParameters) { + List results = new ArrayList<>(outputParameters.size()); - int offset = 0; - for (TypeReference typeReference : outputParameters) { - try { - @SuppressWarnings("unchecked") - Class type = (Class) typeReference.getClassType(); + int offset = 0; + for (TypeReference typeReference : outputParameters) { + try { + @SuppressWarnings("unchecked") + Class type = (Class) typeReference.getClassType(); - int hexStringDataOffset = getDataOffset(input, offset, type); + int hexStringDataOffset = getDataOffset(input, offset, type); - Type result; - if (DynamicArray.class.isAssignableFrom(type)) { - result = TypeDecoder.decodeDynamicArray(input, hexStringDataOffset, typeReference); - offset += TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; - } else if (typeReference instanceof TypeReference.StaticArrayTypeReference) { - int length = ((TypeReference.StaticArrayTypeReference) typeReference).getSize(); - result = TypeDecoder.decodeStaticArray(input, hexStringDataOffset, typeReference, length); - offset += length * TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; - } else if (StaticArray.class.isAssignableFrom(type)) { - int length = - Integer.parseInt( - type.getSimpleName().substring(StaticArray.class.getSimpleName().length())); - result = TypeDecoder.decodeStaticArray(input, hexStringDataOffset, typeReference, length); - offset += length * TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; - } else { - result = TypeDecoder.decode(input, hexStringDataOffset, type); - offset += TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; - } - results.add(result); + Type result; + if (DynamicArray.class.isAssignableFrom(type)) { + result = + TypeDecoder.decodeDynamicArray( + input, hexStringDataOffset, typeReference); + offset += TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; + } else if (typeReference instanceof TypeReference.StaticArrayTypeReference) { + int length = ((TypeReference.StaticArrayTypeReference) typeReference).getSize(); + result = + TypeDecoder.decodeStaticArray( + input, hexStringDataOffset, typeReference, length); + offset += length * TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; + } else if (StaticArray.class.isAssignableFrom(type)) { + int length = + Integer.parseInt( + type.getSimpleName() + .substring(StaticArray.class.getSimpleName().length())); + result = + TypeDecoder.decodeStaticArray( + input, hexStringDataOffset, typeReference, length); + offset += length * TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; + } else { + result = TypeDecoder.decode(input, hexStringDataOffset, type); + offset += TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING; + } + results.add(result); - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException("Invalid class reference provided", e); - } + } catch (ClassNotFoundException e) { + throw new UnsupportedOperationException("Invalid class reference provided", e); + } + } + return results; } - return results; - } - private static int getDataOffset(String input, int offset, Class type) { - if (DynamicBytes.class.isAssignableFrom(type) - || Utf8String.class.isAssignableFrom(type) - || DynamicArray.class.isAssignableFrom(type)) { - return TypeDecoder.decodeUintAsInt(input, offset) << 1; - } else { - return offset; + private static int getDataOffset(String input, int offset, Class type) { + if (DynamicBytes.class.isAssignableFrom(type) + || Utf8String.class.isAssignableFrom(type) + || DynamicArray.class.isAssignableFrom(type)) { + return TypeDecoder.decodeUintAsInt(input, offset) << 1; + } else { + return offset; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/TypeDecoder.java b/src/main/java/org/fisco/bcos/web3j/abi/TypeDecoder.java index 7520121e7..f98f24d20 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/TypeDecoder.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/TypeDecoder.java @@ -33,250 +33,256 @@ */ public class TypeDecoder { - static final int MAX_BYTE_LENGTH_FOR_HEX_STRING = Type.MAX_BYTE_LENGTH << 1; - - static int getSingleElementLength(String input, int offset, Class type) { - if (input.length() == offset) { - return 0; - } else if (DynamicBytes.class.isAssignableFrom(type) - || Utf8String.class.isAssignableFrom(type)) { - // length field + data value - return (decodeUintAsInt(input, offset) / Type.MAX_BYTE_LENGTH) + 2; - } else { - return 1; + static final int MAX_BYTE_LENGTH_FOR_HEX_STRING = Type.MAX_BYTE_LENGTH << 1; + + static int getSingleElementLength(String input, int offset, Class type) { + if (input.length() == offset) { + return 0; + } else if (DynamicBytes.class.isAssignableFrom(type) + || Utf8String.class.isAssignableFrom(type)) { + // length field + data value + return (decodeUintAsInt(input, offset) / Type.MAX_BYTE_LENGTH) + 2; + } else { + return 1; + } } - } - - @SuppressWarnings("unchecked") - static T decode(String input, int offset, Class type) { - if (NumericType.class.isAssignableFrom(type)) { - return (T) decodeNumeric(input.substring(offset), (Class) type); - } else if (Address.class.isAssignableFrom(type)) { - return (T) decodeAddress(input.substring(offset)); - } else if (Bool.class.isAssignableFrom(type)) { - return (T) decodeBool(input, offset); - } else if (Bytes.class.isAssignableFrom(type)) { - return (T) decodeBytes(input, offset, (Class) type); - } else if (DynamicBytes.class.isAssignableFrom(type)) { - return (T) decodeDynamicBytes(input, offset); - } else if (Utf8String.class.isAssignableFrom(type)) { - return (T) decodeUtf8String(input, offset); - } else if (Array.class.isAssignableFrom(type)) { - throw new UnsupportedOperationException("Array types must be wrapped in a TypeReference"); - } else { - throw new UnsupportedOperationException("Type cannot be encoded: " + type.getClass()); + + @SuppressWarnings("unchecked") + static T decode(String input, int offset, Class type) { + if (NumericType.class.isAssignableFrom(type)) { + return (T) decodeNumeric(input.substring(offset), (Class) type); + } else if (Address.class.isAssignableFrom(type)) { + return (T) decodeAddress(input.substring(offset)); + } else if (Bool.class.isAssignableFrom(type)) { + return (T) decodeBool(input, offset); + } else if (Bytes.class.isAssignableFrom(type)) { + return (T) decodeBytes(input, offset, (Class) type); + } else if (DynamicBytes.class.isAssignableFrom(type)) { + return (T) decodeDynamicBytes(input, offset); + } else if (Utf8String.class.isAssignableFrom(type)) { + return (T) decodeUtf8String(input, offset); + } else if (Array.class.isAssignableFrom(type)) { + throw new UnsupportedOperationException( + "Array types must be wrapped in a TypeReference"); + } else { + throw new UnsupportedOperationException("Type cannot be encoded: " + type.getClass()); + } } - } - - public static T decode( - String input, int offset, TypeReference typeReference) { - Class cls = ((ParameterizedType) typeReference.getType()).getRawType().getClass(); - if (StaticArray.class.isAssignableFrom(cls)) { - return decodeStaticArray(input, offset, typeReference, 1); - } else if (DynamicArray.class.isAssignableFrom(cls)) { - return decodeDynamicArray(input, offset, typeReference); - } else { - throw new UnsupportedOperationException( - "Unsupported TypeReference: " - + cls.getName() - + ", only Array types can be passed as TypeReferences"); + + public static T decode( + String input, int offset, TypeReference typeReference) { + Class cls = ((ParameterizedType) typeReference.getType()).getRawType().getClass(); + if (StaticArray.class.isAssignableFrom(cls)) { + return decodeStaticArray(input, offset, typeReference, 1); + } else if (DynamicArray.class.isAssignableFrom(cls)) { + return decodeDynamicArray(input, offset, typeReference); + } else { + throw new UnsupportedOperationException( + "Unsupported TypeReference: " + + cls.getName() + + ", only Array types can be passed as TypeReferences"); + } } - } - static T decode(String input, Class type) { - return decode(input, 0, type); - } + static T decode(String input, Class type) { + return decode(input, 0, type); + } - static Address decodeAddress(String input) { - return new Address(decodeNumeric(input, Uint160.class)); - } + static Address decodeAddress(String input) { + return new Address(decodeNumeric(input, Uint160.class)); + } - static T decodeNumeric(String input, Class type) { - try { - byte[] inputByteArray = Numeric.hexStringToByteArray(input); - int typeLengthAsBytes = getTypeLengthInBytes(type); + static T decodeNumeric(String input, Class type) { + try { + byte[] inputByteArray = Numeric.hexStringToByteArray(input); + int typeLengthAsBytes = getTypeLengthInBytes(type); - byte[] resultByteArray = new byte[typeLengthAsBytes + 1]; + byte[] resultByteArray = new byte[typeLengthAsBytes + 1]; - if (Int.class.isAssignableFrom(type) || Fixed.class.isAssignableFrom(type)) { - resultByteArray[0] = inputByteArray[0]; // take MSB as sign bit - } + if (Int.class.isAssignableFrom(type) || Fixed.class.isAssignableFrom(type)) { + resultByteArray[0] = inputByteArray[0]; // take MSB as sign bit + } - int valueOffset = Type.MAX_BYTE_LENGTH - typeLengthAsBytes; - System.arraycopy(inputByteArray, valueOffset, resultByteArray, 1, typeLengthAsBytes); + int valueOffset = Type.MAX_BYTE_LENGTH - typeLengthAsBytes; + System.arraycopy(inputByteArray, valueOffset, resultByteArray, 1, typeLengthAsBytes); - BigInteger numericValue = new BigInteger(resultByteArray); - return type.getConstructor(BigInteger.class).newInstance(numericValue); + BigInteger numericValue = new BigInteger(resultByteArray); + return type.getConstructor(BigInteger.class).newInstance(numericValue); - } catch (NoSuchMethodException - | SecurityException - | InstantiationException - | IllegalAccessException - | IllegalArgumentException - | InvocationTargetException e) { - throw new UnsupportedOperationException("Unable to create instance of " + type.getName(), e); + } catch (NoSuchMethodException + | SecurityException + | InstantiationException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { + throw new UnsupportedOperationException( + "Unable to create instance of " + type.getName(), e); + } } - } - - static int getTypeLengthInBytes(Class type) { - return getTypeLength(type) >> 3; // divide by 8 - } - - static int getTypeLength(Class type) { - if (IntType.class.isAssignableFrom(type)) { - String regex = "(" + Uint.class.getSimpleName() + "|" + Int.class.getSimpleName() + ")"; - String[] splitName = type.getSimpleName().split(regex); - if (splitName.length == 2) { - return Integer.parseInt(splitName[1]); - } - } else if (FixedPointType.class.isAssignableFrom(type)) { - String regex = "(" + Ufixed.class.getSimpleName() + "|" + Fixed.class.getSimpleName() + ")"; - String[] splitName = type.getSimpleName().split(regex); - if (splitName.length == 2) { - String[] bitsCounts = splitName[1].split("x"); - return Integer.parseInt(bitsCounts[0]) + Integer.parseInt(bitsCounts[1]); - } + + static int getTypeLengthInBytes(Class type) { + return getTypeLength(type) >> 3; // divide by 8 } - return Type.MAX_BIT_LENGTH; - } - - static int decodeUintAsInt(String rawInput, int offset) { - String input = rawInput.substring(offset, offset + MAX_BYTE_LENGTH_FOR_HEX_STRING); - return decode(input, 0, Uint.class).getValue().intValue(); - } - - static Bool decodeBool(String rawInput, int offset) { - String input = rawInput.substring(offset, offset + MAX_BYTE_LENGTH_FOR_HEX_STRING); - BigInteger numericValue = Numeric.toBigInt(input); - boolean value = numericValue.equals(BigInteger.ONE); - return new Bool(value); - } - - static T decodeBytes(String input, Class type) { - return decodeBytes(input, 0, type); - } - - static T decodeBytes(String input, int offset, Class type) { - try { - String simpleName = type.getSimpleName(); - String[] splitName = simpleName.split(Bytes.class.getSimpleName()); - int length = Integer.parseInt(splitName[1]); - int hexStringLength = length << 1; - - byte[] bytes = - Numeric.hexStringToByteArray(input.substring(offset, offset + hexStringLength)); - return type.getConstructor(byte[].class).newInstance(bytes); - } catch (NoSuchMethodException - | SecurityException - | InstantiationException - | IllegalAccessException - | IllegalArgumentException - | InvocationTargetException e) { - throw new UnsupportedOperationException("Unable to create instance of " + type.getName(), e); + + static int getTypeLength(Class type) { + if (IntType.class.isAssignableFrom(type)) { + String regex = "(" + Uint.class.getSimpleName() + "|" + Int.class.getSimpleName() + ")"; + String[] splitName = type.getSimpleName().split(regex); + if (splitName.length == 2) { + return Integer.parseInt(splitName[1]); + } + } else if (FixedPointType.class.isAssignableFrom(type)) { + String regex = + "(" + Ufixed.class.getSimpleName() + "|" + Fixed.class.getSimpleName() + ")"; + String[] splitName = type.getSimpleName().split(regex); + if (splitName.length == 2) { + String[] bitsCounts = splitName[1].split("x"); + return Integer.parseInt(bitsCounts[0]) + Integer.parseInt(bitsCounts[1]); + } + } + return Type.MAX_BIT_LENGTH; } - } - - static DynamicBytes decodeDynamicBytes(String input, int offset) { - int encodedLength = decodeUintAsInt(input, offset); - int hexStringEncodedLength = encodedLength << 1; - - int valueOffset = offset + MAX_BYTE_LENGTH_FOR_HEX_STRING; - - String data = input.substring(valueOffset, valueOffset + hexStringEncodedLength); - byte[] bytes = Numeric.hexStringToByteArray(data); - - return new DynamicBytes(bytes); - } - - static Utf8String decodeUtf8String(String input, int offset) { - DynamicBytes dynamicBytesResult = decodeDynamicBytes(input, offset); - byte[] bytes = dynamicBytesResult.getValue(); - - return new Utf8String(new String(bytes, StandardCharsets.UTF_8)); - } - - /** Static array length cannot be passed as a type. */ - @SuppressWarnings("unchecked") - static T decodeStaticArray( - String input, int offset, TypeReference typeReference, int length) { - - BiFunction, String, T> function = - (elements, typeName) -> { - if (elements.isEmpty()) { - throw new UnsupportedOperationException("Zero length fixed array is invalid type"); - } else { - return instantiateStaticArray(typeReference, elements); - } - }; - - return decodeArrayElements(input, offset, typeReference, length, function); - } - - @SuppressWarnings("unchecked") - private static T instantiateStaticArray( - TypeReference typeReference, List elements) { - try { - Class listClass = List.class; - return typeReference.getClassType().getConstructor(listClass).newInstance(elements); - } catch (ReflectiveOperationException e) { - //noinspection unchecked - return (T) new StaticArray<>(elements); + + static int decodeUintAsInt(String rawInput, int offset) { + String input = rawInput.substring(offset, offset + MAX_BYTE_LENGTH_FOR_HEX_STRING); + return decode(input, 0, Uint.class).getValue().intValue(); } - } - - @SuppressWarnings("unchecked") - static T decodeDynamicArray( - String input, int offset, TypeReference typeReference) { - - int length = decodeUintAsInt(input, offset); - - BiFunction, String, T> function = - (elements, typeName) -> { - if (elements.isEmpty()) { - return (T) DynamicArray.empty(typeName); - } else { - return (T) new DynamicArray<>(elements); - } - }; - - int valueOffset = offset + MAX_BYTE_LENGTH_FOR_HEX_STRING; - - return decodeArrayElements(input, valueOffset, typeReference, length, function); - } - - private static T decodeArrayElements( - String input, - int offset, - TypeReference typeReference, - int length, - BiFunction, String, T> consumer) { - - try { - Class cls = Utils.getParameterizedTypeFromArray(typeReference); - if (Array.class.isAssignableFrom(cls)) { - throw new UnsupportedOperationException( - "Arrays of arrays are not currently supported for external functions, see" - + "http://solidity.readthedocs.io/en/develop/types.html#members"); - } else { - List elements = new ArrayList<>(length); - - for (int i = 0, currOffset = offset; - i < length; - i++, - currOffset += - getSingleElementLength(input, currOffset, cls) - * MAX_BYTE_LENGTH_FOR_HEX_STRING) { - T value = decode(input, currOffset, cls); - elements.add(value); + + static Bool decodeBool(String rawInput, int offset) { + String input = rawInput.substring(offset, offset + MAX_BYTE_LENGTH_FOR_HEX_STRING); + BigInteger numericValue = Numeric.toBigInt(input); + boolean value = numericValue.equals(BigInteger.ONE); + return new Bool(value); + } + + static T decodeBytes(String input, Class type) { + return decodeBytes(input, 0, type); + } + + static T decodeBytes(String input, int offset, Class type) { + try { + String simpleName = type.getSimpleName(); + String[] splitName = simpleName.split(Bytes.class.getSimpleName()); + int length = Integer.parseInt(splitName[1]); + int hexStringLength = length << 1; + + byte[] bytes = + Numeric.hexStringToByteArray(input.substring(offset, offset + hexStringLength)); + return type.getConstructor(byte[].class).newInstance(bytes); + } catch (NoSuchMethodException + | SecurityException + | InstantiationException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { + throw new UnsupportedOperationException( + "Unable to create instance of " + type.getName(), e); } + } + + static DynamicBytes decodeDynamicBytes(String input, int offset) { + int encodedLength = decodeUintAsInt(input, offset); + int hexStringEncodedLength = encodedLength << 1; - String typeName = Utils.getSimpleTypeName(cls); + int valueOffset = offset + MAX_BYTE_LENGTH_FOR_HEX_STRING; - return consumer.apply(elements, typeName); - } - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException( - "Unable to access parameterized type " + typeReference.getType().getTypeName(), e); + String data = input.substring(valueOffset, valueOffset + hexStringEncodedLength); + byte[] bytes = Numeric.hexStringToByteArray(data); + + return new DynamicBytes(bytes); + } + + static Utf8String decodeUtf8String(String input, int offset) { + DynamicBytes dynamicBytesResult = decodeDynamicBytes(input, offset); + byte[] bytes = dynamicBytesResult.getValue(); + + return new Utf8String(new String(bytes, StandardCharsets.UTF_8)); + } + + /** Static array length cannot be passed as a type. */ + @SuppressWarnings("unchecked") + static T decodeStaticArray( + String input, int offset, TypeReference typeReference, int length) { + + BiFunction, String, T> function = + (elements, typeName) -> { + if (elements.isEmpty()) { + throw new UnsupportedOperationException( + "Zero length fixed array is invalid type"); + } else { + return instantiateStaticArray(typeReference, elements); + } + }; + + return decodeArrayElements(input, offset, typeReference, length, function); + } + + @SuppressWarnings("unchecked") + private static T instantiateStaticArray( + TypeReference typeReference, List elements) { + try { + Class listClass = List.class; + return typeReference.getClassType().getConstructor(listClass).newInstance(elements); + } catch (ReflectiveOperationException e) { + //noinspection unchecked + return (T) new StaticArray<>(elements); + } + } + + @SuppressWarnings("unchecked") + static T decodeDynamicArray( + String input, int offset, TypeReference typeReference) { + + int length = decodeUintAsInt(input, offset); + + BiFunction, String, T> function = + (elements, typeName) -> { + if (elements.isEmpty()) { + return (T) DynamicArray.empty(typeName); + } else { + return (T) new DynamicArray<>(elements); + } + }; + + int valueOffset = offset + MAX_BYTE_LENGTH_FOR_HEX_STRING; + + return decodeArrayElements(input, valueOffset, typeReference, length, function); + } + + private static T decodeArrayElements( + String input, + int offset, + TypeReference typeReference, + int length, + BiFunction, String, T> consumer) { + + try { + Class cls = Utils.getParameterizedTypeFromArray(typeReference); + if (Array.class.isAssignableFrom(cls)) { + throw new UnsupportedOperationException( + "Arrays of arrays are not currently supported for external functions, see" + + "http://solidity.readthedocs.io/en/develop/types.html#members"); + } else { + List elements = new ArrayList<>(length); + + for (int i = 0, currOffset = offset; + i < length; + i++, + currOffset += + getSingleElementLength(input, currOffset, cls) + * MAX_BYTE_LENGTH_FOR_HEX_STRING) { + T value = decode(input, currOffset, cls); + elements.add(value); + } + + String typeName = Utils.getSimpleTypeName(cls); + + return consumer.apply(elements, typeName); + } + } catch (ClassNotFoundException e) { + throw new UnsupportedOperationException( + "Unable to access parameterized type " + typeReference.getType().getTypeName(), + e); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/TypeEncoder.java b/src/main/java/org/fisco/bcos/web3j/abi/TypeEncoder.java index 7de1c6982..2a4d3524f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/TypeEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/TypeEncoder.java @@ -1,181 +1,179 @@ package org.fisco.bcos.web3j.abi; +import static org.fisco.bcos.web3j.abi.datatypes.Type.MAX_BYTE_LENGTH; + import java.math.BigInteger; import java.nio.charset.StandardCharsets; import org.fisco.bcos.web3j.abi.datatypes.*; import org.fisco.bcos.web3j.utils.Numeric; -import static org.fisco.bcos.web3j.abi.datatypes.Type.MAX_BYTE_LENGTH; - /** * Ethereum Contract Application Binary Interface (ABI) encoding for types. Further details are * available here. */ public class TypeEncoder { - private TypeEncoder() {} - - static boolean isDynamic(Type parameter) { - return parameter instanceof DynamicBytes - || parameter instanceof Utf8String - || parameter instanceof DynamicArray; - } - - @SuppressWarnings("unchecked") - public static String encode(Type parameter) { - if (parameter instanceof NumericType) { - return encodeNumeric(((NumericType) parameter)); - } else if (parameter instanceof Address) { - return encodeAddress((Address) parameter); - } else if (parameter instanceof Bool) { - return encodeBool((Bool) parameter); - } else if (parameter instanceof Bytes) { - return encodeBytes((Bytes) parameter); - } else if (parameter instanceof DynamicBytes) { - return encodeDynamicBytes((DynamicBytes) parameter); - } else if (parameter instanceof Utf8String) { - return encodeString((Utf8String) parameter); - } else if (parameter instanceof StaticArray) { - return encodeArrayValues((StaticArray) parameter); - } else if (parameter instanceof DynamicArray) { - return encodeDynamicArray((DynamicArray) parameter); - } else { - throw new UnsupportedOperationException("Type cannot be encoded: " + parameter.getClass()); - } - } - - static String encodeAddress(Address address) { - return encodeNumeric(address.toUint160()); - } - - static String encodeNumeric(NumericType numericType) { - byte[] rawValue = toByteArray(numericType); - byte paddingValue = getPaddingValue(numericType); - byte[] paddedRawValue = new byte[MAX_BYTE_LENGTH]; - if (paddingValue != 0) { - for (int i = 0; i < paddedRawValue.length; i++) { - paddedRawValue[i] = paddingValue; - } + private TypeEncoder() {} + + static boolean isDynamic(Type parameter) { + return parameter instanceof DynamicBytes + || parameter instanceof Utf8String + || parameter instanceof DynamicArray; } - System.arraycopy( - rawValue, 0, paddedRawValue, MAX_BYTE_LENGTH - rawValue.length, rawValue.length); - return Numeric.toHexStringNoPrefix(paddedRawValue); - } + @SuppressWarnings("unchecked") + public static String encode(Type parameter) { + if (parameter instanceof NumericType) { + return encodeNumeric(((NumericType) parameter)); + } else if (parameter instanceof Address) { + return encodeAddress((Address) parameter); + } else if (parameter instanceof Bool) { + return encodeBool((Bool) parameter); + } else if (parameter instanceof Bytes) { + return encodeBytes((Bytes) parameter); + } else if (parameter instanceof DynamicBytes) { + return encodeDynamicBytes((DynamicBytes) parameter); + } else if (parameter instanceof Utf8String) { + return encodeString((Utf8String) parameter); + } else if (parameter instanceof StaticArray) { + return encodeArrayValues((StaticArray) parameter); + } else if (parameter instanceof DynamicArray) { + return encodeDynamicArray((DynamicArray) parameter); + } else { + throw new UnsupportedOperationException( + "Type cannot be encoded: " + parameter.getClass()); + } + } - private static byte getPaddingValue(NumericType numericType) { - if (numericType.getValue().signum() == -1) { - return (byte) 0xff; - } else { - return 0; + static String encodeAddress(Address address) { + return encodeNumeric(address.toUint160()); } - } - - private static byte[] toByteArray(NumericType numericType) { - BigInteger value = numericType.getValue(); - if (numericType instanceof Ufixed || numericType instanceof Uint) { - if (value.bitLength() == Type.MAX_BIT_LENGTH) { - // As BigInteger is signed, if we have a 256 bit value, the resultant byte array - // will contain a sign byte in it's MSB, which we should ignore for this unsigned - // integer type. - byte[] byteArray = new byte[MAX_BYTE_LENGTH]; - System.arraycopy(value.toByteArray(), 1, byteArray, 0, MAX_BYTE_LENGTH); - return byteArray; - } + + static String encodeNumeric(NumericType numericType) { + byte[] rawValue = toByteArray(numericType); + byte paddingValue = getPaddingValue(numericType); + byte[] paddedRawValue = new byte[MAX_BYTE_LENGTH]; + if (paddingValue != 0) { + for (int i = 0; i < paddedRawValue.length; i++) { + paddedRawValue[i] = paddingValue; + } + } + + System.arraycopy( + rawValue, 0, paddedRawValue, MAX_BYTE_LENGTH - rawValue.length, rawValue.length); + return Numeric.toHexStringNoPrefix(paddedRawValue); } - return value.toByteArray(); - } - static String encodeBool(Bool value) { - byte[] rawValue = new byte[MAX_BYTE_LENGTH]; - if (value.getValue()) { - rawValue[rawValue.length - 1] = 1; + private static byte getPaddingValue(NumericType numericType) { + if (numericType.getValue().signum() == -1) { + return (byte) 0xff; + } else { + return 0; + } } - return Numeric.toHexStringNoPrefix(rawValue); - } - - static String encodeBytes(BytesType bytesType) { - byte[] value = bytesType.getValue(); - int length = value.length; - int mod = length % Type.MAX_BYTE_LENGTH; - - byte[] dest; - if (mod != 0) { - int padding = MAX_BYTE_LENGTH - mod; - dest = new byte[length + padding]; - System.arraycopy(value, 0, dest, 0, length); - } else { - dest = value; + + private static byte[] toByteArray(NumericType numericType) { + BigInteger value = numericType.getValue(); + if (numericType instanceof Ufixed || numericType instanceof Uint) { + if (value.bitLength() == Type.MAX_BIT_LENGTH) { + // As BigInteger is signed, if we have a 256 bit value, the resultant byte array + // will contain a sign byte in it's MSB, which we should ignore for this unsigned + // integer type. + byte[] byteArray = new byte[MAX_BYTE_LENGTH]; + System.arraycopy(value.toByteArray(), 1, byteArray, 0, MAX_BYTE_LENGTH); + return byteArray; + } + } + return value.toByteArray(); } - return Numeric.toHexStringNoPrefix(dest); - } - - static String encodeDynamicBytes(DynamicBytes dynamicBytes) { - int size = dynamicBytes.getValue().length; - String encodedLength = encode(new Uint(BigInteger.valueOf(size))); - String encodedValue = encodeBytes(dynamicBytes); - - StringBuilder result = new StringBuilder(); - result.append(encodedLength); - result.append(encodedValue); - return result.toString(); - } - - static String encodeString(Utf8String string) { - byte[] utfEncoded = string.getValue().getBytes(StandardCharsets.UTF_8); - return encodeDynamicBytes(new DynamicBytes(utfEncoded)); - } - - static String encodeArrayValues(Array value) { - StringBuilder result = new StringBuilder(); - for (Type type : value.getValue()) { - result.append(TypeEncoder.encode(type)); + + static String encodeBool(Bool value) { + byte[] rawValue = new byte[MAX_BYTE_LENGTH]; + if (value.getValue()) { + rawValue[rawValue.length - 1] = 1; + } + return Numeric.toHexStringNoPrefix(rawValue); } - return result.toString(); - } - - static String encodeDynamicArray(DynamicArray value) { - int size = value.getValue().size(); - String encodedLength = encode(new Uint(BigInteger.valueOf(size))); - String valuesOffsets = encodeArrayValuesOffsets(value); - String encodedValues = encodeArrayValues(value); - - StringBuilder result = new StringBuilder(); - result.append(encodedLength); - result.append(valuesOffsets); - result.append(encodedValues); - return result.toString(); - } - - private static String encodeArrayValuesOffsets(DynamicArray value) { - StringBuilder result = new StringBuilder(); - boolean arrayOfBytes = !value.getValue().isEmpty() - && value.getValue().get(0) instanceof DynamicBytes; - boolean arrayOfString = !value.getValue().isEmpty() - && value.getValue().get(0) instanceof Utf8String; - if (arrayOfBytes || arrayOfString) { - long offset = 0; - for (int i = 0; i < value.getValue().size(); i++) { - if (i == 0) { - offset = value.getValue().size() * MAX_BYTE_LENGTH; + + static String encodeBytes(BytesType bytesType) { + byte[] value = bytesType.getValue(); + int length = value.length; + int mod = length % Type.MAX_BYTE_LENGTH; + + byte[] dest; + if (mod != 0) { + int padding = MAX_BYTE_LENGTH - mod; + dest = new byte[length + padding]; + System.arraycopy(value, 0, dest, 0, length); } else { - int bytesLength = arrayOfBytes - ? ((byte[]) value.getValue().get(i - 1).getValue()).length - : ((String) value.getValue().get(i - 1).getValue()).length(); - int numberOfWords = (bytesLength + MAX_BYTE_LENGTH - 1) / MAX_BYTE_LENGTH; - int totalBytesLength = numberOfWords * MAX_BYTE_LENGTH; - offset += totalBytesLength + MAX_BYTE_LENGTH; + dest = value; + } + return Numeric.toHexStringNoPrefix(dest); + } + + static String encodeDynamicBytes(DynamicBytes dynamicBytes) { + int size = dynamicBytes.getValue().length; + String encodedLength = encode(new Uint(BigInteger.valueOf(size))); + String encodedValue = encodeBytes(dynamicBytes); + + StringBuilder result = new StringBuilder(); + result.append(encodedLength); + result.append(encodedValue); + return result.toString(); + } + + static String encodeString(Utf8String string) { + byte[] utfEncoded = string.getValue().getBytes(StandardCharsets.UTF_8); + return encodeDynamicBytes(new DynamicBytes(utfEncoded)); + } + + static String encodeArrayValues(Array value) { + StringBuilder result = new StringBuilder(); + for (Type type : value.getValue()) { + result.append(TypeEncoder.encode(type)); } - result.append( - Numeric.toHexStringNoPrefix( - Numeric.toBytesPadded( - new BigInteger(Long.toString(offset)), MAX_BYTE_LENGTH - ) - ) - ); - } + return result.toString(); } - return result.toString(); - } + static String encodeDynamicArray(DynamicArray value) { + int size = value.getValue().size(); + String encodedLength = encode(new Uint(BigInteger.valueOf(size))); + String valuesOffsets = encodeArrayValuesOffsets(value); + String encodedValues = encodeArrayValues(value); + + StringBuilder result = new StringBuilder(); + result.append(encodedLength); + result.append(valuesOffsets); + result.append(encodedValues); + return result.toString(); + } + + private static String encodeArrayValuesOffsets(DynamicArray value) { + StringBuilder result = new StringBuilder(); + boolean arrayOfBytes = + !value.getValue().isEmpty() && value.getValue().get(0) instanceof DynamicBytes; + boolean arrayOfString = + !value.getValue().isEmpty() && value.getValue().get(0) instanceof Utf8String; + if (arrayOfBytes || arrayOfString) { + long offset = 0; + for (int i = 0; i < value.getValue().size(); i++) { + if (i == 0) { + offset = value.getValue().size() * MAX_BYTE_LENGTH; + } else { + int bytesLength = + arrayOfBytes + ? ((byte[]) value.getValue().get(i - 1).getValue()).length + : ((String) value.getValue().get(i - 1).getValue()).length(); + int numberOfWords = (bytesLength + MAX_BYTE_LENGTH - 1) / MAX_BYTE_LENGTH; + int totalBytesLength = numberOfWords * MAX_BYTE_LENGTH; + offset += totalBytesLength + MAX_BYTE_LENGTH; + } + result.append( + Numeric.toHexStringNoPrefix( + Numeric.toBytesPadded( + new BigInteger(Long.toString(offset)), MAX_BYTE_LENGTH))); + } + } + return result.toString(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/TypeMappingException.java b/src/main/java/org/fisco/bcos/web3j/abi/TypeMappingException.java index b6542b6c6..4b1b3341b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/TypeMappingException.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/TypeMappingException.java @@ -2,15 +2,15 @@ public class TypeMappingException extends RuntimeException { - public TypeMappingException(Exception e) { - super(e); - } + public TypeMappingException(Exception e) { + super(e); + } - public TypeMappingException(String message) { - super(message); - } + public TypeMappingException(String message) { + super(message); + } - public TypeMappingException(String message, Exception e) { - super(message, e); - } + public TypeMappingException(String message, Exception e) { + super(message, e); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/TypeReference.java b/src/main/java/org/fisco/bcos/web3j/abi/TypeReference.java index 359e5f717..bac4842eb 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/TypeReference.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/TypeReference.java @@ -16,79 +16,79 @@ * working around this fundamental generics limitation. */ public abstract class TypeReference - implements Comparable> { + implements Comparable> { - private final Type type; - private final boolean indexed; + private final Type type; + private final boolean indexed; - protected TypeReference() { - this(false); - } + protected TypeReference() { + this(false); + } - protected TypeReference(boolean indexed) { - Type superclass = getClass().getGenericSuperclass(); - if (superclass instanceof Class) { - throw new RuntimeException("Missing type parameter."); + protected TypeReference(boolean indexed) { + Type superclass = getClass().getGenericSuperclass(); + if (superclass instanceof Class) { + throw new RuntimeException("Missing type parameter."); + } + this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; + this.indexed = indexed; } - this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; - this.indexed = indexed; - } - public int compareTo(TypeReference o) { - // taken from the blog post comments - this results in an errror if the - // type parameter is left out. - return 0; - } + public int compareTo(TypeReference o) { + // taken from the blog post comments - this results in an errror if the + // type parameter is left out. + return 0; + } - public Type getType() { - return type; - } + public Type getType() { + return type; + } - public boolean isIndexed() { - return indexed; - } + public boolean isIndexed() { + return indexed; + } - /** - * Workaround to ensure type does not come back as T due to erasure, this enables you to create a - * TypeReference via {@link Class Class<T>}. - * - * @return the parameterized Class type if applicable, otherwise a regular class - * @throws ClassNotFoundException if the class type cannot be determined - */ - @SuppressWarnings("unchecked") - public Class getClassType() throws ClassNotFoundException { - Type clsType = getType(); + /** + * Workaround to ensure type does not come back as T due to erasure, this enables you to create + * a TypeReference via {@link Class Class<T>}. + * + * @return the parameterized Class type if applicable, otherwise a regular class + * @throws ClassNotFoundException if the class type cannot be determined + */ + @SuppressWarnings("unchecked") + public Class getClassType() throws ClassNotFoundException { + Type clsType = getType(); - if (getType() instanceof ParameterizedType) { - return (Class) ((ParameterizedType) clsType).getRawType(); - } else { - return (Class) Class.forName(clsType.getTypeName()); + if (getType() instanceof ParameterizedType) { + return (Class) ((ParameterizedType) clsType).getRawType(); + } else { + return (Class) Class.forName(clsType.getTypeName()); + } } - } - public static TypeReference create( - Class cls) { - return new TypeReference() { - @Override - public Type getType() { - return cls; - } - }; - } + public static TypeReference create( + Class cls) { + return new TypeReference() { + @Override + public Type getType() { + return cls; + } + }; + } - public abstract static class StaticArrayTypeReference< - T extends org.fisco.bcos.web3j.abi.datatypes.Type> - extends TypeReference { + public abstract static class StaticArrayTypeReference< + T extends org.fisco.bcos.web3j.abi.datatypes.Type> + extends TypeReference { - private final int size; + private final int size; - protected StaticArrayTypeReference(int size) { - super(); - this.size = size; - } + protected StaticArrayTypeReference(int size) { + super(); + this.size = size; + } - public int getSize() { - return size; + public int getSize() { + return size; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/Utils.java b/src/main/java/org/fisco/bcos/web3j/abi/Utils.java index 296e0fe38..cd2a0f05a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/Utils.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/Utils.java @@ -18,123 +18,124 @@ /** Utility functions. */ public class Utils { - private Utils() {} - - static String getTypeName(TypeReference typeReference) { - try { - java.lang.reflect.Type reflectedType = typeReference.getType(); - - Class type; - if (reflectedType instanceof ParameterizedType) { - type = (Class) ((ParameterizedType) reflectedType).getRawType(); - return getParameterizedTypeName(typeReference, type); - } else { - type = Class.forName(reflectedType.getTypeName()); - return getSimpleTypeName(type); - } - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException("Invalid class reference provided", e); + private Utils() {} + + static String getTypeName(TypeReference typeReference) { + try { + java.lang.reflect.Type reflectedType = typeReference.getType(); + + Class type; + if (reflectedType instanceof ParameterizedType) { + type = (Class) ((ParameterizedType) reflectedType).getRawType(); + return getParameterizedTypeName(typeReference, type); + } else { + type = Class.forName(reflectedType.getTypeName()); + return getSimpleTypeName(type); + } + } catch (ClassNotFoundException e) { + throw new UnsupportedOperationException("Invalid class reference provided", e); + } } - } - - static String getSimpleTypeName(Class type) { - String simpleName = type.getSimpleName().toLowerCase(); - - if (type.equals(Uint.class) - || type.equals(Int.class) - || type.equals(Ufixed.class) - || type.equals(Fixed.class)) { - return simpleName + "256"; - } else if (type.equals(Utf8String.class)) { - return "string"; - } else if (type.equals(DynamicBytes.class)) { - return "bytes"; - } else { - return simpleName; + + static String getSimpleTypeName(Class type) { + String simpleName = type.getSimpleName().toLowerCase(); + + if (type.equals(Uint.class) + || type.equals(Int.class) + || type.equals(Ufixed.class) + || type.equals(Fixed.class)) { + return simpleName + "256"; + } else if (type.equals(Utf8String.class)) { + return "string"; + } else if (type.equals(DynamicBytes.class)) { + return "bytes"; + } else { + return simpleName; + } } - } - - static String getParameterizedTypeName( - TypeReference typeReference, Class type) { - - try { - if (type.equals(DynamicArray.class)) { - Class parameterizedType = getParameterizedTypeFromArray(typeReference); - String parameterizedTypeName = getSimpleTypeName(parameterizedType); - return parameterizedTypeName + "[]"; - } else if (type.equals(StaticArray.class)) { - Class parameterizedType = getParameterizedTypeFromArray(typeReference); - String parameterizedTypeName = getSimpleTypeName(parameterizedType); - return parameterizedTypeName - + "[" - + ((TypeReference.StaticArrayTypeReference) typeReference).getSize() - + "]"; - } else { - throw new UnsupportedOperationException("Invalid type provided " + type.getName()); - } - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException("Invalid class reference provided", e); + + static String getParameterizedTypeName( + TypeReference typeReference, Class type) { + + try { + if (type.equals(DynamicArray.class)) { + Class parameterizedType = getParameterizedTypeFromArray(typeReference); + String parameterizedTypeName = getSimpleTypeName(parameterizedType); + return parameterizedTypeName + "[]"; + } else if (type.equals(StaticArray.class)) { + Class parameterizedType = getParameterizedTypeFromArray(typeReference); + String parameterizedTypeName = getSimpleTypeName(parameterizedType); + return parameterizedTypeName + + "[" + + ((TypeReference.StaticArrayTypeReference) typeReference).getSize() + + "]"; + } else { + throw new UnsupportedOperationException("Invalid type provided " + type.getName()); + } + } catch (ClassNotFoundException e) { + throw new UnsupportedOperationException("Invalid class reference provided", e); + } } - } - - @SuppressWarnings("unchecked") - static Class getParameterizedTypeFromArray(TypeReference typeReference) - throws ClassNotFoundException { - - java.lang.reflect.Type type = typeReference.getType(); - java.lang.reflect.Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments(); - - String parameterizedTypeName = typeArguments[0].getTypeName(); - return (Class) Class.forName(parameterizedTypeName); - } - - @SuppressWarnings("unchecked") - public static List> convert(List> input) { - List> result = new ArrayList<>(input.size()); - result.addAll( - input - .stream() - .map(typeReference -> (TypeReference) typeReference) - .collect(Collectors.toList())); - return result; - } - - public static , E extends Type> List typeMap( - List> input, Class outerDestType, Class innerType) { - List result = new ArrayList<>(); - try { - Constructor constructor = outerDestType.getDeclaredConstructor(List.class); - for (List ts : input) { - E e = constructor.newInstance(typeMap(ts, innerType)); - result.add(e); - } - } catch (NoSuchMethodException - | IllegalAccessException - | InstantiationException - | InvocationTargetException e) { - throw new TypeMappingException(e); + + @SuppressWarnings("unchecked") + static Class getParameterizedTypeFromArray(TypeReference typeReference) + throws ClassNotFoundException { + + java.lang.reflect.Type type = typeReference.getType(); + java.lang.reflect.Type[] typeArguments = + ((ParameterizedType) type).getActualTypeArguments(); + + String parameterizedTypeName = typeArguments[0].getTypeName(); + return (Class) Class.forName(parameterizedTypeName); } - return result; - } - public static > List typeMap(List input, Class destType) - throws TypeMappingException { + @SuppressWarnings("unchecked") + public static List> convert(List> input) { + List> result = new ArrayList<>(input.size()); + result.addAll( + input.stream() + .map(typeReference -> (TypeReference) typeReference) + .collect(Collectors.toList())); + return result; + } - List result = new ArrayList(input.size()); + public static , E extends Type> List typeMap( + List> input, Class outerDestType, Class innerType) { + List result = new ArrayList<>(); + try { + Constructor constructor = outerDestType.getDeclaredConstructor(List.class); + for (List ts : input) { + E e = constructor.newInstance(typeMap(ts, innerType)); + result.add(e); + } + } catch (NoSuchMethodException + | IllegalAccessException + | InstantiationException + | InvocationTargetException e) { + throw new TypeMappingException(e); + } + return result; + } - if (!input.isEmpty()) { - try { - Constructor constructor = destType.getDeclaredConstructor(input.get(0).getClass()); - for (T value : input) { - result.add(constructor.newInstance(value)); + public static > List typeMap(List input, Class destType) + throws TypeMappingException { + + List result = new ArrayList(input.size()); + + if (!input.isEmpty()) { + try { + Constructor constructor = + destType.getDeclaredConstructor(input.get(0).getClass()); + for (T value : input) { + result.add(constructor.newInstance(value)); + } + } catch (NoSuchMethodException + | IllegalAccessException + | InvocationTargetException + | InstantiationException e) { + throw new TypeMappingException(e); + } } - } catch (NoSuchMethodException - | IllegalAccessException - | InvocationTargetException - | InstantiationException e) { - throw new TypeMappingException(e); - } + return result; } - return result; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Address.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Address.java index 5f271be68..fe248846e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Address.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Address.java @@ -7,60 +7,60 @@ /** Address type, which is equivalent to uint160. */ public class Address implements Type { - public static final String TYPE_NAME = "address"; - public static final int LENGTH = 160; - public static final int LENGTH_IN_HEX = LENGTH >> 2; - public static final Address DEFAULT = new Address(BigInteger.ZERO); + public static final String TYPE_NAME = "address"; + public static final int LENGTH = 160; + public static final int LENGTH_IN_HEX = LENGTH >> 2; + public static final Address DEFAULT = new Address(BigInteger.ZERO); - private final Uint160 value; + private final Uint160 value; - public Address(Uint160 value) { - this.value = value; - } - - public Address(BigInteger value) { - this(new Uint160(value)); - } - - public Address(String hexValue) { - this(Numeric.toBigInt(hexValue)); - } + public Address(Uint160 value) { + this.value = value; + } - public Uint160 toUint160() { - return value; - } + public Address(BigInteger value) { + this(new Uint160(value)); + } - @Override - public String getTypeAsString() { - return TYPE_NAME; - } + public Address(String hexValue) { + this(Numeric.toBigInt(hexValue)); + } - @Override - public String toString() { - return Numeric.toHexStringWithPrefixZeroPadded(value.getValue(), LENGTH_IN_HEX); - } + public Uint160 toUint160() { + return value; + } - @Override - public String getValue() { - return toString(); - } + @Override + public String getTypeAsString() { + return TYPE_NAME; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + @Override + public String toString() { + return Numeric.toHexStringWithPrefixZeroPadded(value.getValue(), LENGTH_IN_HEX); } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public String getValue() { + return toString(); } - Address address = (Address) o; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - return value != null ? value.equals(address.value) : address.value == null; - } + Address address = (Address) o; - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } + return value != null ? value.equals(address.value) : address.value == null; + } + + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Array.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Array.java index 2b953be9f..5cecf6d4f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Array.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Array.java @@ -7,74 +7,74 @@ /** Fixed size array. */ public abstract class Array implements Type> { - private String type; - protected final List value; - - @SafeVarargs - Array(String type, T... values) { - if (!valid(values, type)) { - throw new UnsupportedOperationException( - "If empty list is provided, use empty array instance"); + private String type; + protected final List value; + + @SafeVarargs + Array(String type, T... values) { + if (!valid(values, type)) { + throw new UnsupportedOperationException( + "If empty list is provided, use empty array instance"); + } + + this.type = type; + this.value = Arrays.asList(values); } - this.type = type; - this.value = Arrays.asList(values); - } + Array(String type, List values) { + if (!valid(values, type)) { + throw new UnsupportedOperationException( + "If empty list is provided, use empty array instance"); + } - Array(String type, List values) { - if (!valid(values, type)) { - throw new UnsupportedOperationException( - "If empty list is provided, use empty array instance"); + this.type = type; + this.value = values; } - this.type = type; - this.value = values; - } - - Array(String type) { - this.type = type; - this.value = Collections.emptyList(); - } - - @Override - public List getValue() { - return value; - } - - @Override - public String getTypeAsString() { - return type; - } - - private boolean valid(T[] values, String type) { - return (values != null && values.length != 0) || type != null; - } - - private boolean valid(List values, String type) { - return (values != null && values.size() != 0) || type != null; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + Array(String type) { + this.type = type; + this.value = Collections.emptyList(); } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public List getValue() { + return value; + } + + @Override + public String getTypeAsString() { + return type; + } + + private boolean valid(T[] values, String type) { + return (values != null && values.length != 0) || type != null; + } + + private boolean valid(List values, String type) { + return (values != null && values.size() != 0) || type != null; } - Array array = (Array) o; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Array array = (Array) o; + + if (!type.equals(array.type)) { + return false; + } + return value != null ? value.equals(array.value) : array.value == null; + } - if (!type.equals(array.type)) { - return false; + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; } - return value != null ? value.equals(array.value) : array.value == null; - } - - @Override - public int hashCode() { - int result = type.hashCode(); - result = 31 * result + (value != null ? value.hashCode() : 0); - return result; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bool.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bool.java index 0d51a5087..0e8948b7a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bool.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bool.java @@ -3,45 +3,45 @@ /** Boolean type. */ public class Bool implements Type { - public static final String TYPE_NAME = "bool"; - public static final Bool DEFAULT = new Bool(false); + public static final String TYPE_NAME = "bool"; + public static final Bool DEFAULT = new Bool(false); - private boolean value; + private boolean value; - public Bool(boolean value) { - this.value = value; - } - - public Bool(Boolean value) { - this.value = value; - } - - @Override - public String getTypeAsString() { - return TYPE_NAME; - } + public Bool(boolean value) { + this.value = value; + } - @Override - public Boolean getValue() { - return value; - } + public Bool(Boolean value) { + this.value = value; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + @Override + public String getTypeAsString() { + return TYPE_NAME; } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public Boolean getValue() { + return value; } - Bool bool = (Bool) o; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Bool bool = (Bool) o; - return value == bool.value; - } + return value == bool.value; + } - @Override - public int hashCode() { - return (value ? 1 : 0); - } + @Override + public int hashCode() { + return (value ? 1 : 0); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bytes.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bytes.java index e9b661612..d0273192d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bytes.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Bytes.java @@ -3,18 +3,18 @@ /** Statically allocated sequence of bytes. */ public class Bytes extends BytesType { - public static final String TYPE_NAME = "bytes"; + public static final String TYPE_NAME = "bytes"; - protected Bytes(int byteSize, byte[] value) { - super(value, TYPE_NAME + value.length); - if (!isValid(byteSize, value)) { - throw new UnsupportedOperationException( - "Input byte array must be in range 0 < M <= 32 and length must match type"); + protected Bytes(int byteSize, byte[] value) { + super(value, TYPE_NAME + value.length); + if (!isValid(byteSize, value)) { + throw new UnsupportedOperationException( + "Input byte array must be in range 0 < M <= 32 and length must match type"); + } } - } - private boolean isValid(int byteSize, byte[] value) { - int length = value.length; - return length > 0 && length <= 32 && length == byteSize; - } + private boolean isValid(int byteSize, byte[] value) { + int length = value.length; + return length > 0 && length <= 32 && length == byteSize; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/BytesType.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/BytesType.java index 6ca3653be..c4c7cca79 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/BytesType.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/BytesType.java @@ -5,45 +5,45 @@ /** Binary sequence of bytes. */ public class BytesType implements Type { - private byte[] value; - private String type; - - public BytesType(byte[] src, String type) { - this.value = src; - this.type = type; - } - - @Override - public byte[] getValue() { - return value; - } - - @Override - public String getTypeAsString() { - return type; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + private byte[] value; + private String type; + + public BytesType(byte[] src, String type) { + this.value = src; + this.type = type; } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public byte[] getValue() { + return value; } - BytesType bytesType = (BytesType) o; + @Override + public String getTypeAsString() { + return type; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + BytesType bytesType = (BytesType) o; + + if (!Arrays.equals(value, bytesType.value)) { + return false; + } + return type.equals(bytesType.type); + } - if (!Arrays.equals(value, bytesType.value)) { - return false; + @Override + public int hashCode() { + int result = Arrays.hashCode(value); + result = 31 * result + type.hashCode(); + return result; } - return type.equals(bytesType.type); - } - - @Override - public int hashCode() { - int result = Arrays.hashCode(value); - result = 31 * result + type.hashCode(); - return result; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicArray.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicArray.java index 0e45847f2..312aad9ac 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicArray.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicArray.java @@ -5,20 +5,20 @@ /** Dynamic array type. */ public class DynamicArray extends Array { - @SafeVarargs - public DynamicArray(T... values) { - super(values[0].getTypeAsString() + "[]", values); - } + @SafeVarargs + public DynamicArray(T... values) { + super(values[0].getTypeAsString() + "[]", values); + } - public DynamicArray(List values) { - super(values.get(0).getTypeAsString() + "[]", values); - } + public DynamicArray(List values) { + super(values.get(0).getTypeAsString() + "[]", values); + } - private DynamicArray(String type) { - super(type); - } + private DynamicArray(String type) { + super(type); + } - public static DynamicArray empty(String type) { - return new DynamicArray(type); - } + public static DynamicArray empty(String type) { + return new DynamicArray(type); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicBytes.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicBytes.java index 296c39bc3..1fdeb0797 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicBytes.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/DynamicBytes.java @@ -3,10 +3,10 @@ /** Dynamically allocated sequence of bytes. */ public class DynamicBytes extends BytesType { - public static final String TYPE_NAME = "bytes"; - public static final DynamicBytes DEFAULT = new DynamicBytes(new byte[] {}); + public static final String TYPE_NAME = "bytes"; + public static final DynamicBytes DEFAULT = new DynamicBytes(new byte[] {}); - public DynamicBytes(byte[] value) { - super(value, TYPE_NAME); - } + public DynamicBytes(byte[] value) { + super(value, TYPE_NAME); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Event.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Event.java index 247a6f378..6ada42a71 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Event.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Event.java @@ -7,27 +7,27 @@ /** Event wrapper type. */ public class Event { - private String name; - private List> parameters; + private String name; + private List> parameters; - public Event(String name, List> parameters) { - this.name = name; - this.parameters = Utils.convert(parameters); - } + public Event(String name, List> parameters) { + this.name = name; + this.parameters = Utils.convert(parameters); + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public List> getParameters() { - return parameters; - } + public List> getParameters() { + return parameters; + } - public List> getIndexedParameters() { - return parameters.stream().filter(TypeReference::isIndexed).collect(Collectors.toList()); - } + public List> getIndexedParameters() { + return parameters.stream().filter(TypeReference::isIndexed).collect(Collectors.toList()); + } - public List> getNonIndexedParameters() { - return parameters.stream().filter(p -> !p.isIndexed()).collect(Collectors.toList()); - } + public List> getNonIndexedParameters() { + return parameters.stream().filter(p -> !p.isIndexed()).collect(Collectors.toList()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Fixed.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Fixed.java index 1f276feb3..56a6d50e4 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Fixed.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Fixed.java @@ -5,22 +5,22 @@ /** Signed fixed type. */ public class Fixed extends FixedPointType { - public static final String TYPE_NAME = "fixed"; - public static final Fixed DEFAULT = new Fixed(BigInteger.ZERO); + public static final String TYPE_NAME = "fixed"; + public static final Fixed DEFAULT = new Fixed(BigInteger.ZERO); - protected Fixed(int mBitSize, int nBitSize, BigInteger value) { - super(TYPE_NAME, mBitSize, nBitSize, value); - } + protected Fixed(int mBitSize, int nBitSize, BigInteger value) { + super(TYPE_NAME, mBitSize, nBitSize, value); + } - public Fixed(BigInteger value) { - this(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, value); - } + public Fixed(BigInteger value) { + this(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, value); + } - public Fixed(BigInteger m, BigInteger n) { - this(convert(m, n)); - } + public Fixed(BigInteger m, BigInteger n) { + this(convert(m, n)); + } - protected Fixed(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { - this(convert(mBitSize, nBitSize, m, n)); - } + protected Fixed(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { + this(convert(mBitSize, nBitSize, m, n)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointType.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointType.java index 98d4a58c6..4fa269123 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointType.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointType.java @@ -5,39 +5,39 @@ /** Common fixed-point type properties. */ public abstract class FixedPointType extends NumericType { - static final int DEFAULT_BIT_LENGTH = MAX_BIT_LENGTH >> 1; - - public FixedPointType(String typePrefix, int mBitSize, int nBitSize, BigInteger value) { - super(typePrefix + mBitSize + "x" + nBitSize, value); - if (!valid(mBitSize, nBitSize, value)) { - throw new UnsupportedOperationException( - "Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256"); + static final int DEFAULT_BIT_LENGTH = MAX_BIT_LENGTH >> 1; + + public FixedPointType(String typePrefix, int mBitSize, int nBitSize, BigInteger value) { + super(typePrefix + mBitSize + "x" + nBitSize, value); + if (!valid(mBitSize, nBitSize, value)) { + throw new UnsupportedOperationException( + "Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256"); + } } - } - boolean valid(int mBitSize, int nBitSize, BigInteger value) { - return isValidBitSize(mBitSize, nBitSize) && isValidBitCount(mBitSize, nBitSize, value); - } + boolean valid(int mBitSize, int nBitSize, BigInteger value) { + return isValidBitSize(mBitSize, nBitSize) && isValidBitCount(mBitSize, nBitSize, value); + } - static boolean isValidBitSize(int mBitSize, int nBitSize) { - int bitSize = mBitSize + nBitSize; - return mBitSize % 8 == 0 && nBitSize % 8 == 0 && bitSize > 0 && bitSize <= MAX_BIT_LENGTH; - } + static boolean isValidBitSize(int mBitSize, int nBitSize) { + int bitSize = mBitSize + nBitSize; + return mBitSize % 8 == 0 && nBitSize % 8 == 0 && bitSize > 0 && bitSize <= MAX_BIT_LENGTH; + } - private static boolean isValidBitCount(int mBitSize, int nBitSize, BigInteger value) { - return value.bitCount() <= mBitSize + nBitSize; - } + private static boolean isValidBitCount(int mBitSize, int nBitSize, BigInteger value) { + return value.bitCount() <= mBitSize + nBitSize; + } - static BigInteger convert(BigInteger m, BigInteger n) { - return convert(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, m, n); - } + static BigInteger convert(BigInteger m, BigInteger n) { + return convert(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, m, n); + } - static BigInteger convert(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { - BigInteger mPadded = m.shiftLeft(nBitSize); - int nBitLength = n.bitLength(); + static BigInteger convert(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { + BigInteger mPadded = m.shiftLeft(nBitSize); + int nBitLength = n.bitLength(); - // find next multiple of 4 - int shift = (nBitLength + 3) & ~0x03; - return mPadded.or(n.shiftLeft(nBitSize - shift)); - } + // find next multiple of 4 + int shift = (nBitLength + 3) & ~0x03; + return mPadded.or(n.shiftLeft(nBitSize - shift)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Function.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Function.java index c75976a3b..a9d1cdbf1 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Function.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Function.java @@ -6,26 +6,26 @@ /** Function type. */ public class Function { - private String name; - private List inputParameters; - private List> outputParameters; + private String name; + private List inputParameters; + private List> outputParameters; - public Function( - String name, List inputParameters, List> outputParameters) { - this.name = name; - this.inputParameters = inputParameters; - this.outputParameters = Utils.convert(outputParameters); - } + public Function( + String name, List inputParameters, List> outputParameters) { + this.name = name; + this.inputParameters = inputParameters; + this.outputParameters = Utils.convert(outputParameters); + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public List getInputParameters() { - return inputParameters; - } + public List getInputParameters() { + return inputParameters; + } - public List> getOutputParameters() { - return outputParameters; - } + public List> getOutputParameters() { + return outputParameters; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Int.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Int.java index abcd077fc..32515365f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Int.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Int.java @@ -5,15 +5,15 @@ /** Integer type. */ public class Int extends IntType { - public static final String TYPE_NAME = "int"; - public static final Int DEFAULT = new Int(BigInteger.ZERO); + public static final String TYPE_NAME = "int"; + public static final Int DEFAULT = new Int(BigInteger.ZERO); - public Int(BigInteger value) { - // "int" values should be declared as int256 in computing function selectors - this(MAX_BIT_LENGTH, value); - } + public Int(BigInteger value) { + // "int" values should be declared as int256 in computing function selectors + this(MAX_BIT_LENGTH, value); + } - protected Int(int bitSize, BigInteger value) { - super(TYPE_NAME, bitSize, value); - } + protected Int(int bitSize, BigInteger value) { + super(TYPE_NAME, bitSize, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/IntType.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/IntType.java index 6320c91a5..b46464d72 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/IntType.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/IntType.java @@ -5,23 +5,23 @@ /** Common integer properties. */ public abstract class IntType extends NumericType { - public IntType(String typePrefix, int bitSize, BigInteger value) { - super(typePrefix + bitSize, value); - if (!valid(bitSize, value)) { - throw new UnsupportedOperationException( - "Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256"); + public IntType(String typePrefix, int bitSize, BigInteger value) { + super(typePrefix + bitSize, value); + if (!valid(bitSize, value)) { + throw new UnsupportedOperationException( + "Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256"); + } } - } - boolean valid(int bitSize, BigInteger value) { - return isValidBitSize(bitSize) && isValidBitCount(bitSize, value); - } + boolean valid(int bitSize, BigInteger value) { + return isValidBitSize(bitSize) && isValidBitCount(bitSize, value); + } - static boolean isValidBitSize(int bitSize) { - return bitSize % 8 == 0 && bitSize > 0 && bitSize <= MAX_BIT_LENGTH; - } + static boolean isValidBitSize(int bitSize) { + return bitSize % 8 == 0 && bitSize > 0 && bitSize <= MAX_BIT_LENGTH; + } - private static boolean isValidBitCount(int bitSize, BigInteger value) { - return value.bitLength() <= bitSize; - } + private static boolean isValidBitCount(int bitSize, BigInteger value) { + return value.bitLength() <= bitSize; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/NumericType.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/NumericType.java index 359168428..c12975efc 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/NumericType.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/NumericType.java @@ -5,46 +5,46 @@ /** Common numeric type. */ public abstract class NumericType implements Type { - private String type; - BigInteger value; - - public NumericType(String type, BigInteger value) { - this.type = type; - this.value = value; - } - - @Override - public String getTypeAsString() { - return type; - } - - @Override - public BigInteger getValue() { - return value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; + private String type; + BigInteger value; + + public NumericType(String type, BigInteger value) { + this.type = type; + this.value = value; } - NumericType that = (NumericType) o; + @Override + public String getTypeAsString() { + return type; + } - if (!type.equals(that.type)) { - return false; + @Override + public BigInteger getValue() { + return value; } - return value != null ? value.equals(that.value) : that.value == null; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + NumericType that = (NumericType) o; - @Override - public int hashCode() { - int result = type.hashCode(); - result = 31 * result + (value != null ? value.hashCode() : 0); - return result; - } + if (!type.equals(that.type)) { + return false; + } + + return value != null ? value.equals(that.value) : that.value == null; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/StaticArray.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/StaticArray.java index 39cde06a2..7f8c71cf9 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/StaticArray.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/StaticArray.java @@ -5,50 +5,49 @@ /** Static array type. */ public class StaticArray extends Array { - /** - * Warning: increasing this constant will cause more generated StaticArrayN types, see: - * AbiTypesGenerator#generateStaticArrayTypes - */ - public static int MAX_SIZE_OF_STATIC_ARRAY = 32; - - private Integer expectedSize; - - @SafeVarargs - public StaticArray(T... values) { - super(values[0].getTypeAsString() + "[" + values.length + "]", values); - isValid(); - } - - @SafeVarargs - public StaticArray(int expectedSize, T... values) { - super(values[0].getTypeAsString() + "[" + values.length + "]", values); - this.expectedSize = expectedSize; - isValid(); - } - - public StaticArray(List values) { - super(values.get(0).getTypeAsString() + "[" + values.size() + "]", values); - isValid(); - } - - public StaticArray(int expectedSize, List values) { - super(values.get(0).getTypeAsString() + "[" + values.size() + "]", values); - this.expectedSize = expectedSize; - isValid(); - } - - private void isValid() { - MAX_SIZE_OF_STATIC_ARRAY = 32; - if (expectedSize == null && value.size() > MAX_SIZE_OF_STATIC_ARRAY) { - throw new UnsupportedOperationException( - "Static arrays with a length greater than 32 are not supported."); - } else if (expectedSize != null && value.size() != expectedSize) { - throw new UnsupportedOperationException( - "Expected array of type [" - + getClass().getSimpleName() - + "] to have [" - + expectedSize - + "] elements."); + /** + * Warning: increasing this constant will cause more generated StaticArrayN types, see: + * AbiTypesGenerator#generateStaticArrayTypes + */ + public static int MAX_SIZE_OF_STATIC_ARRAY = 1024; + + private Integer expectedSize; + + @SafeVarargs + public StaticArray(T... values) { + super(values[0].getTypeAsString() + "[" + values.length + "]", values); + isValid(); + } + + @SafeVarargs + public StaticArray(int expectedSize, T... values) { + super(values[0].getTypeAsString() + "[" + values.length + "]", values); + this.expectedSize = expectedSize; + isValid(); + } + + public StaticArray(List values) { + super(values.get(0).getTypeAsString() + "[" + values.size() + "]", values); + isValid(); + } + + public StaticArray(int expectedSize, List values) { + super(values.get(0).getTypeAsString() + "[" + values.size() + "]", values); + this.expectedSize = expectedSize; + isValid(); + } + + private void isValid() { + if (expectedSize == null && value.size() > MAX_SIZE_OF_STATIC_ARRAY) { + throw new UnsupportedOperationException( + "Static arrays with a length greater than 1024 are not supported."); + } else if (expectedSize != null && value.size() != expectedSize) { + throw new UnsupportedOperationException( + "Expected array of type [" + + getClass().getSimpleName() + + "] to have [" + + expectedSize + + "] elements."); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Type.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Type.java index c19fe9639..2638b32cc 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Type.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Type.java @@ -2,10 +2,10 @@ /** ABI Types. */ public interface Type { - int MAX_BIT_LENGTH = 256; - int MAX_BYTE_LENGTH = MAX_BIT_LENGTH / 8; + int MAX_BIT_LENGTH = 256; + int MAX_BYTE_LENGTH = MAX_BIT_LENGTH / 8; - T getValue(); + T getValue(); - String getTypeAsString(); + String getTypeAsString(); } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Ufixed.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Ufixed.java index ef0f8e4dc..0f4fb13d2 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Ufixed.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Ufixed.java @@ -5,27 +5,27 @@ /** Signed fixed type. */ public class Ufixed extends FixedPointType { - public static final String TYPE_NAME = "ufixed"; - public static final Ufixed DEFAULT = new Ufixed(BigInteger.ZERO); + public static final String TYPE_NAME = "ufixed"; + public static final Ufixed DEFAULT = new Ufixed(BigInteger.ZERO); - protected Ufixed(int mBitSize, int nBitSize, BigInteger value) { - super(TYPE_NAME, mBitSize, nBitSize, value); - } + protected Ufixed(int mBitSize, int nBitSize, BigInteger value) { + super(TYPE_NAME, mBitSize, nBitSize, value); + } - public Ufixed(BigInteger value) { - this(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, value); - } + public Ufixed(BigInteger value) { + this(DEFAULT_BIT_LENGTH, DEFAULT_BIT_LENGTH, value); + } - public Ufixed(BigInteger m, BigInteger n) { - this(convert(m, n)); - } + public Ufixed(BigInteger m, BigInteger n) { + this(convert(m, n)); + } - protected Ufixed(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { - this(convert(mBitSize, nBitSize, m, n)); - } + protected Ufixed(int mBitSize, int nBitSize, BigInteger m, BigInteger n) { + this(convert(mBitSize, nBitSize, m, n)); + } - @Override - boolean valid(int mBitSize, int nBitSize, BigInteger value) { - return super.valid(mBitSize, nBitSize, value) && value.signum() != -1; - } + @Override + boolean valid(int mBitSize, int nBitSize, BigInteger value) { + return super.valid(mBitSize, nBitSize, value) && value.signum() != -1; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Uint.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Uint.java index fca019234..c4731d9ac 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Uint.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Uint.java @@ -5,25 +5,25 @@ /** Unsigned integer type. */ public class Uint extends IntType { - public static final String TYPE_NAME = "uint"; - public static final Uint DEFAULT = new Uint(BigInteger.ZERO); + public static final String TYPE_NAME = "uint"; + public static final Uint DEFAULT = new Uint(BigInteger.ZERO); - /** This constructor is required by the {@link Address} type. */ - Uint(String typePrefix, int bitSize, BigInteger value) { - super(typePrefix, bitSize, value); - } + /** This constructor is required by the {@link Address} type. */ + Uint(String typePrefix, int bitSize, BigInteger value) { + super(typePrefix, bitSize, value); + } - protected Uint(int bitSize, BigInteger value) { - this(TYPE_NAME, bitSize, value); - } + protected Uint(int bitSize, BigInteger value) { + this(TYPE_NAME, bitSize, value); + } - public Uint(BigInteger value) { - // "int" values should be declared as int256 in computing function selectors - this(MAX_BIT_LENGTH, value); - } + public Uint(BigInteger value) { + // "int" values should be declared as int256 in computing function selectors + this(MAX_BIT_LENGTH, value); + } - @Override - boolean valid(int bitSize, BigInteger value) { - return super.valid(bitSize, value) && value.signum() != -1; - } + @Override + boolean valid(int bitSize, BigInteger value) { + return super.valid(bitSize, value) && value.signum() != -1; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Utf8String.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Utf8String.java index b90a191d7..4121058c0 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Utf8String.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/Utf8String.java @@ -3,46 +3,46 @@ /** UTF-8 encoded string type. */ public class Utf8String implements Type { - public static final String TYPE_NAME = "string"; - public static final Utf8String DEFAULT = new Utf8String(""); + public static final String TYPE_NAME = "string"; + public static final Utf8String DEFAULT = new Utf8String(""); - private String value; + private String value; - public Utf8String(String value) { - this.value = value; - } - - @Override - public String getValue() { - return value; - } - - @Override - public String getTypeAsString() { - return TYPE_NAME; - } + public Utf8String(String value) { + this.value = value; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + @Override + public String getValue() { + return value; } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public String getTypeAsString() { + return TYPE_NAME; } - Utf8String that = (Utf8String) o; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - return value != null ? value.equals(that.value) : that.value == null; - } + Utf8String that = (Utf8String) o; - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } + return value != null ? value.equals(that.value) : that.value == null; + } + + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; + } - @Override - public String toString() { - return value; - } + @Override + public String toString() { + return value; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/AbiTypes.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/AbiTypes.java index 8b0e676c9..cf859b57f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/AbiTypes.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/AbiTypes.java @@ -15,214 +15,214 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class AbiTypes { - private AbiTypes() {} + private AbiTypes() {} - public static Class getType(String type) { - switch (type) { - case "address": - return Address.class; - case "bool": - return Bool.class; - case "string": - return Utf8String.class; - case "bytes": - return DynamicBytes.class; - case "uint8": - return Uint8.class; - case "int8": - return Int8.class; - case "uint16": - return Uint16.class; - case "int16": - return Int16.class; - case "uint24": - return Uint24.class; - case "int24": - return Int24.class; - case "uint32": - return Uint32.class; - case "int32": - return Int32.class; - case "uint40": - return Uint40.class; - case "int40": - return Int40.class; - case "uint48": - return Uint48.class; - case "int48": - return Int48.class; - case "uint56": - return Uint56.class; - case "int56": - return Int56.class; - case "uint64": - return Uint64.class; - case "int64": - return Int64.class; - case "uint72": - return Uint72.class; - case "int72": - return Int72.class; - case "uint80": - return Uint80.class; - case "int80": - return Int80.class; - case "uint88": - return Uint88.class; - case "int88": - return Int88.class; - case "uint96": - return Uint96.class; - case "int96": - return Int96.class; - case "uint104": - return Uint104.class; - case "int104": - return Int104.class; - case "uint112": - return Uint112.class; - case "int112": - return Int112.class; - case "uint120": - return Uint120.class; - case "int120": - return Int120.class; - case "uint128": - return Uint128.class; - case "int128": - return Int128.class; - case "uint136": - return Uint136.class; - case "int136": - return Int136.class; - case "uint144": - return Uint144.class; - case "int144": - return Int144.class; - case "uint152": - return Uint152.class; - case "int152": - return Int152.class; - case "uint160": - return Uint160.class; - case "int160": - return Int160.class; - case "uint168": - return Uint168.class; - case "int168": - return Int168.class; - case "uint176": - return Uint176.class; - case "int176": - return Int176.class; - case "uint184": - return Uint184.class; - case "int184": - return Int184.class; - case "uint192": - return Uint192.class; - case "int192": - return Int192.class; - case "uint200": - return Uint200.class; - case "int200": - return Int200.class; - case "uint208": - return Uint208.class; - case "int208": - return Int208.class; - case "uint216": - return Uint216.class; - case "int216": - return Int216.class; - case "uint224": - return Uint224.class; - case "int224": - return Int224.class; - case "uint232": - return Uint232.class; - case "int232": - return Int232.class; - case "uint240": - return Uint240.class; - case "int240": - return Int240.class; - case "uint248": - return Uint248.class; - case "int248": - return Int248.class; - case "uint256": - return Uint256.class; - case "int256": - return Int256.class; - case "bytes1": - return Bytes1.class; - case "bytes2": - return Bytes2.class; - case "bytes3": - return Bytes3.class; - case "bytes4": - return Bytes4.class; - case "bytes5": - return Bytes5.class; - case "bytes6": - return Bytes6.class; - case "bytes7": - return Bytes7.class; - case "bytes8": - return Bytes8.class; - case "bytes9": - return Bytes9.class; - case "bytes10": - return Bytes10.class; - case "bytes11": - return Bytes11.class; - case "bytes12": - return Bytes12.class; - case "bytes13": - return Bytes13.class; - case "bytes14": - return Bytes14.class; - case "bytes15": - return Bytes15.class; - case "bytes16": - return Bytes16.class; - case "bytes17": - return Bytes17.class; - case "bytes18": - return Bytes18.class; - case "bytes19": - return Bytes19.class; - case "bytes20": - return Bytes20.class; - case "bytes21": - return Bytes21.class; - case "bytes22": - return Bytes22.class; - case "bytes23": - return Bytes23.class; - case "bytes24": - return Bytes24.class; - case "bytes25": - return Bytes25.class; - case "bytes26": - return Bytes26.class; - case "bytes27": - return Bytes27.class; - case "bytes28": - return Bytes28.class; - case "bytes29": - return Bytes29.class; - case "bytes30": - return Bytes30.class; - case "bytes31": - return Bytes31.class; - case "bytes32": - return Bytes32.class; - case "TransactionSucCallback": - return TransactionSucCallback.class; - default: - throw new UnsupportedOperationException("Unsupported type encountered: " + type); + public static Class getType(String type) { + switch (type) { + case "address": + return Address.class; + case "bool": + return Bool.class; + case "string": + return Utf8String.class; + case "bytes": + return DynamicBytes.class; + case "uint8": + return Uint8.class; + case "int8": + return Int8.class; + case "uint16": + return Uint16.class; + case "int16": + return Int16.class; + case "uint24": + return Uint24.class; + case "int24": + return Int24.class; + case "uint32": + return Uint32.class; + case "int32": + return Int32.class; + case "uint40": + return Uint40.class; + case "int40": + return Int40.class; + case "uint48": + return Uint48.class; + case "int48": + return Int48.class; + case "uint56": + return Uint56.class; + case "int56": + return Int56.class; + case "uint64": + return Uint64.class; + case "int64": + return Int64.class; + case "uint72": + return Uint72.class; + case "int72": + return Int72.class; + case "uint80": + return Uint80.class; + case "int80": + return Int80.class; + case "uint88": + return Uint88.class; + case "int88": + return Int88.class; + case "uint96": + return Uint96.class; + case "int96": + return Int96.class; + case "uint104": + return Uint104.class; + case "int104": + return Int104.class; + case "uint112": + return Uint112.class; + case "int112": + return Int112.class; + case "uint120": + return Uint120.class; + case "int120": + return Int120.class; + case "uint128": + return Uint128.class; + case "int128": + return Int128.class; + case "uint136": + return Uint136.class; + case "int136": + return Int136.class; + case "uint144": + return Uint144.class; + case "int144": + return Int144.class; + case "uint152": + return Uint152.class; + case "int152": + return Int152.class; + case "uint160": + return Uint160.class; + case "int160": + return Int160.class; + case "uint168": + return Uint168.class; + case "int168": + return Int168.class; + case "uint176": + return Uint176.class; + case "int176": + return Int176.class; + case "uint184": + return Uint184.class; + case "int184": + return Int184.class; + case "uint192": + return Uint192.class; + case "int192": + return Int192.class; + case "uint200": + return Uint200.class; + case "int200": + return Int200.class; + case "uint208": + return Uint208.class; + case "int208": + return Int208.class; + case "uint216": + return Uint216.class; + case "int216": + return Int216.class; + case "uint224": + return Uint224.class; + case "int224": + return Int224.class; + case "uint232": + return Uint232.class; + case "int232": + return Int232.class; + case "uint240": + return Uint240.class; + case "int240": + return Int240.class; + case "uint248": + return Uint248.class; + case "int248": + return Int248.class; + case "uint256": + return Uint256.class; + case "int256": + return Int256.class; + case "bytes1": + return Bytes1.class; + case "bytes2": + return Bytes2.class; + case "bytes3": + return Bytes3.class; + case "bytes4": + return Bytes4.class; + case "bytes5": + return Bytes5.class; + case "bytes6": + return Bytes6.class; + case "bytes7": + return Bytes7.class; + case "bytes8": + return Bytes8.class; + case "bytes9": + return Bytes9.class; + case "bytes10": + return Bytes10.class; + case "bytes11": + return Bytes11.class; + case "bytes12": + return Bytes12.class; + case "bytes13": + return Bytes13.class; + case "bytes14": + return Bytes14.class; + case "bytes15": + return Bytes15.class; + case "bytes16": + return Bytes16.class; + case "bytes17": + return Bytes17.class; + case "bytes18": + return Bytes18.class; + case "bytes19": + return Bytes19.class; + case "bytes20": + return Bytes20.class; + case "bytes21": + return Bytes21.class; + case "bytes22": + return Bytes22.class; + case "bytes23": + return Bytes23.class; + case "bytes24": + return Bytes24.class; + case "bytes25": + return Bytes25.class; + case "bytes26": + return Bytes26.class; + case "bytes27": + return Bytes27.class; + case "bytes28": + return Bytes28.class; + case "bytes29": + return Bytes29.class; + case "bytes30": + return Bytes30.class; + case "bytes31": + return Bytes31.class; + case "bytes32": + return Bytes32.class; + case "TransactionSucCallback": + return TransactionSucCallback.class; + default: + throw new UnsupportedOperationException("Unsupported type encountered: " + type); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes1.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes1.java index 71a152b4c..9ca78aa85 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes1.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes1.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes1 extends Bytes { - public static final Bytes1 DEFAULT = new Bytes1(new byte[1]); + public static final Bytes1 DEFAULT = new Bytes1(new byte[1]); - public Bytes1(byte[] value) { - super(1, value); - } + public Bytes1(byte[] value) { + super(1, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes10.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes10.java index 1cc754d39..85dcbe9ad 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes10.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes10.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes10 extends Bytes { - public static final Bytes10 DEFAULT = new Bytes10(new byte[10]); + public static final Bytes10 DEFAULT = new Bytes10(new byte[10]); - public Bytes10(byte[] value) { - super(10, value); - } + public Bytes10(byte[] value) { + super(10, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes11.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes11.java index 9f5b5daa3..282fa519e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes11.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes11.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes11 extends Bytes { - public static final Bytes11 DEFAULT = new Bytes11(new byte[11]); + public static final Bytes11 DEFAULT = new Bytes11(new byte[11]); - public Bytes11(byte[] value) { - super(11, value); - } + public Bytes11(byte[] value) { + super(11, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes12.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes12.java index 28b74148f..652153d51 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes12.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes12.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes12 extends Bytes { - public static final Bytes12 DEFAULT = new Bytes12(new byte[12]); + public static final Bytes12 DEFAULT = new Bytes12(new byte[12]); - public Bytes12(byte[] value) { - super(12, value); - } + public Bytes12(byte[] value) { + super(12, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes13.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes13.java index ddc637e28..9e211da33 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes13.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes13.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes13 extends Bytes { - public static final Bytes13 DEFAULT = new Bytes13(new byte[13]); + public static final Bytes13 DEFAULT = new Bytes13(new byte[13]); - public Bytes13(byte[] value) { - super(13, value); - } + public Bytes13(byte[] value) { + super(13, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes14.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes14.java index 0848e1af8..5ed8e98e9 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes14.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes14.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes14 extends Bytes { - public static final Bytes14 DEFAULT = new Bytes14(new byte[14]); + public static final Bytes14 DEFAULT = new Bytes14(new byte[14]); - public Bytes14(byte[] value) { - super(14, value); - } + public Bytes14(byte[] value) { + super(14, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes15.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes15.java index 20959a590..167443893 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes15.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes15.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes15 extends Bytes { - public static final Bytes15 DEFAULT = new Bytes15(new byte[15]); + public static final Bytes15 DEFAULT = new Bytes15(new byte[15]); - public Bytes15(byte[] value) { - super(15, value); - } + public Bytes15(byte[] value) { + super(15, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes16.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes16.java index 7f6fb7e42..cf18d6a21 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes16.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes16.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes16 extends Bytes { - public static final Bytes16 DEFAULT = new Bytes16(new byte[16]); + public static final Bytes16 DEFAULT = new Bytes16(new byte[16]); - public Bytes16(byte[] value) { - super(16, value); - } + public Bytes16(byte[] value) { + super(16, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes17.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes17.java index d150eaeb0..78d64b4c0 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes17.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes17.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes17 extends Bytes { - public static final Bytes17 DEFAULT = new Bytes17(new byte[17]); + public static final Bytes17 DEFAULT = new Bytes17(new byte[17]); - public Bytes17(byte[] value) { - super(17, value); - } + public Bytes17(byte[] value) { + super(17, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes18.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes18.java index 98dfd9707..5c4456cef 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes18.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes18.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes18 extends Bytes { - public static final Bytes18 DEFAULT = new Bytes18(new byte[18]); + public static final Bytes18 DEFAULT = new Bytes18(new byte[18]); - public Bytes18(byte[] value) { - super(18, value); - } + public Bytes18(byte[] value) { + super(18, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes19.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes19.java index ad4c837cb..f7bde16d5 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes19.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes19.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes19 extends Bytes { - public static final Bytes19 DEFAULT = new Bytes19(new byte[19]); + public static final Bytes19 DEFAULT = new Bytes19(new byte[19]); - public Bytes19(byte[] value) { - super(19, value); - } + public Bytes19(byte[] value) { + super(19, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes2.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes2.java index bcea4ec86..76bbb2c80 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes2.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes2.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes2 extends Bytes { - public static final Bytes2 DEFAULT = new Bytes2(new byte[2]); + public static final Bytes2 DEFAULT = new Bytes2(new byte[2]); - public Bytes2(byte[] value) { - super(2, value); - } + public Bytes2(byte[] value) { + super(2, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes20.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes20.java index e91b50149..1a0f70b27 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes20.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes20.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes20 extends Bytes { - public static final Bytes20 DEFAULT = new Bytes20(new byte[20]); + public static final Bytes20 DEFAULT = new Bytes20(new byte[20]); - public Bytes20(byte[] value) { - super(20, value); - } + public Bytes20(byte[] value) { + super(20, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes21.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes21.java index ea6ee17b7..1920f52de 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes21.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes21.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes21 extends Bytes { - public static final Bytes21 DEFAULT = new Bytes21(new byte[21]); + public static final Bytes21 DEFAULT = new Bytes21(new byte[21]); - public Bytes21(byte[] value) { - super(21, value); - } + public Bytes21(byte[] value) { + super(21, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes22.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes22.java index 5ee107423..e786b261d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes22.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes22.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes22 extends Bytes { - public static final Bytes22 DEFAULT = new Bytes22(new byte[22]); + public static final Bytes22 DEFAULT = new Bytes22(new byte[22]); - public Bytes22(byte[] value) { - super(22, value); - } + public Bytes22(byte[] value) { + super(22, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes23.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes23.java index e909d361c..6cc523d5f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes23.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes23.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes23 extends Bytes { - public static final Bytes23 DEFAULT = new Bytes23(new byte[23]); + public static final Bytes23 DEFAULT = new Bytes23(new byte[23]); - public Bytes23(byte[] value) { - super(23, value); - } + public Bytes23(byte[] value) { + super(23, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes24.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes24.java index e57b363d7..128f7d0a5 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes24.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes24.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes24 extends Bytes { - public static final Bytes24 DEFAULT = new Bytes24(new byte[24]); + public static final Bytes24 DEFAULT = new Bytes24(new byte[24]); - public Bytes24(byte[] value) { - super(24, value); - } + public Bytes24(byte[] value) { + super(24, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes25.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes25.java index c394021b7..1bedf5d19 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes25.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes25.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes25 extends Bytes { - public static final Bytes25 DEFAULT = new Bytes25(new byte[25]); + public static final Bytes25 DEFAULT = new Bytes25(new byte[25]); - public Bytes25(byte[] value) { - super(25, value); - } + public Bytes25(byte[] value) { + super(25, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes26.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes26.java index a1d7c2e66..1da5d5bcd 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes26.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes26.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes26 extends Bytes { - public static final Bytes26 DEFAULT = new Bytes26(new byte[26]); + public static final Bytes26 DEFAULT = new Bytes26(new byte[26]); - public Bytes26(byte[] value) { - super(26, value); - } + public Bytes26(byte[] value) { + super(26, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes27.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes27.java index a60d2c0cd..82c3f6a60 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes27.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes27.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes27 extends Bytes { - public static final Bytes27 DEFAULT = new Bytes27(new byte[27]); + public static final Bytes27 DEFAULT = new Bytes27(new byte[27]); - public Bytes27(byte[] value) { - super(27, value); - } + public Bytes27(byte[] value) { + super(27, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes28.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes28.java index c548ebf45..ae6120c73 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes28.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes28.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes28 extends Bytes { - public static final Bytes28 DEFAULT = new Bytes28(new byte[28]); + public static final Bytes28 DEFAULT = new Bytes28(new byte[28]); - public Bytes28(byte[] value) { - super(28, value); - } + public Bytes28(byte[] value) { + super(28, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes29.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes29.java index 56716f36e..5094bb5c5 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes29.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes29.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes29 extends Bytes { - public static final Bytes29 DEFAULT = new Bytes29(new byte[29]); + public static final Bytes29 DEFAULT = new Bytes29(new byte[29]); - public Bytes29(byte[] value) { - super(29, value); - } + public Bytes29(byte[] value) { + super(29, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes3.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes3.java index 5b26fabfc..9e63aa800 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes3.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes3.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes3 extends Bytes { - public static final Bytes3 DEFAULT = new Bytes3(new byte[3]); + public static final Bytes3 DEFAULT = new Bytes3(new byte[3]); - public Bytes3(byte[] value) { - super(3, value); - } + public Bytes3(byte[] value) { + super(3, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes30.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes30.java index a7037ba3f..b21d7baa2 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes30.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes30.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes30 extends Bytes { - public static final Bytes30 DEFAULT = new Bytes30(new byte[30]); + public static final Bytes30 DEFAULT = new Bytes30(new byte[30]); - public Bytes30(byte[] value) { - super(30, value); - } + public Bytes30(byte[] value) { + super(30, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes31.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes31.java index d5665f1da..99dc0e100 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes31.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes31.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes31 extends Bytes { - public static final Bytes31 DEFAULT = new Bytes31(new byte[31]); + public static final Bytes31 DEFAULT = new Bytes31(new byte[31]); - public Bytes31(byte[] value) { - super(31, value); - } + public Bytes31(byte[] value) { + super(31, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes32.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes32.java index 39a07a7d4..ac486809b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes32.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes32.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes32 extends Bytes { - public static final Bytes32 DEFAULT = new Bytes32(new byte[32]); + public static final Bytes32 DEFAULT = new Bytes32(new byte[32]); - public Bytes32(byte[] value) { - super(32, value); - } + public Bytes32(byte[] value) { + super(32, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes4.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes4.java index 2772eecbd..2ec497102 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes4.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes4.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes4 extends Bytes { - public static final Bytes4 DEFAULT = new Bytes4(new byte[4]); + public static final Bytes4 DEFAULT = new Bytes4(new byte[4]); - public Bytes4(byte[] value) { - super(4, value); - } + public Bytes4(byte[] value) { + super(4, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes5.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes5.java index 8c8bc5759..09cfef632 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes5.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes5.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes5 extends Bytes { - public static final Bytes5 DEFAULT = new Bytes5(new byte[5]); + public static final Bytes5 DEFAULT = new Bytes5(new byte[5]); - public Bytes5(byte[] value) { - super(5, value); - } + public Bytes5(byte[] value) { + super(5, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes6.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes6.java index 94ce016df..91227b24e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes6.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes6.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes6 extends Bytes { - public static final Bytes6 DEFAULT = new Bytes6(new byte[6]); + public static final Bytes6 DEFAULT = new Bytes6(new byte[6]); - public Bytes6(byte[] value) { - super(6, value); - } + public Bytes6(byte[] value) { + super(6, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes7.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes7.java index 98937f1f4..b9526a593 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes7.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes7.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes7 extends Bytes { - public static final Bytes7 DEFAULT = new Bytes7(new byte[7]); + public static final Bytes7 DEFAULT = new Bytes7(new byte[7]); - public Bytes7(byte[] value) { - super(7, value); - } + public Bytes7(byte[] value) { + super(7, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes8.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes8.java index cad29b858..baf2f1b37 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes8.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes8.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes8 extends Bytes { - public static final Bytes8 DEFAULT = new Bytes8(new byte[8]); + public static final Bytes8 DEFAULT = new Bytes8(new byte[8]); - public Bytes8(byte[] value) { - super(8, value); - } + public Bytes8(byte[] value) { + super(8, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes9.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes9.java index c243df22b..a768dd1f8 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes9.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Bytes9.java @@ -11,9 +11,9 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Bytes9 extends Bytes { - public static final Bytes9 DEFAULT = new Bytes9(new byte[9]); + public static final Bytes9 DEFAULT = new Bytes9(new byte[9]); - public Bytes9(byte[] value) { - super(9, value); - } + public Bytes9(byte[] value) { + super(9, value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int104.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int104.java index 9a2ec17ba..d33517b15 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int104.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int104.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int104 extends Int { - public static final Int104 DEFAULT = new Int104(BigInteger.ZERO); + public static final Int104 DEFAULT = new Int104(BigInteger.ZERO); - public Int104(BigInteger value) { - super(104, value); - } + public Int104(BigInteger value) { + super(104, value); + } - public Int104(long value) { - this(BigInteger.valueOf(value)); - } + public Int104(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int112.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int112.java index 49673ce99..ef6ef2c7c 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int112.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int112.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int112 extends Int { - public static final Int112 DEFAULT = new Int112(BigInteger.ZERO); + public static final Int112 DEFAULT = new Int112(BigInteger.ZERO); - public Int112(BigInteger value) { - super(112, value); - } + public Int112(BigInteger value) { + super(112, value); + } - public Int112(long value) { - this(BigInteger.valueOf(value)); - } + public Int112(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int120.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int120.java index b5b152c4b..1b51db867 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int120.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int120.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int120 extends Int { - public static final Int120 DEFAULT = new Int120(BigInteger.ZERO); + public static final Int120 DEFAULT = new Int120(BigInteger.ZERO); - public Int120(BigInteger value) { - super(120, value); - } + public Int120(BigInteger value) { + super(120, value); + } - public Int120(long value) { - this(BigInteger.valueOf(value)); - } + public Int120(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int128.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int128.java index 90b3a53f9..96a5a0309 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int128.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int128.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int128 extends Int { - public static final Int128 DEFAULT = new Int128(BigInteger.ZERO); + public static final Int128 DEFAULT = new Int128(BigInteger.ZERO); - public Int128(BigInteger value) { - super(128, value); - } + public Int128(BigInteger value) { + super(128, value); + } - public Int128(long value) { - this(BigInteger.valueOf(value)); - } + public Int128(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int136.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int136.java index 136b4f477..410491357 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int136.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int136.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int136 extends Int { - public static final Int136 DEFAULT = new Int136(BigInteger.ZERO); + public static final Int136 DEFAULT = new Int136(BigInteger.ZERO); - public Int136(BigInteger value) { - super(136, value); - } + public Int136(BigInteger value) { + super(136, value); + } - public Int136(long value) { - this(BigInteger.valueOf(value)); - } + public Int136(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int144.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int144.java index c21f5f3c2..b13670a5d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int144.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int144.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int144 extends Int { - public static final Int144 DEFAULT = new Int144(BigInteger.ZERO); + public static final Int144 DEFAULT = new Int144(BigInteger.ZERO); - public Int144(BigInteger value) { - super(144, value); - } + public Int144(BigInteger value) { + super(144, value); + } - public Int144(long value) { - this(BigInteger.valueOf(value)); - } + public Int144(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int152.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int152.java index fdd5d003c..1946440bf 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int152.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int152.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int152 extends Int { - public static final Int152 DEFAULT = new Int152(BigInteger.ZERO); + public static final Int152 DEFAULT = new Int152(BigInteger.ZERO); - public Int152(BigInteger value) { - super(152, value); - } + public Int152(BigInteger value) { + super(152, value); + } - public Int152(long value) { - this(BigInteger.valueOf(value)); - } + public Int152(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int16.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int16.java index aeccfbae7..44acdde8a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int16.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int16.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int16 extends Int { - public static final Int16 DEFAULT = new Int16(BigInteger.ZERO); + public static final Int16 DEFAULT = new Int16(BigInteger.ZERO); - public Int16(BigInteger value) { - super(16, value); - } + public Int16(BigInteger value) { + super(16, value); + } - public Int16(long value) { - this(BigInteger.valueOf(value)); - } + public Int16(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int160.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int160.java index 583f6119d..77791ab1b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int160.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int160.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int160 extends Int { - public static final Int160 DEFAULT = new Int160(BigInteger.ZERO); + public static final Int160 DEFAULT = new Int160(BigInteger.ZERO); - public Int160(BigInteger value) { - super(160, value); - } + public Int160(BigInteger value) { + super(160, value); + } - public Int160(long value) { - this(BigInteger.valueOf(value)); - } + public Int160(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int168.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int168.java index cb06d52ab..a8ca224c3 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int168.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int168.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int168 extends Int { - public static final Int168 DEFAULT = new Int168(BigInteger.ZERO); + public static final Int168 DEFAULT = new Int168(BigInteger.ZERO); - public Int168(BigInteger value) { - super(168, value); - } + public Int168(BigInteger value) { + super(168, value); + } - public Int168(long value) { - this(BigInteger.valueOf(value)); - } + public Int168(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int176.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int176.java index 1349af1d6..323177e64 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int176.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int176.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int176 extends Int { - public static final Int176 DEFAULT = new Int176(BigInteger.ZERO); + public static final Int176 DEFAULT = new Int176(BigInteger.ZERO); - public Int176(BigInteger value) { - super(176, value); - } + public Int176(BigInteger value) { + super(176, value); + } - public Int176(long value) { - this(BigInteger.valueOf(value)); - } + public Int176(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int184.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int184.java index 1ca51bd6d..fbccb4e41 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int184.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int184.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int184 extends Int { - public static final Int184 DEFAULT = new Int184(BigInteger.ZERO); + public static final Int184 DEFAULT = new Int184(BigInteger.ZERO); - public Int184(BigInteger value) { - super(184, value); - } + public Int184(BigInteger value) { + super(184, value); + } - public Int184(long value) { - this(BigInteger.valueOf(value)); - } + public Int184(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int192.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int192.java index b92465da8..2fbf48fda 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int192.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int192.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int192 extends Int { - public static final Int192 DEFAULT = new Int192(BigInteger.ZERO); + public static final Int192 DEFAULT = new Int192(BigInteger.ZERO); - public Int192(BigInteger value) { - super(192, value); - } + public Int192(BigInteger value) { + super(192, value); + } - public Int192(long value) { - this(BigInteger.valueOf(value)); - } + public Int192(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int200.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int200.java index 17dbc62ff..74f9af613 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int200.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int200.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int200 extends Int { - public static final Int200 DEFAULT = new Int200(BigInteger.ZERO); + public static final Int200 DEFAULT = new Int200(BigInteger.ZERO); - public Int200(BigInteger value) { - super(200, value); - } + public Int200(BigInteger value) { + super(200, value); + } - public Int200(long value) { - this(BigInteger.valueOf(value)); - } + public Int200(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int208.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int208.java index 810a6e1ec..c43c5868a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int208.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int208.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int208 extends Int { - public static final Int208 DEFAULT = new Int208(BigInteger.ZERO); + public static final Int208 DEFAULT = new Int208(BigInteger.ZERO); - public Int208(BigInteger value) { - super(208, value); - } + public Int208(BigInteger value) { + super(208, value); + } - public Int208(long value) { - this(BigInteger.valueOf(value)); - } + public Int208(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int216.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int216.java index f9f667de4..873718777 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int216.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int216.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int216 extends Int { - public static final Int216 DEFAULT = new Int216(BigInteger.ZERO); + public static final Int216 DEFAULT = new Int216(BigInteger.ZERO); - public Int216(BigInteger value) { - super(216, value); - } + public Int216(BigInteger value) { + super(216, value); + } - public Int216(long value) { - this(BigInteger.valueOf(value)); - } + public Int216(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int224.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int224.java index 622eebaa1..a4dbaf562 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int224.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int224.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int224 extends Int { - public static final Int224 DEFAULT = new Int224(BigInteger.ZERO); + public static final Int224 DEFAULT = new Int224(BigInteger.ZERO); - public Int224(BigInteger value) { - super(224, value); - } + public Int224(BigInteger value) { + super(224, value); + } - public Int224(long value) { - this(BigInteger.valueOf(value)); - } + public Int224(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int232.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int232.java index 54be3173c..2218845f2 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int232.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int232.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int232 extends Int { - public static final Int232 DEFAULT = new Int232(BigInteger.ZERO); + public static final Int232 DEFAULT = new Int232(BigInteger.ZERO); - public Int232(BigInteger value) { - super(232, value); - } + public Int232(BigInteger value) { + super(232, value); + } - public Int232(long value) { - this(BigInteger.valueOf(value)); - } + public Int232(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int24.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int24.java index 3e2758b7a..9aae970d6 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int24.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int24.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int24 extends Int { - public static final Int24 DEFAULT = new Int24(BigInteger.ZERO); + public static final Int24 DEFAULT = new Int24(BigInteger.ZERO); - public Int24(BigInteger value) { - super(24, value); - } + public Int24(BigInteger value) { + super(24, value); + } - public Int24(long value) { - this(BigInteger.valueOf(value)); - } + public Int24(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int240.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int240.java index 8aa4dea45..1951baf9b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int240.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int240.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int240 extends Int { - public static final Int240 DEFAULT = new Int240(BigInteger.ZERO); + public static final Int240 DEFAULT = new Int240(BigInteger.ZERO); - public Int240(BigInteger value) { - super(240, value); - } + public Int240(BigInteger value) { + super(240, value); + } - public Int240(long value) { - this(BigInteger.valueOf(value)); - } + public Int240(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int248.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int248.java index 62fd45d30..842817e6d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int248.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int248.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int248 extends Int { - public static final Int248 DEFAULT = new Int248(BigInteger.ZERO); + public static final Int248 DEFAULT = new Int248(BigInteger.ZERO); - public Int248(BigInteger value) { - super(248, value); - } + public Int248(BigInteger value) { + super(248, value); + } - public Int248(long value) { - this(BigInteger.valueOf(value)); - } + public Int248(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int256.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int256.java index d039b70de..a85d1b337 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int256.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int256.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int256 extends Int { - public static final Int256 DEFAULT = new Int256(BigInteger.ZERO); + public static final Int256 DEFAULT = new Int256(BigInteger.ZERO); - public Int256(BigInteger value) { - super(256, value); - } + public Int256(BigInteger value) { + super(256, value); + } - public Int256(long value) { - this(BigInteger.valueOf(value)); - } + public Int256(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int32.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int32.java index a25c5078e..461f0fa66 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int32.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int32.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int32 extends Int { - public static final Int32 DEFAULT = new Int32(BigInteger.ZERO); + public static final Int32 DEFAULT = new Int32(BigInteger.ZERO); - public Int32(BigInteger value) { - super(32, value); - } + public Int32(BigInteger value) { + super(32, value); + } - public Int32(long value) { - this(BigInteger.valueOf(value)); - } + public Int32(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int40.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int40.java index 1905127f5..1d7087e5a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int40.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int40.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int40 extends Int { - public static final Int40 DEFAULT = new Int40(BigInteger.ZERO); + public static final Int40 DEFAULT = new Int40(BigInteger.ZERO); - public Int40(BigInteger value) { - super(40, value); - } + public Int40(BigInteger value) { + super(40, value); + } - public Int40(long value) { - this(BigInteger.valueOf(value)); - } + public Int40(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int48.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int48.java index 4fdb8d054..bab3525ba 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int48.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int48.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int48 extends Int { - public static final Int48 DEFAULT = new Int48(BigInteger.ZERO); + public static final Int48 DEFAULT = new Int48(BigInteger.ZERO); - public Int48(BigInteger value) { - super(48, value); - } + public Int48(BigInteger value) { + super(48, value); + } - public Int48(long value) { - this(BigInteger.valueOf(value)); - } + public Int48(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int56.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int56.java index 5170e2a62..7af6bcc4f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int56.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int56.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int56 extends Int { - public static final Int56 DEFAULT = new Int56(BigInteger.ZERO); + public static final Int56 DEFAULT = new Int56(BigInteger.ZERO); - public Int56(BigInteger value) { - super(56, value); - } + public Int56(BigInteger value) { + super(56, value); + } - public Int56(long value) { - this(BigInteger.valueOf(value)); - } + public Int56(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int64.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int64.java index 276ad56a4..7c47d3843 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int64.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int64.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int64 extends Int { - public static final Int64 DEFAULT = new Int64(BigInteger.ZERO); + public static final Int64 DEFAULT = new Int64(BigInteger.ZERO); - public Int64(BigInteger value) { - super(64, value); - } + public Int64(BigInteger value) { + super(64, value); + } - public Int64(long value) { - this(BigInteger.valueOf(value)); - } + public Int64(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int72.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int72.java index a05b0cc83..7836ecc0d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int72.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int72.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int72 extends Int { - public static final Int72 DEFAULT = new Int72(BigInteger.ZERO); + public static final Int72 DEFAULT = new Int72(BigInteger.ZERO); - public Int72(BigInteger value) { - super(72, value); - } + public Int72(BigInteger value) { + super(72, value); + } - public Int72(long value) { - this(BigInteger.valueOf(value)); - } + public Int72(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int8.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int8.java index 88c32d968..d71bf868a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int8.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int8.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int8 extends Int { - public static final Int8 DEFAULT = new Int8(BigInteger.ZERO); + public static final Int8 DEFAULT = new Int8(BigInteger.ZERO); - public Int8(BigInteger value) { - super(8, value); - } + public Int8(BigInteger value) { + super(8, value); + } - public Int8(long value) { - this(BigInteger.valueOf(value)); - } + public Int8(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int80.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int80.java index 16241eed6..17c9bb48b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int80.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int80.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int80 extends Int { - public static final Int80 DEFAULT = new Int80(BigInteger.ZERO); + public static final Int80 DEFAULT = new Int80(BigInteger.ZERO); - public Int80(BigInteger value) { - super(80, value); - } + public Int80(BigInteger value) { + super(80, value); + } - public Int80(long value) { - this(BigInteger.valueOf(value)); - } + public Int80(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int88.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int88.java index 50cae88c2..14ad0419b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int88.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int88.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int88 extends Int { - public static final Int88 DEFAULT = new Int88(BigInteger.ZERO); + public static final Int88 DEFAULT = new Int88(BigInteger.ZERO); - public Int88(BigInteger value) { - super(88, value); - } + public Int88(BigInteger value) { + super(88, value); + } - public Int88(long value) { - this(BigInteger.valueOf(value)); - } + public Int88(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int96.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int96.java index 93aa008c5..50cf141b3 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int96.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Int96.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Int96 extends Int { - public static final Int96 DEFAULT = new Int96(BigInteger.ZERO); + public static final Int96 DEFAULT = new Int96(BigInteger.ZERO); - public Int96(BigInteger value) { - super(96, value); - } + public Int96(BigInteger value) { + super(96, value); + } - public Int96(long value) { - this(BigInteger.valueOf(value)); - } + public Int96(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray1.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray1.java index 4a73b0ef0..9cc33b1ad 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray1.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray1.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray1 extends StaticArray { - public StaticArray1(List values) { - super(1, values); - } + public StaticArray1(List values) { + super(1, values); + } - @SafeVarargs - public StaticArray1(T... values) { - super(1, values); - } + @SafeVarargs + public StaticArray1(T... values) { + super(1, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray10.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray10.java index 28ac7d234..054813c5f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray10.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray10.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray10 extends StaticArray { - public StaticArray10(List values) { - super(10, values); - } + public StaticArray10(List values) { + super(10, values); + } - @SafeVarargs - public StaticArray10(T... values) { - super(10, values); - } + @SafeVarargs + public StaticArray10(T... values) { + super(10, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray11.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray11.java index db512ba48..4ed7d6bc7 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray11.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray11.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray11 extends StaticArray { - public StaticArray11(List values) { - super(11, values); - } + public StaticArray11(List values) { + super(11, values); + } - @SafeVarargs - public StaticArray11(T... values) { - super(11, values); - } + @SafeVarargs + public StaticArray11(T... values) { + super(11, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray12.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray12.java index 0a7cd1a45..6818e0126 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray12.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray12.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray12 extends StaticArray { - public StaticArray12(List values) { - super(12, values); - } + public StaticArray12(List values) { + super(12, values); + } - @SafeVarargs - public StaticArray12(T... values) { - super(12, values); - } + @SafeVarargs + public StaticArray12(T... values) { + super(12, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray128.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray128.java new file mode 100644 index 000000000..45f269b62 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray128.java @@ -0,0 +1,35 @@ +package org.fisco.bcos.web3j.abi.datatypes.generated; + +import java.util.List; +import org.fisco.bcos.web3j.abi.datatypes.StaticArray; +import org.fisco.bcos.web3j.abi.datatypes.Type; + +/** + * Auto generated code. + * + *

Do not modifiy! + * + *

Please use org.web3j.codegen.AbiTypesGenerator in the codegen module to update. + */ +public class StaticArray128 extends StaticArray { + @Deprecated + public StaticArray128(List values) { + super(128, values); + } + + @Deprecated + @SafeVarargs + public StaticArray128(T... values) { + super(128, values); + } + // + // public StaticArray128(Class type, List values) { + // super(type, 128, values); + // } + // + // @SafeVarargs + // public StaticArray128(Class type, T... values) { + // super(type, 128, values); + // } +} diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray13.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray13.java index d58c93e1e..37377cc34 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray13.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray13.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray13 extends StaticArray { - public StaticArray13(List values) { - super(13, values); - } + public StaticArray13(List values) { + super(13, values); + } - @SafeVarargs - public StaticArray13(T... values) { - super(13, values); - } + @SafeVarargs + public StaticArray13(T... values) { + super(13, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray14.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray14.java index 028b0cba8..4cdee32b8 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray14.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray14.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray14 extends StaticArray { - public StaticArray14(List values) { - super(14, values); - } + public StaticArray14(List values) { + super(14, values); + } - @SafeVarargs - public StaticArray14(T... values) { - super(14, values); - } + @SafeVarargs + public StaticArray14(T... values) { + super(14, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray15.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray15.java index 4222e6ded..5158cb1f7 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray15.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray15.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray15 extends StaticArray { - public StaticArray15(List values) { - super(15, values); - } + public StaticArray15(List values) { + super(15, values); + } - @SafeVarargs - public StaticArray15(T... values) { - super(15, values); - } + @SafeVarargs + public StaticArray15(T... values) { + super(15, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray16.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray16.java index e99b2646f..cf6811e99 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray16.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray16.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray16 extends StaticArray { - public StaticArray16(List values) { - super(16, values); - } + public StaticArray16(List values) { + super(16, values); + } - @SafeVarargs - public StaticArray16(T... values) { - super(16, values); - } + @SafeVarargs + public StaticArray16(T... values) { + super(16, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray17.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray17.java index 4147d74ee..1f9259cba 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray17.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray17.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray17 extends StaticArray { - public StaticArray17(List values) { - super(17, values); - } + public StaticArray17(List values) { + super(17, values); + } - @SafeVarargs - public StaticArray17(T... values) { - super(17, values); - } + @SafeVarargs + public StaticArray17(T... values) { + super(17, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray18.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray18.java index ab7540fb6..f0ec9b21a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray18.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray18.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray18 extends StaticArray { - public StaticArray18(List values) { - super(18, values); - } + public StaticArray18(List values) { + super(18, values); + } - @SafeVarargs - public StaticArray18(T... values) { - super(18, values); - } + @SafeVarargs + public StaticArray18(T... values) { + super(18, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray19.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray19.java index 64b07fc95..3addacbbb 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray19.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray19.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray19 extends StaticArray { - public StaticArray19(List values) { - super(19, values); - } + public StaticArray19(List values) { + super(19, values); + } - @SafeVarargs - public StaticArray19(T... values) { - super(19, values); - } + @SafeVarargs + public StaticArray19(T... values) { + super(19, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray2.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray2.java index aae088155..1f9601154 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray2.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray2.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray2 extends StaticArray { - public StaticArray2(List values) { - super(2, values); - } + public StaticArray2(List values) { + super(2, values); + } - @SafeVarargs - public StaticArray2(T... values) { - super(2, values); - } + @SafeVarargs + public StaticArray2(T... values) { + super(2, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray20.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray20.java index 06ffef016..7a6ab6f35 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray20.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray20.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray20 extends StaticArray { - public StaticArray20(List values) { - super(20, values); - } + public StaticArray20(List values) { + super(20, values); + } - @SafeVarargs - public StaticArray20(T... values) { - super(20, values); - } + @SafeVarargs + public StaticArray20(T... values) { + super(20, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray21.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray21.java index 8e4ae1561..3b37a0d43 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray21.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray21.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray21 extends StaticArray { - public StaticArray21(List values) { - super(21, values); - } + public StaticArray21(List values) { + super(21, values); + } - @SafeVarargs - public StaticArray21(T... values) { - super(21, values); - } + @SafeVarargs + public StaticArray21(T... values) { + super(21, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray22.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray22.java index 742d08c42..474cb1512 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray22.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray22.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray22 extends StaticArray { - public StaticArray22(List values) { - super(22, values); - } + public StaticArray22(List values) { + super(22, values); + } - @SafeVarargs - public StaticArray22(T... values) { - super(22, values); - } + @SafeVarargs + public StaticArray22(T... values) { + super(22, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray23.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray23.java index e6f9b8fa2..5b90d75b3 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray23.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray23.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray23 extends StaticArray { - public StaticArray23(List values) { - super(23, values); - } + public StaticArray23(List values) { + super(23, values); + } - @SafeVarargs - public StaticArray23(T... values) { - super(23, values); - } + @SafeVarargs + public StaticArray23(T... values) { + super(23, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray24.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray24.java index 58f106058..e07a6c709 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray24.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray24.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray24 extends StaticArray { - public StaticArray24(List values) { - super(24, values); - } + public StaticArray24(List values) { + super(24, values); + } - @SafeVarargs - public StaticArray24(T... values) { - super(24, values); - } + @SafeVarargs + public StaticArray24(T... values) { + super(24, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray25.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray25.java index 6e7e6e8d9..dfbb7b824 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray25.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray25.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray25 extends StaticArray { - public StaticArray25(List values) { - super(25, values); - } + public StaticArray25(List values) { + super(25, values); + } - @SafeVarargs - public StaticArray25(T... values) { - super(25, values); - } + @SafeVarargs + public StaticArray25(T... values) { + super(25, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray26.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray26.java index ebfd30386..5e241bcae 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray26.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray26.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray26 extends StaticArray { - public StaticArray26(List values) { - super(26, values); - } + public StaticArray26(List values) { + super(26, values); + } - @SafeVarargs - public StaticArray26(T... values) { - super(26, values); - } + @SafeVarargs + public StaticArray26(T... values) { + super(26, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray27.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray27.java index e95aba10f..115227ead 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray27.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray27.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray27 extends StaticArray { - public StaticArray27(List values) { - super(27, values); - } + public StaticArray27(List values) { + super(27, values); + } - @SafeVarargs - public StaticArray27(T... values) { - super(27, values); - } + @SafeVarargs + public StaticArray27(T... values) { + super(27, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray28.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray28.java index dd110034b..b65703899 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray28.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray28.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray28 extends StaticArray { - public StaticArray28(List values) { - super(28, values); - } + public StaticArray28(List values) { + super(28, values); + } - @SafeVarargs - public StaticArray28(T... values) { - super(28, values); - } + @SafeVarargs + public StaticArray28(T... values) { + super(28, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray29.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray29.java index cd48f121c..d8992a26f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray29.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray29.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray29 extends StaticArray { - public StaticArray29(List values) { - super(29, values); - } + public StaticArray29(List values) { + super(29, values); + } - @SafeVarargs - public StaticArray29(T... values) { - super(29, values); - } + @SafeVarargs + public StaticArray29(T... values) { + super(29, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray3.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray3.java index fb9ddc6a4..f907c4901 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray3.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray3.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray3 extends StaticArray { - public StaticArray3(List values) { - super(3, values); - } + public StaticArray3(List values) { + super(3, values); + } - @SafeVarargs - public StaticArray3(T... values) { - super(3, values); - } + @SafeVarargs + public StaticArray3(T... values) { + super(3, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray30.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray30.java index f0bc48712..88cbd53e9 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray30.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray30.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray30 extends StaticArray { - public StaticArray30(List values) { - super(30, values); - } + public StaticArray30(List values) { + super(30, values); + } - @SafeVarargs - public StaticArray30(T... values) { - super(30, values); - } + @SafeVarargs + public StaticArray30(T... values) { + super(30, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray31.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray31.java index d025494c4..373f65c0c 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray31.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray31.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray31 extends StaticArray { - public StaticArray31(List values) { - super(31, values); - } + public StaticArray31(List values) { + super(31, values); + } - @SafeVarargs - public StaticArray31(T... values) { - super(31, values); - } + @SafeVarargs + public StaticArray31(T... values) { + super(31, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray32.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray32.java index 08784e081..75075ab62 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray32.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray32.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray32 extends StaticArray { - public StaticArray32(List values) { - super(32, values); - } + public StaticArray32(List values) { + super(32, values); + } - @SafeVarargs - public StaticArray32(T... values) { - super(32, values); - } + @SafeVarargs + public StaticArray32(T... values) { + super(32, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray4.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray4.java index 76cd70aa7..43e99b8d2 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray4.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray4.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray4 extends StaticArray { - public StaticArray4(List values) { - super(4, values); - } + public StaticArray4(List values) { + super(4, values); + } - @SafeVarargs - public StaticArray4(T... values) { - super(4, values); - } + @SafeVarargs + public StaticArray4(T... values) { + super(4, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray5.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray5.java index ca5c2f0c3..243bafb99 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray5.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray5.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray5 extends StaticArray { - public StaticArray5(List values) { - super(5, values); - } + public StaticArray5(List values) { + super(5, values); + } - @SafeVarargs - public StaticArray5(T... values) { - super(5, values); - } + @SafeVarargs + public StaticArray5(T... values) { + super(5, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray6.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray6.java index 95aa525f1..72fd39329 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray6.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray6.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray6 extends StaticArray { - public StaticArray6(List values) { - super(6, values); - } + public StaticArray6(List values) { + super(6, values); + } - @SafeVarargs - public StaticArray6(T... values) { - super(6, values); - } + @SafeVarargs + public StaticArray6(T... values) { + super(6, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray7.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray7.java index de531a878..e070842bc 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray7.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray7.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray7 extends StaticArray { - public StaticArray7(List values) { - super(7, values); - } + public StaticArray7(List values) { + super(7, values); + } - @SafeVarargs - public StaticArray7(T... values) { - super(7, values); - } + @SafeVarargs + public StaticArray7(T... values) { + super(7, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray8.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray8.java index 43575ad81..31a99b78e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray8.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray8.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray8 extends StaticArray { - public StaticArray8(List values) { - super(8, values); - } + public StaticArray8(List values) { + super(8, values); + } - @SafeVarargs - public StaticArray8(T... values) { - super(8, values); - } + @SafeVarargs + public StaticArray8(T... values) { + super(8, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray9.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray9.java index 4fe85bf51..3a4bcfde8 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray9.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/StaticArray9.java @@ -13,12 +13,12 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class StaticArray9 extends StaticArray { - public StaticArray9(List values) { - super(9, values); - } + public StaticArray9(List values) { + super(9, values); + } - @SafeVarargs - public StaticArray9(T... values) { - super(9, values); - } + @SafeVarargs + public StaticArray9(T... values) { + super(9, values); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint104.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint104.java index b86f081ac..2f05b8c3d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint104.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint104.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint104 extends Uint { - public static final Uint104 DEFAULT = new Uint104(BigInteger.ZERO); + public static final Uint104 DEFAULT = new Uint104(BigInteger.ZERO); - public Uint104(BigInteger value) { - super(104, value); - } + public Uint104(BigInteger value) { + super(104, value); + } - public Uint104(long value) { - this(BigInteger.valueOf(value)); - } + public Uint104(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint112.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint112.java index 2c2383996..134e8a434 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint112.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint112.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint112 extends Uint { - public static final Uint112 DEFAULT = new Uint112(BigInteger.ZERO); + public static final Uint112 DEFAULT = new Uint112(BigInteger.ZERO); - public Uint112(BigInteger value) { - super(112, value); - } + public Uint112(BigInteger value) { + super(112, value); + } - public Uint112(long value) { - this(BigInteger.valueOf(value)); - } + public Uint112(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint120.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint120.java index 07c774354..e187ca508 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint120.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint120.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint120 extends Uint { - public static final Uint120 DEFAULT = new Uint120(BigInteger.ZERO); + public static final Uint120 DEFAULT = new Uint120(BigInteger.ZERO); - public Uint120(BigInteger value) { - super(120, value); - } + public Uint120(BigInteger value) { + super(120, value); + } - public Uint120(long value) { - this(BigInteger.valueOf(value)); - } + public Uint120(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint128.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint128.java index 558afc31d..9841a1a5d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint128.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint128.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint128 extends Uint { - public static final Uint128 DEFAULT = new Uint128(BigInteger.ZERO); + public static final Uint128 DEFAULT = new Uint128(BigInteger.ZERO); - public Uint128(BigInteger value) { - super(128, value); - } + public Uint128(BigInteger value) { + super(128, value); + } - public Uint128(long value) { - this(BigInteger.valueOf(value)); - } + public Uint128(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint136.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint136.java index ddaeac62e..e83867a7a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint136.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint136.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint136 extends Uint { - public static final Uint136 DEFAULT = new Uint136(BigInteger.ZERO); + public static final Uint136 DEFAULT = new Uint136(BigInteger.ZERO); - public Uint136(BigInteger value) { - super(136, value); - } + public Uint136(BigInteger value) { + super(136, value); + } - public Uint136(long value) { - this(BigInteger.valueOf(value)); - } + public Uint136(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint144.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint144.java index b26d7a014..2987c2f76 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint144.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint144.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint144 extends Uint { - public static final Uint144 DEFAULT = new Uint144(BigInteger.ZERO); + public static final Uint144 DEFAULT = new Uint144(BigInteger.ZERO); - public Uint144(BigInteger value) { - super(144, value); - } + public Uint144(BigInteger value) { + super(144, value); + } - public Uint144(long value) { - this(BigInteger.valueOf(value)); - } + public Uint144(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint152.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint152.java index dadaa86d3..63ed12237 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint152.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint152.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint152 extends Uint { - public static final Uint152 DEFAULT = new Uint152(BigInteger.ZERO); + public static final Uint152 DEFAULT = new Uint152(BigInteger.ZERO); - public Uint152(BigInteger value) { - super(152, value); - } + public Uint152(BigInteger value) { + super(152, value); + } - public Uint152(long value) { - this(BigInteger.valueOf(value)); - } + public Uint152(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint16.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint16.java index d7b404f41..d3b7b2a8f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint16.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint16.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint16 extends Uint { - public static final Uint16 DEFAULT = new Uint16(BigInteger.ZERO); + public static final Uint16 DEFAULT = new Uint16(BigInteger.ZERO); - public Uint16(BigInteger value) { - super(16, value); - } + public Uint16(BigInteger value) { + super(16, value); + } - public Uint16(long value) { - this(BigInteger.valueOf(value)); - } + public Uint16(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint160.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint160.java index 5f264b6d4..702d1c42d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint160.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint160.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint160 extends Uint { - public static final Uint160 DEFAULT = new Uint160(BigInteger.ZERO); + public static final Uint160 DEFAULT = new Uint160(BigInteger.ZERO); - public Uint160(BigInteger value) { - super(160, value); - } + public Uint160(BigInteger value) { + super(160, value); + } - public Uint160(long value) { - this(BigInteger.valueOf(value)); - } + public Uint160(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint168.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint168.java index 3e1a8ff89..b7ef48084 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint168.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint168.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint168 extends Uint { - public static final Uint168 DEFAULT = new Uint168(BigInteger.ZERO); + public static final Uint168 DEFAULT = new Uint168(BigInteger.ZERO); - public Uint168(BigInteger value) { - super(168, value); - } + public Uint168(BigInteger value) { + super(168, value); + } - public Uint168(long value) { - this(BigInteger.valueOf(value)); - } + public Uint168(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint176.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint176.java index 7c8554878..5f06ad0de 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint176.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint176.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint176 extends Uint { - public static final Uint176 DEFAULT = new Uint176(BigInteger.ZERO); + public static final Uint176 DEFAULT = new Uint176(BigInteger.ZERO); - public Uint176(BigInteger value) { - super(176, value); - } + public Uint176(BigInteger value) { + super(176, value); + } - public Uint176(long value) { - this(BigInteger.valueOf(value)); - } + public Uint176(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint184.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint184.java index 3298195d5..ad1600d55 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint184.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint184.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint184 extends Uint { - public static final Uint184 DEFAULT = new Uint184(BigInteger.ZERO); + public static final Uint184 DEFAULT = new Uint184(BigInteger.ZERO); - public Uint184(BigInteger value) { - super(184, value); - } + public Uint184(BigInteger value) { + super(184, value); + } - public Uint184(long value) { - this(BigInteger.valueOf(value)); - } + public Uint184(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint192.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint192.java index 8a4c97bcd..2276cb820 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint192.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint192.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint192 extends Uint { - public static final Uint192 DEFAULT = new Uint192(BigInteger.ZERO); + public static final Uint192 DEFAULT = new Uint192(BigInteger.ZERO); - public Uint192(BigInteger value) { - super(192, value); - } + public Uint192(BigInteger value) { + super(192, value); + } - public Uint192(long value) { - this(BigInteger.valueOf(value)); - } + public Uint192(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint200.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint200.java index 6d39fee46..df10dda57 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint200.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint200.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint200 extends Uint { - public static final Uint200 DEFAULT = new Uint200(BigInteger.ZERO); + public static final Uint200 DEFAULT = new Uint200(BigInteger.ZERO); - public Uint200(BigInteger value) { - super(200, value); - } + public Uint200(BigInteger value) { + super(200, value); + } - public Uint200(long value) { - this(BigInteger.valueOf(value)); - } + public Uint200(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint208.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint208.java index e36cc6253..580665070 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint208.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint208.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint208 extends Uint { - public static final Uint208 DEFAULT = new Uint208(BigInteger.ZERO); + public static final Uint208 DEFAULT = new Uint208(BigInteger.ZERO); - public Uint208(BigInteger value) { - super(208, value); - } + public Uint208(BigInteger value) { + super(208, value); + } - public Uint208(long value) { - this(BigInteger.valueOf(value)); - } + public Uint208(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint216.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint216.java index 00c0998f0..7ba8b3a16 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint216.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint216.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint216 extends Uint { - public static final Uint216 DEFAULT = new Uint216(BigInteger.ZERO); + public static final Uint216 DEFAULT = new Uint216(BigInteger.ZERO); - public Uint216(BigInteger value) { - super(216, value); - } + public Uint216(BigInteger value) { + super(216, value); + } - public Uint216(long value) { - this(BigInteger.valueOf(value)); - } + public Uint216(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint224.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint224.java index 4cbb8603f..fa000f772 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint224.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint224.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint224 extends Uint { - public static final Uint224 DEFAULT = new Uint224(BigInteger.ZERO); + public static final Uint224 DEFAULT = new Uint224(BigInteger.ZERO); - public Uint224(BigInteger value) { - super(224, value); - } + public Uint224(BigInteger value) { + super(224, value); + } - public Uint224(long value) { - this(BigInteger.valueOf(value)); - } + public Uint224(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint232.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint232.java index b8e7b2cfa..61eb440f3 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint232.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint232.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint232 extends Uint { - public static final Uint232 DEFAULT = new Uint232(BigInteger.ZERO); + public static final Uint232 DEFAULT = new Uint232(BigInteger.ZERO); - public Uint232(BigInteger value) { - super(232, value); - } + public Uint232(BigInteger value) { + super(232, value); + } - public Uint232(long value) { - this(BigInteger.valueOf(value)); - } + public Uint232(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint24.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint24.java index be64fa370..ba89da34e 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint24.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint24.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint24 extends Uint { - public static final Uint24 DEFAULT = new Uint24(BigInteger.ZERO); + public static final Uint24 DEFAULT = new Uint24(BigInteger.ZERO); - public Uint24(BigInteger value) { - super(24, value); - } + public Uint24(BigInteger value) { + super(24, value); + } - public Uint24(long value) { - this(BigInteger.valueOf(value)); - } + public Uint24(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint240.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint240.java index 82d1f7274..bd5adb14b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint240.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint240.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint240 extends Uint { - public static final Uint240 DEFAULT = new Uint240(BigInteger.ZERO); + public static final Uint240 DEFAULT = new Uint240(BigInteger.ZERO); - public Uint240(BigInteger value) { - super(240, value); - } + public Uint240(BigInteger value) { + super(240, value); + } - public Uint240(long value) { - this(BigInteger.valueOf(value)); - } + public Uint240(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint248.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint248.java index ab63b1477..464eb8050 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint248.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint248.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint248 extends Uint { - public static final Uint248 DEFAULT = new Uint248(BigInteger.ZERO); + public static final Uint248 DEFAULT = new Uint248(BigInteger.ZERO); - public Uint248(BigInteger value) { - super(248, value); - } + public Uint248(BigInteger value) { + super(248, value); + } - public Uint248(long value) { - this(BigInteger.valueOf(value)); - } + public Uint248(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint256.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint256.java index bbf5124d2..8fb9dc776 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint256.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint256.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint256 extends Uint { - public static final Uint256 DEFAULT = new Uint256(BigInteger.ZERO); + public static final Uint256 DEFAULT = new Uint256(BigInteger.ZERO); - public Uint256(BigInteger value) { - super(256, value); - } + public Uint256(BigInteger value) { + super(256, value); + } - public Uint256(long value) { - this(BigInteger.valueOf(value)); - } + public Uint256(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint32.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint32.java index 9a89b5719..55fa9872f 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint32.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint32.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint32 extends Uint { - public static final Uint32 DEFAULT = new Uint32(BigInteger.ZERO); + public static final Uint32 DEFAULT = new Uint32(BigInteger.ZERO); - public Uint32(BigInteger value) { - super(32, value); - } + public Uint32(BigInteger value) { + super(32, value); + } - public Uint32(long value) { - this(BigInteger.valueOf(value)); - } + public Uint32(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint40.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint40.java index e6564667b..fc89dc7eb 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint40.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint40.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint40 extends Uint { - public static final Uint40 DEFAULT = new Uint40(BigInteger.ZERO); + public static final Uint40 DEFAULT = new Uint40(BigInteger.ZERO); - public Uint40(BigInteger value) { - super(40, value); - } + public Uint40(BigInteger value) { + super(40, value); + } - public Uint40(long value) { - this(BigInteger.valueOf(value)); - } + public Uint40(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint48.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint48.java index 9a130bc01..2057915e6 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint48.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint48.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint48 extends Uint { - public static final Uint48 DEFAULT = new Uint48(BigInteger.ZERO); + public static final Uint48 DEFAULT = new Uint48(BigInteger.ZERO); - public Uint48(BigInteger value) { - super(48, value); - } + public Uint48(BigInteger value) { + super(48, value); + } - public Uint48(long value) { - this(BigInteger.valueOf(value)); - } + public Uint48(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint56.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint56.java index 3754a767d..7464df5b5 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint56.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint56.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint56 extends Uint { - public static final Uint56 DEFAULT = new Uint56(BigInteger.ZERO); + public static final Uint56 DEFAULT = new Uint56(BigInteger.ZERO); - public Uint56(BigInteger value) { - super(56, value); - } + public Uint56(BigInteger value) { + super(56, value); + } - public Uint56(long value) { - this(BigInteger.valueOf(value)); - } + public Uint56(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint64.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint64.java index 062333e62..2924cc757 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint64.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint64.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint64 extends Uint { - public static final Uint64 DEFAULT = new Uint64(BigInteger.ZERO); + public static final Uint64 DEFAULT = new Uint64(BigInteger.ZERO); - public Uint64(BigInteger value) { - super(64, value); - } + public Uint64(BigInteger value) { + super(64, value); + } - public Uint64(long value) { - this(BigInteger.valueOf(value)); - } + public Uint64(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint72.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint72.java index 795c4b97d..b272aad3b 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint72.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint72.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint72 extends Uint { - public static final Uint72 DEFAULT = new Uint72(BigInteger.ZERO); + public static final Uint72 DEFAULT = new Uint72(BigInteger.ZERO); - public Uint72(BigInteger value) { - super(72, value); - } + public Uint72(BigInteger value) { + super(72, value); + } - public Uint72(long value) { - this(BigInteger.valueOf(value)); - } + public Uint72(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint8.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint8.java index 6e728a1b0..38fc49caf 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint8.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint8.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint8 extends Uint { - public static final Uint8 DEFAULT = new Uint8(BigInteger.ZERO); + public static final Uint8 DEFAULT = new Uint8(BigInteger.ZERO); - public Uint8(BigInteger value) { - super(8, value); - } + public Uint8(BigInteger value) { + super(8, value); + } - public Uint8(long value) { - this(BigInteger.valueOf(value)); - } + public Uint8(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint80.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint80.java index 629991fc6..7696d71b3 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint80.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint80.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint80 extends Uint { - public static final Uint80 DEFAULT = new Uint80(BigInteger.ZERO); + public static final Uint80 DEFAULT = new Uint80(BigInteger.ZERO); - public Uint80(BigInteger value) { - super(80, value); - } + public Uint80(BigInteger value) { + super(80, value); + } - public Uint80(long value) { - this(BigInteger.valueOf(value)); - } + public Uint80(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint88.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint88.java index ef0a9d013..ade53eb1a 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint88.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint88.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint88 extends Uint { - public static final Uint88 DEFAULT = new Uint88(BigInteger.ZERO); + public static final Uint88 DEFAULT = new Uint88(BigInteger.ZERO); - public Uint88(BigInteger value) { - super(88, value); - } + public Uint88(BigInteger value) { + super(88, value); + } - public Uint88(long value) { - this(BigInteger.valueOf(value)); - } + public Uint88(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint96.java b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint96.java index 3ad6d1989..e76e1306d 100644 --- a/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint96.java +++ b/src/main/java/org/fisco/bcos/web3j/abi/datatypes/generated/Uint96.java @@ -12,13 +12,13 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public class Uint96 extends Uint { - public static final Uint96 DEFAULT = new Uint96(BigInteger.ZERO); + public static final Uint96 DEFAULT = new Uint96(BigInteger.ZERO); - public Uint96(BigInteger value) { - super(96, value); - } + public Uint96(BigInteger value) { + super(96, value); + } - public Uint96(long value) { - this(BigInteger.valueOf(value)); - } + public Uint96(long value) { + this(BigInteger.valueOf(value)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesGenerator.java index c754381f4..5e3f952e8 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesGenerator.java @@ -11,205 +11,227 @@ /** Generator class for creating all the different numeric type variants. */ public class AbiTypesGenerator extends Generator { - private static final String CODEGEN_WARNING = buildWarning(AbiTypesGenerator.class); + private static final String CODEGEN_WARNING = buildWarning(AbiTypesGenerator.class); - private static final String DEFAULT = "DEFAULT"; + private static final String DEFAULT = "DEFAULT"; - public static void main(String[] args) throws Exception { - AbiTypesGenerator abiTypesGenerator = new AbiTypesGenerator(); - if (args.length == 1) { - abiTypesGenerator.generate(args[0]); - } else { - abiTypesGenerator.generate(System.getProperty("user.dir") + "/abi/src/main/java/"); - } - } - - private void generate(String destinationDir) throws IOException { - generateIntTypes(Int.class, destinationDir); - generateIntTypes(Uint.class, destinationDir); - - // TODO: Enable once Solidity supports fixed types - see - // https://github.com/ethereum/solidity/issues/409 - // generateFixedTypes(Fixed.class, destinationDir); - // generateFixedTypes(Ufixed.class, destinationDir); - - generateBytesTypes(Bytes.class, destinationDir); - generateStaticArrayTypes(StaticArray.class, destinationDir); - } - - private void generateIntTypes(Class superclass, String path) - throws IOException { - String packageName = createPackageName(superclass); - ClassName className; - - for (int bitSize = 8; bitSize <= Type.MAX_BIT_LENGTH; bitSize += 8) { - className = ClassName.get(packageName, superclass.getSimpleName() + bitSize); - - MethodSpec constructorSpec = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter(BigInteger.class, "value") - .addStatement("super($L, $N)", bitSize, "value") - .build(); - - MethodSpec overideConstructorSpec = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter(long.class, "value") - .addStatement("this(BigInteger.valueOf(value))") - .build(); - - FieldSpec defaultFieldSpec = - FieldSpec.builder(className, DEFAULT, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T(BigInteger.ZERO)", className) - .build(); - - TypeSpec intType = - TypeSpec.classBuilder(className.simpleName()) - .addJavadoc(CODEGEN_WARNING) - .superclass(superclass) - .addModifiers(Modifier.PUBLIC) - .addField(defaultFieldSpec) - .addMethods(Arrays.asList(constructorSpec, overideConstructorSpec)) - .build(); - - write(packageName, intType, path); + public static void main(String[] args) throws Exception { + AbiTypesGenerator abiTypesGenerator = new AbiTypesGenerator(); + if (args.length == 1) { + abiTypesGenerator.generate(args[0]); + } else { + abiTypesGenerator.generate(System.getProperty("user.dir") + "/abi/src/main/java/"); + } } - } - private void generateFixedTypes(Class superclass, String path) - throws IOException { - String packageName = createPackageName(superclass); - ClassName className; + private void generate(String destinationDir) throws IOException { + generateIntTypes(Int.class, destinationDir); + generateIntTypes(Uint.class, destinationDir); + + // TODO: Enable once Solidity supports fixed types - see + // https://github.com/ethereum/solidity/issues/409 + // generateFixedTypes(Fixed.class, destinationDir); + // generateFixedTypes(Ufixed.class, destinationDir); - for (int mBitSize = 8; mBitSize < Type.MAX_BIT_LENGTH; mBitSize += 8) { - inner: - for (int nBitSize = 8; nBitSize < Type.MAX_BIT_LENGTH; nBitSize += 8) { + generateBytesTypes(Bytes.class, destinationDir); + generateStaticArrayTypes(StaticArray.class, destinationDir); + } - if (mBitSize + nBitSize > Type.MAX_BIT_LENGTH) { - break inner; + private void generateIntTypes(Class superclass, String path) + throws IOException { + String packageName = createPackageName(superclass); + ClassName className; + + for (int bitSize = 8; bitSize <= Type.MAX_BIT_LENGTH; bitSize += 8) { + className = ClassName.get(packageName, superclass.getSimpleName() + bitSize); + + MethodSpec constructorSpec = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(BigInteger.class, "value") + .addStatement("super($L, $N)", bitSize, "value") + .build(); + + MethodSpec overideConstructorSpec = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(long.class, "value") + .addStatement("this(BigInteger.valueOf(value))") + .build(); + + FieldSpec defaultFieldSpec = + FieldSpec.builder( + className, + DEFAULT, + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer("new $T(BigInteger.ZERO)", className) + .build(); + + TypeSpec intType = + TypeSpec.classBuilder(className.simpleName()) + .addJavadoc(CODEGEN_WARNING) + .superclass(superclass) + .addModifiers(Modifier.PUBLIC) + .addField(defaultFieldSpec) + .addMethods(Arrays.asList(constructorSpec, overideConstructorSpec)) + .build(); + + write(packageName, intType, path); } + } - MethodSpec constructorSpec1 = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter(BigInteger.class, "value") - .addStatement("super($L, $L, $N)", mBitSize, nBitSize, "value") - .build(); - - MethodSpec constructorSpec2 = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter(int.class, "mBitSize") - .addParameter(int.class, "nBitSize") - .addParameter(BigInteger.class, "m") - .addParameter(BigInteger.class, "n") - .addStatement("super($L, $L, $N, $N)", mBitSize, nBitSize, "m", "n") - .build(); - - className = - ClassName.get(packageName, superclass.getSimpleName() + mBitSize + "x" + nBitSize); - - FieldSpec defaultFieldSpec = - FieldSpec.builder(className, DEFAULT, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T(BigInteger.ZERO)", className) - .build(); - - TypeSpec fixedType = - TypeSpec.classBuilder(className.simpleName()) - .addJavadoc(CODEGEN_WARNING) - .superclass(superclass) - .addModifiers(Modifier.PUBLIC) - .addField(defaultFieldSpec) - .addMethod(constructorSpec1) - .addMethod(constructorSpec2) - .build(); - - write(packageName, fixedType, path); - } + private void generateFixedTypes(Class superclass, String path) + throws IOException { + String packageName = createPackageName(superclass); + ClassName className; + + for (int mBitSize = 8; mBitSize < Type.MAX_BIT_LENGTH; mBitSize += 8) { + inner: + for (int nBitSize = 8; nBitSize < Type.MAX_BIT_LENGTH; nBitSize += 8) { + + if (mBitSize + nBitSize > Type.MAX_BIT_LENGTH) { + break inner; + } + + MethodSpec constructorSpec1 = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(BigInteger.class, "value") + .addStatement("super($L, $L, $N)", mBitSize, nBitSize, "value") + .build(); + + MethodSpec constructorSpec2 = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "mBitSize") + .addParameter(int.class, "nBitSize") + .addParameter(BigInteger.class, "m") + .addParameter(BigInteger.class, "n") + .addStatement("super($L, $L, $N, $N)", mBitSize, nBitSize, "m", "n") + .build(); + + className = + ClassName.get( + packageName, + superclass.getSimpleName() + mBitSize + "x" + nBitSize); + + FieldSpec defaultFieldSpec = + FieldSpec.builder( + className, + DEFAULT, + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer("new $T(BigInteger.ZERO)", className) + .build(); + + TypeSpec fixedType = + TypeSpec.classBuilder(className.simpleName()) + .addJavadoc(CODEGEN_WARNING) + .superclass(superclass) + .addModifiers(Modifier.PUBLIC) + .addField(defaultFieldSpec) + .addMethod(constructorSpec1) + .addMethod(constructorSpec2) + .build(); + + write(packageName, fixedType, path); + } + } } - } - - private void generateBytesTypes(Class superclass, String path) - throws IOException { - String packageName = createPackageName(superclass); - ClassName className; - - for (int byteSize = 1; byteSize <= 32; byteSize++) { - - MethodSpec constructorSpec = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter(byte[].class, "value") - .addStatement("super($L, $N)", byteSize, "value") - .build(); - - className = ClassName.get(packageName, superclass.getSimpleName() + byteSize); - - FieldSpec defaultFieldSpec = - FieldSpec.builder(className, DEFAULT, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T(new byte[$L])", className, byteSize) - .build(); - - TypeSpec bytesType = - TypeSpec.classBuilder(className.simpleName()) - .addJavadoc(CODEGEN_WARNING) - .superclass(superclass) - .addModifiers(Modifier.PUBLIC) - .addField(defaultFieldSpec) - .addMethod(constructorSpec) - .build(); - - write(packageName, bytesType, path); + + private void generateBytesTypes(Class superclass, String path) + throws IOException { + String packageName = createPackageName(superclass); + ClassName className; + + for (int byteSize = 1; byteSize <= 32; byteSize++) { + + MethodSpec constructorSpec = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(byte[].class, "value") + .addStatement("super($L, $N)", byteSize, "value") + .build(); + + className = ClassName.get(packageName, superclass.getSimpleName() + byteSize); + + FieldSpec defaultFieldSpec = + FieldSpec.builder( + className, + DEFAULT, + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer("new $T(new byte[$L])", className, byteSize) + .build(); + + TypeSpec bytesType = + TypeSpec.classBuilder(className.simpleName()) + .addJavadoc(CODEGEN_WARNING) + .superclass(superclass) + .addModifiers(Modifier.PUBLIC) + .addField(defaultFieldSpec) + .addMethod(constructorSpec) + .build(); + + write(packageName, bytesType, path); + } } - } - - private void generateStaticArrayTypes(Class superclass, String path) - throws IOException { - String packageName = createPackageName(superclass); - ClassName className; - - for (int length = 1; length <= StaticArray.MAX_SIZE_OF_STATIC_ARRAY; length++) { - - TypeVariableName typeVariableName = TypeVariableName.get("T").withBounds(Type.class); - - MethodSpec constructorSpec = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PUBLIC) - .addParameter( - ParameterizedTypeName.get(ClassName.get(List.class), typeVariableName), "values") - .addStatement("super($L, $N)", length, "values") - .build(); - - MethodSpec arrayOverloadConstructorSpec = - MethodSpec.constructorBuilder() - .addAnnotation(SafeVarargs.class) - .addModifiers(Modifier.PUBLIC) - .addParameter(ArrayTypeName.of(typeVariableName), "values") - .varargs() - .addStatement("super($L, $N)", length, "values") - .build(); - - className = ClassName.get(packageName, superclass.getSimpleName() + length); - - TypeSpec bytesType = - TypeSpec.classBuilder(className.simpleName()) - .addTypeVariable(typeVariableName) - .addJavadoc(CODEGEN_WARNING) - .superclass(ParameterizedTypeName.get(ClassName.get(superclass), typeVariableName)) - .addModifiers(Modifier.PUBLIC) - .addMethods(Arrays.asList(constructorSpec, arrayOverloadConstructorSpec)) - .build(); - - write(packageName, bytesType, path); + + private void generateStaticArrayTypes(Class superclass, String path) + throws IOException { + String packageName = createPackageName(superclass); + ClassName className; + + for (int length = 1; length <= StaticArray.MAX_SIZE_OF_STATIC_ARRAY; length++) { + + TypeVariableName typeVariableName = TypeVariableName.get("T").withBounds(Type.class); + + MethodSpec constructorSpec = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter( + ParameterizedTypeName.get( + ClassName.get(List.class), typeVariableName), + "values") + .addStatement("super($L, $N)", length, "values") + .build(); + + MethodSpec arrayOverloadConstructorSpec = + MethodSpec.constructorBuilder() + .addAnnotation(SafeVarargs.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(ArrayTypeName.of(typeVariableName), "values") + .varargs() + .addStatement("super($L, $N)", length, "values") + .build(); + + className = ClassName.get(packageName, superclass.getSimpleName() + length); + + TypeSpec bytesType = + TypeSpec.classBuilder(className.simpleName()) + .addTypeVariable(typeVariableName) + .addJavadoc(CODEGEN_WARNING) + .superclass( + ParameterizedTypeName.get( + ClassName.get(superclass), typeVariableName)) + .addModifiers(Modifier.PUBLIC) + .addMethods( + Arrays.asList(constructorSpec, arrayOverloadConstructorSpec)) + .build(); + + write(packageName, bytesType, path); + } } - } - static String createPackageName(Class cls) { - return getPackageName(cls) + ".generated"; - } + static String createPackageName(Class cls) { + return getPackageName(cls) + ".generated"; + } - static String getPackageName(Class cls) { - return cls.getPackage().getName(); - } + static String getPackageName(Class cls) { + return cls.getPackage().getName(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesMapperGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesMapperGenerator.java index 2747472fa..188e76da0 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesMapperGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/AbiTypesMapperGenerator.java @@ -21,133 +21,153 @@ /** Generator class for creating all the different numeric type variants. */ public class AbiTypesMapperGenerator extends Generator { - private static final String TYPE = "type"; - - public static void main(String[] args) throws Exception { - AbiTypesMapperGenerator abiTypesMapperGenerator = new AbiTypesMapperGenerator(); - if (args.length == 1) { - abiTypesMapperGenerator.generate(args[0]); - } else { - abiTypesMapperGenerator.generate(System.getProperty("user.dir") + "/core/src/main/java/"); + private static final String TYPE = "type"; + + public static void main(String[] args) throws Exception { + AbiTypesMapperGenerator abiTypesMapperGenerator = new AbiTypesMapperGenerator(); + if (args.length == 1) { + abiTypesMapperGenerator.generate(args[0]); + } else { + abiTypesMapperGenerator.generate( + System.getProperty("user.dir") + "/core/src/main/java/"); + } } - } - private void generate(String destinationDir) throws IOException { - - String typesPackageName = "org.fisco.bcos.web3j.abi.datatypes"; - String autoGeneratedTypesPackageName = typesPackageName + ".generated"; - - MethodSpec.Builder builder = - MethodSpec.methodBuilder("getType") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addParameter(String.class, TYPE) - .returns( - ParameterizedTypeName.get( - ClassName.get(Class.class), WildcardTypeName.subtypeOf(Object.class))) - .beginControlFlow("switch (type)"); - - builder = addTypes(builder, typesPackageName); - builder = addGeneratedTypes(builder, autoGeneratedTypesPackageName); - builder = - builder.addStatement( - "default:\nthrow new $T($S\n+ $N)", - UnsupportedOperationException.class, - "Unsupported type encountered: ", - TYPE); - builder.endControlFlow(); - - MethodSpec methodSpec = builder.build(); - - MethodSpec constructorSpec = - MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build(); - - TypeSpec typeSpec = - TypeSpec.classBuilder("AbiTypes") - .addJavadoc(buildWarning(AbiTypesMapperGenerator.class)) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addMethod(constructorSpec) - .addMethod(methodSpec) - .build(); - - write(autoGeneratedTypesPackageName, typeSpec, destinationDir); - } - - private MethodSpec.Builder addTypes(MethodSpec.Builder builder, String packageName) { - builder = addStatement(builder, packageName, Address.TYPE_NAME, Address.class.getSimpleName()); - - builder = addStatement(builder, packageName, Bool.TYPE_NAME, Bool.class.getSimpleName()); - - builder = - addStatement(builder, packageName, Utf8String.TYPE_NAME, Utf8String.class.getSimpleName()); - - builder = - addStatement( - builder, packageName, DynamicBytes.TYPE_NAME, DynamicBytes.class.getSimpleName()); + private void generate(String destinationDir) throws IOException { + + String typesPackageName = "org.fisco.bcos.web3j.abi.datatypes"; + String autoGeneratedTypesPackageName = typesPackageName + ".generated"; + + MethodSpec.Builder builder = + MethodSpec.methodBuilder("getType") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addParameter(String.class, TYPE) + .returns( + ParameterizedTypeName.get( + ClassName.get(Class.class), + WildcardTypeName.subtypeOf(Object.class))) + .beginControlFlow("switch (type)"); + + builder = addTypes(builder, typesPackageName); + builder = addGeneratedTypes(builder, autoGeneratedTypesPackageName); + builder = + builder.addStatement( + "default:\nthrow new $T($S\n+ $N)", + UnsupportedOperationException.class, + "Unsupported type encountered: ", + TYPE); + builder.endControlFlow(); + + MethodSpec methodSpec = builder.build(); + + MethodSpec constructorSpec = + MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build(); + + TypeSpec typeSpec = + TypeSpec.classBuilder("AbiTypes") + .addJavadoc(buildWarning(AbiTypesMapperGenerator.class)) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addMethod(constructorSpec) + .addMethod(methodSpec) + .build(); + + write(autoGeneratedTypesPackageName, typeSpec, destinationDir); + } - // TODO: Fixed array & dynamic array support - return builder; - } + private MethodSpec.Builder addTypes(MethodSpec.Builder builder, String packageName) { + builder = + addStatement( + builder, packageName, Address.TYPE_NAME, Address.class.getSimpleName()); + + builder = addStatement(builder, packageName, Bool.TYPE_NAME, Bool.class.getSimpleName()); + + builder = + addStatement( + builder, + packageName, + Utf8String.TYPE_NAME, + Utf8String.class.getSimpleName()); + + builder = + addStatement( + builder, + packageName, + DynamicBytes.TYPE_NAME, + DynamicBytes.class.getSimpleName()); + + // TODO: Fixed array & dynamic array support + return builder; + } - private MethodSpec.Builder addGeneratedTypes(MethodSpec.Builder builder, String packageName) { + private MethodSpec.Builder addGeneratedTypes(MethodSpec.Builder builder, String packageName) { - builder = generateIntTypes(builder, packageName); + builder = generateIntTypes(builder, packageName); - // TODO: Enable once Solidity supports fixed types - see - // https://github.com/ethereum/solidity/issues/409 - // builder = generateFixedTypes(builder, packageName); + // TODO: Enable once Solidity supports fixed types - see + // https://github.com/ethereum/solidity/issues/409 + // builder = generateFixedTypes(builder, packageName); - builder = generateFixedBytesTypes(builder, packageName); + builder = generateFixedBytesTypes(builder, packageName); - return builder; - } + return builder; + } - private MethodSpec.Builder generateIntTypes(MethodSpec.Builder builder, String packageName) { - for (int bitSize = 8; bitSize <= Type.MAX_BIT_LENGTH; bitSize += 8) { + private MethodSpec.Builder generateIntTypes(MethodSpec.Builder builder, String packageName) { + for (int bitSize = 8; bitSize <= Type.MAX_BIT_LENGTH; bitSize += 8) { + + builder = + addStatement( + builder, + packageName, + Uint.TYPE_NAME + bitSize, + Uint.class.getSimpleName() + bitSize); + builder = + addStatement( + builder, + packageName, + Int.TYPE_NAME + bitSize, + Int.class.getSimpleName() + bitSize); + } + return builder; + } - builder = - addStatement( - builder, packageName, Uint.TYPE_NAME + bitSize, Uint.class.getSimpleName() + bitSize); - builder = - addStatement( - builder, packageName, Int.TYPE_NAME + bitSize, Int.class.getSimpleName() + bitSize); + private MethodSpec.Builder generateFixedTypes(MethodSpec.Builder builder, String packageName) { + for (int mBitSize = 8, nBitSize = Type.MAX_BIT_LENGTH - 8; + mBitSize < Type.MAX_BIT_LENGTH && nBitSize > 0; + mBitSize += 8, nBitSize -= 8) { + String suffix = mBitSize + "x" + nBitSize; + builder = + addStatement( + builder, + packageName, + Ufixed.TYPE_NAME + suffix, + Ufixed.class.getSimpleName() + suffix); + builder = + addStatement( + builder, + packageName, + Fixed.TYPE_NAME + suffix, + Fixed.class.getSimpleName() + suffix); + } + return builder; } - return builder; - } - - private MethodSpec.Builder generateFixedTypes(MethodSpec.Builder builder, String packageName) { - for (int mBitSize = 8, nBitSize = Type.MAX_BIT_LENGTH - 8; - mBitSize < Type.MAX_BIT_LENGTH && nBitSize > 0; - mBitSize += 8, nBitSize -= 8) { - String suffix = mBitSize + "x" + nBitSize; - builder = - addStatement( - builder, - packageName, - Ufixed.TYPE_NAME + suffix, - Ufixed.class.getSimpleName() + suffix); - builder = - addStatement( - builder, packageName, Fixed.TYPE_NAME + suffix, Fixed.class.getSimpleName() + suffix); + + private MethodSpec.Builder generateFixedBytesTypes( + MethodSpec.Builder builder, String packageName) { + for (int byteSize = 1; byteSize <= 32; byteSize++) { + builder = + addStatement( + builder, + packageName, + Bytes.TYPE_NAME + byteSize, + Bytes.class.getSimpleName() + byteSize); + } + return builder; } - return builder; - } - - private MethodSpec.Builder generateFixedBytesTypes( - MethodSpec.Builder builder, String packageName) { - for (int byteSize = 1; byteSize <= 32; byteSize++) { - builder = - addStatement( - builder, - packageName, - Bytes.TYPE_NAME + byteSize, - Bytes.class.getSimpleName() + byteSize); + + private MethodSpec.Builder addStatement( + MethodSpec.Builder builder, String packageName, String typeName, String className) { + return builder.addStatement( + "case \"$L\":\nreturn $T.class", typeName, ClassName.get(packageName, className)); } - return builder; - } - - private MethodSpec.Builder addStatement( - MethodSpec.Builder builder, String packageName, String typeName, String className) { - return builder.addStatement( - "case \"$L\":\nreturn $T.class", typeName, ClassName.get(packageName, className)); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/Console.java b/src/main/java/org/fisco/bcos/web3j/codegen/Console.java index 8d7444960..d91cb5e4b 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/Console.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/Console.java @@ -2,17 +2,17 @@ /** Command line utility classes. */ public class Console { - public static void exitError(String message) { - System.err.println(message); - System.exit(1); - } + public static void exitError(String message) { + System.err.println(message); + System.exit(1); + } - public static void exitError(Throwable throwable) { - exitError(throwable.getMessage()); - } + public static void exitError(Throwable throwable) { + exitError(throwable.getMessage()); + } - public static void exitSuccess(String message) { - System.out.println(message); - System.exit(0); - } + public static void exitSuccess(String message) { + System.out.println(message); + System.exit(0); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/FunctionWrapperGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/FunctionWrapperGenerator.java index 0d4e91447..4bdacf7a8 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/FunctionWrapperGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/FunctionWrapperGenerator.java @@ -5,57 +5,57 @@ /** Abstract base class for the concrete function wrapper generators. */ abstract class FunctionWrapperGenerator { - static final String JAVA_TYPES_ARG = "--javaTypes"; - static final String SOLIDITY_TYPES_ARG = "--solidityTypes"; - - final File destinationDirLocation; - final String basePackageName; - final boolean useJavaNativeTypes; - - FunctionWrapperGenerator( - File destinationDirLocation, String basePackageName, boolean useJavaNativeTypes) { - - this.destinationDirLocation = destinationDirLocation; - this.basePackageName = basePackageName; - this.useJavaNativeTypes = useJavaNativeTypes; - } - - static boolean useJavaNativeTypes(String argVal, String usageString) { - boolean useJavaNativeTypes = true; - if (SOLIDITY_TYPES_ARG.equals(argVal)) { - useJavaNativeTypes = false; - } else if (JAVA_TYPES_ARG.equals(argVal)) { - useJavaNativeTypes = true; - } else { - Console.exitError(usageString); + static final String JAVA_TYPES_ARG = "--javaTypes"; + static final String SOLIDITY_TYPES_ARG = "--solidityTypes"; + + final File destinationDirLocation; + final String basePackageName; + final boolean useJavaNativeTypes; + + FunctionWrapperGenerator( + File destinationDirLocation, String basePackageName, boolean useJavaNativeTypes) { + + this.destinationDirLocation = destinationDirLocation; + this.basePackageName = basePackageName; + this.useJavaNativeTypes = useJavaNativeTypes; + } + + static boolean useJavaNativeTypes(String argVal, String usageString) { + boolean useJavaNativeTypes = true; + if (SOLIDITY_TYPES_ARG.equals(argVal)) { + useJavaNativeTypes = false; + } else if (JAVA_TYPES_ARG.equals(argVal)) { + useJavaNativeTypes = true; + } else { + Console.exitError(usageString); + } + return useJavaNativeTypes; } - return useJavaNativeTypes; - } - - static String parsePositionalArg(String[] args, int idx) { - if (args != null && args.length > idx) { - return args[idx]; - } else { - return ""; + + static String parsePositionalArg(String[] args, int idx) { + if (args != null && args.length > idx) { + return args[idx]; + } else { + return ""; + } } - } - - static String parseParameterArgument(String[] args, String... parameters) { - for (String parameter : parameters) { - for (int i = 0; i < args.length; i++) { - if (args[i].equals(parameter) && i + 1 < args.length) { - String parameterValue = args[i + 1]; - if (!parameterValue.startsWith("-")) { - return parameterValue; - } + + static String parseParameterArgument(String[] args, String... parameters) { + for (String parameter : parameters) { + for (int i = 0; i < args.length; i++) { + if (args[i].equals(parameter) && i + 1 < args.length) { + String parameterValue = args[i + 1]; + if (!parameterValue.startsWith("-")) { + return parameterValue; + } + } + } } - } + return ""; } - return ""; - } - static String getFileNameNoExtension(String fileName) { - String[] splitName = fileName.split("\\.(?=[^.]*$)"); - return splitName[0]; - } + static String getFileNameNoExtension(String fileName) { + String[] splitName = fileName.split("\\.(?=[^.]*$)"); + return splitName[0]; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/GenerationReporter.java b/src/main/java/org/fisco/bcos/web3j/codegen/GenerationReporter.java index b0402cb17..4b1f01996 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/GenerationReporter.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/GenerationReporter.java @@ -2,5 +2,5 @@ /** Can be used to provide report about a code generation process. */ interface GenerationReporter { - void report(String msg); + void report(String msg); } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/Generator.java b/src/main/java/org/fisco/bcos/web3j/codegen/Generator.java index 3486276b3..22b3b4bb3 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/Generator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/Generator.java @@ -7,20 +7,23 @@ /** Common code generator methods. */ class Generator { - void write(String packageName, TypeSpec typeSpec, String destinationDir) throws IOException { - JavaFile javaFile = - JavaFile.builder(packageName, typeSpec).indent(" ").skipJavaLangImports(true).build(); + void write(String packageName, TypeSpec typeSpec, String destinationDir) throws IOException { + JavaFile javaFile = + JavaFile.builder(packageName, typeSpec) + .indent(" ") + .skipJavaLangImports(true) + .build(); - javaFile.writeTo(new File(destinationDir)); - } + javaFile.writeTo(new File(destinationDir)); + } - static String buildWarning(Class cls) { - return "Auto generated code.\n" - + "

Do not modifiy!\n" - + "

Please use " - + cls.getName() - + " in the \n" - + "" - + "codegen module to update.\n"; - } + static String buildWarning(Class cls) { + return "Auto generated code.\n" + + "

Do not modifiy!\n" + + "

Please use " + + cls.getName() + + " in the \n" + + "" + + "codegen module to update.\n"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/LogGenerationReporter.java b/src/main/java/org/fisco/bcos/web3j/codegen/LogGenerationReporter.java index 6394e091a..70477de34 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/LogGenerationReporter.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/LogGenerationReporter.java @@ -5,14 +5,14 @@ /** A reporter generation that outputs messages using a logger instance. */ class LogGenerationReporter implements GenerationReporter { - private final Logger logger; + private final Logger logger; - public LogGenerationReporter(Logger logger) { - this.logger = logger; - } + public LogGenerationReporter(Logger logger) { + this.logger = logger; + } - @Override - public void report(String msg) { - logger.warn(msg); - } + @Override + public void report(String msg) { + logger.warn(msg); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapper.java b/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapper.java index b1e1f4827..aad2c051c 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapper.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapper.java @@ -1,5 +1,17 @@ package org.fisco.bcos.web3j.codegen; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeVariableName; +import io.reactivex.Flowable; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; @@ -14,10 +26,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; - import javax.lang.model.SourceVersion; import javax.lang.model.element.Modifier; - import org.fisco.bcos.web3j.abi.EventEncoder; import org.fisco.bcos.web3j.abi.FunctionEncoder; import org.fisco.bcos.web3j.abi.TypeReference; @@ -49,1380 +59,1516 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.squareup.javapoet.AnnotationSpec; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterSpec; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import com.squareup.javapoet.TypeVariableName; - -import io.reactivex.Flowable; - // import com.sun.media.jfxmedia.logging.Logger; /** Generate Java Classes based on generated Solidity bin and abi files. */ public class SolidityFunctionWrapper extends Generator { - private static final String BINARY = "BINARY"; - private static final String WEB3J = "web3j"; - private static final String CREDENTIALS = "credentials"; - private static final String CONTRACT_GAS_PROVIDER = "contractGasProvider"; - private static final String TRANSACTION_MANAGER = "transactionManager"; - private static final String INITIAL_VALUE = "initialWeiValue"; - private static final String CONTRACT_ADDRESS = "contractAddress"; - private static final String GAS_PRICE = "gasPrice"; - private static final String GAS_LIMIT = "gasLimit"; - private static final String FILTER = "filter"; - private static final String START_BLOCK = "startBlock"; - private static final String END_BLOCK = "endBlock"; - private static final String WEI_VALUE = "weiValue"; - private static final String FUNC_NAME_PREFIX = "FUNC_"; - - private static final ClassName LOG = ClassName.get(Log.class); - private static final Logger LOGGER = LoggerFactory.getLogger(SolidityFunctionWrapper.class); - - private static final String CODEGEN_WARNING = - "

Auto generated code.\n" - + "

Do not modify!\n" - + "

Please use the " - + "web3j command line tools,\n" - + "or the " - + SolidityFunctionWrapperGenerator.class.getName() - + " in the \n" - + "" - + "codegen module to update.\n"; - - private final boolean useNativeJavaTypes; - private static final String regex = "(\\w+)(?:\\[(.*?)\\])(?:\\[(.*?)\\])?"; - private static final Pattern pattern = Pattern.compile(regex); - private final GenerationReporter reporter; - - public SolidityFunctionWrapper(boolean useNativeJavaTypes) { - this(useNativeJavaTypes, new LogGenerationReporter(LOGGER)); - } - - SolidityFunctionWrapper(boolean useNativeJavaTypes, GenerationReporter reporter) { - this.useNativeJavaTypes = useNativeJavaTypes; - this.reporter = reporter; - } - - @SuppressWarnings("unchecked") - public void generateJavaFiles( - String contractName, String bin, String abi, String destinationDir, String basePackageName) - throws IOException, ClassNotFoundException { - generateJavaFiles( - contractName, bin, loadContractDefinition(abi), destinationDir, basePackageName, null); - } - - void generateJavaFiles( - String contractName, - String bin, - List abi, - String destinationDir, - String basePackageName, - Map addresses) - throws IOException, ClassNotFoundException { - String className = Strings.capitaliseFirstLetter(contractName); - - TypeSpec.Builder classBuilder = createClassBuilder(className, bin); - - classBuilder.addMethod(buildConstructor(Credentials.class, CREDENTIALS, false)); - classBuilder.addMethod(buildConstructor(Credentials.class, CREDENTIALS, true)); - classBuilder.addMethod(buildConstructor(TransactionManager.class, TRANSACTION_MANAGER, false)); - classBuilder.addMethod(buildConstructor(TransactionManager.class, TRANSACTION_MANAGER, true)); - classBuilder.addFields(buildFuncNameConstants(abi)); - classBuilder.addMethods(buildFunctionDefinitions(className, classBuilder, abi)); - classBuilder.addMethod(buildLoad(className, Credentials.class, CREDENTIALS, false)); - classBuilder.addMethod( - buildLoad(className, TransactionManager.class, TRANSACTION_MANAGER, false)); - classBuilder.addMethod(buildLoad(className, Credentials.class, CREDENTIALS, true)); - classBuilder.addMethod( - buildLoad(className, TransactionManager.class, TRANSACTION_MANAGER, true)); - if (!bin.equals(Contract.BIN_NOT_PROVIDED)) { - classBuilder.addMethods(buildDeployMethods(className, classBuilder, abi)); + private static final String BINARY = "BINARY"; + private static final String WEB3J = "web3j"; + private static final String CREDENTIALS = "credentials"; + private static final String CONTRACT_GAS_PROVIDER = "contractGasProvider"; + private static final String TRANSACTION_MANAGER = "transactionManager"; + private static final String INITIAL_VALUE = "initialWeiValue"; + private static final String CONTRACT_ADDRESS = "contractAddress"; + private static final String GAS_PRICE = "gasPrice"; + private static final String GAS_LIMIT = "gasLimit"; + private static final String FILTER = "filter"; + private static final String START_BLOCK = "startBlock"; + private static final String END_BLOCK = "endBlock"; + private static final String WEI_VALUE = "weiValue"; + private static final String FUNC_NAME_PREFIX = "FUNC_"; + private String abiContent; + private static final ClassName LOG = ClassName.get(Log.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SolidityFunctionWrapper.class); + + private static final String CODEGEN_WARNING = + "

Auto generated code.\n" + + "

Do not modify!\n" + + "

Please use the " + + "web3j command line tools,\n" + + "or the " + + SolidityFunctionWrapperGenerator.class.getName() + + " in the \n" + + "" + + "codegen module to update.\n"; + private static final String ABI = "ABI"; + private final boolean useNativeJavaTypes; + private static final String regex = "(\\w+)(?:\\[(.*?)\\])(?:\\[(.*?)\\])?"; + private static final Pattern pattern = Pattern.compile(regex); + private final GenerationReporter reporter; + + public SolidityFunctionWrapper(boolean useNativeJavaTypes) { + this(useNativeJavaTypes, new LogGenerationReporter(LOGGER)); } - addAddressesSupport(classBuilder, addresses); - - write(basePackageName, classBuilder.build(), destinationDir); - } - - private void addAddressesSupport(TypeSpec.Builder classBuilder, Map addresses) { - if (addresses != null) { - - ClassName stringType = ClassName.get(String.class); - ClassName mapType = ClassName.get(HashMap.class); - TypeName mapStringString = ParameterizedTypeName.get(mapType, stringType, stringType); - FieldSpec addressesStaticField = - FieldSpec.builder( - mapStringString, - "_addresses", - Modifier.PROTECTED, - Modifier.STATIC, - Modifier.FINAL) - .build(); - classBuilder.addField(addressesStaticField); - - final CodeBlock.Builder staticInit = CodeBlock.builder(); - staticInit.addStatement("_addresses = new HashMap()"); - addresses.forEach( - (k, v) -> - staticInit.addStatement(String.format("_addresses.put(\"%1s\", \"%2s\")", k, v))); - classBuilder.addStaticBlock(staticInit.build()); - - // See Contract#getStaticDeployedAddress(String) - MethodSpec getAddress = - MethodSpec.methodBuilder("getStaticDeployedAddress") - .addModifiers(Modifier.PROTECTED) - .returns(stringType) - .addParameter(stringType, "networkId") - .addCode(CodeBlock.builder().addStatement("return _addresses.get(networkId)").build()) - .build(); - classBuilder.addMethod(getAddress); - - MethodSpec getPreviousAddress = - MethodSpec.methodBuilder("getPreviouslyDeployedAddress") - .addModifiers(Modifier.PUBLIC) - .addModifiers(Modifier.STATIC) - .returns(stringType) - .addParameter(stringType, "networkId") - .addCode(CodeBlock.builder().addStatement("return _addresses.get(networkId)").build()) - .build(); - classBuilder.addMethod(getPreviousAddress); + SolidityFunctionWrapper(boolean useNativeJavaTypes, GenerationReporter reporter) { + this.useNativeJavaTypes = useNativeJavaTypes; + this.reporter = reporter; } - } - - private TypeSpec.Builder createClassBuilder(String className, String binary) { - String javadoc = CODEGEN_WARNING + getWeb3jVersion(); + @SuppressWarnings("unchecked") + public void generateJavaFiles( + String contractName, + String bin, + String abi, + String destinationDir, + String basePackageName) + throws IOException, ClassNotFoundException { + abiContent = abi; + generateJavaFiles( + contractName, + bin, + loadContractDefinition(abi), + destinationDir, + basePackageName, + null); + } - return TypeSpec.classBuilder(className) - .addModifiers(Modifier.PUBLIC) - .addJavadoc(javadoc) - .superclass(Contract.class) - .addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unchecked").build()) - .addField(createBinaryDefinition(binary)); - } + void generateJavaFiles( + String contractName, + String bin, + List abi, + String destinationDir, + String basePackageName, + Map addresses) + throws IOException, ClassNotFoundException { + String className = Strings.capitaliseFirstLetter(contractName); + + TypeSpec.Builder classBuilder = createClassBuilder(className, bin, abi); + + classBuilder.addMethod(buildConstructor(Credentials.class, CREDENTIALS, false)); + classBuilder.addMethod(buildConstructor(Credentials.class, CREDENTIALS, true)); + classBuilder.addMethod( + buildConstructor(TransactionManager.class, TRANSACTION_MANAGER, false)); + classBuilder.addMethod( + buildConstructor(TransactionManager.class, TRANSACTION_MANAGER, true)); + classBuilder.addFields(buildFuncNameConstants(abi)); + classBuilder.addMethods(buildFunctionDefinitions(className, classBuilder, abi)); + classBuilder.addMethod(buildLoad(className, Credentials.class, CREDENTIALS, false)); + classBuilder.addMethod( + buildLoad(className, TransactionManager.class, TRANSACTION_MANAGER, false)); + classBuilder.addMethod(buildLoad(className, Credentials.class, CREDENTIALS, true)); + classBuilder.addMethod( + buildLoad(className, TransactionManager.class, TRANSACTION_MANAGER, true)); + if (!bin.equals(Contract.BIN_NOT_PROVIDED)) { + classBuilder.addMethods(buildDeployMethods(className, classBuilder, abi)); + } - private String getWeb3jVersion() { - String version; + addAddressesSupport(classBuilder, addresses); - try { - // This only works if run as part of the web3j command line tools which contains - // a version.properties file - version = Version.getVersion(); - } catch (IOException | NullPointerException e) { - version = Version.DEFAULT; + write(basePackageName, classBuilder.build(), destinationDir); } - return "\n

Generated with web3j version " + version + ".\n"; - } - - private FieldSpec createBinaryDefinition(String binary) { - return FieldSpec.builder(String.class, BINARY) - .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC) - .initializer("$S", binary) - .build(); - } - - private FieldSpec createEventDefinition(String name, List parameters) { - - CodeBlock initializer = buildVariableLengthEventInitializer(name, parameters); - - return FieldSpec.builder(Event.class, buildEventDefinitionName(name)) - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer(initializer) - .build(); - } - - private String buildEventDefinitionName(String eventName) { - return eventName.toUpperCase() + "_EVENT"; - } - - private List buildFunctionDefinitions( - String className, TypeSpec.Builder classBuilder, List functionDefinitions) - throws ClassNotFoundException { - - List methodSpecs = new ArrayList<>(); - for (AbiDefinition functionDefinition : functionDefinitions) { - if (functionDefinition.getType().equals("function")) { - MethodSpec ms = buildFunction(functionDefinition); - methodSpecs.add(ms); - - if (!functionDefinition.isConstant()) { - MethodSpec msCallback = buildFunctionWithCallback(functionDefinition); - methodSpecs.add(msCallback); + + private void addAddressesSupport(TypeSpec.Builder classBuilder, Map addresses) { + if (addresses != null) { + + ClassName stringType = ClassName.get(String.class); + ClassName mapType = ClassName.get(HashMap.class); + TypeName mapStringString = ParameterizedTypeName.get(mapType, stringType, stringType); + FieldSpec addressesStaticField = + FieldSpec.builder( + mapStringString, + "_addresses", + Modifier.PROTECTED, + Modifier.STATIC, + Modifier.FINAL) + .build(); + classBuilder.addField(addressesStaticField); + + final CodeBlock.Builder staticInit = CodeBlock.builder(); + staticInit.addStatement("_addresses = new HashMap()"); + addresses.forEach( + (k, v) -> + staticInit.addStatement( + String.format("_addresses.put(\"%1s\", \"%2s\")", k, v))); + classBuilder.addStaticBlock(staticInit.build()); + + // See Contract#getStaticDeployedAddress(String) + MethodSpec getAddress = + MethodSpec.methodBuilder("getStaticDeployedAddress") + .addModifiers(Modifier.PROTECTED) + .returns(stringType) + .addParameter(stringType, "networkId") + .addCode( + CodeBlock.builder() + .addStatement("return _addresses.get(networkId)") + .build()) + .build(); + classBuilder.addMethod(getAddress); + + MethodSpec getPreviousAddress = + MethodSpec.methodBuilder("getPreviouslyDeployedAddress") + .addModifiers(Modifier.PUBLIC) + .addModifiers(Modifier.STATIC) + .returns(stringType) + .addParameter(stringType, "networkId") + .addCode( + CodeBlock.builder() + .addStatement("return _addresses.get(networkId)") + .build()) + .build(); + classBuilder.addMethod(getPreviousAddress); } - } else if (functionDefinition.getType().equals("event")) { - methodSpecs.addAll(buildEventFunctions(functionDefinition, classBuilder)); - } } - return methodSpecs; - } - - List buildDeployMethods( - String className, TypeSpec.Builder classBuilder, List functionDefinitions) { - boolean constructor = false; - List methodSpecs = new ArrayList<>(); - for (AbiDefinition functionDefinition : functionDefinitions) { - if (functionDefinition.getType().equals("constructor")) { - constructor = true; - methodSpecs.add( - buildDeploy(className, functionDefinition, Credentials.class, CREDENTIALS, true)); - methodSpecs.add( - buildDeploy( - className, - functionDefinition, - TransactionManager.class, - TRANSACTION_MANAGER, - true)); - methodSpecs.add( - buildDeploy(className, functionDefinition, Credentials.class, CREDENTIALS, false)); - methodSpecs.add( - buildDeploy( - className, - functionDefinition, - TransactionManager.class, - TRANSACTION_MANAGER, - false)); - } + private TypeSpec.Builder createClassBuilder( + String className, String binary, List abi) { + + String javadoc = CODEGEN_WARNING + getWeb3jVersion(); + + return TypeSpec.classBuilder(className) + .addModifiers(Modifier.PUBLIC) + .addJavadoc(javadoc) + .superclass(Contract.class) + .addAnnotation( + AnnotationSpec.builder(SuppressWarnings.class) + .addMember("value", "$S", "unchecked") + .build()) + .addField(createBinaryDefinition(binary)) + .addField(createABIDefinition(abi)); } - // constructor will not be specified in ABI file if its empty - if (!constructor) { - MethodSpec.Builder credentialsMethodBuilder = - getDeployMethodSpec(className, Credentials.class, CREDENTIALS, false, true); - methodSpecs.add( - buildDeployNoParams(credentialsMethodBuilder, className, CREDENTIALS, false, true)); - - MethodSpec.Builder credentialsMethodBuilderNoGasProvider = - getDeployMethodSpec(className, Credentials.class, CREDENTIALS, false, false); - methodSpecs.add( - buildDeployNoParams( - credentialsMethodBuilderNoGasProvider, className, CREDENTIALS, false, false)); - - MethodSpec.Builder transactionManagerMethodBuilder = - getDeployMethodSpec( - className, TransactionManager.class, TRANSACTION_MANAGER, false, true); - methodSpecs.add( - buildDeployNoParams( - transactionManagerMethodBuilder, className, TRANSACTION_MANAGER, false, true)); - - MethodSpec.Builder transactionManagerMethodBuilderNoGasProvider = - getDeployMethodSpec( - className, TransactionManager.class, TRANSACTION_MANAGER, false, false); - methodSpecs.add( - buildDeployNoParams( - transactionManagerMethodBuilderNoGasProvider, - className, - TRANSACTION_MANAGER, - false, - false)); - } + private String getWeb3jVersion() { + String version; - return methodSpecs; - } - - Iterable buildFuncNameConstants(List functionDefinitions) { - List fields = new ArrayList<>(); - Set fieldNames = new HashSet<>(); - fieldNames.add(Contract.FUNC_DEPLOY); - - for (AbiDefinition functionDefinition : functionDefinitions) { - if (functionDefinition.getType().equals("function")) { - String funcName = functionDefinition.getName(); - - if (!fieldNames.contains(funcName)) { - FieldSpec field = - FieldSpec.builder( - String.class, - funcNameToConst(funcName), - Modifier.PUBLIC, - Modifier.STATIC, - Modifier.FINAL) - .initializer("$S", funcName) - .build(); - fields.add(field); - fieldNames.add(funcName); + try { + // This only works if run as part of the web3j command line tools which contains + // a version.properties file + version = Version.getVersion(); + } catch (IOException | NullPointerException e) { + version = Version.DEFAULT; } - } + return "\n

Generated with web3j version " + version + ".\n"; } - return fields; - } - - private static MethodSpec buildConstructor( - Class authType, String authName, boolean withGasProvider) { - MethodSpec.Builder toReturn = - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PROTECTED) - .addParameter(String.class, CONTRACT_ADDRESS) - .addParameter(Web3j.class, WEB3J) - .addParameter(authType, authName); - - if (withGasProvider) { - toReturn - .addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) - .addStatement( - "super($N, $N, $N, $N, $N)", - BINARY, - CONTRACT_ADDRESS, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER); - } else { - toReturn - .addParameter(BigInteger.class, GAS_PRICE) - .addParameter(BigInteger.class, GAS_LIMIT) - .addStatement( - "super($N, $N, $N, $N, $N, $N)", - BINARY, - CONTRACT_ADDRESS, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT) - .addAnnotation(Deprecated.class); + + private FieldSpec createBinaryDefinition(String binary) { + return FieldSpec.builder(String.class, BINARY) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC) + .initializer("$S", binary) + .build(); } - return toReturn.build(); - } + private FieldSpec createABIDefinition(List abi) { + return FieldSpec.builder(String.class, "ABI") + .addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC) + .initializer("$S", abiContent) + .build(); + } - private MethodSpec buildDeploy( - String className, - AbiDefinition functionDefinition, - Class authType, - String authName, - boolean withGasProvider) { + private FieldSpec createEventDefinition(String name, List parameters) { - boolean isPayable = functionDefinition.isPayable(); + CodeBlock initializer = buildVariableLengthEventInitializer(name, parameters); - MethodSpec.Builder methodBuilder = - getDeployMethodSpec(className, authType, authName, isPayable, withGasProvider); - String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); + return FieldSpec.builder(Event.class, buildEventDefinitionName(name)) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer(initializer) + .build(); + } - if (!inputParams.isEmpty()) { - return buildDeployWithParams( - methodBuilder, className, inputParams, authName, isPayable, withGasProvider); - } else { - return buildDeployNoParams(methodBuilder, className, authName, isPayable, withGasProvider); + private String buildEventDefinitionName(String eventName) { + return eventName.toUpperCase() + "_EVENT"; } - } - - private static MethodSpec buildDeployWithParams( - MethodSpec.Builder methodBuilder, - String className, - String inputParams, - String authName, - boolean isPayable, - boolean withGasProvider) { - - methodBuilder.addStatement( - "$T encodedConstructor = $T.encodeConstructor(" + "$T.<$T>asList($L)" + ")", - String.class, - FunctionEncoder.class, - Arrays.class, - Type.class, - inputParams); - if (isPayable && !withGasProvider) { - methodBuilder.addStatement( - "return deployRemoteCall(" + "$L.class, $L, $L, $L, $L, $L, encodedConstructor, $L)", - className, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT, - BINARY, - INITIAL_VALUE); - methodBuilder.addAnnotation(Deprecated.class); - } else if (isPayable && withGasProvider) { - methodBuilder.addStatement( - "return deployRemoteCall(" + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", - className, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER, - BINARY, - INITIAL_VALUE); - } else if (!isPayable && !withGasProvider) { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, encodedConstructor)", - className, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT, - BINARY); - methodBuilder.addAnnotation(Deprecated.class); - } else { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, encodedConstructor)", - className, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER, - BINARY); + + private List buildFunctionDefinitions( + String className, + TypeSpec.Builder classBuilder, + List functionDefinitions) + throws ClassNotFoundException { + + List methodSpecs = new ArrayList<>(); + for (AbiDefinition functionDefinition : functionDefinitions) { + if (functionDefinition.getType().equals("function")) { + MethodSpec ms = buildFunction(functionDefinition); + methodSpecs.add(ms); + + if (!functionDefinition.isConstant()) { + MethodSpec msCallback = buildFunctionWithCallback(functionDefinition); + methodSpecs.add(msCallback); + + MethodSpec msSeq = buildFunctionSeq(functionDefinition); + methodSpecs.add(msSeq); + } + } else if (functionDefinition.getType().equals("event")) { + methodSpecs.addAll(buildEventFunctions(functionDefinition, classBuilder)); + } + } + + return methodSpecs; } - return methodBuilder.build(); - } - - private static MethodSpec buildDeployNoParams( - MethodSpec.Builder methodBuilder, - String className, - String authName, - boolean isPayable, - boolean withGasPRovider) { - if (isPayable && !withGasPRovider) { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, \"\", $L)", - className, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT, - BINARY, - INITIAL_VALUE); - methodBuilder.addAnnotation(Deprecated.class); - } else if (isPayable && withGasPRovider) { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, \"\", $L)", - className, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER, - BINARY, - INITIAL_VALUE); - } else if (!isPayable && !withGasPRovider) { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, \"\")", - className, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT, - BINARY); - methodBuilder.addAnnotation(Deprecated.class); - } else { - methodBuilder.addStatement( - "return deployRemoteCall($L.class, $L, $L, $L, $L, \"\")", - className, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER, - BINARY); + List buildDeployMethods( + String className, + TypeSpec.Builder classBuilder, + List functionDefinitions) { + boolean constructor = false; + List methodSpecs = new ArrayList<>(); + for (AbiDefinition functionDefinition : functionDefinitions) { + if (functionDefinition.getType().equals("constructor")) { + constructor = true; + methodSpecs.add( + buildDeploy( + className, + functionDefinition, + Credentials.class, + CREDENTIALS, + true)); + methodSpecs.add( + buildDeploy( + className, + functionDefinition, + TransactionManager.class, + TRANSACTION_MANAGER, + true)); + methodSpecs.add( + buildDeploy( + className, + functionDefinition, + Credentials.class, + CREDENTIALS, + false)); + methodSpecs.add( + buildDeploy( + className, + functionDefinition, + TransactionManager.class, + TRANSACTION_MANAGER, + false)); + } + } + + // constructor will not be specified in ABI file if its empty + if (!constructor) { + MethodSpec.Builder credentialsMethodBuilder = + getDeployMethodSpec(className, Credentials.class, CREDENTIALS, false, true); + methodSpecs.add( + buildDeployNoParams( + credentialsMethodBuilder, className, CREDENTIALS, false, true)); + + MethodSpec.Builder credentialsMethodBuilderNoGasProvider = + getDeployMethodSpec(className, Credentials.class, CREDENTIALS, false, false); + methodSpecs.add( + buildDeployNoParams( + credentialsMethodBuilderNoGasProvider, + className, + CREDENTIALS, + false, + false)); + + MethodSpec.Builder transactionManagerMethodBuilder = + getDeployMethodSpec( + className, TransactionManager.class, TRANSACTION_MANAGER, false, true); + methodSpecs.add( + buildDeployNoParams( + transactionManagerMethodBuilder, + className, + TRANSACTION_MANAGER, + false, + true)); + + MethodSpec.Builder transactionManagerMethodBuilderNoGasProvider = + getDeployMethodSpec( + className, TransactionManager.class, TRANSACTION_MANAGER, false, false); + methodSpecs.add( + buildDeployNoParams( + transactionManagerMethodBuilderNoGasProvider, + className, + TRANSACTION_MANAGER, + false, + false)); + } + + return methodSpecs; } - return methodBuilder.build(); - } - - private static MethodSpec.Builder getDeployMethodSpec( - String className, - Class authType, - String authName, - boolean isPayable, - boolean withGasProvider) { - MethodSpec.Builder builder = - MethodSpec.methodBuilder("deploy") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .returns(buildRemoteCall(TypeVariableName.get(className, Type.class))) - .addParameter(Web3j.class, WEB3J) - .addParameter(authType, authName); - if (isPayable && !withGasProvider) { - return builder - .addParameter(BigInteger.class, GAS_PRICE) - .addParameter(BigInteger.class, GAS_LIMIT) - .addParameter(BigInteger.class, INITIAL_VALUE); - } else if (isPayable && withGasProvider) { - return builder - .addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) - .addParameter(BigInteger.class, INITIAL_VALUE); - } else if (!isPayable && withGasProvider) { - return builder.addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER); - } else { - return builder - .addParameter(BigInteger.class, GAS_PRICE) - .addParameter(BigInteger.class, GAS_LIMIT); + Iterable buildFuncNameConstants(List functionDefinitions) { + List fields = new ArrayList<>(); + Set fieldNames = new HashSet<>(); + fieldNames.add(Contract.FUNC_DEPLOY); + + for (AbiDefinition functionDefinition : functionDefinitions) { + if (functionDefinition.getType().equals("function")) { + String funcName = functionDefinition.getName(); + + if (!fieldNames.contains(funcName)) { + FieldSpec field = + FieldSpec.builder( + String.class, + funcNameToConst(funcName), + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer("$S", funcName) + .build(); + fields.add(field); + fieldNames.add(funcName); + } + } + } + return fields; } - } - - private static MethodSpec buildLoad( - String className, Class authType, String authName, boolean withGasProvider) { - MethodSpec.Builder toReturn = - MethodSpec.methodBuilder("load") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .returns(TypeVariableName.get(className, Type.class)) - .addParameter(String.class, CONTRACT_ADDRESS) - .addParameter(Web3j.class, WEB3J) - .addParameter(authType, authName); - - if (withGasProvider) { - toReturn - .addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) - .addStatement( - "return new $L($L, $L, $L, $L)", - className, - CONTRACT_ADDRESS, - WEB3J, - authName, - CONTRACT_GAS_PROVIDER); - } else { - toReturn - .addParameter(BigInteger.class, GAS_PRICE) - .addParameter(BigInteger.class, GAS_LIMIT) - .addStatement( - "return new $L($L, $L, $L, $L, $L)", - className, - CONTRACT_ADDRESS, - WEB3J, - authName, - GAS_PRICE, - GAS_LIMIT) - .addAnnotation(Deprecated.class); + + private static MethodSpec buildConstructor( + Class authType, String authName, boolean withGasProvider) { + MethodSpec.Builder toReturn = + MethodSpec.constructorBuilder() + .addModifiers(Modifier.PROTECTED) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Web3j.class, WEB3J) + .addParameter(authType, authName); + + if (withGasProvider) { + toReturn.addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) + .addStatement( + "super($N, $N, $N, $N, $N)", + BINARY, + CONTRACT_ADDRESS, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER); + } else { + toReturn.addParameter(BigInteger.class, GAS_PRICE) + .addParameter(BigInteger.class, GAS_LIMIT) + .addStatement( + "super($N, $N, $N, $N, $N, $N)", + BINARY, + CONTRACT_ADDRESS, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT) + .addAnnotation(Deprecated.class); + } + + return toReturn.build(); } - return toReturn.build(); - } + private MethodSpec buildDeploy( + String className, + AbiDefinition functionDefinition, + Class authType, + String authName, + boolean withGasProvider) { - String addParameters(MethodSpec.Builder methodBuilder, List namedTypes) { + boolean isPayable = functionDefinition.isPayable(); - List inputParameterTypes = buildParameterTypes(namedTypes); + MethodSpec.Builder methodBuilder = + getDeployMethodSpec(className, authType, authName, isPayable, withGasProvider); + String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); - List nativeInputParameterTypes = new ArrayList<>(inputParameterTypes.size()); - for (ParameterSpec parameterSpec : inputParameterTypes) { - TypeName typeName = getWrapperType(parameterSpec.type); - nativeInputParameterTypes.add(ParameterSpec.builder(typeName, parameterSpec.name).build()); + if (!inputParams.isEmpty()) { + return buildDeployWithParams( + methodBuilder, className, inputParams, authName, isPayable, withGasProvider); + } else { + return buildDeployNoParams( + methodBuilder, className, authName, isPayable, withGasProvider); + } } - methodBuilder.addParameters(nativeInputParameterTypes); + private static MethodSpec buildDeployWithParams( + MethodSpec.Builder methodBuilder, + String className, + String inputParams, + String authName, + boolean isPayable, + boolean withGasProvider) { + + methodBuilder.addStatement( + "$T encodedConstructor = $T.encodeConstructor(" + "$T.<$T>asList($L)" + ")", + String.class, + FunctionEncoder.class, + Arrays.class, + Type.class, + inputParams); + if (isPayable && !withGasProvider) { + methodBuilder.addStatement( + "return deployRemoteCall(" + + "$L.class, $L, $L, $L, $L, $L, encodedConstructor, $L)", + className, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT, + BINARY, + INITIAL_VALUE); + methodBuilder.addAnnotation(Deprecated.class); + } else if (isPayable && withGasProvider) { + methodBuilder.addStatement( + "return deployRemoteCall(" + + "$L.class, $L, $L, $L, $L, encodedConstructor, $L)", + className, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER, + BINARY, + INITIAL_VALUE); + } else if (!isPayable && !withGasProvider) { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, encodedConstructor)", + className, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT, + BINARY); + methodBuilder.addAnnotation(Deprecated.class); + } else { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, encodedConstructor)", + className, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER, + BINARY); + } - if (useNativeJavaTypes) { - return Collection.join( - inputParameterTypes, - ", \n", - // this results in fully qualified names being generated - this::createMappedParameterTypes); - } else { - return Collection.join(inputParameterTypes, ", ", parameterSpec -> parameterSpec.name); + return methodBuilder.build(); } - } - - private String createMappedParameterTypes(ParameterSpec parameterSpec) { - if (parameterSpec.type instanceof ParameterizedTypeName) { - List typeNames = ((ParameterizedTypeName) parameterSpec.type).typeArguments; - if (typeNames.size() != 1) { - throw new UnsupportedOperationException("Only a single parameterized type is supported"); - } else { - String parameterSpecType = parameterSpec.type.toString(); - TypeName typeName = typeNames.get(0); - String typeMapInput = typeName + ".class"; - if (typeName instanceof ParameterizedTypeName) { - List typeArguments = ((ParameterizedTypeName) typeName).typeArguments; - if (typeArguments.size() != 1) { - throw new UnsupportedOperationException( - "Only a single parameterized type is supported"); - } - TypeName innerTypeName = typeArguments.get(0); - parameterSpecType = ((ParameterizedTypeName) parameterSpec.type).rawType.toString(); - typeMapInput = - ((ParameterizedTypeName) typeName).rawType + ".class, " + innerTypeName + ".class"; + + private static MethodSpec buildDeployNoParams( + MethodSpec.Builder methodBuilder, + String className, + String authName, + boolean isPayable, + boolean withGasPRovider) { + if (isPayable && !withGasPRovider) { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, \"\", $L)", + className, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT, + BINARY, + INITIAL_VALUE); + methodBuilder.addAnnotation(Deprecated.class); + } else if (isPayable && withGasPRovider) { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, \"\", $L)", + className, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER, + BINARY, + INITIAL_VALUE); + } else if (!isPayable && !withGasPRovider) { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, $L, \"\")", + className, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT, + BINARY); + methodBuilder.addAnnotation(Deprecated.class); + } else { + methodBuilder.addStatement( + "return deployRemoteCall($L.class, $L, $L, $L, $L, \"\")", + className, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER, + BINARY); } - return "new " - + parameterSpecType - + "(\n" - + " org.fisco.bcos.web3j.abi.Utils.typeMap(" - + parameterSpec.name - + ", " - + typeMapInput - + "))"; - } - } else { - return "new " + parameterSpec.type + "(" + parameterSpec.name + ")"; - } - } - private TypeName getWrapperType(TypeName typeName) { - if (useNativeJavaTypes) { - return getNativeType(typeName); - } else { - return typeName; + return methodBuilder.build(); } - } - - private TypeName getWrapperRawType(TypeName typeName) { - if (useNativeJavaTypes) { - if (typeName instanceof ParameterizedTypeName) { - return ClassName.get(List.class); - } - return getNativeType(typeName); - } else { - return typeName; + + private static MethodSpec.Builder getDeployMethodSpec( + String className, + Class authType, + String authName, + boolean isPayable, + boolean withGasProvider) { + MethodSpec.Builder builder = + MethodSpec.methodBuilder("deploy") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(buildRemoteCall(TypeVariableName.get(className, Type.class))) + .addParameter(Web3j.class, WEB3J) + .addParameter(authType, authName); + if (isPayable && !withGasProvider) { + return builder.addParameter(BigInteger.class, GAS_PRICE) + .addParameter(BigInteger.class, GAS_LIMIT) + .addParameter(BigInteger.class, INITIAL_VALUE); + } else if (isPayable && withGasProvider) { + return builder.addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) + .addParameter(BigInteger.class, INITIAL_VALUE); + } else if (!isPayable && withGasProvider) { + return builder.addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER); + } else { + return builder.addParameter(BigInteger.class, GAS_PRICE) + .addParameter(BigInteger.class, GAS_LIMIT); + } } - } - private TypeName getIndexedEventWrapperType(TypeName typeName) { - if (useNativeJavaTypes) { - return getEventNativeType(typeName); - } else { - return typeName; + private static MethodSpec buildLoad( + String className, Class authType, String authName, boolean withGasProvider) { + MethodSpec.Builder toReturn = + MethodSpec.methodBuilder("load") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(TypeVariableName.get(className, Type.class)) + .addParameter(String.class, CONTRACT_ADDRESS) + .addParameter(Web3j.class, WEB3J) + .addParameter(authType, authName); + + if (withGasProvider) { + toReturn.addParameter(ContractGasProvider.class, CONTRACT_GAS_PROVIDER) + .addStatement( + "return new $L($L, $L, $L, $L)", + className, + CONTRACT_ADDRESS, + WEB3J, + authName, + CONTRACT_GAS_PROVIDER); + } else { + toReturn.addParameter(BigInteger.class, GAS_PRICE) + .addParameter(BigInteger.class, GAS_LIMIT) + .addStatement( + "return new $L($L, $L, $L, $L, $L)", + className, + CONTRACT_ADDRESS, + WEB3J, + authName, + GAS_PRICE, + GAS_LIMIT) + .addAnnotation(Deprecated.class); + } + + return toReturn.build(); } - } - static TypeName getNativeType(TypeName typeName) { + String addParameters( + MethodSpec.Builder methodBuilder, List namedTypes) { + + List inputParameterTypes = buildParameterTypes(namedTypes); + + List nativeInputParameterTypes = new ArrayList<>(inputParameterTypes.size()); + for (ParameterSpec parameterSpec : inputParameterTypes) { + TypeName typeName = getWrapperType(parameterSpec.type); + nativeInputParameterTypes.add( + ParameterSpec.builder(typeName, parameterSpec.name).build()); + } + + methodBuilder.addParameters(nativeInputParameterTypes); - if (typeName instanceof ParameterizedTypeName) { - return getNativeType((ParameterizedTypeName) typeName); + if (useNativeJavaTypes) { + return Collection.join( + inputParameterTypes, + ", \n", + // this results in fully qualified names being generated + this::createMappedParameterTypes); + } else { + return Collection.join(inputParameterTypes, ", ", parameterSpec -> parameterSpec.name); + } } - String simpleName = ((ClassName) typeName).simpleName(); - - if (simpleName.startsWith(Address.class.getSimpleName())) { - return TypeName.get(String.class); - } else if (simpleName.startsWith("Uint")) { - return TypeName.get(BigInteger.class); - } else if (simpleName.startsWith("Int")) { - return TypeName.get(BigInteger.class); - } else if (simpleName.startsWith(Utf8String.class.getSimpleName())) { - return TypeName.get(String.class); - } else if (simpleName.startsWith("Bytes")) { - return TypeName.get(byte[].class); - } else if (simpleName.startsWith(DynamicBytes.class.getSimpleName())) { - return TypeName.get(byte[].class); - } else if (simpleName.startsWith(Bool.class.getSimpleName())) { - return TypeName.get(Boolean.class); // boolean cannot be a parameterized type - } else { - throw new UnsupportedOperationException( - "Unsupported type: " + typeName + ", no native type mapping exists."); + private String createMappedParameterTypes(ParameterSpec parameterSpec) { + if (parameterSpec.type instanceof ParameterizedTypeName) { + List typeNames = ((ParameterizedTypeName) parameterSpec.type).typeArguments; + if (typeNames.size() != 1) { + throw new UnsupportedOperationException( + "Only a single parameterized type is supported"); + } else { + String parameterSpecType = parameterSpec.type.toString(); + TypeName typeName = typeNames.get(0); + String typeMapInput = typeName + ".class"; + if (typeName instanceof ParameterizedTypeName) { + List typeArguments = ((ParameterizedTypeName) typeName).typeArguments; + if (typeArguments.size() != 1) { + throw new UnsupportedOperationException( + "Only a single parameterized type is supported"); + } + TypeName innerTypeName = typeArguments.get(0); + parameterSpecType = + ((ParameterizedTypeName) parameterSpec.type).rawType.toString(); + typeMapInput = + ((ParameterizedTypeName) typeName).rawType + + ".class, " + + innerTypeName + + ".class"; + } + return "new " + + parameterSpecType + + "(\n" + + " org.fisco.bcos.web3j.abi.Utils.typeMap(" + + parameterSpec.name + + ", " + + typeMapInput + + "))"; + } + } else { + return "new " + parameterSpec.type + "(" + parameterSpec.name + ")"; + } } - } - static TypeName getNativeType(ParameterizedTypeName parameterizedTypeName) { - List typeNames = parameterizedTypeName.typeArguments; - List nativeTypeNames = new ArrayList<>(typeNames.size()); - for (TypeName enclosedTypeName : typeNames) { - nativeTypeNames.add(getNativeType(enclosedTypeName)); + private TypeName getWrapperType(TypeName typeName) { + if (useNativeJavaTypes) { + return getNativeType(typeName); + } else { + return typeName; + } } - return ParameterizedTypeName.get( - ClassName.get(List.class), nativeTypeNames.toArray(new TypeName[nativeTypeNames.size()])); - } - static TypeName getEventNativeType(TypeName typeName) { - if (typeName instanceof ParameterizedTypeName) { - return TypeName.get(byte[].class); + private TypeName getWrapperRawType(TypeName typeName) { + if (useNativeJavaTypes) { + if (typeName instanceof ParameterizedTypeName) { + return ClassName.get(List.class); + } + return getNativeType(typeName); + } else { + return typeName; + } } - String simpleName = ((ClassName) typeName).simpleName(); - if ("Utf8String".equals(simpleName)) { - return TypeName.get(byte[].class); - } else { - return getNativeType(typeName); + private TypeName getIndexedEventWrapperType(TypeName typeName) { + if (useNativeJavaTypes) { + return getEventNativeType(typeName); + } else { + return typeName; + } } - } - static List buildParameterTypes(List namedTypes) { - List result = new ArrayList<>(namedTypes.size()); - for (int i = 0; i < namedTypes.size(); i++) { - AbiDefinition.NamedType namedType = namedTypes.get(i); + static TypeName getNativeType(TypeName typeName) { - String name = createValidParamName(namedType.getName(), i); - String type = namedTypes.get(i).getType(); + if (typeName instanceof ParameterizedTypeName) { + return getNativeType((ParameterizedTypeName) typeName); + } - result.add(ParameterSpec.builder(buildTypeName(type), name).build()); + String simpleName = ((ClassName) typeName).simpleName(); + + if (simpleName.startsWith(Address.class.getSimpleName())) { + return TypeName.get(String.class); + } else if (simpleName.startsWith("Uint")) { + return TypeName.get(BigInteger.class); + } else if (simpleName.startsWith("Int")) { + return TypeName.get(BigInteger.class); + } else if (simpleName.startsWith(Utf8String.class.getSimpleName())) { + return TypeName.get(String.class); + } else if (simpleName.startsWith("Bytes")) { + return TypeName.get(byte[].class); + } else if (simpleName.startsWith(DynamicBytes.class.getSimpleName())) { + return TypeName.get(byte[].class); + } else if (simpleName.startsWith(Bool.class.getSimpleName())) { + return TypeName.get(Boolean.class); // boolean cannot be a parameterized type + } else { + throw new UnsupportedOperationException( + "Unsupported type: " + typeName + ", no native type mapping exists."); + } } - return result; - } - - /** - * Public Solidity arrays and maps require an unnamed input parameter - multiple if they require a - * struct type. - * - * @param name parameter name - * @param idx parameter index - * @return non-empty parameter name - */ - static String createValidParamName(String name, int idx) { - if (name.equals("")) { - return "param" + idx; - } else { - return name; + + static TypeName getNativeType(ParameterizedTypeName parameterizedTypeName) { + List typeNames = parameterizedTypeName.typeArguments; + List nativeTypeNames = new ArrayList<>(typeNames.size()); + for (TypeName enclosedTypeName : typeNames) { + nativeTypeNames.add(getNativeType(enclosedTypeName)); + } + return ParameterizedTypeName.get( + ClassName.get(List.class), + nativeTypeNames.toArray(new TypeName[nativeTypeNames.size()])); } - } - static List buildTypeNames(List namedTypes) { - List result = new ArrayList<>(namedTypes.size()); - for (AbiDefinition.NamedType namedType : namedTypes) { - result.add(buildTypeName(namedType.getType())); + static TypeName getEventNativeType(TypeName typeName) { + if (typeName instanceof ParameterizedTypeName) { + return TypeName.get(byte[].class); + } + + String simpleName = ((ClassName) typeName).simpleName(); + if ("Utf8String".equals(simpleName)) { + return TypeName.get(byte[].class); + } else { + return getNativeType(typeName); + } } - return result; - } - MethodSpec buildFunction(AbiDefinition functionDefinition) throws ClassNotFoundException { - String functionName = functionDefinition.getName(); + static List buildParameterTypes(List namedTypes) { + List result = new ArrayList<>(namedTypes.size()); + for (int i = 0; i < namedTypes.size(); i++) { + AbiDefinition.NamedType namedType = namedTypes.get(i); - if(!SourceVersion.isName(functionName)) { - functionName = "_" + functionName; + String name = createValidParamName(namedType.getName(), i); + String type = namedTypes.get(i).getType(); + + result.add(ParameterSpec.builder(buildTypeName(type), name).build()); + } + return result; } - MethodSpec.Builder methodBuilder = - MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC); + /** + * Public Solidity arrays and maps require an unnamed input parameter - multiple if they require + * a struct type. + * + * @param name parameter name + * @param idx parameter index + * @return non-empty parameter name + */ + static String createValidParamName(String name, int idx) { + if (name.equals("")) { + return "param" + idx; + } else { + return name; + } + } + + static List buildTypeNames(List namedTypes) { + List result = new ArrayList<>(namedTypes.size()); + for (AbiDefinition.NamedType namedType : namedTypes) { + result.add(buildTypeName(namedType.getType())); + } + return result; + } + + MethodSpec buildFunction(AbiDefinition functionDefinition) throws ClassNotFoundException { + String functionName = functionDefinition.getName(); - String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); + if (!SourceVersion.isName(functionName)) { + functionName = "_" + functionName; + } + + MethodSpec.Builder methodBuilder = + MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC); + + String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); + + List outputParameterTypes = buildTypeNames(functionDefinition.getOutputs()); + if (functionDefinition.isConstant()) { + buildConstantFunction( + functionDefinition, methodBuilder, outputParameterTypes, inputParams); + } else { + buildTransactionFunction(functionDefinition, methodBuilder, inputParams); + } - List outputParameterTypes = buildTypeNames(functionDefinition.getOutputs()); - if (functionDefinition.isConstant()) { - buildConstantFunction(functionDefinition, methodBuilder, outputParameterTypes, inputParams); - } else { - buildTransactionFunction(functionDefinition, methodBuilder, inputParams); + return methodBuilder.build(); } - return methodBuilder.build(); - } + MethodSpec buildFunctionSeq(AbiDefinition functionDefinition) throws ClassNotFoundException { + String functionName = functionDefinition.getName(); + functionName += "Seq"; - MethodSpec buildFunctionWithCallback(AbiDefinition functionDefinition) - throws ClassNotFoundException { - String functionName = functionDefinition.getName(); + if (!SourceVersion.isName(functionName)) { + functionName = "_" + functionName; + } - MethodSpec.Builder methodBuilder = - MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC); + MethodSpec.Builder methodBuilder = + MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC); - List outputParameterTypes = buildTypeNames(functionDefinition.getOutputs()); + String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); - if (functionDefinition.isConstant()) { - String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); - buildConstantFunction(functionDefinition, methodBuilder, outputParameterTypes, inputParams); - } else { - // functionDefinition.getInputs().add(new NamedType("callback", - // "org.fisco.bcos.channel.dto.FiscoResponse.TransactionSucCallback")); - String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); - methodBuilder.addParameter( - ParameterSpec.builder(buildTypeName("TransactionSucCallback"), "callback").build()); + buildTransactionFunctionSeq(functionDefinition, methodBuilder, inputParams); - buildTransactionFunctionWithCallback(functionDefinition, methodBuilder, inputParams); + return methodBuilder.build(); } - return methodBuilder.build(); - } - - private void buildConstantFunction( - AbiDefinition functionDefinition, - MethodSpec.Builder methodBuilder, - List outputParameterTypes, - String inputParams) - throws ClassNotFoundException { - - String functionName = functionDefinition.getName(); - - if (outputParameterTypes.isEmpty()) { - methodBuilder.addStatement( - "throw new RuntimeException" - + "(\"cannot call constant function with void return type\")"); - } else if (outputParameterTypes.size() == 1) { - - TypeName typeName = outputParameterTypes.get(0); - TypeName nativeReturnTypeName; - if (useNativeJavaTypes) { - nativeReturnTypeName = getWrapperRawType(typeName); - } else { - nativeReturnTypeName = getWrapperType(typeName); - } - methodBuilder.returns(buildRemoteCall(nativeReturnTypeName)); - - methodBuilder.addStatement( - "final $T function = " - + "new $T($N, \n$T.<$T>asList($L), " - + "\n$T.<$T>asList(new $T<$T>() {}))", - Function.class, - Function.class, - funcNameToConst(functionName), - Arrays.class, - Type.class, - inputParams, - Arrays.class, - TypeReference.class, - TypeReference.class, - typeName); - - if (useNativeJavaTypes) { - if (nativeReturnTypeName.equals(ClassName.get(List.class))) { - // We return list. So all the list elements should - // also be converted to native types - TypeName listType = ParameterizedTypeName.get(List.class, Type.class); - - CodeBlock.Builder callCode = CodeBlock.builder(); - callCode.addStatement( - "$T result = " + "($T) executeCallSingleValueReturn(function, $T.class)", - listType, - listType, - nativeReturnTypeName); - callCode.addStatement("return convertToNative(result)"); - - TypeSpec callableType = - TypeSpec.anonymousClassBuilder("") - .addSuperinterface( - ParameterizedTypeName.get( - ClassName.get(Callable.class), nativeReturnTypeName)) - .addMethod( - MethodSpec.methodBuilder("call") - .addAnnotation(Override.class) - .addAnnotation( - AnnotationSpec.builder(SuppressWarnings.class) - .addMember("value", "$S", "unchecked") - .build()) - .addModifiers(Modifier.PUBLIC) - .addException(Exception.class) - .returns(nativeReturnTypeName) - .addCode(callCode.build()) - .build()) - .build(); - - methodBuilder.addStatement( - "return new $T(\n$L)", buildRemoteCall(nativeReturnTypeName), callableType); + MethodSpec buildFunctionWithCallback(AbiDefinition functionDefinition) + throws ClassNotFoundException { + String functionName = functionDefinition.getName(); + + MethodSpec.Builder methodBuilder = + MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC); + + List outputParameterTypes = buildTypeNames(functionDefinition.getOutputs()); + + if (functionDefinition.isConstant()) { + String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); + buildConstantFunction( + functionDefinition, methodBuilder, outputParameterTypes, inputParams); } else { - methodBuilder.addStatement( - "return executeRemoteCallSingleValueReturn(function, $T.class)", - nativeReturnTypeName); + // functionDefinition.getInputs().add(new NamedType("callback", + // "org.fisco.bcos.channel.dto.FiscoResponse.TransactionSucCallback")); + String inputParams = addParameters(methodBuilder, functionDefinition.getInputs()); + methodBuilder.addParameter( + ParameterSpec.builder(buildTypeName("TransactionSucCallback"), "callback") + .build()); + + buildTransactionFunctionWithCallback(functionDefinition, methodBuilder, inputParams); } - } else { - methodBuilder.addStatement("return executeRemoteCallSingleValueReturn(function)"); - } - } else { - List returnTypes = buildReturnTypes(outputParameterTypes); - ParameterizedTypeName parameterizedTupleType = - ParameterizedTypeName.get( - ClassName.get("org.fisco.bcos.web3j.tuples.generated", "Tuple" + returnTypes.size()), - returnTypes.toArray(new TypeName[returnTypes.size()])); + return methodBuilder.build(); + } + + private void buildConstantFunction( + AbiDefinition functionDefinition, + MethodSpec.Builder methodBuilder, + List outputParameterTypes, + String inputParams) + throws ClassNotFoundException { + + String functionName = functionDefinition.getName(); + + if (outputParameterTypes.isEmpty()) { + methodBuilder.addStatement( + "throw new RuntimeException" + + "(\"cannot call constant function with void return type\")"); + } else if (outputParameterTypes.size() == 1) { + + TypeName typeName = outputParameterTypes.get(0); + TypeName nativeReturnTypeName; + if (useNativeJavaTypes) { + nativeReturnTypeName = getWrapperRawType(typeName); + } else { + nativeReturnTypeName = getWrapperType(typeName); + } + methodBuilder.returns(buildRemoteCall(nativeReturnTypeName)); + + methodBuilder.addStatement( + "final $T function = " + + "new $T($N, \n$T.<$T>asList($L), " + + "\n$T.<$T>asList(new $T<$T>() {}))", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Arrays.class, + TypeReference.class, + TypeReference.class, + typeName); + + if (useNativeJavaTypes) { + if (nativeReturnTypeName.equals(ClassName.get(List.class))) { + // We return list. So all the list elements should + // also be converted to native types + TypeName listType = ParameterizedTypeName.get(List.class, Type.class); + + CodeBlock.Builder callCode = CodeBlock.builder(); + callCode.addStatement( + "$T result = " + + "($T) executeCallSingleValueReturn(function, $T.class)", + listType, + listType, + nativeReturnTypeName); + callCode.addStatement("return convertToNative(result)"); + + TypeSpec callableType = + TypeSpec.anonymousClassBuilder("") + .addSuperinterface( + ParameterizedTypeName.get( + ClassName.get(Callable.class), + nativeReturnTypeName)) + .addMethod( + MethodSpec.methodBuilder("call") + .addAnnotation(Override.class) + .addAnnotation( + AnnotationSpec.builder( + SuppressWarnings.class) + .addMember( + "value", + "$S", + "unchecked") + .build()) + .addModifiers(Modifier.PUBLIC) + .addException(Exception.class) + .returns(nativeReturnTypeName) + .addCode(callCode.build()) + .build()) + .build(); + + methodBuilder.addStatement( + "return new $T(\n$L)", + buildRemoteCall(nativeReturnTypeName), + callableType); + } else { + methodBuilder.addStatement( + "return executeRemoteCallSingleValueReturn(function, $T.class)", + nativeReturnTypeName); + } + } else { + methodBuilder.addStatement("return executeRemoteCallSingleValueReturn(function)"); + } + } else { + List returnTypes = buildReturnTypes(outputParameterTypes); + + ParameterizedTypeName parameterizedTupleType = + ParameterizedTypeName.get( + ClassName.get( + "org.fisco.bcos.web3j.tuples.generated", + "Tuple" + returnTypes.size()), + returnTypes.toArray(new TypeName[returnTypes.size()])); - methodBuilder.returns(buildRemoteCall(parameterizedTupleType)); + methodBuilder.returns(buildRemoteCall(parameterizedTupleType)); - buildVariableLengthReturnFunctionConstructor( - methodBuilder, functionName, inputParams, outputParameterTypes); + buildVariableLengthReturnFunctionConstructor( + methodBuilder, functionName, inputParams, outputParameterTypes); - buildTupleResultContainer(methodBuilder, parameterizedTupleType, outputParameterTypes); + buildTupleResultContainer(methodBuilder, parameterizedTupleType, outputParameterTypes); + } } - } - - private static ParameterizedTypeName buildRemoteCall(TypeName typeName) { - return ParameterizedTypeName.get(ClassName.get(RemoteCall.class), typeName); - } - - private void buildTransactionFunction( - AbiDefinition functionDefinition, MethodSpec.Builder methodBuilder, String inputParams) - throws ClassNotFoundException { - - if (functionDefinition.hasOutputs()) { - // CHECKSTYLE:OFF - reporter.report( - String.format( - "Definition of the function %s returns a value but is not defined as a view function. " - + "Please ensure it contains the view modifier if you want to read the return value", - functionDefinition.getName())); - // CHECKSTYLE:ON + + private static ParameterizedTypeName buildRemoteCall(TypeName typeName) { + return ParameterizedTypeName.get(ClassName.get(RemoteCall.class), typeName); } - if (functionDefinition.isPayable()) { - methodBuilder.addParameter(BigInteger.class, WEI_VALUE); + private void buildTransactionFunction( + AbiDefinition functionDefinition, MethodSpec.Builder methodBuilder, String inputParams) + throws ClassNotFoundException { + + if (functionDefinition.hasOutputs()) { + // CHECKSTYLE:OFF + reporter.report( + String.format( + "Definition of the function %s returns a value but is not defined as a view function. " + + "Please ensure it contains the view modifier if you want to read the return value", + functionDefinition.getName())); + // CHECKSTYLE:ON + } + + if (functionDefinition.isPayable()) { + methodBuilder.addParameter(BigInteger.class, WEI_VALUE); + } + + String functionName = functionDefinition.getName(); + + methodBuilder.returns(buildRemoteCall(TypeName.get(TransactionReceipt.class))); + + methodBuilder.addStatement( + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList())", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Collections.class, + TypeReference.class); + if (functionDefinition.isPayable()) { + methodBuilder.addStatement( + "return executeRemoteCallTransaction(function, $N)", WEI_VALUE); + } else { + methodBuilder.addStatement("return executeRemoteCallTransaction(function)"); + } } - String functionName = functionDefinition.getName(); - - methodBuilder.returns(buildRemoteCall(TypeName.get(TransactionReceipt.class))); - - methodBuilder.addStatement( - "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + ".<$T>emptyList())", - Function.class, - Function.class, - funcNameToConst(functionName), - Arrays.class, - Type.class, - inputParams, - Collections.class, - TypeReference.class); - if (functionDefinition.isPayable()) { - methodBuilder.addStatement("return executeRemoteCallTransaction(function, $N)", WEI_VALUE); - } else { - methodBuilder.addStatement("return executeRemoteCallTransaction(function)"); + private void buildTransactionFunctionWithCallback( + AbiDefinition functionDefinition, MethodSpec.Builder methodBuilder, String inputParams) + throws ClassNotFoundException { + + if (functionDefinition.hasOutputs()) { + // CHECKSTYLE:OFF + reporter.report( + String.format( + "Definition of the function %s returns a value but is not defined as a view function. " + + "Please ensure it contains the view modifier if you want to read the return value", + functionDefinition.getName())); + // CHECKSTYLE:ON + } + + if (functionDefinition.isPayable()) { + methodBuilder.addParameter(BigInteger.class, WEI_VALUE); + } + // methodBuilder.addParameter(TransactionSucCallback.class, "callback"); + + String functionName = functionDefinition.getName(); + + methodBuilder.returns(TypeName.VOID); + + methodBuilder.addStatement( + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList())", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Collections.class, + TypeReference.class); + methodBuilder.addStatement("asyncExecuteTransaction(function, callback)"); } - } - - private void buildTransactionFunctionWithCallback( - AbiDefinition functionDefinition, MethodSpec.Builder methodBuilder, String inputParams) - throws ClassNotFoundException { - - if (functionDefinition.hasOutputs()) { - // CHECKSTYLE:OFF - reporter.report( - String.format( - "Definition of the function %s returns a value but is not defined as a view function. " - + "Please ensure it contains the view modifier if you want to read the return value", - functionDefinition.getName())); - // CHECKSTYLE:ON + + private void buildTransactionFunctionSeq( + AbiDefinition functionDefinition, MethodSpec.Builder methodBuilder, String inputParams) + throws ClassNotFoundException { + + if (functionDefinition.hasOutputs()) { + // CHECKSTYLE:OFF + reporter.report( + String.format( + "Definition of the function %s returns a value but is not defined as a view function. " + + "Please ensure it contains the view modifier if you want to read the return value", + functionDefinition.getName())); + // CHECKSTYLE:ON + } + + if (functionDefinition.isPayable()) { + methodBuilder.addParameter(BigInteger.class, WEI_VALUE); + } + + String functionName = functionDefinition.getName(); + + TypeName returnType = TypeName.get(String.class); + methodBuilder.returns(returnType); + + methodBuilder.addStatement( + "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + + ".<$T>emptyList())", + Function.class, + Function.class, + funcNameToConst(functionName), + Arrays.class, + Type.class, + inputParams, + Collections.class, + TypeReference.class); + + methodBuilder.addStatement("return createTransactionSeq(function)"); } - if (functionDefinition.isPayable()) { - methodBuilder.addParameter(BigInteger.class, WEI_VALUE); + TypeSpec buildEventResponseObject( + String className, + List indexedParameters, + List nonIndexedParameters) { + + TypeSpec.Builder builder = + TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC, Modifier.STATIC); + + builder.addField(LOG, "log", Modifier.PUBLIC); + for (SolidityFunctionWrapper.NamedTypeName namedType : indexedParameters) { + TypeName typeName = getIndexedEventWrapperType(namedType.typeName); + builder.addField(typeName, namedType.getName(), Modifier.PUBLIC); + } + + for (SolidityFunctionWrapper.NamedTypeName namedType : nonIndexedParameters) { + TypeName typeName = getWrapperType(namedType.typeName); + builder.addField(typeName, namedType.getName(), Modifier.PUBLIC); + } + + return builder.build(); } - // methodBuilder.addParameter(TransactionSucCallback.class, "callback"); - - String functionName = functionDefinition.getName(); - - methodBuilder.returns(TypeName.VOID); - - methodBuilder.addStatement( - "final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T" + ".<$T>emptyList())", - Function.class, - Function.class, - funcNameToConst(functionName), - Arrays.class, - Type.class, - inputParams, - Collections.class, - TypeReference.class); - methodBuilder.addStatement("asyncExecuteTransaction(function, callback)"); - } - - TypeSpec buildEventResponseObject( - String className, - List indexedParameters, - List nonIndexedParameters) { - - TypeSpec.Builder builder = - TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC, Modifier.STATIC); - - builder.addField(LOG, "log", Modifier.PUBLIC); - for (SolidityFunctionWrapper.NamedTypeName namedType : indexedParameters) { - TypeName typeName = getIndexedEventWrapperType(namedType.typeName); - builder.addField(typeName, namedType.getName(), Modifier.PUBLIC); + + MethodSpec buildEventFlowableFunction( + String responseClassName, + String functionName, + List indexedParameters, + List nonIndexedParameters) + throws ClassNotFoundException { + + String generatedFunctionName = Strings.lowercaseFirstLetter(functionName) + "EventFlowable"; + ParameterizedTypeName parameterizedTypeName = + ParameterizedTypeName.get( + ClassName.get(Flowable.class), ClassName.get("", responseClassName)); + + MethodSpec.Builder flowableMethodBuilder = + MethodSpec.methodBuilder(generatedFunctionName) + .addModifiers(Modifier.PUBLIC) + .addParameter(BcosFilter.class, FILTER) + .returns(parameterizedTypeName); + + TypeSpec converter = + TypeSpec.anonymousClassBuilder("") + .addSuperinterface( + ParameterizedTypeName.get( + ClassName.get(io.reactivex.functions.Function.class), + ClassName.get(Log.class), + ClassName.get("", responseClassName))) + .addMethod( + MethodSpec.methodBuilder("apply") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(Log.class, "log") + .returns(ClassName.get("", responseClassName)) + .addStatement( + "$T eventValues = extractEventParametersWithLog(" + + buildEventDefinitionName(functionName) + + ", log)", + Contract.EventValuesWithLog.class) + .addStatement( + "$1T typedResponse = new $1T()", + ClassName.get("", responseClassName)) + .addCode( + buildTypedResponse( + "typedResponse", + indexedParameters, + nonIndexedParameters, + true)) + .addStatement("return typedResponse") + .build()) + .build(); + + flowableMethodBuilder.addStatement("return web3j.logFlowable(filter).map($L)", converter); + + return flowableMethodBuilder.build(); } - for (SolidityFunctionWrapper.NamedTypeName namedType : nonIndexedParameters) { - TypeName typeName = getWrapperType(namedType.typeName); - builder.addField(typeName, namedType.getName(), Modifier.PUBLIC); + MethodSpec buildDefaultEventFlowableFunction(String responseClassName, String functionName) { + + String generatedFunctionName = Strings.lowercaseFirstLetter(functionName) + "EventFlowable"; + ParameterizedTypeName parameterizedTypeName = + ParameterizedTypeName.get( + ClassName.get(Flowable.class), ClassName.get("", responseClassName)); + + MethodSpec.Builder flowableMethodBuilder = + MethodSpec.methodBuilder(generatedFunctionName) + .addModifiers(Modifier.PUBLIC) + .addParameter(DefaultBlockParameter.class, START_BLOCK) + .addParameter(DefaultBlockParameter.class, END_BLOCK) + .returns(parameterizedTypeName); + + flowableMethodBuilder + .addStatement( + "$1T filter = new $1T($2L, $3L, " + "getContractAddress())", + BcosFilter.class, + START_BLOCK, + END_BLOCK) + .addStatement( + "filter.addSingleTopic($T.encode(" + + buildEventDefinitionName(functionName) + + "))", + EventEncoder.class) + .addStatement("return " + generatedFunctionName + "(filter)"); + + return flowableMethodBuilder.build(); } - return builder.build(); - } - - MethodSpec buildEventFlowableFunction( - String responseClassName, - String functionName, - List indexedParameters, - List nonIndexedParameters) - throws ClassNotFoundException { - - String generatedFunctionName = Strings.lowercaseFirstLetter(functionName) + "EventFlowable"; - ParameterizedTypeName parameterizedTypeName = - ParameterizedTypeName.get( - ClassName.get(Flowable.class), ClassName.get("", responseClassName)); - - MethodSpec.Builder flowableMethodBuilder = - MethodSpec.methodBuilder(generatedFunctionName) - .addModifiers(Modifier.PUBLIC) - .addParameter(BcosFilter.class, FILTER) - .returns(parameterizedTypeName); - - TypeSpec converter = - TypeSpec.anonymousClassBuilder("") - .addSuperinterface( + MethodSpec buildEventTransactionReceiptFunction( + String responseClassName, + String functionName, + List indexedParameters, + List nonIndexedParameters) { + + ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName.get( - ClassName.get(io.reactivex.functions.Function.class), - ClassName.get(Log.class), - ClassName.get("", responseClassName))) - .addMethod( - MethodSpec.methodBuilder("apply") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .addParameter(Log.class, "log") - .returns(ClassName.get("", responseClassName)) - .addStatement( - "$T eventValues = extractEventParametersWithLog(" - + buildEventDefinitionName(functionName) - + ", log)", - Contract.EventValuesWithLog.class) - .addStatement( - "$1T typedResponse = new $1T()", ClassName.get("", responseClassName)) - .addCode( + ClassName.get(List.class), ClassName.get("", responseClassName)); + + String generatedFunctionName = + "get" + Strings.capitaliseFirstLetter(functionName) + "Events"; + MethodSpec.Builder transactionMethodBuilder = + MethodSpec.methodBuilder(generatedFunctionName) + .addModifiers(Modifier.PUBLIC) + .addParameter(TransactionReceipt.class, "transactionReceipt") + .returns(parameterizedTypeName); + + transactionMethodBuilder + .addStatement( + "$T valueList = extractEventParametersWithLog(" + + buildEventDefinitionName(functionName) + + ", " + + "transactionReceipt)", + ParameterizedTypeName.get(List.class, Contract.EventValuesWithLog.class)) + .addStatement( + "$1T responses = new $1T(valueList.size())", + ParameterizedTypeName.get( + ClassName.get(ArrayList.class), + ClassName.get("", responseClassName))) + .beginControlFlow( + "for ($T eventValues : valueList)", Contract.EventValuesWithLog.class) + .addStatement("$1T typedResponse = new $1T()", ClassName.get("", responseClassName)) + .addCode( buildTypedResponse( - "typedResponse", indexedParameters, nonIndexedParameters, true)) - .addStatement("return typedResponse") - .build()) - .build(); - - flowableMethodBuilder.addStatement("return web3j.logFlowable(filter).map($L)", converter); - - return flowableMethodBuilder.build(); - } - - MethodSpec buildDefaultEventFlowableFunction(String responseClassName, String functionName) { - - String generatedFunctionName = Strings.lowercaseFirstLetter(functionName) + "EventFlowable"; - ParameterizedTypeName parameterizedTypeName = - ParameterizedTypeName.get( - ClassName.get(Flowable.class), ClassName.get("", responseClassName)); - - MethodSpec.Builder flowableMethodBuilder = - MethodSpec.methodBuilder(generatedFunctionName) - .addModifiers(Modifier.PUBLIC) - .addParameter(DefaultBlockParameter.class, START_BLOCK) - .addParameter(DefaultBlockParameter.class, END_BLOCK) - .returns(parameterizedTypeName); - - flowableMethodBuilder - .addStatement( - "$1T filter = new $1T($2L, $3L, " + "getContractAddress())", - BcosFilter.class, - START_BLOCK, - END_BLOCK) - .addStatement( - "filter.addSingleTopic($T.encode(" + buildEventDefinitionName(functionName) + "))", - EventEncoder.class) - .addStatement("return " + generatedFunctionName + "(filter)"); - - return flowableMethodBuilder.build(); - } - - MethodSpec buildEventTransactionReceiptFunction( - String responseClassName, - String functionName, - List indexedParameters, - List nonIndexedParameters) { - - ParameterizedTypeName parameterizedTypeName = - ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get("", responseClassName)); - - String generatedFunctionName = "get" + Strings.capitaliseFirstLetter(functionName) + "Events"; - MethodSpec.Builder transactionMethodBuilder = - MethodSpec.methodBuilder(generatedFunctionName) - .addModifiers(Modifier.PUBLIC) - .addParameter(TransactionReceipt.class, "transactionReceipt") - .returns(parameterizedTypeName); - - transactionMethodBuilder - .addStatement( - "$T valueList = extractEventParametersWithLog(" - + buildEventDefinitionName(functionName) - + ", " - + "transactionReceipt)", - ParameterizedTypeName.get(List.class, Contract.EventValuesWithLog.class)) - .addStatement( - "$1T responses = new $1T(valueList.size())", - ParameterizedTypeName.get( - ClassName.get(ArrayList.class), ClassName.get("", responseClassName))) - .beginControlFlow("for ($T eventValues : valueList)", Contract.EventValuesWithLog.class) - .addStatement("$1T typedResponse = new $1T()", ClassName.get("", responseClassName)) - .addCode( - buildTypedResponse("typedResponse", indexedParameters, nonIndexedParameters, false)) - .addStatement("responses.add(typedResponse)") - .endControlFlow(); - - transactionMethodBuilder.addStatement("return responses"); - return transactionMethodBuilder.build(); - } - - List buildEventFunctions( - AbiDefinition functionDefinition, TypeSpec.Builder classBuilder) - throws ClassNotFoundException { - String functionName = functionDefinition.getName(); - List inputs = functionDefinition.getInputs(); - String responseClassName = Strings.capitaliseFirstLetter(functionName) + "EventResponse"; - - List parameters = new ArrayList<>(); - List indexedParameters = new ArrayList<>(); - List nonIndexedParameters = new ArrayList<>(); - - for (AbiDefinition.NamedType namedType : inputs) { - NamedTypeName parameter = - new NamedTypeName( - namedType.getName(), buildTypeName(namedType.getType()), namedType.isIndexed()); - if (namedType.isIndexed()) { - indexedParameters.add(parameter); - } else { - nonIndexedParameters.add(parameter); - } - parameters.add(parameter); - } + "typedResponse", indexedParameters, nonIndexedParameters, false)) + .addStatement("responses.add(typedResponse)") + .endControlFlow(); - classBuilder.addField(createEventDefinition(functionName, parameters)); - - classBuilder.addType( - buildEventResponseObject(responseClassName, indexedParameters, nonIndexedParameters)); - - List methods = new ArrayList<>(); - methods.add( - buildEventTransactionReceiptFunction( - responseClassName, functionName, indexedParameters, nonIndexedParameters)); - - methods.add( - buildEventFlowableFunction( - responseClassName, functionName, indexedParameters, nonIndexedParameters)); - methods.add(buildDefaultEventFlowableFunction(responseClassName, functionName)); - return methods; - } - - CodeBlock buildTypedResponse( - String objectName, - List indexedParameters, - List nonIndexedParameters, - boolean flowable) { - String nativeConversion; - - if (useNativeJavaTypes) { - nativeConversion = ".getValue()"; - } else { - nativeConversion = ""; + transactionMethodBuilder.addStatement("return responses"); + return transactionMethodBuilder.build(); } - CodeBlock.Builder builder = CodeBlock.builder(); - if (flowable) { - builder.addStatement("$L.log = log", objectName); - } else { - builder.addStatement("$L.log = eventValues.getLog()", objectName); - } - for (int i = 0; i < indexedParameters.size(); i++) { - builder.addStatement( - "$L.$L = ($T) eventValues.getIndexedValues().get($L)" + nativeConversion, - objectName, - indexedParameters.get(i).getName(), - getIndexedEventWrapperType(indexedParameters.get(i).getTypeName()), - i); - } + List buildEventFunctions( + AbiDefinition functionDefinition, TypeSpec.Builder classBuilder) + throws ClassNotFoundException { + String functionName = functionDefinition.getName(); + List inputs = functionDefinition.getInputs(); + String responseClassName = Strings.capitaliseFirstLetter(functionName) + "EventResponse"; + + List parameters = new ArrayList<>(); + List indexedParameters = new ArrayList<>(); + List nonIndexedParameters = new ArrayList<>(); + + for (AbiDefinition.NamedType namedType : inputs) { + NamedTypeName parameter = + new NamedTypeName( + namedType.getName(), + buildTypeName(namedType.getType()), + namedType.isIndexed()); + if (namedType.isIndexed()) { + indexedParameters.add(parameter); + } else { + nonIndexedParameters.add(parameter); + } + parameters.add(parameter); + } + + classBuilder.addField(createEventDefinition(functionName, parameters)); + + classBuilder.addType( + buildEventResponseObject( + responseClassName, indexedParameters, nonIndexedParameters)); + + List methods = new ArrayList<>(); + methods.add( + buildEventTransactionReceiptFunction( + responseClassName, functionName, indexedParameters, nonIndexedParameters)); - for (int i = 0; i < nonIndexedParameters.size(); i++) { - builder.addStatement( - "$L.$L = ($T) eventValues.getNonIndexedValues().get($L)" + nativeConversion, - objectName, - nonIndexedParameters.get(i).getName(), - getWrapperType(nonIndexedParameters.get(i).getTypeName()), - i); + methods.add( + buildEventFlowableFunction( + responseClassName, functionName, indexedParameters, nonIndexedParameters)); + methods.add(buildDefaultEventFlowableFunction(responseClassName, functionName)); + return methods; } - return builder.build(); - } - - static TypeName buildTypeName(String typeDeclaration) { - String type = trimStorageDeclaration(typeDeclaration); - Matcher matcher = pattern.matcher(type); - if (matcher.find()) { - Class baseType = AbiTypes.getType(matcher.group(1)); - String firstArrayDimension = matcher.group(2); - String secondArrayDimension = matcher.group(3); - - TypeName typeName; - - if ("".equals(firstArrayDimension)) { - typeName = ParameterizedTypeName.get(DynamicArray.class, baseType); - } else { - Class rawType = getStaticArrayTypeReferenceClass(firstArrayDimension); - typeName = ParameterizedTypeName.get(rawType, baseType); - } - - if (secondArrayDimension != null) { - if ("".equals(secondArrayDimension)) { - return ParameterizedTypeName.get(ClassName.get(DynamicArray.class), typeName); + + CodeBlock buildTypedResponse( + String objectName, + List indexedParameters, + List nonIndexedParameters, + boolean flowable) { + String nativeConversion; + + if (useNativeJavaTypes) { + nativeConversion = ".getValue()"; + } else { + nativeConversion = ""; + } + + CodeBlock.Builder builder = CodeBlock.builder(); + if (flowable) { + builder.addStatement("$L.log = log", objectName); } else { - Class rawType = getStaticArrayTypeReferenceClass(secondArrayDimension); - return ParameterizedTypeName.get(ClassName.get(rawType), typeName); + builder.addStatement("$L.log = eventValues.getLog()", objectName); + } + for (int i = 0; i < indexedParameters.size(); i++) { + builder.addStatement( + "$L.$L = ($T) eventValues.getIndexedValues().get($L)" + nativeConversion, + objectName, + indexedParameters.get(i).getName(), + getIndexedEventWrapperType(indexedParameters.get(i).getTypeName()), + i); } - } - return typeName; - } else { - Class cls = AbiTypes.getType(type); - return ClassName.get(cls); + for (int i = 0; i < nonIndexedParameters.size(); i++) { + builder.addStatement( + "$L.$L = ($T) eventValues.getNonIndexedValues().get($L)" + nativeConversion, + objectName, + nonIndexedParameters.get(i).getName(), + getWrapperType(nonIndexedParameters.get(i).getTypeName()), + i); + } + return builder.build(); } - } - - private static Class getStaticArrayTypeReferenceClass(String type) { - try { - return Class.forName("org.fisco.bcos.web3j.abi.datatypes.generated.StaticArray" + type); - } catch (ClassNotFoundException e) { - // Unfortunately we can't encode it's length as a type if it's > 32. - return StaticArray.class; + + static TypeName buildTypeName(String typeDeclaration) { + String type = trimStorageDeclaration(typeDeclaration); + Matcher matcher = pattern.matcher(type); + if (matcher.find()) { + Class baseType = AbiTypes.getType(matcher.group(1)); + String firstArrayDimension = matcher.group(2); + String secondArrayDimension = matcher.group(3); + + TypeName typeName; + + if ("".equals(firstArrayDimension)) { + typeName = ParameterizedTypeName.get(DynamicArray.class, baseType); + } else { + Class rawType = getStaticArrayTypeReferenceClass(firstArrayDimension); + typeName = ParameterizedTypeName.get(rawType, baseType); + } + + if (secondArrayDimension != null) { + if ("".equals(secondArrayDimension)) { + return ParameterizedTypeName.get(ClassName.get(DynamicArray.class), typeName); + } else { + Class rawType = getStaticArrayTypeReferenceClass(secondArrayDimension); + return ParameterizedTypeName.get(ClassName.get(rawType), typeName); + } + } + + return typeName; + } else { + Class cls = AbiTypes.getType(type); + return ClassName.get(cls); + } } - } - private static String trimStorageDeclaration(String type) { - if (type.endsWith(" storage") || type.endsWith(" memory")) { - return type.split(" ")[0]; - } else { - return type; + private static Class getStaticArrayTypeReferenceClass(String type) { + try { + return Class.forName("org.fisco.bcos.web3j.abi.datatypes.generated.StaticArray" + type); + } catch (ClassNotFoundException e) { + // Unfortunately we can't encode it's length as a type if it's > 32. + return StaticArray.class; + } } - } - private List buildReturnTypes(List outputParameterTypes) { - List result = new ArrayList<>(outputParameterTypes.size()); - for (TypeName typeName : outputParameterTypes) { - result.add(getWrapperType(typeName)); + private static String trimStorageDeclaration(String type) { + if (type.endsWith(" storage") || type.endsWith(" memory")) { + return type.split(" ")[0]; + } else { + return type; + } } - return result; - } - - private static void buildVariableLengthReturnFunctionConstructor( - MethodSpec.Builder methodBuilder, - String functionName, - String inputParameters, - List outputParameterTypes) - throws ClassNotFoundException { - - List objects = new ArrayList<>(); - objects.add(Function.class); - objects.add(Function.class); - objects.add(funcNameToConst(functionName)); - - objects.add(Arrays.class); - objects.add(Type.class); - objects.add(inputParameters); - - objects.add(Arrays.class); - objects.add(TypeReference.class); - for (TypeName outputParameterType : outputParameterTypes) { - objects.add(TypeReference.class); - objects.add(outputParameterType); + + private List buildReturnTypes(List outputParameterTypes) { + List result = new ArrayList<>(outputParameterTypes.size()); + for (TypeName typeName : outputParameterTypes) { + result.add(getWrapperType(typeName)); + } + return result; } - String asListParams = - Collection.join(outputParameterTypes, ", ", typeName -> "new $T<$T>() {}"); - - methodBuilder.addStatement( - "final $T function = new $T($N, \n$T.<$T>asList($L), \n$T" - + ".<$T>asList(" - + asListParams - + "))", - objects.toArray()); - } - - private void buildTupleResultContainer( - MethodSpec.Builder methodBuilder, - ParameterizedTypeName tupleType, - List outputParameterTypes) - throws ClassNotFoundException { - - List typeArguments = tupleType.typeArguments; - - CodeBlock.Builder tupleConstructor = CodeBlock.builder(); - tupleConstructor - .addStatement( - "$T results = executeCallMultipleValueReturn(function)", - ParameterizedTypeName.get(List.class, Type.class)) - .add("return new $T(", tupleType) - .add("$>$>"); - - String resultStringSimple = "\n($T) results.get($L)"; - if (useNativeJavaTypes) { - resultStringSimple += ".getValue()"; + private static void buildVariableLengthReturnFunctionConstructor( + MethodSpec.Builder methodBuilder, + String functionName, + String inputParameters, + List outputParameterTypes) + throws ClassNotFoundException { + + List objects = new ArrayList<>(); + objects.add(Function.class); + objects.add(Function.class); + objects.add(funcNameToConst(functionName)); + + objects.add(Arrays.class); + objects.add(Type.class); + objects.add(inputParameters); + + objects.add(Arrays.class); + objects.add(TypeReference.class); + for (TypeName outputParameterType : outputParameterTypes) { + objects.add(TypeReference.class); + objects.add(outputParameterType); + } + + String asListParams = + Collection.join(outputParameterTypes, ", ", typeName -> "new $T<$T>() {}"); + + methodBuilder.addStatement( + "final $T function = new $T($N, \n$T.<$T>asList($L), \n$T" + + ".<$T>asList(" + + asListParams + + "))", + objects.toArray()); } - String resultStringNativeList = "\nconvertToNative(($T) results.get($L).getValue())"; + private void buildTupleResultContainer( + MethodSpec.Builder methodBuilder, + ParameterizedTypeName tupleType, + List outputParameterTypes) + throws ClassNotFoundException { + + List typeArguments = tupleType.typeArguments; + + CodeBlock.Builder tupleConstructor = CodeBlock.builder(); + tupleConstructor + .addStatement( + "$T results = executeCallMultipleValueReturn(function)", + ParameterizedTypeName.get(List.class, Type.class)) + .add("return new $T(", tupleType) + .add("$>$>"); + + String resultStringSimple = "\n($T) results.get($L)"; + if (useNativeJavaTypes) { + resultStringSimple += ".getValue()"; + } - int size = typeArguments.size(); - ClassName classList = ClassName.get(List.class); + String resultStringNativeList = "\nconvertToNative(($T) results.get($L).getValue())"; - for (int i = 0; i < size; i++) { - TypeName param = outputParameterTypes.get(i); - TypeName convertTo = typeArguments.get(i); + int size = typeArguments.size(); + ClassName classList = ClassName.get(List.class); - String resultString = resultStringSimple; + for (int i = 0; i < size; i++) { + TypeName param = outputParameterTypes.get(i); + TypeName convertTo = typeArguments.get(i); - // If we use native java types we need to convert - // elements of arrays to native java types too - if (useNativeJavaTypes && param instanceof ParameterizedTypeName) { - ParameterizedTypeName oldContainer = (ParameterizedTypeName) param; - ParameterizedTypeName newContainer = (ParameterizedTypeName) convertTo; - if (newContainer.rawType.compareTo(classList) == 0 - && newContainer.typeArguments.size() == 1) { - convertTo = ParameterizedTypeName.get(classList, oldContainer.typeArguments.get(0)); - resultString = resultStringNativeList; - } - } + String resultString = resultStringSimple; - tupleConstructor.add(resultString, convertTo, i); - tupleConstructor.add(i < size - 1 ? ", " : ");\n"); - } - tupleConstructor.add("$<$<"); - - TypeSpec callableType = - TypeSpec.anonymousClassBuilder("") - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(Callable.class), tupleType)) - .addMethod( - MethodSpec.methodBuilder("call") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .addException(Exception.class) - .returns(tupleType) - .addCode(tupleConstructor.build()) - .build()) - .build(); - - methodBuilder.addStatement("return new $T(\n$L)", buildRemoteCall(tupleType), callableType); - } - - private static CodeBlock buildVariableLengthEventInitializer( - String eventName, List parameterTypes) { - - List objects = new ArrayList<>(); - objects.add(Event.class); - objects.add(eventName); - - objects.add(Arrays.class); - objects.add(TypeReference.class); - for (NamedTypeName parameterType : parameterTypes) { - objects.add(TypeReference.class); - objects.add(parameterType.getTypeName()); + // If we use native java types we need to convert + // elements of arrays to native java types too + if (useNativeJavaTypes && param instanceof ParameterizedTypeName) { + ParameterizedTypeName oldContainer = (ParameterizedTypeName) param; + ParameterizedTypeName newContainer = (ParameterizedTypeName) convertTo; + if (newContainer.rawType.compareTo(classList) == 0 + && newContainer.typeArguments.size() == 1) { + convertTo = + ParameterizedTypeName.get(classList, oldContainer.typeArguments.get(0)); + resultString = resultStringNativeList; + } + } + + tupleConstructor.add(resultString, convertTo, i); + tupleConstructor.add(i < size - 1 ? ", " : ");\n"); + } + tupleConstructor.add("$<$<"); + + TypeSpec callableType = + TypeSpec.anonymousClassBuilder("") + .addSuperinterface( + ParameterizedTypeName.get(ClassName.get(Callable.class), tupleType)) + .addMethod( + MethodSpec.methodBuilder("call") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addException(Exception.class) + .returns(tupleType) + .addCode(tupleConstructor.build()) + .build()) + .build(); + + methodBuilder.addStatement("return new $T(\n$L)", buildRemoteCall(tupleType), callableType); } - String asListParams = - parameterTypes - .stream() - .map( - type -> { - if (type.isIndexed()) { - return "new $T<$T>(true) {}"; - } else { - return "new $T<$T>() {}"; - } - }) - .collect(Collectors.joining(", ")); - - return CodeBlock.builder() - .addStatement( - "new $T($S, \n" + "$T.<$T>asList(" + asListParams + "))", objects.toArray()) - .build(); - } - - private List loadContractDefinition(String abi) throws IOException { - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - AbiDefinition[] abiDefinition = objectMapper.readValue(abi, AbiDefinition[].class); - return Arrays.asList(abiDefinition); - } - - private static String funcNameToConst(String funcName) { - return FUNC_NAME_PREFIX + funcName.toUpperCase(); - } - - private static class NamedTypeName { - private final TypeName typeName; - private final String name; - private final boolean indexed; - - NamedTypeName(String name, TypeName typeName, boolean indexed) { - this.name = name; - this.typeName = typeName; - this.indexed = indexed; + private static CodeBlock buildVariableLengthEventInitializer( + String eventName, List parameterTypes) { + + List objects = new ArrayList<>(); + objects.add(Event.class); + objects.add(eventName); + + objects.add(Arrays.class); + objects.add(TypeReference.class); + for (NamedTypeName parameterType : parameterTypes) { + objects.add(TypeReference.class); + objects.add(parameterType.getTypeName()); + } + + String asListParams = + parameterTypes + .stream() + .map( + type -> { + if (type.isIndexed()) { + return "new $T<$T>(true) {}"; + } else { + return "new $T<$T>() {}"; + } + }) + .collect(Collectors.joining(", ")); + + return CodeBlock.builder() + .addStatement( + "new $T($S, \n" + "$T.<$T>asList(" + asListParams + "))", + objects.toArray()) + .build(); } - public String getName() { - return name; + private List loadContractDefinition(String abi) throws IOException { + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + AbiDefinition[] abiDefinition = objectMapper.readValue(abi, AbiDefinition[].class); + return Arrays.asList(abiDefinition); } - public TypeName getTypeName() { - return typeName; + private static String funcNameToConst(String funcName) { + return FUNC_NAME_PREFIX + funcName.toUpperCase(); } - public boolean isIndexed() { - return indexed; + private static class NamedTypeName { + private final TypeName typeName; + private final String name; + private final boolean indexed; + + NamedTypeName(String name, TypeName typeName, boolean indexed) { + this.name = name; + this.typeName = typeName; + this.indexed = indexed; + } + + public String getName() { + return name; + } + + public TypeName getTypeName() { + return typeName; + } + + public boolean isIndexed() { + return indexed; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapperGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapperGenerator.java index 7285ee0c8..b9811126e 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapperGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/SolidityFunctionWrapperGenerator.java @@ -19,138 +19,143 @@ /** Java wrapper source code generator for Solidity ABI format. */ public class SolidityFunctionWrapperGenerator extends FunctionWrapperGenerator { - public static final String COMMAND_SOLIDITY = "solidity"; - public static final String COMMAND_GENERATE = "generate"; - public static final String COMMAND_PREFIX = COMMAND_SOLIDITY + " " + COMMAND_GENERATE; - - /* - * Usage: solidity generate [-hV] [-jt] [-st] -a= [-b=] - * -o= -p= - * -h, --help Show this help message and exit. - * -V, --version Print version information and exit. - * -a, --abiFile= abi file with contract definition. - * -b, --binFile= bin file with contract compiled code in order to - * generate deploy methods. - * -o, --outputDir= - * destination base directory. - * -p, --package= - * base package name. - * -jt, --javaTypes use native java types. - * Default: true - * -st, --solidityTypes use solidity types. - */ - - private final File binFile; - private final File abiFile; - - private SolidityFunctionWrapperGenerator( - File binFile, - File abiFile, - File destinationDir, - String basePackageName, - boolean useJavaNativeTypes) { - - super(destinationDir, basePackageName, useJavaNativeTypes); - this.binFile = binFile; - this.abiFile = abiFile; - } - - static List loadContractDefinition(File absFile) throws IOException { - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - AbiDefinition[] abiDefinition = objectMapper.readValue(absFile, AbiDefinition[].class); - return Arrays.asList(abiDefinition); - } - - private void generate() throws IOException, ClassNotFoundException { - String binary = Contract.BIN_NOT_PROVIDED; - if (binFile != null) { - byte[] bytes = Files.readBytes(binFile); - binary = new String(bytes); + public static final String COMMAND_SOLIDITY = "solidity"; + public static final String COMMAND_GENERATE = "generate"; + public static final String COMMAND_PREFIX = COMMAND_SOLIDITY + " " + COMMAND_GENERATE; + + /* + * Usage: solidity generate [-hV] [-jt] [-st] -a= [-b=] + * -o= -p= + * -h, --help Show this help message and exit. + * -V, --version Print version information and exit. + * -a, --abiFile= abi file with contract definition. + * -b, --binFile= bin file with contract compiled code in order to + * generate deploy methods. + * -o, --outputDir= + * destination base directory. + * -p, --package= + * base package name. + * -jt, --javaTypes use native java types. + * Default: true + * -st, --solidityTypes use solidity types. + */ + + private final File binFile; + private final File abiFile; + + private SolidityFunctionWrapperGenerator( + File binFile, + File abiFile, + File destinationDir, + String basePackageName, + boolean useJavaNativeTypes) { + + super(destinationDir, basePackageName, useJavaNativeTypes); + this.binFile = binFile; + this.abiFile = abiFile; } - byte[] bytes = Files.readBytes(abiFile); - String abi = new String(bytes); - - List functionDefinitions = loadContractDefinition(abiFile); - - if (functionDefinitions.isEmpty()) { - exitError("Unable to parse input ABI file"); - } else { - String contractName = getFileNameNoExtension(abiFile.getName()); - new SolidityFunctionWrapper(useJavaNativeTypes) - .generateJavaFiles( - contractName, binary, abi, destinationDirLocation.toString(), basePackageName); + static List loadContractDefinition(File absFile) throws IOException { + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + AbiDefinition[] abiDefinition = objectMapper.readValue(absFile, AbiDefinition[].class); + return Arrays.asList(abiDefinition); } - } - public static void main(String[] args) { - if (args.length > 0 && args[0].equals(COMMAND_SOLIDITY)) { - args = tail(args); + private void generate() throws IOException, ClassNotFoundException { + String binary = Contract.BIN_NOT_PROVIDED; + if (binFile != null) { + byte[] bytes = Files.readBytes(binFile); + binary = new String(bytes); + } + + byte[] bytes = Files.readBytes(abiFile); + String abi = new String(bytes); + + List functionDefinitions = loadContractDefinition(abiFile); + + if (functionDefinitions.isEmpty()) { + exitError("Unable to parse input ABI file"); + } else { + String contractName = getFileNameNoExtension(abiFile.getName()); + new SolidityFunctionWrapper(useJavaNativeTypes) + .generateJavaFiles( + contractName, + binary, + abi, + destinationDirLocation.toString(), + basePackageName); + } } - if (args.length > 0 && args[0].equals(COMMAND_GENERATE)) { - args = tail(args); + public static void main(String[] args) { + if (args.length > 0 && args[0].equals(COMMAND_SOLIDITY)) { + args = tail(args); + } + + if (args.length > 0 && args[0].equals(COMMAND_GENERATE)) { + args = tail(args); + } + + CommandLine.run(new PicocliRunner(), args); } - CommandLine.run(new PicocliRunner(), args); - } - - @Command( - name = COMMAND_PREFIX, - mixinStandardHelpOptions = true, - version = "4.0", - sortOptions = false) - static class PicocliRunner implements Runnable { - @Option( - names = {"-a", "--abiFile"}, - description = "abi file with contract definition.", - required = true) - private File abiFile; - - @Option( - names = {"-b", "--binFile"}, - description = - "bin file with contract compiled code " + "in order to generate deploy methods.", - required = false) - private File binFile; - - @Option( - names = {"-o", "--outputDir"}, - description = "destination base directory.", - required = true) - private File destinationFileDir; - - @Option( - names = {"-p", "--package"}, - description = "base package name.", - required = true) - private String packageName; - - @Option( - names = {"-jt", JAVA_TYPES_ARG}, - description = "use native java types.", - required = false, - showDefaultValue = ALWAYS) - private boolean javaTypes = true; - - @Option( - names = {"-st", SOLIDITY_TYPES_ARG}, - description = "use solidity types.", - required = false) - private boolean solidityTypes; - - @Override - public void run() { - try { - // grouping is not implemented in picocli yet(planned for 3.1), therefore - // simply check if solidityTypes were requested - boolean useJavaTypes = !(solidityTypes); - new SolidityFunctionWrapperGenerator( - binFile, abiFile, destinationFileDir, packageName, useJavaTypes) - .generate(); - } catch (Exception e) { - exitError(e); - } + @Command( + name = COMMAND_PREFIX, + mixinStandardHelpOptions = true, + version = "4.0", + sortOptions = false) + static class PicocliRunner implements Runnable { + @Option( + names = {"-a", "--abiFile"}, + description = "abi file with contract definition.", + required = true) + private File abiFile; + + @Option( + names = {"-b", "--binFile"}, + description = + "bin file with contract compiled code " + + "in order to generate deploy methods.", + required = false) + private File binFile; + + @Option( + names = {"-o", "--outputDir"}, + description = "destination base directory.", + required = true) + private File destinationFileDir; + + @Option( + names = {"-p", "--package"}, + description = "base package name.", + required = true) + private String packageName; + + @Option( + names = {"-jt", JAVA_TYPES_ARG}, + description = "use native java types.", + required = false, + showDefaultValue = ALWAYS) + private boolean javaTypes = true; + + @Option( + names = {"-st", SOLIDITY_TYPES_ARG}, + description = "use solidity types.", + required = false) + private boolean solidityTypes; + + @Override + public void run() { + try { + // grouping is not implemented in picocli yet(planned for 3.1), therefore + // simply check if solidityTypes were requested + boolean useJavaTypes = !(solidityTypes); + new SolidityFunctionWrapperGenerator( + binFile, abiFile, destinationFileDir, packageName, useJavaTypes) + .generate(); + } catch (Exception e) { + exitError(e); + } + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/TruffleJsonFunctionWrapperGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/TruffleJsonFunctionWrapperGenerator.java index 52bb4f6a6..cf9be3a1a 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/TruffleJsonFunctionWrapperGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/TruffleJsonFunctionWrapperGenerator.java @@ -21,332 +21,345 @@ */ public class TruffleJsonFunctionWrapperGenerator extends FunctionWrapperGenerator { - private static final String USAGE = - "truffle generate " - + "[--javaTypes|--solidityTypes] " - + ".json " - + "-p|--package " - + "-o|--outputDir "; - - private String jsonFileLocation; - - private TruffleJsonFunctionWrapperGenerator( - String jsonFileLocation, - String destinationDirLocation, - String basePackageName, - boolean useJavaNativeTypes) { - - super(new File(destinationDirLocation), basePackageName, useJavaNativeTypes); - this.jsonFileLocation = jsonFileLocation; - } - - public static void run(String[] args) throws Exception { - if (args.length < 1 || !"generate".equals(args[0])) { - Console.exitError(USAGE); - } else { - main(Collection.tail(args)); + private static final String USAGE = + "truffle generate " + + "[--javaTypes|--solidityTypes] " + + ".json " + + "-p|--package " + + "-o|--outputDir "; + + private String jsonFileLocation; + + private TruffleJsonFunctionWrapperGenerator( + String jsonFileLocation, + String destinationDirLocation, + String basePackageName, + boolean useJavaNativeTypes) { + + super(new File(destinationDirLocation), basePackageName, useJavaNativeTypes); + this.jsonFileLocation = jsonFileLocation; } - } - public static void main(String[] args) throws Exception { - - String[] fullArgs; - if (args.length == 5) { - fullArgs = new String[args.length + 1]; - fullArgs[0] = JAVA_TYPES_ARG; - System.arraycopy(args, 0, fullArgs, 1, args.length); - } else { - fullArgs = args; - } - - if (fullArgs.length != 6) { - Console.exitError(USAGE); - } - - boolean useJavaNativeTypes = useJavaNativeTypes(fullArgs[0], USAGE); - - String jsonFileLocation = parsePositionalArg(fullArgs, 1); - String destinationDirLocation = parseParameterArgument(fullArgs, "-o", "--outputDir"); - String basePackageName = parseParameterArgument(fullArgs, "-p", "--package"); - - if (Strings.isEmpty(jsonFileLocation) - || Strings.isEmpty(destinationDirLocation) - || Strings.isEmpty(basePackageName)) { - Console.exitError(USAGE); - } - - new TruffleJsonFunctionWrapperGenerator( - jsonFileLocation, destinationDirLocation, basePackageName, useJavaNativeTypes) - .generate(); - } - - static Contract loadContractDefinition(File jsonFile) throws IOException { - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - return objectMapper.readValue(jsonFile, Contract.class); - } - - @SuppressWarnings("unchecked") - private void generate() throws IOException, ClassNotFoundException { - - File truffleJsonFile = new File(jsonFileLocation); - if (!truffleJsonFile.exists() || !truffleJsonFile.canRead()) { - Console.exitError("Invalid input json file specified: " + jsonFileLocation); - } - - String fileName = truffleJsonFile.getName(); - String contractName = getFileNameNoExtension(fileName); - - Contract c = loadContractDefinition(truffleJsonFile); - if (c == null) { - Console.exitError("Unable to parse input json file"); - } else { - String className = Strings.capitaliseFirstLetter(contractName); - System.out.printf("Generating " + basePackageName + "." + className + " ... "); - Map addresses; - if (c.networks != null && !c.networks.isEmpty()) { - addresses = - c.networks - .entrySet() - .stream() - .filter(e -> (e.getValue() != null && e.getValue().getAddress() != null)) - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getAddress())); - } else { - addresses = Collections.EMPTY_MAP; - } - new SolidityFunctionWrapper(useJavaNativeTypes) - .generateJavaFiles( - contractName, - c.getBytecode(), - c.getAbi(), - destinationDirLocation.toString(), - basePackageName, - addresses); - System.out.println("File written to " + destinationDirLocation.toString() + "\n"); - } - } - - /** - * Truffle Contract - * - *

Describes a contract exported by and consumable by Truffle, which may include information - * about deployed instances on networks. - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({ - "contractName", - "abi", - "bytecode", - "deployedBytecode", - "sourceMap", - "deployedSourceMap", - "source", - "sourcePath", - "ast", - "compiler", - "networks", - "schemaVersion", - "updatedAt" - }) - public static class Contract { - - @JsonProperty("contractName") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^[a-zA-Z_][a-zA-Z0-9_]*$") - public String contractName; - - @JsonProperty(value = "abi", required = true) - public List abi; - - @JsonProperty("bytecode") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") - public String bytecode; - - @JsonProperty("deployedBytecode") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") - public String deployedBytecode; - - @JsonProperty("sourceMap") - public String sourceMap; - - @JsonProperty("deployedSourceMap") - public String deployedSourceMap; - - @JsonProperty("source") - public String source; - - @JsonProperty("sourcePath") - public String sourcePath; - - @JsonProperty("ast") - public JsonNode ast; - - @JsonProperty("compiler") - public Compiler compiler; - - @JsonProperty("networks") - public Map networks; - - @JsonProperty("schemaVersion") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "[0-9]+\\.[0-9]+\\.[0-9]+") - public String schemaVersion; - - @JsonProperty("updatedAt") - @JsonFormat( - shape = JsonFormat.Shape.STRING, - pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", - timezone = "GMT") - public Date updatedAt; - - public Contract() {} - - public Contract( - String contractName, - List abi, - String bytecode, - String deployedBytecode, - String sourceMap, - String deployedSourceMap, - String source, - String sourcePath, - JsonNode ast, - Compiler compiler, - Map networks, - String schemaVersion, - Date updatedAt) { - super(); - this.contractName = contractName; - this.abi = abi; - this.bytecode = bytecode; - this.deployedBytecode = deployedBytecode; - this.sourceMap = sourceMap; - this.deployedSourceMap = deployedSourceMap; - this.source = source; - this.sourcePath = sourcePath; - this.ast = ast; - this.compiler = compiler; - this.networks = networks; - this.schemaVersion = schemaVersion; - this.updatedAt = updatedAt; - } - - public String getContractName() { - return contractName; + public static void run(String[] args) throws Exception { + if (args.length < 1 || !"generate".equals(args[0])) { + Console.exitError(USAGE); + } else { + main(Collection.tail(args)); + } } - public List getAbi() { - return abi; + public static void main(String[] args) throws Exception { + + String[] fullArgs; + if (args.length == 5) { + fullArgs = new String[args.length + 1]; + fullArgs[0] = JAVA_TYPES_ARG; + System.arraycopy(args, 0, fullArgs, 1, args.length); + } else { + fullArgs = args; + } + + if (fullArgs.length != 6) { + Console.exitError(USAGE); + } + + boolean useJavaNativeTypes = useJavaNativeTypes(fullArgs[0], USAGE); + + String jsonFileLocation = parsePositionalArg(fullArgs, 1); + String destinationDirLocation = parseParameterArgument(fullArgs, "-o", "--outputDir"); + String basePackageName = parseParameterArgument(fullArgs, "-p", "--package"); + + if (Strings.isEmpty(jsonFileLocation) + || Strings.isEmpty(destinationDirLocation) + || Strings.isEmpty(basePackageName)) { + Console.exitError(USAGE); + } + + new TruffleJsonFunctionWrapperGenerator( + jsonFileLocation, + destinationDirLocation, + basePackageName, + useJavaNativeTypes) + .generate(); } - public String getBytecode() { - return bytecode; + static Contract loadContractDefinition(File jsonFile) throws IOException { + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + return objectMapper.readValue(jsonFile, Contract.class); } - public NetworkInfo getNetwork(String networkId) { - return networks == null ? null : networks.get(networkId); - } - - public String getAddress(String networkId) { - NetworkInfo network = getNetwork(networkId); - return network == null ? null : network.getAddress(); + @SuppressWarnings("unchecked") + private void generate() throws IOException, ClassNotFoundException { + + File truffleJsonFile = new File(jsonFileLocation); + if (!truffleJsonFile.exists() || !truffleJsonFile.canRead()) { + Console.exitError("Invalid input json file specified: " + jsonFileLocation); + } + + String fileName = truffleJsonFile.getName(); + String contractName = getFileNameNoExtension(fileName); + + Contract c = loadContractDefinition(truffleJsonFile); + if (c == null) { + Console.exitError("Unable to parse input json file"); + } else { + String className = Strings.capitaliseFirstLetter(contractName); + System.out.printf("Generating " + basePackageName + "." + className + " ... "); + Map addresses; + if (c.networks != null && !c.networks.isEmpty()) { + addresses = + c.networks + .entrySet() + .stream() + .filter( + e -> + (e.getValue() != null + && e.getValue().getAddress() != null)) + .collect( + Collectors.toMap( + Map.Entry::getKey, e -> e.getValue().getAddress())); + } else { + addresses = Collections.EMPTY_MAP; + } + new SolidityFunctionWrapper(useJavaNativeTypes) + .generateJavaFiles( + contractName, + c.getBytecode(), + c.getAbi(), + destinationDirLocation.toString(), + basePackageName, + addresses); + System.out.println("File written to " + destinationDirLocation.toString() + "\n"); + } } /** - * Convenience method to get the deployed address of the contract. - * - * @param network the contract's address on this Ethereum network - * @return the contract's address or null if there isn't one known. - */ - public String getAddress(Network network) { - return getAddress(Long.toString(network.id)); - } - - /* - * c.f., ChainId + * Truffle Contract * - * This should be updated with https://github.com/web3j/web3j/issues/234 + *

Describes a contract exported by and consumable by Truffle, which may include information + * about deployed instances on networks. */ - enum Network { - olympic(0), - mainnet(ChainId.MAINNET), - morden(ChainId.EXPANSE_MAINNET), - ropsten(ChainId.ROPSTEN), - rinkeby(ChainId.RINKEBY), - kovan(ChainId.KOVAN); - - public final long id; - - Network(long id) { - this.id = id; - } + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonPropertyOrder({ + "contractName", + "abi", + "bytecode", + "deployedBytecode", + "sourceMap", + "deployedSourceMap", + "source", + "sourcePath", + "ast", + "compiler", + "networks", + "schemaVersion", + "updatedAt" + }) + public static class Contract { + + @JsonProperty("contractName") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^[a-zA-Z_][a-zA-Z0-9_]*$") + public String contractName; + + @JsonProperty(value = "abi", required = true) + public List abi; + + @JsonProperty("bytecode") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") + public String bytecode; + + @JsonProperty("deployedBytecode") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") + public String deployedBytecode; + + @JsonProperty("sourceMap") + public String sourceMap; + + @JsonProperty("deployedSourceMap") + public String deployedSourceMap; + + @JsonProperty("source") + public String source; + + @JsonProperty("sourcePath") + public String sourcePath; + + @JsonProperty("ast") + public JsonNode ast; + + @JsonProperty("compiler") + public Compiler compiler; + + @JsonProperty("networks") + public Map networks; + + @JsonProperty("schemaVersion") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "[0-9]+\\.[0-9]+\\.[0-9]+") + public String schemaVersion; + + @JsonProperty("updatedAt") + @JsonFormat( + shape = JsonFormat.Shape.STRING, + pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + timezone = "GMT") + public Date updatedAt; + + public Contract() {} + + public Contract( + String contractName, + List abi, + String bytecode, + String deployedBytecode, + String sourceMap, + String deployedSourceMap, + String source, + String sourcePath, + JsonNode ast, + Compiler compiler, + Map networks, + String schemaVersion, + Date updatedAt) { + super(); + this.contractName = contractName; + this.abi = abi; + this.bytecode = bytecode; + this.deployedBytecode = deployedBytecode; + this.sourceMap = sourceMap; + this.deployedSourceMap = deployedSourceMap; + this.source = source; + this.sourcePath = sourcePath; + this.ast = ast; + this.compiler = compiler; + this.networks = networks; + this.schemaVersion = schemaVersion; + this.updatedAt = updatedAt; + } + + public String getContractName() { + return contractName; + } + + public List getAbi() { + return abi; + } + + public String getBytecode() { + return bytecode; + } + + public NetworkInfo getNetwork(String networkId) { + return networks == null ? null : networks.get(networkId); + } + + public String getAddress(String networkId) { + NetworkInfo network = getNetwork(networkId); + return network == null ? null : network.getAddress(); + } + + /** + * Convenience method to get the deployed address of the contract. + * + * @param network the contract's address on this Ethereum network + * @return the contract's address or null if there isn't one known. + */ + public String getAddress(Network network) { + return getAddress(Long.toString(network.id)); + } + + /* + * c.f., ChainId + * + * This should be updated with https://github.com/web3j/web3j/issues/234 + */ + enum Network { + olympic(0), + mainnet(ChainId.MAINNET), + morden(ChainId.EXPANSE_MAINNET), + ropsten(ChainId.ROPSTEN), + rinkeby(ChainId.RINKEBY), + kovan(ChainId.KOVAN); + + public final long id; + + Network(long id) { + this.id = id; + } + } } - } - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"name", "version"}) - public static class Compiler { + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonPropertyOrder({"name", "version"}) + public static class Compiler { - @JsonProperty("name") - public String name; + @JsonProperty("name") + public String name; - @JsonProperty("version") - public String version; + @JsonProperty("version") + public String version; - @JsonIgnore - private Map additionalProperties = new HashMap(); + @JsonIgnore + private Map additionalProperties = new HashMap(); - public Compiler() {} + public Compiler() {} - public Compiler(String name, String version) { - super(); - this.name = name; - this.version = version; - } + public Compiler(String name, String version) { + super(); + this.name = name; + this.version = version; + } - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } - @JsonAnySetter - public void setAdditionalProperty(String name, JsonNode value) { - this.additionalProperties.put(name, value); - } + @JsonAnySetter + public void setAdditionalProperty(String name, JsonNode value) { + this.additionalProperties.put(name, value); + } - public Compiler withAdditionalProperty(String name, JsonNode value) { - this.additionalProperties.put(name, value); - return this; + public Compiler withAdditionalProperty(String name, JsonNode value) { + this.additionalProperties.put(name, value); + return this; + } } - } - // For now we just ignore "events" - @JsonIgnoreProperties(ignoreUnknown = true) - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonPropertyOrder({"events", "links", "address"}) - public static class NetworkInfo { + // For now we just ignore "events" + @JsonIgnoreProperties(ignoreUnknown = true) + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonPropertyOrder({"events", "links", "address"}) + public static class NetworkInfo { - @JsonProperty("events") - public Map events; + @JsonProperty("events") + public Map events; - @JsonProperty("links") - public Map links; + @JsonProperty("links") + public Map links; - @JsonProperty("address") - public String address; + @JsonProperty("address") + public String address; - public NetworkInfo() {} + public NetworkInfo() {} - public NetworkInfo(Map events, Map links, String address) { - super(); - this.events = events; - this.links = links; - this.address = address; - } + public NetworkInfo( + Map events, Map links, String address) { + super(); + this.events = events; + this.links = links; + this.address = address; + } - public String getAddress() { - return address; - } + public String getAddress() { + return address; + } - public void setAddress(String address) { - this.address = address; + public void setAddress(String address) { + this.address = address; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/codegen/TupleGenerator.java b/src/main/java/org/fisco/bcos/web3j/codegen/TupleGenerator.java index 27c9baaee..d742160b7 100644 --- a/src/main/java/org/fisco/bcos/web3j/codegen/TupleGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/codegen/TupleGenerator.java @@ -14,181 +14,187 @@ /** A class for generating arbitrary sized tuples. */ public class TupleGenerator extends Generator { - static final int LIMIT = 20; - static final String PACKAGE_NAME = "org.fisco.bcos.web3j.tuples.generated"; - static final String CLASS_NAME = "Tuple"; - - private static final String SIZE = "SIZE"; - private static final String RESULT = "result"; - private static final String VALUE = "value"; - - public static void main(String[] args) throws IOException { - TupleGenerator tupleGenerator = new TupleGenerator(); - if (args.length == 1) { - tupleGenerator.generate(args[0]); - } else { - tupleGenerator.generate(System.getProperty("user.dir") + "/tuples/src/main/java/"); + static final int LIMIT = 20; + static final String PACKAGE_NAME = "org.fisco.bcos.web3j.tuples.generated"; + static final String CLASS_NAME = "Tuple"; + + private static final String SIZE = "SIZE"; + private static final String RESULT = "result"; + private static final String VALUE = "value"; + + public static void main(String[] args) throws IOException { + TupleGenerator tupleGenerator = new TupleGenerator(); + if (args.length == 1) { + tupleGenerator.generate(args[0]); + } else { + tupleGenerator.generate(System.getProperty("user.dir") + "/tuples/src/main/java/"); + } } - } - private void generate(String destinationDir) throws IOException { - for (int i = 1; i <= LIMIT; i++) { - TypeSpec typeSpec = createTuple(i); + private void generate(String destinationDir) throws IOException { + for (int i = 1; i <= LIMIT; i++) { + TypeSpec typeSpec = createTuple(i); - write(PACKAGE_NAME, typeSpec, destinationDir); + write(PACKAGE_NAME, typeSpec, destinationDir); + } } - } - - private TypeSpec createTuple(int size) { - String className = CLASS_NAME + size; - TypeSpec.Builder typeSpecBuilder = - TypeSpec.classBuilder(className) - .addSuperinterface(Tuple.class) - .addField( - FieldSpec.builder(int.class, SIZE) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) - .initializer("$L", size) - .build()); - - MethodSpec.Builder constructorBuilder = - MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC); - - List methodSpecs = new ArrayList<>(size); - - for (int i = 1; i <= size; i++) { - String value = VALUE + i; - TypeVariableName typeVariableName = TypeVariableName.get("T" + i); - - typeSpecBuilder - .addTypeVariable(typeVariableName) - .addField(typeVariableName, value, Modifier.PRIVATE, Modifier.FINAL); - - constructorBuilder - .addParameter(typeVariableName, value) - .addStatement("this.$N = $N", value, value); - - MethodSpec getterSpec = - MethodSpec.methodBuilder("get" + Strings.capitaliseFirstLetter(value)) - .addModifiers(Modifier.PUBLIC) - .returns(typeVariableName) - .addStatement("return $N", value) - .build(); - methodSpecs.add(getterSpec); + + private TypeSpec createTuple(int size) { + String className = CLASS_NAME + size; + TypeSpec.Builder typeSpecBuilder = + TypeSpec.classBuilder(className) + .addSuperinterface(Tuple.class) + .addField( + FieldSpec.builder(int.class, SIZE) + .addModifiers( + Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .initializer("$L", size) + .build()); + + MethodSpec.Builder constructorBuilder = + MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC); + + List methodSpecs = new ArrayList<>(size); + + for (int i = 1; i <= size; i++) { + String value = VALUE + i; + TypeVariableName typeVariableName = TypeVariableName.get("T" + i); + + typeSpecBuilder + .addTypeVariable(typeVariableName) + .addField(typeVariableName, value, Modifier.PRIVATE, Modifier.FINAL); + + constructorBuilder + .addParameter(typeVariableName, value) + .addStatement("this.$N = $N", value, value); + + MethodSpec getterSpec = + MethodSpec.methodBuilder("get" + Strings.capitaliseFirstLetter(value)) + .addModifiers(Modifier.PUBLIC) + .returns(typeVariableName) + .addStatement("return $N", value) + .build(); + methodSpecs.add(getterSpec); + } + + MethodSpec constructorSpec = constructorBuilder.build(); + MethodSpec sizeSpec = generateSizeSpec(); + MethodSpec equalsSpec = generateEqualsSpec(className, size); + MethodSpec hashCodeSpec = generateHashCodeSpec(size); + MethodSpec toStringSpec = generateToStringSpec(size); + + return typeSpecBuilder + .addJavadoc(buildWarning(TupleGenerator.class)) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addMethod(constructorSpec) + .addMethods(methodSpecs) + .addMethod(sizeSpec) + .addMethod(equalsSpec) + .addMethod(hashCodeSpec) + .addMethod(toStringSpec) + .build(); } - MethodSpec constructorSpec = constructorBuilder.build(); - MethodSpec sizeSpec = generateSizeSpec(); - MethodSpec equalsSpec = generateEqualsSpec(className, size); - MethodSpec hashCodeSpec = generateHashCodeSpec(size); - MethodSpec toStringSpec = generateToStringSpec(size); - - return typeSpecBuilder - .addJavadoc(buildWarning(TupleGenerator.class)) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addMethod(constructorSpec) - .addMethods(methodSpecs) - .addMethod(sizeSpec) - .addMethod(equalsSpec) - .addMethod(hashCodeSpec) - .addMethod(toStringSpec) - .build(); - } - - private MethodSpec generateSizeSpec() { - return MethodSpec.methodBuilder("getSize") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(int.class) - .addStatement("return $L", SIZE) - .build(); - } - - private MethodSpec generateEqualsSpec(String className, int size) { - MethodSpec.Builder equalsSpecBuilder = - MethodSpec.methodBuilder("equals") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .addParameter(Object.class, "o") - .returns(boolean.class) - .beginControlFlow("if (this == o)") - .addStatement("return true") - .endControlFlow() - .beginControlFlow("if (o == null || getClass() != o.getClass())") - .addStatement("return false") - .endControlFlow(); - - String typeParams = Strings.repeat('?', size).replaceAll("\\?", "?, "); - typeParams = typeParams.substring(0, typeParams.length() - 2); - String wildcardClassName = className + "<" + typeParams + ">"; - - String name = "tuple" + size; - equalsSpecBuilder.addStatement("$L $L = ($L) o", wildcardClassName, name, wildcardClassName); - - for (int i = 1; i < size; i++) { - String value = VALUE + i; - - equalsSpecBuilder - .beginControlFlow( - "if ($L != null ? !$L.equals($L.$L) : $L.$L != null)", - value, - value, - name, - value, - name, - value) - .addStatement("return false") - .endControlFlow(); + private MethodSpec generateSizeSpec() { + return MethodSpec.methodBuilder("getSize") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(int.class) + .addStatement("return $L", SIZE) + .build(); } - String lastValue = VALUE + size; - equalsSpecBuilder.addStatement( - "return $L != null ? $L.equals($L.$L) : $L.$L == null", - lastValue, - lastValue, - name, - lastValue, - name, - lastValue); - - return equalsSpecBuilder.build(); - } - - private MethodSpec generateHashCodeSpec(int size) { - MethodSpec.Builder hashCodeSpec = - MethodSpec.methodBuilder("hashCode") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(int.class) - .addStatement("int $L = $L.hashCode()", RESULT, VALUE + 1); - - for (int i = 2; i <= size; i++) { - String value = "value" + i; - hashCodeSpec.addStatement( - "$L = 31 * $L + ($L != null ? $L.hashCode() : 0)", RESULT, RESULT, value, value); + private MethodSpec generateEqualsSpec(String className, int size) { + MethodSpec.Builder equalsSpecBuilder = + MethodSpec.methodBuilder("equals") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(Object.class, "o") + .returns(boolean.class) + .beginControlFlow("if (this == o)") + .addStatement("return true") + .endControlFlow() + .beginControlFlow("if (o == null || getClass() != o.getClass())") + .addStatement("return false") + .endControlFlow(); + + String typeParams = Strings.repeat('?', size).replaceAll("\\?", "?, "); + typeParams = typeParams.substring(0, typeParams.length() - 2); + String wildcardClassName = className + "<" + typeParams + ">"; + + String name = "tuple" + size; + equalsSpecBuilder.addStatement( + "$L $L = ($L) o", wildcardClassName, name, wildcardClassName); + + for (int i = 1; i < size; i++) { + String value = VALUE + i; + + equalsSpecBuilder + .beginControlFlow( + "if ($L != null ? !$L.equals($L.$L) : $L.$L != null)", + value, + value, + name, + value, + name, + value) + .addStatement("return false") + .endControlFlow(); + } + + String lastValue = VALUE + size; + equalsSpecBuilder.addStatement( + "return $L != null ? $L.equals($L.$L) : $L.$L == null", + lastValue, + lastValue, + name, + lastValue, + name, + lastValue); + + return equalsSpecBuilder.build(); } - hashCodeSpec.addStatement("return $L", RESULT); + private MethodSpec generateHashCodeSpec(int size) { + MethodSpec.Builder hashCodeSpec = + MethodSpec.methodBuilder("hashCode") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(int.class) + .addStatement("int $L = $L.hashCode()", RESULT, VALUE + 1); + + for (int i = 2; i <= size; i++) { + String value = "value" + i; + hashCodeSpec.addStatement( + "$L = 31 * $L + ($L != null ? $L.hashCode() : 0)", + RESULT, + RESULT, + value, + value); + } + + hashCodeSpec.addStatement("return $L", RESULT); + + return hashCodeSpec.build(); + } - return hashCodeSpec.build(); - } + private MethodSpec generateToStringSpec(int size) { + String toString = "return \"" + CLASS_NAME + size + "{\" +\n"; + String firstValue = VALUE + 1; + toString += "\"" + firstValue + "=\"" + " + " + firstValue + " +\n"; - private MethodSpec generateToStringSpec(int size) { - String toString = "return \"" + CLASS_NAME + size + "{\" +\n"; - String firstValue = VALUE + 1; - toString += "\"" + firstValue + "=\"" + " + " + firstValue + " +\n"; + for (int i = 2; i <= size; i++) { + String value = VALUE + i; + toString += "\", " + value + "=\"" + " + " + value + " +\n"; + } - for (int i = 2; i <= size; i++) { - String value = VALUE + i; - toString += "\", " + value + "=\"" + " + " + value + " +\n"; - } + toString += "\"}\""; - toString += "\"}\""; - - return MethodSpec.methodBuilder("toString") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(String.class) - .addStatement(toString) - .build(); - } + return MethodSpec.methodBuilder("toString") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(String.class) + .addStatement(toString) + .build(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/console/ConsoleDevice.java b/src/main/java/org/fisco/bcos/web3j/console/ConsoleDevice.java deleted file mode 100644 index e14f833dc..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/ConsoleDevice.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.fisco.bcos.web3j.console; - -import java.io.Console; - -/** System Console device wrapper. */ -public class ConsoleDevice implements IODevice { - - private Console console = System.console(); - - @Override - public void printf(String format, Object... args) { - console.printf(format, args); - } - - @Override - public String readLine(String fmt, Object... args) { - return console.readLine(fmt, args); - } - - @Override - public char[] readPassword(String fmt, Object... args) { - return console.readPassword(fmt, args); - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/console/IODevice.java b/src/main/java/org/fisco/bcos/web3j/console/IODevice.java deleted file mode 100644 index 9d0c9dd04..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/IODevice.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.fisco.bcos.web3j.console; - -/** IO device abstraction. */ -public interface IODevice { - void printf(String format, Object... args); - - String readLine(String fmt, Object... args); - - char[] readPassword(String fmt, Object... args); -} diff --git a/src/main/java/org/fisco/bcos/web3j/console/KeyImporter.java b/src/main/java/org/fisco/bcos/web3j/console/KeyImporter.java deleted file mode 100644 index 1cd205726..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/KeyImporter.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.fisco.bcos.web3j.console; - -import static org.fisco.bcos.web3j.crypto.Keys.PRIVATE_KEY_LENGTH_IN_HEX; -import static org.fisco.bcos.web3j.utils.Console.exitError; - -import java.io.File; -import java.io.IOException; -import org.fisco.bcos.web3j.crypto.CipherException; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.crypto.WalletUtils; -import org.fisco.bcos.web3j.utils.Files; - -/** Create Ethereum wallet file from a provided private key. */ -public class KeyImporter extends WalletManager { - - public KeyImporter() {} - - public KeyImporter(IODevice console) { - super(console); - } - - public static void main(String[] args) { - if (args.length == 1) { - new KeyImporter().run(args[0]); - } else { - new KeyImporter().run(); - } - } - - static void main(IODevice console) { - new KeyImporter(console).run(); - } - - private void run(String input) { - File keyFile = new File(input); - - if (keyFile.isFile()) { - String privateKey = null; - try { - privateKey = Files.readString(keyFile); - } catch (IOException e) { - exitError("Unable to read file " + input); - } - - createWalletFile(privateKey.trim()); - } else { - createWalletFile(input.trim()); - } - } - - private void run() { - String input = - console.readLine("Please enter the hex encoded private key or key file location: ").trim(); - run(input); - } - - private void createWalletFile(String privateKey) { - if (!WalletUtils.isValidPrivateKey(privateKey)) { - exitError( - "Invalid private key specified, must be " - + PRIVATE_KEY_LENGTH_IN_HEX - + " digit hex value"); - } - - Credentials credentials = Credentials.create(privateKey); - String password = getPassword("Please enter a wallet file password: "); - - String destinationDir = getDestinationDir(); - File destination = createDir(destinationDir); - - try { - String walletFileName = - WalletUtils.generateWalletFile(password, credentials.getEcKeyPair(), destination, true); - console.printf( - "Wallet file " + walletFileName + " successfully created in: " + destinationDir + "\n"); - } catch (CipherException | IOException e) { - exitError(e); - } - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/console/WalletCreator.java b/src/main/java/org/fisco/bcos/web3j/console/WalletCreator.java deleted file mode 100644 index 9ed76417a..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/WalletCreator.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.fisco.bcos.web3j.console; - -import java.io.File; -import java.io.IOException; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import org.fisco.bcos.web3j.crypto.CipherException; -import org.fisco.bcos.web3j.crypto.WalletUtils; -import org.fisco.bcos.web3j.utils.Console; - -/** Simple class for creating a wallet file. */ -public class WalletCreator extends WalletManager { - - public WalletCreator() {} - - public WalletCreator(IODevice console) { - super(console); - } - - public static void main(String[] args) { - new WalletCreator().run(); - } - - static void main(IODevice console) { - new WalletCreator(console).run(); - } - - private void run() { - String password = getPassword("Please enter a wallet file password: "); - String destinationDir = getDestinationDir(); - File destination = createDir(destinationDir); - - try { - String walletFileName = WalletUtils.generateFullNewWalletFile(password, destination); - console.printf( - "Wallet file " + walletFileName + " successfully created in: " + destinationDir + "\n"); - } catch (CipherException - | IOException - | InvalidAlgorithmParameterException - | NoSuchAlgorithmException - | NoSuchProviderException e) { - Console.exitError(e); - } - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/console/WalletManager.java b/src/main/java/org/fisco/bcos/web3j/console/WalletManager.java deleted file mode 100644 index 3af3d4787..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/WalletManager.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.fisco.bcos.web3j.console; - -import static org.fisco.bcos.web3j.utils.Console.exitError; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import org.fisco.bcos.web3j.crypto.CipherException; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.crypto.WalletUtils; -import org.fisco.bcos.web3j.utils.Console; - -/** Common functions used by the wallet console tools. */ -abstract class WalletManager { - - final IODevice console; - - WalletManager() { - console = new ConsoleDevice(); - } - - WalletManager(IODevice console) { - this.console = console; - } - - String getPassword(String initialPrompt) { - while (true) { - char[] input1 = console.readPassword(initialPrompt); - char[] input2 = console.readPassword("Please re-enter the password: "); - - if (Arrays.equals(input1, input2)) { - String s = new String(input1); - Arrays.fill(input1, ' '); - Arrays.fill(input2, ' '); - return s; - } else { - console.printf("Sorry, passwords did not match\n"); - } - } - } - - String getDestinationDir() { - String defaultDir = WalletUtils.getTestnetKeyDirectory(); - String destinationDir = - console.readLine("Please enter a destination directory location [" + defaultDir + "]: "); - if (destinationDir.equals("")) { - return defaultDir; - } else if (destinationDir.startsWith("~")) { - return System.getProperty("user.home") + destinationDir.substring(1); - } else { - return destinationDir; - } - } - - File createDir(String destinationDir) { - File destination = new File(destinationDir); - - if (!destination.exists()) { - console.printf("Creating directory: " + destinationDir + " ..."); - if (!destination.mkdirs()) { - Console.exitError( - "Unable to create destination directory [" + destinationDir + "], exiting..."); - } else { - console.printf("complete\n"); - } - } - - return destination; - } - - Credentials getCredentials(File walletFile) { - if (!walletFile.exists() || !walletFile.isFile()) { - exitError("Unable to read wallet file: " + walletFile); - } - return loadWalletFile(walletFile); - } - - private Credentials loadWalletFile(File walletFile) { - while (true) { - char[] password = console.readPassword("Please enter your existing wallet file password: "); - String currentPassword = new String(password); - Arrays.fill(password, ' '); - try { - return WalletUtils.loadCredentials(currentPassword, walletFile); - } catch (CipherException e) { - console.printf("Invalid password specified\n"); - } catch (IOException e) { - exitError("Unable to load wallet file: " + walletFile + "\n" + e.getMessage()); - } - } - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/console/WalletUpdater.java b/src/main/java/org/fisco/bcos/web3j/console/WalletUpdater.java deleted file mode 100644 index 7afd31f93..000000000 --- a/src/main/java/org/fisco/bcos/web3j/console/WalletUpdater.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.fisco.bcos.web3j.console; - -import static org.fisco.bcos.web3j.utils.Console.exitError; - -import java.io.File; -import java.io.IOException; -import org.fisco.bcos.web3j.crypto.CipherException; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.crypto.WalletUtils; - -/** Simple class for creating a wallet file. */ -public class WalletUpdater extends WalletManager { - - public WalletUpdater() {} - - public WalletUpdater(IODevice console) { - super(console); - } - - public static void main(String[] args) { - if (args.length != 1) { - exitError("You must provide an existing wallet file"); - } else { - new WalletUpdater().run(args[0]); - } - } - - public static void main(IODevice console, String walletFileLocation) { - new WalletUpdater(console).run(walletFileLocation); - } - - private void run(String walletFileLocation) { - File walletFile = new File(walletFileLocation); - Credentials credentials = getCredentials(walletFile); - - console.printf("Wallet for address " + credentials.getAddress() + " loaded\n"); - - String newPassword = getPassword("Please enter a new wallet file password: "); - - String destinationDir = getDestinationDir(); - File destination = createDir(destinationDir); - - try { - String walletFileName = - WalletUtils.generateWalletFile( - newPassword, credentials.getEcKeyPair(), destination, true); - console.printf( - "New wallet file " - + walletFileName - + " successfully created in: " - + destinationDir - + "\n"); - } catch (CipherException | IOException e) { - exitError(e); - } - - String delete = - console.readLine("Would you like to delete your existing wallet file (Y/N)? [N]: "); - if (delete.toUpperCase().equals("Y")) { - if (!walletFile.delete()) { - exitError("Unable to remove wallet file\n"); - } else { - console.printf("Deleted previous wallet file: %s\n", walletFile.getName()); - } - } - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/CipherException.java b/src/main/java/org/fisco/bcos/web3j/crypto/CipherException.java index b73cc7d9e..12250eea6 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/CipherException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/CipherException.java @@ -3,15 +3,15 @@ /** Cipher exception wrapper. */ public class CipherException extends Exception { - public CipherException(String message) { - super(message); - } + public CipherException(String message) { + super(message); + } - public CipherException(Throwable cause) { - super(cause); - } + public CipherException(Throwable cause) { + super(cause); + } - public CipherException(String message, Throwable cause) { - super(message, cause); - } + public CipherException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ContractUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/ContractUtils.java index 8e3132821..7252029ef 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ContractUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ContractUtils.java @@ -13,28 +13,28 @@ /** Smart Contract utility functions. */ public class ContractUtils { - /** - * Generate a smart contract address. This enables you to identify what address a smart contract - * will be deployed to on the network. - * - * @param address of sender - * @param nonce of transaction - * @return the generated smart contract address - */ - public static byte[] generateContractAddress(byte[] address, BigInteger nonce) { - List values = new ArrayList<>(); + /** + * Generate a smart contract address. This enables you to identify what address a smart contract + * will be deployed to on the network. + * + * @param address of sender + * @param nonce of transaction + * @return the generated smart contract address + */ + public static byte[] generateContractAddress(byte[] address, BigInteger nonce) { + List values = new ArrayList<>(); - values.add(RlpString.create(address)); - values.add(RlpString.create(nonce)); - RlpList rlpList = new RlpList(values); + values.add(RlpString.create(address)); + values.add(RlpString.create(nonce)); + RlpList rlpList = new RlpList(values); - byte[] encoded = RlpEncoder.encode(rlpList); - byte[] hashed = Hash.sha3(encoded); - return Arrays.copyOfRange(hashed, 12, hashed.length); - } + byte[] encoded = RlpEncoder.encode(rlpList); + byte[] hashed = Hash.sha3(encoded); + return Arrays.copyOfRange(hashed, 12, hashed.length); + } - public static String generateContractAddress(String address, BigInteger nonce) { - byte[] result = generateContractAddress(Numeric.hexStringToByteArray(address), nonce); - return Numeric.toHexString(result); - } + public static String generateContractAddress(String address, BigInteger nonce) { + byte[] result = generateContractAddress(Numeric.hexStringToByteArray(address), nonce); + return Numeric.toHexString(result); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/Credentials.java b/src/main/java/org/fisco/bcos/web3j/crypto/Credentials.java index f582a2309..0e2449d39 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/Credentials.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/Credentials.java @@ -5,57 +5,57 @@ /** Credentials wrapper. */ public class Credentials { - private final ECKeyPair ecKeyPair; - private final String address; + private final ECKeyPair ecKeyPair; + private final String address; - private Credentials(ECKeyPair ecKeyPair, String address) { - this.ecKeyPair = ecKeyPair; - this.address = address; - } - - public ECKeyPair getEcKeyPair() { - return ecKeyPair; - } - - public String getAddress() { - return address; - } + private Credentials(ECKeyPair ecKeyPair, String address) { + this.ecKeyPair = ecKeyPair; + this.address = address; + } - public static Credentials create(ECKeyPair ecKeyPair) { - String address = Numeric.prependHexPrefix(Keys.getAddress(ecKeyPair)); - return new Credentials(ecKeyPair, address); - } + public ECKeyPair getEcKeyPair() { + return ecKeyPair; + } - public static Credentials create(String privateKey, String publicKey) { - return create(new ECKeyPair(Numeric.toBigInt(privateKey), Numeric.toBigInt(publicKey))); - } + public String getAddress() { + return address; + } - public static Credentials create(String privateKey) { - return create(ECKeyPair.create(Numeric.toBigInt(privateKey))); - } + public static Credentials create(ECKeyPair ecKeyPair) { + String address = Numeric.prependHexPrefix(Keys.getAddress(ecKeyPair)); + return new Credentials(ecKeyPair, address); + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public static Credentials create(String privateKey, String publicKey) { + return create(new ECKeyPair(Numeric.toBigInt(privateKey), Numeric.toBigInt(publicKey))); } - if (o == null || getClass() != o.getClass()) { - return false; + + public static Credentials create(String privateKey) { + return create(ECKeyPair.create(Numeric.toBigInt(privateKey))); } - Credentials that = (Credentials) o; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - if (ecKeyPair != null ? !ecKeyPair.equals(that.ecKeyPair) : that.ecKeyPair != null) { - return false; - } + Credentials that = (Credentials) o; - return address != null ? address.equals(that.address) : that.address == null; - } + if (ecKeyPair != null ? !ecKeyPair.equals(that.ecKeyPair) : that.ecKeyPair != null) { + return false; + } - @Override - public int hashCode() { - int result = ecKeyPair != null ? ecKeyPair.hashCode() : 0; - result = 31 * result + (address != null ? address.hashCode() : 0); - return result; - } + return address != null ? address.equals(that.address) : that.address == null; + } + + @Override + public int hashCode() { + int result = ecKeyPair != null ? ecKeyPair.hashCode() : 0; + result = 31 * result + (address != null ? address.hashCode() : 0); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASign.java b/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASign.java index 742e6f526..6379260be 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASign.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASign.java @@ -11,45 +11,45 @@ /** Created by websterchen on 2018/4/25. */ public class ECDSASign implements SignInterface { - @Override - public Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair) { - BigInteger privateKey = keyPair.getPrivateKey(); - BigInteger publicKey = keyPair.getPublicKey(); - - byte[] messageHash = Hash.sha3(message); - - ECDSASignature sig = sign(messageHash, privateKey); - // Now we have to work backwards to figure out the recId needed to recover the signature. - int recId = -1; - for (int i = 0; i < 4; i++) { - BigInteger k = Sign.recoverFromSignature(i, sig, messageHash); - if (k != null && k.equals(publicKey)) { - recId = i; - break; - } + @Override + public Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair) { + BigInteger privateKey = keyPair.getPrivateKey(); + BigInteger publicKey = keyPair.getPublicKey(); + + byte[] messageHash = Hash.sha3(message); + + ECDSASignature sig = sign(messageHash, privateKey); + // Now we have to work backwards to figure out the recId needed to recover the signature. + int recId = -1; + for (int i = 0; i < 4; i++) { + BigInteger k = Sign.recoverFromSignature(i, sig, messageHash); + if (k != null && k.equals(publicKey)) { + recId = i; + break; + } + } + if (recId == -1) { + throw new RuntimeException( + "Could not construct a recoverable key. This should never happen."); + } + + int headerByte = recId + 27; + + // 1 header + 32 bytes for R + 32 bytes for S + byte v = (byte) headerByte; + byte[] r = Numeric.toBytesPadded(sig.r, 32); + byte[] s = Numeric.toBytesPadded(sig.s, 32); + + return new Sign.SignatureData(v, r, s); } - if (recId == -1) { - throw new RuntimeException( - "Could not construct a recoverable key. This should never happen."); - } - - int headerByte = recId + 27; - - // 1 header + 32 bytes for R + 32 bytes for S - byte v = (byte) headerByte; - byte[] r = Numeric.toBytesPadded(sig.r, 32); - byte[] s = Numeric.toBytesPadded(sig.s, 32); - return new Sign.SignatureData(v, r, s); - } + public static ECDSASignature sign(byte[] transactionHash, BigInteger privateKey) { + ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); - public static ECDSASignature sign(byte[] transactionHash, BigInteger privateKey) { - ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, CURVE); + signer.init(true, privKey); + BigInteger[] components = signer.generateSignature(transactionHash); - ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, CURVE); - signer.init(true, privKey); - BigInteger[] components = signer.generateSignature(transactionHash); - - return new ECDSASignature(components[0], components[1]).toCanonicalised(); - } + return new ECDSASignature(components[0], components[1]).toCanonicalised(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASignature.java b/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASignature.java index 57c72d33f..cb7294d9b 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASignature.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ECDSASignature.java @@ -4,44 +4,45 @@ /** An ECDSA Signature. */ public class ECDSASignature { - public final BigInteger r; - public final BigInteger s; + public final BigInteger r; + public final BigInteger s; - public ECDSASignature(BigInteger r, BigInteger s) { - this.r = r; - this.s = s; - } + public ECDSASignature(BigInteger r, BigInteger s) { + this.r = r; + this.s = s; + } - /** - * @return true if the S component is "low", that means it is below {@link Sign#HALF_CURVE_ORDER}. - * See - * BIP62. - */ - public boolean isCanonical() { - return s.compareTo(Sign.HALF_CURVE_ORDER) <= 0; - } + /** + * @return true if the S component is "low", that means it is below {@link + * Sign#HALF_CURVE_ORDER}. See + * BIP62. + */ + public boolean isCanonical() { + return s.compareTo(Sign.HALF_CURVE_ORDER) <= 0; + } - /** - * Will automatically adjust the S component to be less than or equal to half the curve order, if - * necessary. This is required because for every signature (r,s) the signature (r, -s (mod N)) is - * a valid signature of the same message. However, we dislike the ability to modify the bits of a - * Bitcoin transaction after it's been signed, as that violates various assumed invariants. Thus - * in future only one of those forms will be considered legal and the other will be banned. - * - * @return the signature in a canonicalised form. - */ - public ECDSASignature toCanonicalised() { - if (!isCanonical()) { - // The order of the curve is the number of valid points that exist on that curve. - // If S is in the upper half of the number of valid points, then bring it back to - // the lower half. Otherwise, imagine that - // N = 10 - // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. - // 10 - 8 == 2, giving us always the latter solution, which is canonical. - return new ECDSASignature(r, Sign.CURVE.getN().subtract(s)); - } else { - return this; + /** + * Will automatically adjust the S component to be less than or equal to half the curve order, + * if necessary. This is required because for every signature (r,s) the signature (r, -s (mod + * N)) is a valid signature of the same message. However, we dislike the ability to modify the + * bits of a Bitcoin transaction after it's been signed, as that violates various assumed + * invariants. Thus in future only one of those forms will be considered legal and the other + * will be banned. + * + * @return the signature in a canonicalised form. + */ + public ECDSASignature toCanonicalised() { + if (!isCanonical()) { + // The order of the curve is the number of valid points that exist on that curve. + // If S is in the upper half of the number of valid points, then bring it back to + // the lower half. Otherwise, imagine that + // N = 10 + // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. + // 10 - 8 == 2, giving us always the latter solution, which is canonical. + return new ECDSASignature(r, Sign.CURVE.getN().subtract(s)); + } else { + return this; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ECKeyPair.java b/src/main/java/org/fisco/bcos/web3j/crypto/ECKeyPair.java index fe4da8ef7..c75b8a45b 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ECKeyPair.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ECKeyPair.java @@ -13,86 +13,88 @@ /** Elliptic Curve SECP-256k1 generated key pair. */ public class ECKeyPair { - private final BigInteger privateKey; - private final BigInteger publicKey; - - public ECKeyPair(BigInteger privateKey, BigInteger publicKey) { - this.privateKey = privateKey; - this.publicKey = publicKey; - } - - public BigInteger getPrivateKey() { - return privateKey; - } - - public BigInteger getPublicKey() { - return publicKey; - } - - /** - * Sign a hash with the private key of this key pair. - * - * @param transactionHash the hash to sign - * @return An {@link ECDSASignature} of the hash - */ - public ECDSASignature sign(byte[] transactionHash) { - ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); - - ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, Sign.CURVE); - signer.init(true, privKey); - BigInteger[] components = signer.generateSignature(transactionHash); - - return new ECDSASignature(components[0], components[1]).toCanonicalised(); - } - - public static ECKeyPair create(KeyPair keyPair) { - BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate(); - BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic(); - - BigInteger privateKeyValue = privateKey.getD(); - - // Ethereum does not use encoded public keys like bitcoin - see - // https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details - // Additionally, as the first bit is a constant prefix (0x04) we ignore this value - byte[] publicKeyBytes = publicKey.getQ().getEncoded(false); - BigInteger publicKeyValue = - new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length)); - - return new ECKeyPair(privateKeyValue, publicKeyValue); - } - - public static ECKeyPair create(BigInteger privateKey) { - return new ECKeyPair(privateKey, Sign.publicKeyFromPrivate(privateKey)); - } - - public static ECKeyPair create(byte[] privateKey) { - return create(Numeric.toBigInt(privateKey)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + private final BigInteger privateKey; + private final BigInteger publicKey; + + public ECKeyPair(BigInteger privateKey, BigInteger publicKey) { + this.privateKey = privateKey; + this.publicKey = publicKey; + } + + public BigInteger getPrivateKey() { + return privateKey; + } + + public BigInteger getPublicKey() { + return publicKey; + } + + /** + * Sign a hash with the private key of this key pair. + * + * @param transactionHash the hash to sign + * @return An {@link ECDSASignature} of the hash + */ + public ECDSASignature sign(byte[] transactionHash) { + ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); + + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, Sign.CURVE); + signer.init(true, privKey); + BigInteger[] components = signer.generateSignature(transactionHash); + + return new ECDSASignature(components[0], components[1]).toCanonicalised(); } - if (o == null || getClass() != o.getClass()) { - return false; + + public static ECKeyPair create(KeyPair keyPair) { + BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate(); + BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic(); + + BigInteger privateKeyValue = privateKey.getD(); + + // Ethereum does not use encoded public keys like bitcoin - see + // https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details + // Additionally, as the first bit is a constant prefix (0x04) we ignore this value + byte[] publicKeyBytes = publicKey.getQ().getEncoded(false); + BigInteger publicKeyValue = + new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length)); + + return new ECKeyPair(privateKeyValue, publicKeyValue); } - ECKeyPair ecKeyPair = (ECKeyPair) o; + public static ECKeyPair create(BigInteger privateKey) { + return new ECKeyPair(privateKey, Sign.publicKeyFromPrivate(privateKey)); + } - if (privateKey != null - ? !privateKey.equals(ecKeyPair.privateKey) - : ecKeyPair.privateKey != null) { - return false; + public static ECKeyPair create(byte[] privateKey) { + return create(Numeric.toBigInt(privateKey)); } - return publicKey != null ? publicKey.equals(ecKeyPair.publicKey) : ecKeyPair.publicKey == null; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ECKeyPair ecKeyPair = (ECKeyPair) o; + + if (privateKey != null + ? !privateKey.equals(ecKeyPair.privateKey) + : ecKeyPair.privateKey != null) { + return false; + } + + return publicKey != null + ? publicKey.equals(ecKeyPair.publicKey) + : ecKeyPair.publicKey == null; + } - @Override - public int hashCode() { - int result = privateKey != null ? privateKey.hashCode() : 0; - result = 31 * result + (publicKey != null ? publicKey.hashCode() : 0); - return result; - } + @Override + public int hashCode() { + int result = privateKey != null ? privateKey.hashCode() : 0; + result = 31 * result + (publicKey != null ? publicKey.hashCode() : 0); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/EncryptType.java b/src/main/java/org/fisco/bcos/web3j/crypto/EncryptType.java index c5ed82b93..8ab9384e1 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/EncryptType.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/EncryptType.java @@ -5,28 +5,28 @@ /** Created by websterchen on 2018/4/25. */ public class EncryptType { - public static int encryptType = 0; // 0:ECDSA 1:SM2 + public static int encryptType = 0; // 0:ECDSA 1:SM2 - public EncryptType(int encryptType) { - EncryptType.encryptType = encryptType; - SignInterface signInterface; - HashInterface hashInterface; - if (encryptType == 1) { - signInterface = new SM2Sign(); - hashInterface = new SM3Digest(); - } else { - signInterface = new ECDSASign(); - hashInterface = new SHA3Digest(); + public EncryptType(int encryptType) { + EncryptType.encryptType = encryptType; + SignInterface signInterface; + HashInterface hashInterface; + if (encryptType == 1) { + signInterface = new SM2Sign(); + hashInterface = new SM3Digest(); + } else { + signInterface = new ECDSASign(); + hashInterface = new SHA3Digest(); + } + Sign.setSignInterface(signInterface); + Hash.setHashInterface(hashInterface); } - Sign.setSignInterface(signInterface); - Hash.setHashInterface(hashInterface); - } - public int getEncryptType() { - return encryptType; - } + public int getEncryptType() { + return encryptType; + } - public void setEncryptType(int encryptType) { - EncryptType.encryptType = encryptType; - } + public void setEncryptType(int encryptType) { + EncryptType.encryptType = encryptType; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedRawTransaction.java b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedRawTransaction.java index 43c4e2b65..0c9d7638a 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedRawTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedRawTransaction.java @@ -1,10 +1,9 @@ package org.fisco.bcos.web3j.crypto; -import org.fisco.bcos.web3j.tx.TransactionConstant; -import org.fisco.bcos.web3j.utils.Numeric; - import java.io.Serializable; import java.math.BigInteger; +import org.fisco.bcos.web3j.tx.TransactionConstant; +import org.fisco.bcos.web3j.utils.Numeric; /** * Transaction class used for signing transactions locally.
@@ -64,19 +63,30 @@ public static ExtendedRawTransaction createContractTransaction( BigInteger groupId, String extraData) { - return new ExtendedRawTransaction(randomid, gasPrice, gasLimit, blockLimit, "", value, init,chainId,groupId,extraData); - } -// -// -// public static ExtendedRawTransaction createTransaction( -// BigInteger randomid, -// BigInteger gasPrice, -// BigInteger gasLimit, -// BigInteger blockLimit, -// String to, -// String data) { -// return createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, BigInteger.ZERO, data); -// } + return new ExtendedRawTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + "", + value, + init, + chainId, + groupId, + extraData); + } + // + // + // public static ExtendedRawTransaction createTransaction( + // BigInteger randomid, + // BigInteger gasPrice, + // BigInteger gasLimit, + // BigInteger blockLimit, + // String to, + // String data) { + // return createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, + // BigInteger.ZERO, data); + // } public static ExtendedRawTransaction createTransaction( BigInteger randomid, @@ -90,7 +100,17 @@ public static ExtendedRawTransaction createTransaction( BigInteger groupId, String extraData) { - return new ExtendedRawTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data,chainId, groupId, extraData); + return new ExtendedRawTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + to, + value, + data, + chainId, + groupId, + extraData); } public BigInteger getRandomid() { @@ -124,6 +144,7 @@ public String getData() { public BigInteger getVersion() { return version; } + public BigInteger getGroupId() { return groupId; } @@ -132,7 +153,6 @@ public void setGroupId(BigInteger groupId) { this.groupId = groupId; } - public String getExtraData() { return extraData; } @@ -148,5 +168,4 @@ public BigInteger getFiscoChainId() { public void setFiscoChainId(BigInteger fiscoChainId) { this.fiscoChainId = fiscoChainId; } - } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionDecoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionDecoder.java index 121026bc1..aab20718e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionDecoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionDecoder.java @@ -1,44 +1,64 @@ package org.fisco.bcos.web3j.crypto; +import java.math.BigInteger; import org.fisco.bcos.web3j.rlp.RlpDecoder; import org.fisco.bcos.web3j.rlp.RlpList; import org.fisco.bcos.web3j.rlp.RlpString; import org.fisco.bcos.web3j.utils.Numeric; -import java.math.BigInteger; - public class ExtendedTransactionDecoder { - public static ExtendedRawTransaction decode(String hexTransaction) { - byte[] transaction = Numeric.hexStringToByteArray(hexTransaction); - RlpList rlpList = RlpDecoder.decode(transaction); - RlpList values = (RlpList) rlpList.getValues().get(0); - BigInteger randomid = ((RlpString) values.getValues().get(0)).asPositiveBigInteger(); - BigInteger gasPrice = ((RlpString) values.getValues().get(1)).asPositiveBigInteger(); - BigInteger gasLimit = ((RlpString) values.getValues().get(2)).asPositiveBigInteger(); - BigInteger blockLimit = ((RlpString) values.getValues().get(3)).asPositiveBigInteger(); - String to = ((RlpString) values.getValues().get(4)).asString(); - BigInteger value = ((RlpString) values.getValues().get(5)).asPositiveBigInteger(); - String data = ((RlpString) values.getValues().get(6)).asString(); + public static ExtendedRawTransaction decode(String hexTransaction) { + byte[] transaction = Numeric.hexStringToByteArray(hexTransaction); + RlpList rlpList = RlpDecoder.decode(transaction); + RlpList values = (RlpList) rlpList.getValues().get(0); + BigInteger randomid = ((RlpString) values.getValues().get(0)).asPositiveBigInteger(); + BigInteger gasPrice = ((RlpString) values.getValues().get(1)).asPositiveBigInteger(); + BigInteger gasLimit = ((RlpString) values.getValues().get(2)).asPositiveBigInteger(); + BigInteger blockLimit = ((RlpString) values.getValues().get(3)).asPositiveBigInteger(); + String to = ((RlpString) values.getValues().get(4)).asString(); + BigInteger value = ((RlpString) values.getValues().get(5)).asPositiveBigInteger(); + String data = ((RlpString) values.getValues().get(6)).asString(); - //add extra data - BigInteger chainId = ((RlpString) values.getValues().get(7)).asPositiveBigInteger(); - BigInteger groupId = ((RlpString) values.getValues().get(8)).asPositiveBigInteger(); - String extraData = ((RlpString) values.getValues().get(9)).asString(); - if (values.getValues().size() > 9) { - byte v = ((RlpString) values.getValues().get(10)).getBytes()[0]; - byte[] r = - Numeric.toBytesPadded( - Numeric.toBigInt(((RlpString) values.getValues().get(11)).getBytes()), 32); - byte[] s = - Numeric.toBytesPadded( - Numeric.toBigInt(((RlpString) values.getValues().get(12)).getBytes()), 32); - Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); - return new SignedExtendedRawTransaction( - randomid, gasPrice, gasLimit, blockLimit, to, value, data,chainId, groupId, extraData, signatureData); - } else { - return ExtendedRawTransaction.createTransaction( - randomid, gasPrice, gasLimit, blockLimit, to, value, data,chainId, groupId, extraData); + // add extra data + BigInteger chainId = ((RlpString) values.getValues().get(7)).asPositiveBigInteger(); + BigInteger groupId = ((RlpString) values.getValues().get(8)).asPositiveBigInteger(); + String extraData = ((RlpString) values.getValues().get(9)).asString(); + if (values.getValues().size() > 9) { + byte v = ((RlpString) values.getValues().get(10)).getBytes()[0]; + byte[] r = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.getValues().get(11)).getBytes()), + 32); + byte[] s = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.getValues().get(12)).getBytes()), + 32); + Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); + return new SignedExtendedRawTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + to, + value, + data, + chainId, + groupId, + extraData, + signatureData); + } else { + return ExtendedRawTransaction.createTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + to, + value, + data, + chainId, + groupId, + extraData); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionEncoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionEncoder.java index 17b57dbb3..da7372285 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/ExtendedTransactionEncoder.java @@ -1,5 +1,7 @@ package org.fisco.bcos.web3j.crypto; +import java.util.ArrayList; +import java.util.List; import org.fisco.bcos.web3j.rlp.RlpEncoder; import org.fisco.bcos.web3j.rlp.RlpList; import org.fisco.bcos.web3j.rlp.RlpString; @@ -7,102 +9,102 @@ import org.fisco.bcos.web3j.utils.Bytes; import org.fisco.bcos.web3j.utils.Numeric; -import java.util.ArrayList; -import java.util.List; - /** * Create RLP encoded transaction, implementation as per p4 of the yellow paper. */ public class ExtendedTransactionEncoder { - public static byte[] signMessage(ExtendedRawTransaction rawTransaction, Credentials credentials) { - byte[] encodedTransaction = encode(rawTransaction); - Sign.SignatureData signatureData = - Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); - - return encode(rawTransaction, signatureData); - } - - public static byte[] signMessage( - ExtendedRawTransaction rawTransaction, byte chainId, Credentials credentials) { - byte[] encodedTransaction = encode(rawTransaction, chainId); - Sign.SignatureData signatureData = - Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); - - Sign.SignatureData eip155SignatureData = createEip155SignatureData(signatureData, chainId); - return encode(rawTransaction, eip155SignatureData); - } - - public static Sign.SignatureData createEip155SignatureData( - Sign.SignatureData signatureData, byte chainId) { - byte v = (byte) (signatureData.getV() + (chainId << 1) + 8); - - return new Sign.SignatureData(v, signatureData.getR(), signatureData.getS()); - } - - public static byte[] encode(ExtendedRawTransaction rawTransaction) { - return encode(rawTransaction, null); - } - - public static byte[] encode(ExtendedRawTransaction rawTransaction, byte chainId) { - Sign.SignatureData signatureData = - new Sign.SignatureData(chainId, new byte[] {}, new byte[] {}); - return encode(rawTransaction, signatureData); - } - - public static byte[] encode(ExtendedRawTransaction rawTransaction, Sign.SignatureData signatureData) { - List values = asRlpValues(rawTransaction, signatureData); - RlpList rlpList = new RlpList(values); - return RlpEncoder.encode(rlpList); - } - - static List asRlpValues( - ExtendedRawTransaction rawTransaction, Sign.SignatureData signatureData) { - List result = new ArrayList<>(); - result.add(RlpString.create(rawTransaction.getRandomid())); - result.add(RlpString.create(rawTransaction.getGasPrice())); - result.add(RlpString.create(rawTransaction.getGasLimit())); - result.add(RlpString.create(rawTransaction.getBlockLimit())); - // an empty to address (contract creation) should not be encoded as a numeric 0 value - String to = rawTransaction.getTo(); - if (to != null && to.length() > 0) { - // addresses that start with zeros should be encoded with the zeros included, not - // as numeric values - result.add(RlpString.create(Numeric.hexStringToByteArray(to))); - } else { - result.add(RlpString.create("")); + public static byte[] signMessage( + ExtendedRawTransaction rawTransaction, Credentials credentials) { + byte[] encodedTransaction = encode(rawTransaction); + Sign.SignatureData signatureData = + Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); + + return encode(rawTransaction, signatureData); + } + + public static byte[] signMessage( + ExtendedRawTransaction rawTransaction, byte chainId, Credentials credentials) { + byte[] encodedTransaction = encode(rawTransaction, chainId); + Sign.SignatureData signatureData = + Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); + + Sign.SignatureData eip155SignatureData = createEip155SignatureData(signatureData, chainId); + return encode(rawTransaction, eip155SignatureData); } - result.add(RlpString.create(rawTransaction.getValue())); + public static Sign.SignatureData createEip155SignatureData( + Sign.SignatureData signatureData, byte chainId) { + byte v = (byte) (signatureData.getV() + (chainId << 1) + 8); - // value field will already be hex encoded, so we need to convert into binary first - byte[] data = Numeric.hexStringToByteArray(rawTransaction.getData()); - result.add(RlpString.create(data)); + return new Sign.SignatureData(v, signatureData.getR(), signatureData.getS()); + } - // add extra data!!! + public static byte[] encode(ExtendedRawTransaction rawTransaction) { + return encode(rawTransaction, null); + } - result.add(RlpString.create(rawTransaction.getFiscoChainId())); - result.add(RlpString.create(rawTransaction.getGroupId())); - if(rawTransaction.getExtraData()==null){ - result.add(RlpString.create("")); - } else { - result.add(RlpString.create(Numeric.hexStringToByteArray(rawTransaction.getExtraData()))); + public static byte[] encode(ExtendedRawTransaction rawTransaction, byte chainId) { + Sign.SignatureData signatureData = + new Sign.SignatureData(chainId, new byte[] {}, new byte[] {}); + return encode(rawTransaction, signatureData); } - if (signatureData != null) { - if (EncryptType.encryptType == 1) { - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getPub()))); - // logger.debug("RLP-Pub:{},RLP-PubLen:{}",Hex.toHexString(signatureData.getPub()),signatureData.getPub().length); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); - // logger.debug("RLP-R:{},RLP-RLen:{}",Hex.toHexString(signatureData.getR()),signatureData.getR().length); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); - // logger.debug("RLP-S:{},RLP-SLen:{}",Hex.toHexString(signatureData.getS()),signatureData.getS().length); - } else { - result.add(RlpString.create(signatureData.getV())); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); - } + + public static byte[] encode( + ExtendedRawTransaction rawTransaction, Sign.SignatureData signatureData) { + List values = asRlpValues(rawTransaction, signatureData); + RlpList rlpList = new RlpList(values); + return RlpEncoder.encode(rlpList); + } + + static List asRlpValues( + ExtendedRawTransaction rawTransaction, Sign.SignatureData signatureData) { + List result = new ArrayList<>(); + result.add(RlpString.create(rawTransaction.getRandomid())); + result.add(RlpString.create(rawTransaction.getGasPrice())); + result.add(RlpString.create(rawTransaction.getGasLimit())); + result.add(RlpString.create(rawTransaction.getBlockLimit())); + // an empty to address (contract creation) should not be encoded as a numeric 0 value + String to = rawTransaction.getTo(); + if (to != null && to.length() > 0) { + // addresses that start with zeros should be encoded with the zeros included, not + // as numeric values + result.add(RlpString.create(Numeric.hexStringToByteArray(to))); + } else { + result.add(RlpString.create("")); + } + + result.add(RlpString.create(rawTransaction.getValue())); + + // value field will already be hex encoded, so we need to convert into binary first + byte[] data = Numeric.hexStringToByteArray(rawTransaction.getData()); + result.add(RlpString.create(data)); + + // add extra data!!! + + result.add(RlpString.create(rawTransaction.getFiscoChainId())); + result.add(RlpString.create(rawTransaction.getGroupId())); + if (rawTransaction.getExtraData() == null) { + result.add(RlpString.create("")); + } else { + result.add( + RlpString.create(Numeric.hexStringToByteArray(rawTransaction.getExtraData()))); + } + if (signatureData != null) { + if (EncryptType.encryptType == 1) { + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getPub()))); + // logger.debug("RLP-Pub:{},RLP-PubLen:{}",Hex.toHexString(signatureData.getPub()),signatureData.getPub().length); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); + // logger.debug("RLP-R:{},RLP-RLen:{}",Hex.toHexString(signatureData.getR()),signatureData.getR().length); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); + // logger.debug("RLP-S:{},RLP-SLen:{}",Hex.toHexString(signatureData.getS()),signatureData.getS().length); + } else { + result.add(RlpString.create(signatureData.getV())); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); + } + } + return result; } - return result; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/Hash.java b/src/main/java/org/fisco/bcos/web3j/crypto/Hash.java index 0dfc53a67..773295bb5 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/Hash.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/Hash.java @@ -11,91 +11,91 @@ /** Crypto related functions. */ public class Hash { - private Hash() {} + private Hash() {} - private static HashInterface hashInterface = new SHA3Digest(); + private static HashInterface hashInterface = new SHA3Digest(); - public static HashInterface getHashInterface() { - return hashInterface; - } + public static HashInterface getHashInterface() { + return hashInterface; + } - public static void setHashInterface(HashInterface hashInterface) { - Hash.hashInterface = hashInterface; - } + public static void setHashInterface(HashInterface hashInterface) { + Hash.hashInterface = hashInterface; + } - /** - * Keccak-256 hash function. - * - * @param hexInput hex encoded input data with optional 0x prefix - * @return hash value as hex encoded string - */ - public static String sha3(String hexInput) { - return hashInterface.hash(hexInput); - } + /** + * Keccak-256 hash function. + * + * @param hexInput hex encoded input data with optional 0x prefix + * @return hash value as hex encoded string + */ + public static String sha3(String hexInput) { + return hashInterface.hash(hexInput); + } - /** - * Keccak-256 hash function. - * - * @param input binary encoded input data - * @param offset of start of data - * @param length of data - * @return hash value - */ - public static byte[] sha3(byte[] input, int offset, int length) { - return hashInterface.hash(input, offset, length); - } + /** + * Keccak-256 hash function. + * + * @param input binary encoded input data + * @param offset of start of data + * @param length of data + * @return hash value + */ + public static byte[] sha3(byte[] input, int offset, int length) { + return hashInterface.hash(input, offset, length); + } - /** - * Keccak-256 hash function. - * - * @param input binary encoded input data - * @return hash value - */ - public static byte[] sha3(byte[] input) { - return hashInterface.hash(input, 0, input.length); - } + /** + * Keccak-256 hash function. + * + * @param input binary encoded input data + * @return hash value + */ + public static byte[] sha3(byte[] input) { + return hashInterface.hash(input, 0, input.length); + } - /** - * Keccak-256 hash function that operates on a UTF-8 encoded String. - * - * @param utf8String UTF-8 encoded string - * @return hash value as hex encoded string - */ - public static String sha3String(String utf8String) { - return Numeric.toHexString(sha3(utf8String.getBytes(StandardCharsets.UTF_8))); - } + /** + * Keccak-256 hash function that operates on a UTF-8 encoded String. + * + * @param utf8String UTF-8 encoded string + * @return hash value as hex encoded string + */ + public static String sha3String(String utf8String) { + return Numeric.toHexString(sha3(utf8String.getBytes(StandardCharsets.UTF_8))); + } - /** - * Generates SHA-256 digest for the given {@code input}. - * - * @param input The input to digest - * @return The hash value for the given input - * @throws RuntimeException If we couldn't find any SHA-256 provider - */ - public static byte[] sha256(byte[] input) { - try { - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - return digest.digest(input); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Couldn't find a SHA-256 provider", e); + /** + * Generates SHA-256 digest for the given {@code input}. + * + * @param input The input to digest + * @return The hash value for the given input + * @throws RuntimeException If we couldn't find any SHA-256 provider + */ + public static byte[] sha256(byte[] input) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + return digest.digest(input); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Couldn't find a SHA-256 provider", e); + } } - } - public static byte[] hmacSha512(byte[] key, byte[] input) { - HMac hMac = new HMac(new SHA512Digest()); - hMac.init(new KeyParameter(key)); - hMac.update(input, 0, input.length); - byte[] out = new byte[64]; - hMac.doFinal(out, 0); - return out; - } + public static byte[] hmacSha512(byte[] key, byte[] input) { + HMac hMac = new HMac(new SHA512Digest()); + hMac.init(new KeyParameter(key)); + hMac.update(input, 0, input.length); + byte[] out = new byte[64]; + hMac.doFinal(out, 0); + return out; + } - public static byte[] sha256hash160(byte[] input) { - byte[] sha256 = sha256(input); - RIPEMD160Digest digest = new RIPEMD160Digest(); - digest.update(sha256, 0, sha256.length); - byte[] out = new byte[20]; - digest.doFinal(out, 0); - return out; - } + public static byte[] sha256hash160(byte[] input) { + byte[] sha256 = sha256(input); + RIPEMD160Digest digest = new RIPEMD160Digest(); + digest.update(sha256, 0, sha256.length); + byte[] out = new byte[20]; + digest.doFinal(out, 0); + return out; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/HashInterface.java b/src/main/java/org/fisco/bcos/web3j/crypto/HashInterface.java index ea91883b0..789e2a0c1 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/HashInterface.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/HashInterface.java @@ -1,9 +1,9 @@ package org.fisco.bcos.web3j.crypto; /** Created by websterchen on 2018/3/4. */ public interface HashInterface { - String hash(String hexInput); + String hash(String hexInput); - byte[] hash(byte[] input, int offset, int length); + byte[] hash(byte[] input, int offset, int length); - byte[] hash(byte[] input); + byte[] hash(byte[] input); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/Keys.java b/src/main/java/org/fisco/bcos/web3j/crypto/Keys.java index 300d4d196..2bd8794c2 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/Keys.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/Keys.java @@ -19,133 +19,139 @@ /** Crypto key utilities. */ public class Keys { - static final int PRIVATE_KEY_SIZE = 32; - static final int PUBLIC_KEY_SIZE = 64; + static final int PRIVATE_KEY_SIZE = 32; + static final int PUBLIC_KEY_SIZE = 64; - public static final int ADDRESS_SIZE = 160; - public static final int ADDRESS_LENGTH_IN_HEX = ADDRESS_SIZE >> 2; + public static final int ADDRESS_SIZE = 160; + public static final int ADDRESS_LENGTH_IN_HEX = ADDRESS_SIZE >> 2; - static final int PUBLIC_KEY_LENGTH_IN_HEX = PUBLIC_KEY_SIZE << 1; - public static final int PRIVATE_KEY_LENGTH_IN_HEX = PRIVATE_KEY_SIZE << 1; + static final int PUBLIC_KEY_LENGTH_IN_HEX = PUBLIC_KEY_SIZE << 1; + public static final int PRIVATE_KEY_LENGTH_IN_HEX = PRIVATE_KEY_SIZE << 1; - static { - if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { - Security.addProvider(new BouncyCastleProvider()); + static { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { + Security.addProvider(new BouncyCastleProvider()); + } } - } - - private Keys() {} - - /** - * Create a keypair using SECP-256k1 curve. - * - *

Private keypairs are encoded using PKCS8 - * - *

Private keys are encoded using X.509 - */ - /** - * Create a keypair using SECP-256k1 curve. - * - *

Private keypairs are encoded using PKCS8 - * - *

Private keys are encoded using X.509 - */ - static KeyPair createSecp256k1KeyPair() - throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { - return createSecp256k1KeyPair(secureRandom()); - } - - static KeyPair createSecp256k1KeyPair(SecureRandom random) - throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { - - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC"); - ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1"); - if (random != null) { - keyPairGenerator.initialize(ecGenParameterSpec, random); - } else { - keyPairGenerator.initialize(ecGenParameterSpec); + + private Keys() {} + + /** + * Create a keypair using SECP-256k1 curve. + * + *

Private keypairs are encoded using PKCS8 + * + *

Private keys are encoded using X.509 + */ + /** + * Create a keypair using SECP-256k1 curve. + * + *

Private keypairs are encoded using PKCS8 + * + *

Private keys are encoded using X.509 + */ + static KeyPair createSecp256k1KeyPair() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + return createSecp256k1KeyPair(secureRandom()); + } + + static KeyPair createSecp256k1KeyPair(SecureRandom random) + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC"); + ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1"); + if (random != null) { + keyPairGenerator.initialize(ecGenParameterSpec, random); + } else { + keyPairGenerator.initialize(ecGenParameterSpec); + } + return keyPairGenerator.generateKeyPair(); + } + + public static ECKeyPair createEcKeyPair() + throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, + NoSuchProviderException { + return createEcKeyPair(secureRandom()); + } + + public static ECKeyPair createEcKeyPair(SecureRandom random) + throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, + NoSuchProviderException { + KeyPair keyPair = createSecp256k1KeyPair(random); + return ECKeyPair.create(keyPair); + } + + public static String getAddress(ECKeyPair ecKeyPair) { + return getAddress(ecKeyPair.getPublicKey()); } - return keyPairGenerator.generateKeyPair(); - } - - public static ECKeyPair createEcKeyPair() - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { - return createEcKeyPair(secureRandom()); - } - - public static ECKeyPair createEcKeyPair(SecureRandom random) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { - KeyPair keyPair = createSecp256k1KeyPair(random); - return ECKeyPair.create(keyPair); - } - - public static String getAddress(ECKeyPair ecKeyPair) { - return getAddress(ecKeyPair.getPublicKey()); - } - - public static String getAddress(BigInteger publicKey) { - return getAddress(Numeric.toHexStringWithPrefixZeroPadded(publicKey, PUBLIC_KEY_LENGTH_IN_HEX)); - } - - public static String getAddress(String publicKey) { - String publicKeyNoPrefix = Numeric.cleanHexPrefix(publicKey); - - if (publicKeyNoPrefix.length() < PUBLIC_KEY_LENGTH_IN_HEX) { - publicKeyNoPrefix = - Strings.zeros(PUBLIC_KEY_LENGTH_IN_HEX - publicKeyNoPrefix.length()) + publicKeyNoPrefix; + + public static String getAddress(BigInteger publicKey) { + return getAddress( + Numeric.toHexStringWithPrefixZeroPadded(publicKey, PUBLIC_KEY_LENGTH_IN_HEX)); } - String hash = Hash.sha3(publicKeyNoPrefix); - return hash.substring(hash.length() - ADDRESS_LENGTH_IN_HEX); // right most 160 bits - } - - public static byte[] getAddress(byte[] publicKey) { - byte[] hash = Hash.sha3(publicKey); - return Arrays.copyOfRange(hash, hash.length - 20, hash.length); // right most 160 bits - } - - /** - * Checksum address encoding as per EIP-55. - * - * @param address a valid hex encoded address - * @return hex encoded checksum address - */ - public static String toChecksumAddress(String address) { - String lowercaseAddress = Numeric.cleanHexPrefix(address).toLowerCase(); - String addressHash = Numeric.cleanHexPrefix(Hash.sha3String(lowercaseAddress)); - - StringBuilder result = new StringBuilder(lowercaseAddress.length() + 2); - - result.append("0x"); - - for (int i = 0; i < lowercaseAddress.length(); i++) { - if (Integer.parseInt(String.valueOf(addressHash.charAt(i)), 16) >= 8) { - result.append(String.valueOf(lowercaseAddress.charAt(i)).toUpperCase()); - } else { - result.append(lowercaseAddress.charAt(i)); - } + + public static String getAddress(String publicKey) { + String publicKeyNoPrefix = Numeric.cleanHexPrefix(publicKey); + + if (publicKeyNoPrefix.length() < PUBLIC_KEY_LENGTH_IN_HEX) { + publicKeyNoPrefix = + Strings.zeros(PUBLIC_KEY_LENGTH_IN_HEX - publicKeyNoPrefix.length()) + + publicKeyNoPrefix; + } + String hash = Hash.sha3(publicKeyNoPrefix); + return hash.substring(hash.length() - ADDRESS_LENGTH_IN_HEX); // right most 160 bits } - return result.toString(); - } + public static byte[] getAddress(byte[] publicKey) { + byte[] hash = Hash.sha3(publicKey); + return Arrays.copyOfRange(hash, hash.length - 20, hash.length); // right most 160 bits + } - public static byte[] serialize(ECKeyPair ecKeyPair) { - byte[] privateKey = Numeric.toBytesPadded(ecKeyPair.getPrivateKey(), PRIVATE_KEY_SIZE); - byte[] publicKey = Numeric.toBytesPadded(ecKeyPair.getPublicKey(), PUBLIC_KEY_SIZE); + /** + * Checksum address encoding as per EIP-55. + * + * @param address a valid hex encoded address + * @return hex encoded checksum address + */ + public static String toChecksumAddress(String address) { + String lowercaseAddress = Numeric.cleanHexPrefix(address).toLowerCase(); + String addressHash = Numeric.cleanHexPrefix(Hash.sha3String(lowercaseAddress)); + + StringBuilder result = new StringBuilder(lowercaseAddress.length() + 2); + + result.append("0x"); + + for (int i = 0; i < lowercaseAddress.length(); i++) { + if (Integer.parseInt(String.valueOf(addressHash.charAt(i)), 16) >= 8) { + result.append(String.valueOf(lowercaseAddress.charAt(i)).toUpperCase()); + } else { + result.append(lowercaseAddress.charAt(i)); + } + } + + return result.toString(); + } - byte[] result = Arrays.copyOf(privateKey, PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE); - System.arraycopy(publicKey, 0, result, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE); - return result; - } + public static byte[] serialize(ECKeyPair ecKeyPair) { + byte[] privateKey = Numeric.toBytesPadded(ecKeyPair.getPrivateKey(), PRIVATE_KEY_SIZE); + byte[] publicKey = Numeric.toBytesPadded(ecKeyPair.getPublicKey(), PUBLIC_KEY_SIZE); - public static ECKeyPair deserialize(byte[] input) { - if (input.length != PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE) { - throw new RuntimeException("Invalid input key size"); + byte[] result = Arrays.copyOf(privateKey, PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE); + System.arraycopy(publicKey, 0, result, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE); + return result; } - BigInteger privateKey = Numeric.toBigInt(input, 0, PRIVATE_KEY_SIZE); - BigInteger publicKey = Numeric.toBigInt(input, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE); + public static ECKeyPair deserialize(byte[] input) { + if (input.length != PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE) { + throw new RuntimeException("Invalid input key size"); + } - return new ECKeyPair(privateKey, publicKey); - } + BigInteger privateKey = Numeric.toBigInt(input, 0, PRIVATE_KEY_SIZE); + BigInteger publicKey = Numeric.toBigInt(input, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE); + + return new ECKeyPair(privateKey, publicKey); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/LinuxSecureRandom.java b/src/main/java/org/fisco/bcos/web3j/crypto/LinuxSecureRandom.java index cd75bb298..79153289e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/LinuxSecureRandom.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/LinuxSecureRandom.java @@ -35,71 +35,71 @@ * all from the same source. */ public class LinuxSecureRandom extends SecureRandomSpi { - private static final FileInputStream urandom; + private static final FileInputStream urandom; - private static class LinuxSecureRandomProvider extends Provider { - public LinuxSecureRandomProvider() { - super( - "LinuxSecureRandom", - 1.0, - "A Linux specific random number provider that uses /dev/urandom"); - put("SecureRandom.LinuxSecureRandom", LinuxSecureRandom.class.getName()); + private static class LinuxSecureRandomProvider extends Provider { + public LinuxSecureRandomProvider() { + super( + "LinuxSecureRandom", + 1.0, + "A Linux specific random number provider that uses /dev/urandom"); + put("SecureRandom.LinuxSecureRandom", LinuxSecureRandom.class.getName()); + } } - } - private static final Logger log = LoggerFactory.getLogger(LinuxSecureRandom.class); + private static final Logger log = LoggerFactory.getLogger(LinuxSecureRandom.class); - static { - try { - File file = new File("/dev/urandom"); - // This stream is deliberately leaked. - urandom = new FileInputStream(file); - if (urandom.read() == -1) { - throw new RuntimeException("/dev/urandom not readable?"); - } - // Now override the default SecureRandom implementation with this one. - int position = Security.insertProviderAt(new LinuxSecureRandomProvider(), 1); + static { + try { + File file = new File("/dev/urandom"); + // This stream is deliberately leaked. + urandom = new FileInputStream(file); + if (urandom.read() == -1) { + throw new RuntimeException("/dev/urandom not readable?"); + } + // Now override the default SecureRandom implementation with this one. + int position = Security.insertProviderAt(new LinuxSecureRandomProvider(), 1); - if (position != -1) { - log.info("Secure randomness will be read from {} only.", file); - } else { - log.info("Randomness is already secure."); - } - } catch (FileNotFoundException e) { - // Should never happen. - log.error("/dev/urandom does not appear to exist or is not openable"); - throw new RuntimeException(e); - } catch (IOException e) { - log.error("/dev/urandom does not appear to be readable"); - throw new RuntimeException(e); + if (position != -1) { + log.info("Secure randomness will be read from {} only.", file); + } else { + log.info("Randomness is already secure."); + } + } catch (FileNotFoundException e) { + // Should never happen. + log.error("/dev/urandom does not appear to exist or is not openable"); + throw new RuntimeException(e); + } catch (IOException e) { + log.error("/dev/urandom does not appear to be readable"); + throw new RuntimeException(e); + } } - } - private final DataInputStream dis; + private final DataInputStream dis; - public LinuxSecureRandom() { - // DataInputStream is not thread safe, so each random object has its own. - dis = new DataInputStream(urandom); - } + public LinuxSecureRandom() { + // DataInputStream is not thread safe, so each random object has its own. + dis = new DataInputStream(urandom); + } - @Override - protected void engineSetSeed(byte[] bytes) { - // Ignore. - } + @Override + protected void engineSetSeed(byte[] bytes) { + // Ignore. + } - @Override - protected void engineNextBytes(byte[] bytes) { - try { - dis.readFully(bytes); // This will block until all the bytes can be read. - } catch (IOException e) { - throw new RuntimeException(e); // Fatal error. Do not attempt to recover from this. + @Override + protected void engineNextBytes(byte[] bytes) { + try { + dis.readFully(bytes); // This will block until all the bytes can be read. + } catch (IOException e) { + throw new RuntimeException(e); // Fatal error. Do not attempt to recover from this. + } } - } - @Override - protected byte[] engineGenerateSeed(int i) { - byte[] bits = new byte[i]; - engineNextBytes(bits); - return bits; - } + @Override + protected byte[] engineGenerateSeed(int i) { + byte[] bits = new byte[i]; + engineNextBytes(bits); + return bits; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/MnemonicUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/MnemonicUtils.java index 6b5fc3c87..83b8af101 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/MnemonicUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/MnemonicUtils.java @@ -19,238 +19,238 @@ */ public class MnemonicUtils { - private static final int SEED_ITERATIONS = 2048; - private static final int SEED_KEY_SIZE = 512; - private static List WORD_LIST = null; - - /** - * The mnemonic must encode entropy in a multiple of 32 bits. With more entropy security is - * improved but the sentence length increases. We refer to the initial entropy length as ENT. The - * allowed size of ENT is 128-256 bits. - * - *

Mnemonic generation algorithm

- * - * Given a randomly generated initial entropy of size ENT, first a checksum is generated by taking - * the first {@code ENT / 32} bits of its SHA256 hash. This checksum is appended to the end of the - * initial entropy. Next, these concatenated bits are split into groups of 11 bits, each encoding - * a number from 0-2047, serving as an index into a wordlist. Finally, we convert these numbers - * into words and use the joined words as a mnemonic sentence. - * - * @param initialEntropy The initial entropy to generate mnemonic from - * @return The generated mnemonic - * @throws IllegalArgumentException If the given entropy is invalid - * @throws IllegalStateException If the word list has not been loaded - */ - public static String generateMnemonic(byte[] initialEntropy) { - if (WORD_LIST == null) { - WORD_LIST = populateWordList(); + private static final int SEED_ITERATIONS = 2048; + private static final int SEED_KEY_SIZE = 512; + private static List WORD_LIST = null; + + /** + * The mnemonic must encode entropy in a multiple of 32 bits. With more entropy security is + * improved but the sentence length increases. We refer to the initial entropy length as ENT. + * The allowed size of ENT is 128-256 bits. + * + *

Mnemonic generation algorithm

+ * + * Given a randomly generated initial entropy of size ENT, first a checksum is generated by + * taking the first {@code ENT / 32} bits of its SHA256 hash. This checksum is appended to the + * end of the initial entropy. Next, these concatenated bits are split into groups of 11 bits, + * each encoding a number from 0-2047, serving as an index into a wordlist. Finally, we convert + * these numbers into words and use the joined words as a mnemonic sentence. + * + * @param initialEntropy The initial entropy to generate mnemonic from + * @return The generated mnemonic + * @throws IllegalArgumentException If the given entropy is invalid + * @throws IllegalStateException If the word list has not been loaded + */ + public static String generateMnemonic(byte[] initialEntropy) { + if (WORD_LIST == null) { + WORD_LIST = populateWordList(); + } + validateEntropy(initialEntropy); + + int ent = initialEntropy.length * 8; + int checksumLength = ent / 32; + + byte checksum = calculateChecksum(initialEntropy); + boolean[] bits = convertToBits(initialEntropy, checksum); + + int iterations = (ent + checksumLength) / 11; + StringBuilder mnemonicBuilder = new StringBuilder(); + for (int i = 0; i < iterations; i++) { + int index = toInt(nextElevenBits(bits, i)); + mnemonicBuilder.append(WORD_LIST.get(index)); + + boolean notLastIteration = i < iterations - 1; + if (notLastIteration) { + mnemonicBuilder.append(" "); + } + } + + return mnemonicBuilder.toString(); } - validateEntropy(initialEntropy); - int ent = initialEntropy.length * 8; - int checksumLength = ent / 32; - - byte checksum = calculateChecksum(initialEntropy); - boolean[] bits = convertToBits(initialEntropy, checksum); - - int iterations = (ent + checksumLength) / 11; - StringBuilder mnemonicBuilder = new StringBuilder(); - for (int i = 0; i < iterations; i++) { - int index = toInt(nextElevenBits(bits, i)); - mnemonicBuilder.append(WORD_LIST.get(index)); - - boolean notLastIteration = i < iterations - 1; - if (notLastIteration) { - mnemonicBuilder.append(" "); - } + /** + * Create entropy from the mnemonic. + * + * @param mnemonic The input mnemonic which should be 128-160 bits in length containing only + * valid words + * @return Byte array representation of the entropy + */ + public static byte[] generateEntropy(String mnemonic) { + if (WORD_LIST == null) { + WORD_LIST = populateWordList(); + } + final BitSet bits = new BitSet(); + final int size = mnemonicToBits(mnemonic, bits); + if (size == 0) { + throw new IllegalArgumentException("Empty mnemonic"); + } + + final int ent = 32 * size / 33; + if (ent % 8 != 0) { + throw new IllegalArgumentException("Wrong mnemonic size"); + } + final byte[] entropy = new byte[ent / 8]; + for (int i = 0; i < entropy.length; i++) { + entropy[i] = readByte(bits, i); + } + validateEntropy(entropy); + + final byte expectedChecksum = calculateChecksum(entropy); + final byte actualChecksum = readByte(bits, entropy.length); + if (expectedChecksum != actualChecksum) { + throw new IllegalArgumentException("Wrong checksum"); + } + + return entropy; } - return mnemonicBuilder.toString(); - } - - /** - * Create entropy from the mnemonic. - * - * @param mnemonic The input mnemonic which should be 128-160 bits in length containing only valid - * words - * @return Byte array representation of the entropy - */ - public static byte[] generateEntropy(String mnemonic) { - if (WORD_LIST == null) { - WORD_LIST = populateWordList(); - } - final BitSet bits = new BitSet(); - final int size = mnemonicToBits(mnemonic, bits); - if (size == 0) { - throw new IllegalArgumentException("Empty mnemonic"); + /** + * To create a binary seed from the mnemonic, we use the PBKDF2 function with a mnemonic + * sentence (in UTF-8 NFKD) used as the password and the string "mnemonic" + passphrase (again + * in UTF-8 NFKD) used as the salt. The iteration count is set to 2048 and HMAC-SHA512 is used + * as the pseudo-random function. The length of the derived key is 512 bits (= 64 bytes). + * + * @param mnemonic The input mnemonic which should be 128-160 bits in length containing only + * valid words + * @param passphrase The passphrase which will be used as part of salt for PBKDF2 function + * @return Byte array representation of the generated seed + */ + public static byte[] generateSeed(String mnemonic, String passphrase) { + if (isMnemonicEmpty(mnemonic)) { + throw new IllegalArgumentException("Mnemonic is required to generate a seed"); + } + passphrase = passphrase == null ? "" : passphrase; + + String salt = String.format("mnemonic%s", passphrase); + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA512Digest()); + gen.init(mnemonic.getBytes(UTF_8), salt.getBytes(UTF_8), SEED_ITERATIONS); + + return ((KeyParameter) gen.generateDerivedParameters(SEED_KEY_SIZE)).getKey(); } - final int ent = 32 * size / 33; - if (ent % 8 != 0) { - throw new IllegalArgumentException("Wrong mnemonic size"); + public static boolean validateMnemonic(String mnemonic) { + try { + generateEntropy(mnemonic); + return true; + } catch (Exception ex) { + return false; + } } - final byte[] entropy = new byte[ent / 8]; - for (int i = 0; i < entropy.length; i++) { - entropy[i] = readByte(bits, i); + + private static boolean isMnemonicEmpty(String mnemonic) { + return mnemonic == null || mnemonic.trim().isEmpty(); } - validateEntropy(entropy); - final byte expectedChecksum = calculateChecksum(entropy); - final byte actualChecksum = readByte(bits, entropy.length); - if (expectedChecksum != actualChecksum) { - throw new IllegalArgumentException("Wrong checksum"); + private static boolean[] nextElevenBits(boolean[] bits, int i) { + int from = i * 11; + int to = from + 11; + return Arrays.copyOfRange(bits, from, to); } - return entropy; - } - - /** - * To create a binary seed from the mnemonic, we use the PBKDF2 function with a mnemonic sentence - * (in UTF-8 NFKD) used as the password and the string "mnemonic" + passphrase (again in UTF-8 - * NFKD) used as the salt. The iteration count is set to 2048 and HMAC-SHA512 is used as the - * pseudo-random function. The length of the derived key is 512 bits (= 64 bytes). - * - * @param mnemonic The input mnemonic which should be 128-160 bits in length containing only valid - * words - * @param passphrase The passphrase which will be used as part of salt for PBKDF2 function - * @return Byte array representation of the generated seed - */ - public static byte[] generateSeed(String mnemonic, String passphrase) { - if (isMnemonicEmpty(mnemonic)) { - throw new IllegalArgumentException("Mnemonic is required to generate a seed"); + private static void validateEntropy(byte[] entropy) { + if (entropy == null) { + throw new IllegalArgumentException("Entropy is required"); + } + + int ent = entropy.length * 8; + if (ent < 128 || ent > 256 || ent % 32 != 0) { + throw new IllegalArgumentException( + "The allowed size of ENT is 128-256 bits of " + "multiples of 32"); + } } - passphrase = passphrase == null ? "" : passphrase; - String salt = String.format("mnemonic%s", passphrase); - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA512Digest()); - gen.init(mnemonic.getBytes(UTF_8), salt.getBytes(UTF_8), SEED_ITERATIONS); + private static boolean[] convertToBits(byte[] initialEntropy, byte checksum) { + int ent = initialEntropy.length * 8; + int checksumLength = ent / 32; + int totalLength = ent + checksumLength; + boolean[] bits = new boolean[totalLength]; - return ((KeyParameter) gen.generateDerivedParameters(SEED_KEY_SIZE)).getKey(); - } + for (int i = 0; i < initialEntropy.length; i++) { + for (int j = 0; j < 8; j++) { + byte b = initialEntropy[i]; + bits[8 * i + j] = toBit(b, j); + } + } - public static boolean validateMnemonic(String mnemonic) { - try { - generateEntropy(mnemonic); - return true; - } catch (Exception ex) { - return false; + for (int i = 0; i < checksumLength; i++) { + bits[ent + i] = toBit(checksum, i); + } + + return bits; } - } - private static boolean isMnemonicEmpty(String mnemonic) { - return mnemonic == null || mnemonic.trim().isEmpty(); - } + private static boolean toBit(byte value, int index) { + return ((value >>> (7 - index)) & 1) > 0; + } - private static boolean[] nextElevenBits(boolean[] bits, int i) { - int from = i * 11; - int to = from + 11; - return Arrays.copyOfRange(bits, from, to); - } + private static int toInt(boolean[] bits) { + int value = 0; + for (int i = 0; i < bits.length; i++) { + boolean isSet = bits[i]; + if (isSet) { + value += 1 << bits.length - i - 1; + } + } - private static void validateEntropy(byte[] entropy) { - if (entropy == null) { - throw new IllegalArgumentException("Entropy is required"); + return value; } - int ent = entropy.length * 8; - if (ent < 128 || ent > 256 || ent % 32 != 0) { - throw new IllegalArgumentException( - "The allowed size of ENT is 128-256 bits of " + "multiples of 32"); - } - } - - private static boolean[] convertToBits(byte[] initialEntropy, byte checksum) { - int ent = initialEntropy.length * 8; - int checksumLength = ent / 32; - int totalLength = ent + checksumLength; - boolean[] bits = new boolean[totalLength]; - - for (int i = 0; i < initialEntropy.length; i++) { - for (int j = 0; j < 8; j++) { - byte b = initialEntropy[i]; - bits[8 * i + j] = toBit(b, j); - } + private static int mnemonicToBits(String mnemonic, BitSet bits) { + int bit = 0; + final StringTokenizer tokenizer = new StringTokenizer(mnemonic, " "); + while (tokenizer.hasMoreTokens()) { + final String word = tokenizer.nextToken(); + final int index = WORD_LIST.indexOf(word); + if (index < 0) { + throw new IllegalArgumentException("Illegal word: " + word); + } + for (int k = 0; k < 11; k++) { + bits.set(bit++, isBitSet(index, 10 - k)); + } + } + return bit; } - for (int i = 0; i < checksumLength; i++) { - bits[ent + i] = toBit(checksum, i); + private static byte readByte(BitSet bits, int startByte) { + byte res = 0; + for (int k = 0; k < 8; k++) { + if (bits.get(startByte * 8 + k)) { + res = (byte) ((res & 0xff) | (1 << (7 - k))); + } + } + return res; } - return bits; - } + private static boolean isBitSet(int n, int k) { + return ((n >> k) & 1) == 1; + } - private static boolean toBit(byte value, int index) { - return ((value >>> (7 - index)) & 1) > 0; - } + private static byte calculateChecksum(byte[] initialEntropy) { + int ent = initialEntropy.length * 8; + byte mask = (byte) (0xff << 8 - ent / 32); + byte[] bytes = Hash.sha256(initialEntropy); - private static int toInt(boolean[] bits) { - int value = 0; - for (int i = 0; i < bits.length; i++) { - boolean isSet = bits[i]; - if (isSet) { - value += 1 << bits.length - i - 1; - } + return (byte) (bytes[0] & mask); } - return value; - } - - private static int mnemonicToBits(String mnemonic, BitSet bits) { - int bit = 0; - final StringTokenizer tokenizer = new StringTokenizer(mnemonic, " "); - while (tokenizer.hasMoreTokens()) { - final String word = tokenizer.nextToken(); - final int index = WORD_LIST.indexOf(word); - if (index < 0) { - throw new IllegalArgumentException("Illegal word: " + word); - } - for (int k = 0; k < 11; k++) { - bits.set(bit++, isBitSet(index, 10 - k)); - } - } - return bit; - } - - private static byte readByte(BitSet bits, int startByte) { - byte res = 0; - for (int k = 0; k < 8; k++) { - if (bits.get(startByte * 8 + k)) { - res = (byte) ((res & 0xff) | (1 << (7 - k))); - } - } - return res; - } - - private static boolean isBitSet(int n, int k) { - return ((n >> k) & 1) == 1; - } - - private static byte calculateChecksum(byte[] initialEntropy) { - int ent = initialEntropy.length * 8; - byte mask = (byte) (0xff << 8 - ent / 32); - byte[] bytes = Hash.sha256(initialEntropy); - - return (byte) (bytes[0] & mask); - } - - private static List populateWordList() { - InputStream inputStream = - Thread.currentThread() - .getContextClassLoader() - .getResourceAsStream("en-mnemonic-word-list.txt"); - try { - return readAllLines(inputStream); - } catch (Exception e) { - throw new IllegalStateException(e); + private static List populateWordList() { + InputStream inputStream = + Thread.currentThread() + .getContextClassLoader() + .getResourceAsStream("en-mnemonic-word-list.txt"); + try { + return readAllLines(inputStream); + } catch (Exception e) { + throw new IllegalStateException(e); + } } - } - private static List readAllLines(InputStream inputStream) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); - List data = new ArrayList<>(); - for (String line; (line = br.readLine()) != null; ) { - data.add(line); + private static List readAllLines(InputStream inputStream) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); + List data = new ArrayList<>(); + for (String line; (line = br.readLine()) != null; ) { + data.add(line); + } + return data; } - return data; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/RawTransaction.java b/src/main/java/org/fisco/bcos/web3j/crypto/RawTransaction.java index b6048c82f..4d144921f 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/RawTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/RawTransaction.java @@ -12,111 +12,112 @@ */ public class RawTransaction implements Serializable { - private static final long serialVersionUID = -5580814755985097996L; - private BigInteger randomid; - private BigInteger gasPrice; - private BigInteger gasLimit; - private BigInteger blockLimit; - private String to; - private BigInteger value; - private String data; - private BigInteger version = TransactionConstant.version; - - protected RawTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - BigInteger value, - String data) { - this.randomid = randomid; - this.gasPrice = gasPrice; - this.gasLimit = gasLimit; - this.blockLimit = blockLimit; - - this.to = to; - - this.value = value; - - if (data != null) { - this.data = Numeric.cleanHexPrefix(data); + private static final long serialVersionUID = -5580814755985097996L; + private BigInteger randomid; + private BigInteger gasPrice; + private BigInteger gasLimit; + private BigInteger blockLimit; + private String to; + private BigInteger value; + private String data; + private BigInteger version = TransactionConstant.version; + + protected RawTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + BigInteger value, + String data) { + this.randomid = randomid; + this.gasPrice = gasPrice; + this.gasLimit = gasLimit; + this.blockLimit = blockLimit; + + this.to = to; + + this.value = value; + + if (data != null) { + this.data = Numeric.cleanHexPrefix(data); + } + } + + public static RawTransaction createContractTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + BigInteger value, + String init) { + + return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, "", value, init); + } + + public static RawTransaction createEtherTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + BigInteger value) { + + return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, ""); + } + + public static RawTransaction createTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + String data) { + return createTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, BigInteger.ZERO, data); + } + + public static RawTransaction createTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + BigInteger value, + String data) { + + return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data); + } + + public BigInteger getRandomid() { + return randomid; + } + + public BigInteger getGasPrice() { + return gasPrice; + } + + public BigInteger getGasLimit() { + return gasLimit; + } + + public BigInteger getBlockLimit() { + return blockLimit; + } + + public String getTo() { + return to; + } + + public BigInteger getValue() { + return value; + } + + public String getData() { + return data; + } + + public BigInteger getVersion() { + return version; } - } - - public static RawTransaction createContractTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - BigInteger value, - String init) { - - return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, "", value, init); - } - - public static RawTransaction createEtherTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - BigInteger value) { - - return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, ""); - } - - public static RawTransaction createTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - String data) { - return createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, BigInteger.ZERO, data); - } - - public static RawTransaction createTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - BigInteger value, - String data) { - - return new RawTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data); - } - - public BigInteger getRandomid() { - return randomid; - } - - public BigInteger getGasPrice() { - return gasPrice; - } - - public BigInteger getGasLimit() { - return gasLimit; - } - - public BigInteger getBlockLimit() { - return blockLimit; - } - - public String getTo() { - return to; - } - - public BigInteger getValue() { - return value; - } - - public String getData() { - return data; - } - - public BigInteger getVersion() { - return version; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/SHA3Digest.java b/src/main/java/org/fisco/bcos/web3j/crypto/SHA3Digest.java index 01598b5f5..f454b8d96 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/SHA3Digest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/SHA3Digest.java @@ -5,24 +5,24 @@ /** Created by websterchen on 2018/3/21. */ public class SHA3Digest implements HashInterface { - public SHA3Digest() {} + public SHA3Digest() {} - @Override - public String hash(String hexInput) { - byte[] bytes = Numeric.hexStringToByteArray(hexInput); - byte[] result = hash(bytes); - return Numeric.toHexString(result); - } + @Override + public String hash(String hexInput) { + byte[] bytes = Numeric.hexStringToByteArray(hexInput); + byte[] result = hash(bytes); + return Numeric.toHexString(result); + } - @Override - public byte[] hash(byte[] input, int offset, int length) { - Keccak.DigestKeccak kecc = new Keccak.Digest256(); - kecc.update(input, offset, length); - return kecc.digest(); - } + @Override + public byte[] hash(byte[] input, int offset, int length) { + Keccak.DigestKeccak kecc = new Keccak.Digest256(); + kecc.update(input, offset, length); + return kecc.digest(); + } - @Override - public byte[] hash(byte[] input) { - return hash(input, 0, input.length); - } + @Override + public byte[] hash(byte[] input) { + return hash(input, 0, input.length); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/SecureRandomUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/SecureRandomUtils.java index 7c57fa007..9e22ab26f 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/SecureRandomUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/SecureRandomUtils.java @@ -10,30 +10,30 @@ */ final class SecureRandomUtils { - private static final SecureRandom SECURE_RANDOM; + private static final SecureRandom SECURE_RANDOM; - static { - if (isAndroidRuntime()) { - new LinuxSecureRandom(); + static { + if (isAndroidRuntime()) { + new LinuxSecureRandom(); + } + SECURE_RANDOM = new SecureRandom(); } - SECURE_RANDOM = new SecureRandom(); - } - static SecureRandom secureRandom() { - return SECURE_RANDOM; - } + static SecureRandom secureRandom() { + return SECURE_RANDOM; + } - // Taken from BitcoinJ implementation - // https://github.com/bitcoinj/bitcoinj/blob/3cb1f6c6c589f84fe6e1fb56bf26d94cccc85429/core/src/main/java/org/bitcoinj/core/Utils.java#L573 - private static int isAndroid = -1; + // Taken from BitcoinJ implementation + // https://github.com/bitcoinj/bitcoinj/blob/3cb1f6c6c589f84fe6e1fb56bf26d94cccc85429/core/src/main/java/org/bitcoinj/core/Utils.java#L573 + private static int isAndroid = -1; - static boolean isAndroidRuntime() { - if (isAndroid == -1) { - final String runtime = System.getProperty("java.runtime.name"); - isAndroid = (runtime != null && runtime.equals("Android Runtime")) ? 1 : 0; + static boolean isAndroidRuntime() { + if (isAndroid == -1) { + final String runtime = System.getProperty("java.runtime.name"); + isAndroid = (runtime != null && runtime.equals("Android Runtime")) ? 1 : 0; + } + return isAndroid == 1; } - return isAndroid == 1; - } - private SecureRandomUtils() {} + private SecureRandomUtils() {} } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/Sign.java b/src/main/java/org/fisco/bcos/web3j/crypto/Sign.java index 8334501f8..9497d7a33 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/Sign.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/Sign.java @@ -22,331 +22,336 @@ * BitcoinJ ECKey implementation. */ public class Sign { - private static SignInterface signInterface = new ECDSASign(); - - public static SignInterface getSignInterface() { - return signInterface; - } - - public static void setSignInterface(SignInterface signInterface) { - Sign.signInterface = signInterface; - } - - private static final X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1"); - static final ECDomainParameters CURVE = - new ECDomainParameters( - CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(), CURVE_PARAMS.getH()); - static final BigInteger HALF_CURVE_ORDER = CURVE_PARAMS.getN().shiftRight(1); - - static final String MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; - - static byte[] getEthereumMessagePrefix(int messageLength) { - return MESSAGE_PREFIX.concat(String.valueOf(messageLength)).getBytes(); - } - - static byte[] getEthereumMessageHash(byte[] message) { - byte[] prefix = getEthereumMessagePrefix(message.length); - - byte[] result = new byte[prefix.length + message.length]; - System.arraycopy(prefix, 0, result, 0, prefix.length); - System.arraycopy(message, 0, result, prefix.length, message.length); - - return Hash.sha3(result); - } - - // public static SignatureData signPrefixedMessage(byte[] message, ECKeyPair keyPair) { - // return signMessage(getEthereumMessageHash(message), keyPair, false); - // } - - // very important add 0x19 Ethreum - // public static SignatureData signMessage(byte[] message, ECKeyPair keyPair) { - // return signMessage(message, keyPair, true); - // } - - // public static SignatureData signMessage(byte[] message, ECKeyPair keyPair, boolean - // needToHash) { - // BigInteger publicKey = keyPair.getPublicKey(); - // byte[] messageHash; - // if (needToHash) { - // messageHash = Hash.sha3(message); - // } else { - // messageHash = message; - // } - // - // ECDSASignature sig = keyPair.sign(messageHash); - // // Now we have to work backwards to figure out the recId needed to recover the - // signature. - // int recId = -1; - // for (int i = 0; i < 4; i++) { - // BigInteger k = recoverFromSignature(i, sig, messageHash); - // if (k != null && k.equals(publicKey)) { - // recId = i; - // break; - // } - // } - // if (recId == -1) { - // throw new RuntimeException( - // "Could not construct a recoverable key. Are your credentials valid?"); - // } - // - // int headerByte = recId + 27; - // - // // 1 header + 32 bytes for R + 32 bytes for S - // byte v = (byte) headerByte; - // byte[] r = Numeric.toBytesPadded(sig.r, 32); - // byte[] s = Numeric.toBytesPadded(sig.s, 32); - // - // return new SignatureData(v, r, s); - // } - - /** - * Given the components of a signature and a selector value, recover and return the public key - * that generated the signature according to the algorithm in SEC1v2 section 4.1.6. - * - *

The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the - * correct one. Because the key recovery operation yields multiple potential keys, the correct key - * must either be stored alongside the signature, or you must be willing to try each recId in turn - * until you find one that outputs the key you are expecting. - * - *

If this method returns null it means recovery was not possible and recId should be iterated. - * - *

Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, - * and if the output is null OR a key that is not the one you expect, you try again with the next - * recId. - * - * @param recId Which possible key to recover. - * @param sig the R and S components of the signature, wrapped. - * @param message Hash of the data that was signed. - * @return An ECKey containing only the public part, or null if recovery wasn't possible. - */ - public static BigInteger recoverFromSignature(int recId, ECDSASignature sig, byte[] message) { - verifyPrecondition(recId >= 0, "recId must be positive"); - verifyPrecondition(sig.r.signum() >= 0, "r must be positive"); - verifyPrecondition(sig.s.signum() >= 0, "s must be positive"); - verifyPrecondition(message != null, "message cannot be null"); - - // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) - // 1.1 Let x = r + jn - BigInteger n = CURVE.getN(); // Curve order. - BigInteger i = BigInteger.valueOf((long) recId / 2); - BigInteger x = sig.r.add(i.multiply(n)); - // 1.2. Convert the integer x to an octet string X of length mlen using the conversion - // routine specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉. - // 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R - // using the conversion routine specified in Section 2.3.4. If this conversion - // routine outputs "invalid", then do another iteration of Step 1. - // - // More concisely, what these points mean is to use X as a compressed public key. - BigInteger prime = SecP256K1Curve.q; - if (x.compareTo(prime) >= 0) { - // Cannot have point co-ordinates larger than this as everything takes place modulo Q. - return null; + private static SignInterface signInterface = new ECDSASign(); + + public static SignInterface getSignInterface() { + return signInterface; } - // Compressed keys require you to know an extra bit of data about the y-coord as there are - // two possibilities. So it's encoded in the recId. - ECPoint R = decompressKey(x, (recId & 1) == 1); - // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers - // responsibility). - if (!R.multiply(n).isInfinity()) { - return null; + + public static void setSignInterface(SignInterface signInterface) { + Sign.signInterface = signInterface; } - // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. - BigInteger e = new BigInteger(1, message); - // 1.6. For k from 1 to 2 do the following. (loop is outside this function via - // iterating recId) - // 1.6.1. Compute a candidate public key as: - // Q = mi(r) * (sR - eG) - // - // Where mi(x) is the modular multiplicative inverse. We transform this into the following: - // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) - // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). - // In the above equation ** is point multiplication and + is point addition (the EC group - // operator). - // - // We can find the additive inverse by subtracting e from zero then taking the mod. For - // example the additive inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and - // -3 mod 11 = 8. - BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); - BigInteger rInv = sig.r.modInverse(n); - BigInteger srInv = rInv.multiply(sig.s).mod(n); - BigInteger eInvrInv = rInv.multiply(eInv).mod(n); - ECPoint q = ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv); - - byte[] qBytes = q.getEncoded(false); - // We remove the prefix - return new BigInteger(1, Arrays.copyOfRange(qBytes, 1, qBytes.length)); - } - - /** Decompress a compressed public key (x co-ord and low-bit of y-coord). */ - private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { - X9IntegerConverter x9 = new X9IntegerConverter(); - byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve())); - compEnc[0] = (byte) (yBit ? 0x03 : 0x02); - return CURVE.getCurve().decodePoint(compEnc); - } - - /** - * Given an arbitrary piece of text and an Ethereum message signature encoded in bytes, returns - * the public key that was used to sign it. This can then be compared to the expected public key - * to determine if the signature was correct. - * - * @param message RLP encoded message. - * @param signatureData The message signature components - * @return the public key used to sign the message - * @throws SignatureException If the public key could not be recovered or if there was a signature - * format error. - */ - public static BigInteger signedMessageToKey(byte[] message, SignatureData signatureData) - throws SignatureException { - return signedMessageHashToKey(Hash.sha3(message), signatureData); - } - - /** - * Given an arbitrary message and an Ethereum message signature encoded in bytes, returns the - * public key that was used to sign it. This can then be compared to the expected public key to - * determine if the signature was correct. - * - * @param message The message. - * @param signatureData The message signature components - * @return the public key used to sign the message - * @throws SignatureException If the public key could not be recovered or if there was a signature - * format error. - */ - public static BigInteger signedPrefixedMessageToKey(byte[] message, SignatureData signatureData) - throws SignatureException { - return signedMessageHashToKey(getEthereumMessageHash(message), signatureData); - } - - static BigInteger signedMessageHashToKey(byte[] messageHash, SignatureData signatureData) - throws SignatureException { - - byte[] r = signatureData.getR(); - byte[] s = signatureData.getS(); - verifyPrecondition(r != null && r.length == 32, "r must be 32 bytes"); - verifyPrecondition(s != null && s.length == 32, "s must be 32 bytes"); - - int header = signatureData.getV() & 0xFF; - // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, - // 0x1D = second key with even y, 0x1E = second key with odd y - if (header < 27 || header > 34) { - throw new SignatureException("Header byte out of range: " + header); + + private static final X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1"); + static final ECDomainParameters CURVE = + new ECDomainParameters( + CURVE_PARAMS.getCurve(), + CURVE_PARAMS.getG(), + CURVE_PARAMS.getN(), + CURVE_PARAMS.getH()); + static final BigInteger HALF_CURVE_ORDER = CURVE_PARAMS.getN().shiftRight(1); + + static final String MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; + + static byte[] getEthereumMessagePrefix(int messageLength) { + return MESSAGE_PREFIX.concat(String.valueOf(messageLength)).getBytes(); } - ECDSASignature sig = - new ECDSASignature( - new BigInteger(1, signatureData.getR()), new BigInteger(1, signatureData.getS())); + static byte[] getEthereumMessageHash(byte[] message) { + byte[] prefix = getEthereumMessagePrefix(message.length); + + byte[] result = new byte[prefix.length + message.length]; + System.arraycopy(prefix, 0, result, 0, prefix.length); + System.arraycopy(message, 0, result, prefix.length, message.length); - int recId = header - 27; - BigInteger key = recoverFromSignature(recId, sig, messageHash); - if (key == null) { - throw new SignatureException("Could not recover public key from signature"); + return Hash.sha3(result); } - return key; - } - - /** - * Returns public key from the given private key. - * - * @param privKey the private key to derive the public key from - * @return BigInteger encoded public key - */ - public static BigInteger publicKeyFromPrivate(BigInteger privKey) { - ECPoint point = publicPointFromPrivate(privKey); - - byte[] encoded = point.getEncoded(false); - return new BigInteger(1, Arrays.copyOfRange(encoded, 1, encoded.length)); // remove prefix - } - - /** - * Returns public key point from the given private key. - * - * @param privKey the private key to derive the public key from - * @return ECPoint public key - */ - public static ECPoint publicPointFromPrivate(BigInteger privKey) { - /* - * TODO: FixedPointCombMultiplier currently doesn't support scalars longer than the group - * order, but that could change in future versions. + + // public static SignatureData signPrefixedMessage(byte[] message, ECKeyPair keyPair) { + // return signMessage(getEthereumMessageHash(message), keyPair, false); + // } + + // very important add 0x19 Ethreum + // public static SignatureData signMessage(byte[] message, ECKeyPair keyPair) { + // return signMessage(message, keyPair, true); + // } + + // public static SignatureData signMessage(byte[] message, ECKeyPair keyPair, boolean + // needToHash) { + // BigInteger publicKey = keyPair.getPublicKey(); + // byte[] messageHash; + // if (needToHash) { + // messageHash = Hash.sha3(message); + // } else { + // messageHash = message; + // } + // + // ECDSASignature sig = keyPair.sign(messageHash); + // // Now we have to work backwards to figure out the recId needed to recover the + // signature. + // int recId = -1; + // for (int i = 0; i < 4; i++) { + // BigInteger k = recoverFromSignature(i, sig, messageHash); + // if (k != null && k.equals(publicKey)) { + // recId = i; + // break; + // } + // } + // if (recId == -1) { + // throw new RuntimeException( + // "Could not construct a recoverable key. Are your credentials valid?"); + // } + // + // int headerByte = recId + 27; + // + // // 1 header + 32 bytes for R + 32 bytes for S + // byte v = (byte) headerByte; + // byte[] r = Numeric.toBytesPadded(sig.r, 32); + // byte[] s = Numeric.toBytesPadded(sig.s, 32); + // + // return new SignatureData(v, r, s); + // } + + /** + * Given the components of a signature and a selector value, recover and return the public key + * that generated the signature according to the algorithm in SEC1v2 section 4.1.6. + * + *

The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the + * correct one. Because the key recovery operation yields multiple potential keys, the correct + * key must either be stored alongside the signature, or you must be willing to try each recId + * in turn until you find one that outputs the key you are expecting. + * + *

If this method returns null it means recovery was not possible and recId should be + * iterated. + * + *

Given the above two points, a correct usage of this method is inside a for loop from 0 to + * 3, and if the output is null OR a key that is not the one you expect, you try again with the + * next recId. + * + * @param recId Which possible key to recover. + * @param sig the R and S components of the signature, wrapped. + * @param message Hash of the data that was signed. + * @return An ECKey containing only the public part, or null if recovery wasn't possible. */ - if (privKey.bitLength() > CURVE.getN().bitLength()) { - privKey = privKey.mod(CURVE.getN()); + public static BigInteger recoverFromSignature(int recId, ECDSASignature sig, byte[] message) { + verifyPrecondition(recId >= 0, "recId must be positive"); + verifyPrecondition(sig.r.signum() >= 0, "r must be positive"); + verifyPrecondition(sig.s.signum() >= 0, "s must be positive"); + verifyPrecondition(message != null, "message cannot be null"); + + // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) + // 1.1 Let x = r + jn + BigInteger n = CURVE.getN(); // Curve order. + BigInteger i = BigInteger.valueOf((long) recId / 2); + BigInteger x = sig.r.add(i.multiply(n)); + // 1.2. Convert the integer x to an octet string X of length mlen using the conversion + // routine specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉. + // 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R + // using the conversion routine specified in Section 2.3.4. If this conversion + // routine outputs "invalid", then do another iteration of Step 1. + // + // More concisely, what these points mean is to use X as a compressed public key. + BigInteger prime = SecP256K1Curve.q; + if (x.compareTo(prime) >= 0) { + // Cannot have point co-ordinates larger than this as everything takes place modulo Q. + return null; + } + // Compressed keys require you to know an extra bit of data about the y-coord as there are + // two possibilities. So it's encoded in the recId. + ECPoint R = decompressKey(x, (recId & 1) == 1); + // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers + // responsibility). + if (!R.multiply(n).isInfinity()) { + return null; + } + // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. + BigInteger e = new BigInteger(1, message); + // 1.6. For k from 1 to 2 do the following. (loop is outside this function via + // iterating recId) + // 1.6.1. Compute a candidate public key as: + // Q = mi(r) * (sR - eG) + // + // Where mi(x) is the modular multiplicative inverse. We transform this into the following: + // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) + // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). + // In the above equation ** is point multiplication and + is point addition (the EC group + // operator). + // + // We can find the additive inverse by subtracting e from zero then taking the mod. For + // example the additive inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and + // -3 mod 11 = 8. + BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); + BigInteger rInv = sig.r.modInverse(n); + BigInteger srInv = rInv.multiply(sig.s).mod(n); + BigInteger eInvrInv = rInv.multiply(eInv).mod(n); + ECPoint q = ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv); + + byte[] qBytes = q.getEncoded(false); + // We remove the prefix + return new BigInteger(1, Arrays.copyOfRange(qBytes, 1, qBytes.length)); } - return new FixedPointCombMultiplier().multiply(CURVE.getG(), privKey); - } - - /** - * Returns public key point from the given curve. - * - * @param bits representing the point on the curve - * @return BigInteger encoded public key - */ - public static BigInteger publicFromPoint(byte[] bits) { - return new BigInteger(1, Arrays.copyOfRange(bits, 1, bits.length)); // remove prefix - } - - public static class SignatureData { - private final byte v; - private final byte[] r; - private final byte[] s; - private final byte[] pub; - - public SignatureData(byte v, byte[] r, byte[] s) { - this.v = v; - this.r = r; - this.s = s; - pub = null; + + /** Decompress a compressed public key (x co-ord and low-bit of y-coord). */ + private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { + X9IntegerConverter x9 = new X9IntegerConverter(); + byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve())); + compEnc[0] = (byte) (yBit ? 0x03 : 0x02); + return CURVE.getCurve().decodePoint(compEnc); } - public SignatureData(byte v, byte[] r, byte[] s, byte[] pub) { - this.v = v; - this.r = r; - this.s = s; - this.pub = pub; + /** + * Given an arbitrary piece of text and an Ethereum message signature encoded in bytes, returns + * the public key that was used to sign it. This can then be compared to the expected public key + * to determine if the signature was correct. + * + * @param message RLP encoded message. + * @param signatureData The message signature components + * @return the public key used to sign the message + * @throws SignatureException If the public key could not be recovered or if there was a + * signature format error. + */ + public static BigInteger signedMessageToKey(byte[] message, SignatureData signatureData) + throws SignatureException { + return signedMessageHashToKey(Hash.sha3(message), signatureData); } - public byte getV() { - return v; + /** + * Given an arbitrary message and an Ethereum message signature encoded in bytes, returns the + * public key that was used to sign it. This can then be compared to the expected public key to + * determine if the signature was correct. + * + * @param message The message. + * @param signatureData The message signature components + * @return the public key used to sign the message + * @throws SignatureException If the public key could not be recovered or if there was a + * signature format error. + */ + public static BigInteger signedPrefixedMessageToKey(byte[] message, SignatureData signatureData) + throws SignatureException { + return signedMessageHashToKey(getEthereumMessageHash(message), signatureData); } - public byte[] getR() { - return r; + static BigInteger signedMessageHashToKey(byte[] messageHash, SignatureData signatureData) + throws SignatureException { + + byte[] r = signatureData.getR(); + byte[] s = signatureData.getS(); + verifyPrecondition(r != null && r.length == 32, "r must be 32 bytes"); + verifyPrecondition(s != null && s.length == 32, "s must be 32 bytes"); + + int header = signatureData.getV() & 0xFF; + // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, + // 0x1D = second key with even y, 0x1E = second key with odd y + if (header < 27 || header > 34) { + throw new SignatureException("Header byte out of range: " + header); + } + + ECDSASignature sig = + new ECDSASignature( + new BigInteger(1, signatureData.getR()), + new BigInteger(1, signatureData.getS())); + + int recId = header - 27; + BigInteger key = recoverFromSignature(recId, sig, messageHash); + if (key == null) { + throw new SignatureException("Could not recover public key from signature"); + } + return key; } - public byte[] getS() { - return s; + /** + * Returns public key from the given private key. + * + * @param privKey the private key to derive the public key from + * @return BigInteger encoded public key + */ + public static BigInteger publicKeyFromPrivate(BigInteger privKey) { + ECPoint point = publicPointFromPrivate(privKey); + + byte[] encoded = point.getEncoded(false); + return new BigInteger(1, Arrays.copyOfRange(encoded, 1, encoded.length)); // remove prefix } - public byte[] getPub() { - return pub; + /** + * Returns public key point from the given private key. + * + * @param privKey the private key to derive the public key from + * @return ECPoint public key + */ + public static ECPoint publicPointFromPrivate(BigInteger privKey) { + /* + * TODO: FixedPointCombMultiplier currently doesn't support scalars longer than the group + * order, but that could change in future versions. + */ + if (privKey.bitLength() > CURVE.getN().bitLength()) { + privKey = privKey.mod(CURVE.getN()); + } + return new FixedPointCombMultiplier().multiply(CURVE.getG(), privKey); } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - SignatureData that = (SignatureData) o; - - if (v != that.v) { - return false; - } - if (!Arrays.equals(r, that.r)) { - return false; - } - return Arrays.equals(s, that.s); + /** + * Returns public key point from the given curve. + * + * @param bits representing the point on the curve + * @return BigInteger encoded public key + */ + public static BigInteger publicFromPoint(byte[] bits) { + return new BigInteger(1, Arrays.copyOfRange(bits, 1, bits.length)); // remove prefix } - @Override - public int hashCode() { - int result = (int) v; - result = 31 * result + Arrays.hashCode(r); - result = 31 * result + Arrays.hashCode(s); - result = 63 * result + Arrays.hashCode(pub); - return result; + public static class SignatureData { + private final byte v; + private final byte[] r; + private final byte[] s; + private final byte[] pub; + + public SignatureData(byte v, byte[] r, byte[] s) { + this.v = v; + this.r = r; + this.s = s; + pub = null; + } + + public SignatureData(byte v, byte[] r, byte[] s, byte[] pub) { + this.v = v; + this.r = r; + this.s = s; + this.pub = pub; + } + + public byte getV() { + return v; + } + + public byte[] getR() { + return r; + } + + public byte[] getS() { + return s; + } + + public byte[] getPub() { + return pub; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SignatureData that = (SignatureData) o; + + if (v != that.v) { + return false; + } + if (!Arrays.equals(r, that.r)) { + return false; + } + return Arrays.equals(s, that.s); + } + + @Override + public int hashCode() { + int result = (int) v; + result = 31 * result + Arrays.hashCode(r); + result = 31 * result + Arrays.hashCode(s); + result = 63 * result + Arrays.hashCode(pub); + return result; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/SignInterface.java b/src/main/java/org/fisco/bcos/web3j/crypto/SignInterface.java index 100bb816f..ac2130311 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/SignInterface.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/SignInterface.java @@ -1,5 +1,5 @@ package org.fisco.bcos.web3j.crypto; /** Created by websterchen on 2018/3/22. */ public interface SignInterface { - Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair); + Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/SignedExtendedRawTransaction.java b/src/main/java/org/fisco/bcos/web3j/crypto/SignedExtendedRawTransaction.java index 9c31b012d..9ffe2fdaf 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/SignedExtendedRawTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/SignedExtendedRawTransaction.java @@ -5,72 +5,82 @@ public class SignedExtendedRawTransaction extends ExtendedRawTransaction { - private static final int CHAIN_ID_INC = 35; - private static final int LOWER_REAL_V = 27; + private static final int CHAIN_ID_INC = 35; + private static final int LOWER_REAL_V = 27; - private Sign.SignatureData signatureData; + private Sign.SignatureData signatureData; - public SignedExtendedRawTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - BigInteger value, - String data, - BigInteger chainId, - BigInteger groupId, - String extraData, - Sign.SignatureData signatureData) { - super(randomid, gasPrice, gasLimit, blockLimit, to, value, data,chainId, groupId, extraData); - this.signatureData = signatureData; - } - - public Sign.SignatureData getSignatureData() { - return signatureData; - } + public SignedExtendedRawTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + BigInteger value, + String data, + BigInteger chainId, + BigInteger groupId, + String extraData, + Sign.SignatureData signatureData) { + super( + randomid, + gasPrice, + gasLimit, + blockLimit, + to, + value, + data, + chainId, + groupId, + extraData); + this.signatureData = signatureData; + } - public String getFrom() throws SignatureException { - Integer chainId = getChainId(); - byte[] encodedTransaction; - if (null == chainId) { - encodedTransaction = ExtendedTransactionEncoder.encode(this); - } else { - encodedTransaction = ExtendedTransactionEncoder.encode(this, chainId.byteValue()); + public Sign.SignatureData getSignatureData() { + return signatureData; } - byte v = signatureData.getV(); - byte[] r = signatureData.getR(); - byte[] s = signatureData.getS(); - Sign.SignatureData signatureDataV = new Sign.SignatureData(getRealV(v), r, s); - BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureDataV); - return "0x" + Keys.getAddress(key); - } - public void verify(String from) throws SignatureException { - String actualFrom = getFrom(); - if (!actualFrom.equals(from)) { - throw new SignatureException("from mismatch"); + public String getFrom() throws SignatureException { + Integer chainId = getChainId(); + byte[] encodedTransaction; + if (null == chainId) { + encodedTransaction = ExtendedTransactionEncoder.encode(this); + } else { + encodedTransaction = ExtendedTransactionEncoder.encode(this, chainId.byteValue()); + } + byte v = signatureData.getV(); + byte[] r = signatureData.getR(); + byte[] s = signatureData.getS(); + Sign.SignatureData signatureDataV = new Sign.SignatureData(getRealV(v), r, s); + BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureDataV); + return "0x" + Keys.getAddress(key); } - } - private byte getRealV(byte v) { - if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { - return v; + public void verify(String from) throws SignatureException { + String actualFrom = getFrom(); + if (!actualFrom.equals(from)) { + throw new SignatureException("from mismatch"); + } } - byte realV = LOWER_REAL_V; - int inc = 0; - if ((int) v % 2 == 0) { - inc = 1; + + private byte getRealV(byte v) { + if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { + return v; + } + byte realV = LOWER_REAL_V; + int inc = 0; + if ((int) v % 2 == 0) { + inc = 1; + } + return (byte) (realV + inc); } - return (byte) (realV + inc); - } - public Integer getChainId() { - byte v = signatureData.getV(); - if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { - return null; + public Integer getChainId() { + byte v = signatureData.getV(); + if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { + return null; + } + Integer chainId = (v - CHAIN_ID_INC) / 2; + return chainId; } - Integer chainId = (v - CHAIN_ID_INC) / 2; - return chainId; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/SignedRawTransaction.java b/src/main/java/org/fisco/bcos/web3j/crypto/SignedRawTransaction.java index 040558c0b..f66f5c380 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/SignedRawTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/SignedRawTransaction.java @@ -5,69 +5,69 @@ public class SignedRawTransaction extends RawTransaction { - private static final int CHAIN_ID_INC = 35; - private static final int LOWER_REAL_V = 27; + private static final int CHAIN_ID_INC = 35; + private static final int LOWER_REAL_V = 27; - private Sign.SignatureData signatureData; + private Sign.SignatureData signatureData; - public SignedRawTransaction( - BigInteger randomid, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger blockLimit, - String to, - BigInteger value, - String data, - Sign.SignatureData signatureData) { - super(randomid, gasPrice, gasLimit, blockLimit, to, value, data); - this.signatureData = signatureData; - } - - public Sign.SignatureData getSignatureData() { - return signatureData; - } + public SignedRawTransaction( + BigInteger randomid, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger blockLimit, + String to, + BigInteger value, + String data, + Sign.SignatureData signatureData) { + super(randomid, gasPrice, gasLimit, blockLimit, to, value, data); + this.signatureData = signatureData; + } - public String getFrom() throws SignatureException { - Integer chainId = getChainId(); - byte[] encodedTransaction; - if (null == chainId) { - encodedTransaction = TransactionEncoder.encode(this); - } else { - encodedTransaction = TransactionEncoder.encode(this, chainId.byteValue()); + public Sign.SignatureData getSignatureData() { + return signatureData; } - byte v = signatureData.getV(); - byte[] r = signatureData.getR(); - byte[] s = signatureData.getS(); - Sign.SignatureData signatureDataV = new Sign.SignatureData(getRealV(v), r, s); - BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureDataV); - return "0x" + Keys.getAddress(key); - } - public void verify(String from) throws SignatureException { - String actualFrom = getFrom(); - if (!actualFrom.equals(from)) { - throw new SignatureException("from mismatch"); + public String getFrom() throws SignatureException { + Integer chainId = getChainId(); + byte[] encodedTransaction; + if (null == chainId) { + encodedTransaction = TransactionEncoder.encode(this); + } else { + encodedTransaction = TransactionEncoder.encode(this, chainId.byteValue()); + } + byte v = signatureData.getV(); + byte[] r = signatureData.getR(); + byte[] s = signatureData.getS(); + Sign.SignatureData signatureDataV = new Sign.SignatureData(getRealV(v), r, s); + BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureDataV); + return "0x" + Keys.getAddress(key); } - } - private byte getRealV(byte v) { - if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { - return v; + public void verify(String from) throws SignatureException { + String actualFrom = getFrom(); + if (!actualFrom.equals(from)) { + throw new SignatureException("from mismatch"); + } } - byte realV = LOWER_REAL_V; - int inc = 0; - if ((int) v % 2 == 0) { - inc = 1; + + private byte getRealV(byte v) { + if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { + return v; + } + byte realV = LOWER_REAL_V; + int inc = 0; + if ((int) v % 2 == 0) { + inc = 1; + } + return (byte) (realV + inc); } - return (byte) (realV + inc); - } - public Integer getChainId() { - byte v = signatureData.getV(); - if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { - return null; + public Integer getChainId() { + byte v = signatureData.getV(); + if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) { + return null; + } + Integer chainId = (v - CHAIN_ID_INC) / 2; + return chainId; } - Integer chainId = (v - CHAIN_ID_INC) / 2; - return chainId; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionDecoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionDecoder.java index 6bcb849e1..951ee4d4c 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionDecoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionDecoder.java @@ -8,31 +8,33 @@ public class TransactionDecoder { - public static RawTransaction decode(String hexTransaction) { - byte[] transaction = Numeric.hexStringToByteArray(hexTransaction); - RlpList rlpList = RlpDecoder.decode(transaction); - RlpList values = (RlpList) rlpList.getValues().get(0); - BigInteger randomid = ((RlpString) values.getValues().get(0)).asPositiveBigInteger(); - BigInteger gasPrice = ((RlpString) values.getValues().get(1)).asPositiveBigInteger(); - BigInteger gasLimit = ((RlpString) values.getValues().get(2)).asPositiveBigInteger(); - BigInteger blockLimit = ((RlpString) values.getValues().get(3)).asPositiveBigInteger(); - String to = ((RlpString) values.getValues().get(4)).asString(); - BigInteger value = ((RlpString) values.getValues().get(5)).asPositiveBigInteger(); - String data = ((RlpString) values.getValues().get(6)).asString(); - if (values.getValues().size() > 7) { - byte v = ((RlpString) values.getValues().get(7)).getBytes()[0]; - byte[] r = - Numeric.toBytesPadded( - Numeric.toBigInt(((RlpString) values.getValues().get(8)).getBytes()), 32); - byte[] s = - Numeric.toBytesPadded( - Numeric.toBigInt(((RlpString) values.getValues().get(9)).getBytes()), 32); - Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); - return new SignedRawTransaction( - randomid, gasPrice, gasLimit, blockLimit, to, value, data, signatureData); - } else { - return RawTransaction.createTransaction( - randomid, gasPrice, gasLimit, blockLimit, to, value, data); + public static RawTransaction decode(String hexTransaction) { + byte[] transaction = Numeric.hexStringToByteArray(hexTransaction); + RlpList rlpList = RlpDecoder.decode(transaction); + RlpList values = (RlpList) rlpList.getValues().get(0); + BigInteger randomid = ((RlpString) values.getValues().get(0)).asPositiveBigInteger(); + BigInteger gasPrice = ((RlpString) values.getValues().get(1)).asPositiveBigInteger(); + BigInteger gasLimit = ((RlpString) values.getValues().get(2)).asPositiveBigInteger(); + BigInteger blockLimit = ((RlpString) values.getValues().get(3)).asPositiveBigInteger(); + String to = ((RlpString) values.getValues().get(4)).asString(); + BigInteger value = ((RlpString) values.getValues().get(5)).asPositiveBigInteger(); + String data = ((RlpString) values.getValues().get(6)).asString(); + if (values.getValues().size() > 7) { + byte v = ((RlpString) values.getValues().get(7)).getBytes()[0]; + byte[] r = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.getValues().get(8)).getBytes()), + 32); + byte[] s = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.getValues().get(9)).getBytes()), + 32); + Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); + return new SignedRawTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value, data, signatureData); + } else { + return RawTransaction.createTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value, data); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionEncoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionEncoder.java index ec6bfe3b2..299d3d555 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionEncoder.java @@ -15,84 +15,84 @@ */ public class TransactionEncoder { - public static byte[] signMessage(RawTransaction rawTransaction, Credentials credentials) { - byte[] encodedTransaction = encode(rawTransaction); - Sign.SignatureData signatureData = - Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); + public static byte[] signMessage(RawTransaction rawTransaction, Credentials credentials) { + byte[] encodedTransaction = encode(rawTransaction); + Sign.SignatureData signatureData = + Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); - return encode(rawTransaction, signatureData); - } - - public static byte[] signMessage( - RawTransaction rawTransaction, byte chainId, Credentials credentials) { - byte[] encodedTransaction = encode(rawTransaction, chainId); - Sign.SignatureData signatureData = - Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); + return encode(rawTransaction, signatureData); + } - Sign.SignatureData eip155SignatureData = createEip155SignatureData(signatureData, chainId); - return encode(rawTransaction, eip155SignatureData); - } + public static byte[] signMessage( + RawTransaction rawTransaction, byte chainId, Credentials credentials) { + byte[] encodedTransaction = encode(rawTransaction, chainId); + Sign.SignatureData signatureData = + Sign.getSignInterface().signMessage(encodedTransaction, credentials.getEcKeyPair()); - public static Sign.SignatureData createEip155SignatureData( - Sign.SignatureData signatureData, byte chainId) { - byte v = (byte) (signatureData.getV() + (chainId << 1) + 8); + Sign.SignatureData eip155SignatureData = createEip155SignatureData(signatureData, chainId); + return encode(rawTransaction, eip155SignatureData); + } - return new Sign.SignatureData(v, signatureData.getR(), signatureData.getS()); - } + public static Sign.SignatureData createEip155SignatureData( + Sign.SignatureData signatureData, byte chainId) { + byte v = (byte) (signatureData.getV() + (chainId << 1) + 8); - public static byte[] encode(RawTransaction rawTransaction) { - return encode(rawTransaction, null); - } + return new Sign.SignatureData(v, signatureData.getR(), signatureData.getS()); + } - public static byte[] encode(RawTransaction rawTransaction, byte chainId) { - Sign.SignatureData signatureData = - new Sign.SignatureData(chainId, new byte[] {}, new byte[] {}); - return encode(rawTransaction, signatureData); - } + public static byte[] encode(RawTransaction rawTransaction) { + return encode(rawTransaction, null); + } - public static byte[] encode(RawTransaction rawTransaction, Sign.SignatureData signatureData) { - List values = asRlpValues(rawTransaction, signatureData); - RlpList rlpList = new RlpList(values); - return RlpEncoder.encode(rlpList); - } + public static byte[] encode(RawTransaction rawTransaction, byte chainId) { + Sign.SignatureData signatureData = + new Sign.SignatureData(chainId, new byte[] {}, new byte[] {}); + return encode(rawTransaction, signatureData); + } - static List asRlpValues( - RawTransaction rawTransaction, Sign.SignatureData signatureData) { - List result = new ArrayList<>(); - result.add(RlpString.create(rawTransaction.getRandomid())); - result.add(RlpString.create(rawTransaction.getGasPrice())); - result.add(RlpString.create(rawTransaction.getGasLimit())); - result.add(RlpString.create(rawTransaction.getBlockLimit())); - // an empty to address (contract creation) should not be encoded as a numeric 0 value - String to = rawTransaction.getTo(); - if (to != null && to.length() > 0) { - // addresses that start with zeros should be encoded with the zeros included, not - // as numeric values - result.add(RlpString.create(Numeric.hexStringToByteArray(to))); - } else { - result.add(RlpString.create("")); + public static byte[] encode(RawTransaction rawTransaction, Sign.SignatureData signatureData) { + List values = asRlpValues(rawTransaction, signatureData); + RlpList rlpList = new RlpList(values); + return RlpEncoder.encode(rlpList); } - result.add(RlpString.create(rawTransaction.getValue())); + static List asRlpValues( + RawTransaction rawTransaction, Sign.SignatureData signatureData) { + List result = new ArrayList<>(); + result.add(RlpString.create(rawTransaction.getRandomid())); + result.add(RlpString.create(rawTransaction.getGasPrice())); + result.add(RlpString.create(rawTransaction.getGasLimit())); + result.add(RlpString.create(rawTransaction.getBlockLimit())); + // an empty to address (contract creation) should not be encoded as a numeric 0 value + String to = rawTransaction.getTo(); + if (to != null && to.length() > 0) { + // addresses that start with zeros should be encoded with the zeros included, not + // as numeric values + result.add(RlpString.create(Numeric.hexStringToByteArray(to))); + } else { + result.add(RlpString.create("")); + } + + result.add(RlpString.create(rawTransaction.getValue())); - // value field will already be hex encoded, so we need to convert into binary first - byte[] data = Numeric.hexStringToByteArray(rawTransaction.getData()); - result.add(RlpString.create(data)); + // value field will already be hex encoded, so we need to convert into binary first + byte[] data = Numeric.hexStringToByteArray(rawTransaction.getData()); + result.add(RlpString.create(data)); - if (signatureData != null) { - if (EncryptType.encryptType == 1) { - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getPub()))); - // logger.debug("RLP-Pub:{},RLP-PubLen:{}",Hex.toHexString(signatureData.getPub()),signatureData.getPub().length); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); - // logger.debug("RLP-R:{},RLP-RLen:{}",Hex.toHexString(signatureData.getR()),signatureData.getR().length); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); - // logger.debug("RLP-S:{},RLP-SLen:{}",Hex.toHexString(signatureData.getS()),signatureData.getS().length); - } else { - result.add(RlpString.create(signatureData.getV())); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); - result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); - } + if (signatureData != null) { + if (EncryptType.encryptType == 1) { + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getPub()))); + // logger.debug("RLP-Pub:{},RLP-PubLen:{}",Hex.toHexString(signatureData.getPub()),signatureData.getPub().length); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); + // logger.debug("RLP-R:{},RLP-RLen:{}",Hex.toHexString(signatureData.getR()),signatureData.getR().length); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); + // logger.debug("RLP-S:{},RLP-SLen:{}",Hex.toHexString(signatureData.getS()),signatureData.getS().length); + } else { + result.add(RlpString.create(signatureData.getV())); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR()))); + result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS()))); + } + } + return result; } - return result; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionUtils.java index b5bca3382..6a4823b0d 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/TransactionUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/TransactionUtils.java @@ -5,55 +5,55 @@ /** Transaction utility functions. */ public class TransactionUtils { - /** - * Utility method to provide the transaction hash for a given transaction. - * - * @param rawTransaction we wish to send - * @param credentials of the sender - * @return encoded transaction hash - */ - public static byte[] generateTransactionHash( - RawTransaction rawTransaction, Credentials credentials) { - byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); - return Hash.sha3(signedMessage); - } + /** + * Utility method to provide the transaction hash for a given transaction. + * + * @param rawTransaction we wish to send + * @param credentials of the sender + * @return encoded transaction hash + */ + public static byte[] generateTransactionHash( + RawTransaction rawTransaction, Credentials credentials) { + byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + return Hash.sha3(signedMessage); + } - /** - * Utility method to provide the transaction hash for a given transaction. - * - * @param rawTransaction we wish to send - * @param chainId of the intended chain - * @param credentials of the sender - * @return encoded transaction hash - */ - public static byte[] generateTransactionHash( - RawTransaction rawTransaction, byte chainId, Credentials credentials) { - byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); - return Hash.sha3(signedMessage); - } + /** + * Utility method to provide the transaction hash for a given transaction. + * + * @param rawTransaction we wish to send + * @param chainId of the intended chain + * @param credentials of the sender + * @return encoded transaction hash + */ + public static byte[] generateTransactionHash( + RawTransaction rawTransaction, byte chainId, Credentials credentials) { + byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); + return Hash.sha3(signedMessage); + } - /** - * Utility method to provide the transaction hash for a given transaction. - * - * @param rawTransaction we wish to send - * @param credentials of the sender - * @return transaction hash as a hex encoded string - */ - public static String generateTransactionHashHexEncoded( - RawTransaction rawTransaction, Credentials credentials) { - return Numeric.toHexString(generateTransactionHash(rawTransaction, credentials)); - } + /** + * Utility method to provide the transaction hash for a given transaction. + * + * @param rawTransaction we wish to send + * @param credentials of the sender + * @return transaction hash as a hex encoded string + */ + public static String generateTransactionHashHexEncoded( + RawTransaction rawTransaction, Credentials credentials) { + return Numeric.toHexString(generateTransactionHash(rawTransaction, credentials)); + } - /** - * Utility method to provide the transaction hash for a given transaction. - * - * @param rawTransaction we wish to send - * @param chainId of the intended chain - * @param credentials of the sender - * @return transaction hash as a hex encoded string - */ - public static String generateTransactionHashHexEncoded( - RawTransaction rawTransaction, byte chainId, Credentials credentials) { - return Numeric.toHexString(generateTransactionHash(rawTransaction, chainId, credentials)); - } + /** + * Utility method to provide the transaction hash for a given transaction. + * + * @param rawTransaction we wish to send + * @param chainId of the intended chain + * @param credentials of the sender + * @return transaction hash as a hex encoded string + */ + public static String generateTransactionHashHexEncoded( + RawTransaction rawTransaction, byte chainId, Credentials credentials) { + return Numeric.toHexString(generateTransactionHash(rawTransaction, chainId, credentials)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/Wallet.java b/src/main/java/org/fisco/bcos/web3j/crypto/Wallet.java index b5ce62844..44ec7d34d 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/Wallet.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/Wallet.java @@ -44,203 +44,210 @@ */ public class Wallet { - private static SecureRandom SECURE_RANDOM = new SecureRandom(); + private static SecureRandom SECURE_RANDOM = new SecureRandom(); - private static final int N_LIGHT = 1 << 12; - private static final int P_LIGHT = 6; + private static final int N_LIGHT = 1 << 12; + private static final int P_LIGHT = 6; - private static final int N_STANDARD = 1 << 18; - private static final int P_STANDARD = 1; + private static final int N_STANDARD = 1 << 18; + private static final int P_STANDARD = 1; - private static final int R = 8; - private static final int DKLEN = 32; + private static final int R = 8; + private static final int DKLEN = 32; - private static final int CURRENT_VERSION = 3; + private static final int CURRENT_VERSION = 3; - private static final String CIPHER = "aes-128-ctr"; - static final String AES_128_CTR = "pbkdf2"; - static final String SCRYPT = "scrypt"; + private static final String CIPHER = "aes-128-ctr"; + static final String AES_128_CTR = "pbkdf2"; + static final String SCRYPT = "scrypt"; - public static WalletFile create(String password, ECKeyPair ecKeyPair, int n, int p) - throws CipherException { + public static WalletFile create(String password, ECKeyPair ecKeyPair, int n, int p) + throws CipherException { - byte[] salt = generateRandomBytes(32); + byte[] salt = generateRandomBytes(32); - byte[] derivedKey = generateDerivedScryptKey(password.getBytes(UTF_8), salt, n, R, p, DKLEN); + byte[] derivedKey = + generateDerivedScryptKey(password.getBytes(UTF_8), salt, n, R, p, DKLEN); - byte[] encryptKey = Arrays.copyOfRange(derivedKey, 0, 16); - byte[] iv = generateRandomBytes(16); + byte[] encryptKey = Arrays.copyOfRange(derivedKey, 0, 16); + byte[] iv = generateRandomBytes(16); - byte[] privateKeyBytes = - Numeric.toBytesPadded(ecKeyPair.getPrivateKey(), Keys.PRIVATE_KEY_SIZE); + byte[] privateKeyBytes = + Numeric.toBytesPadded(ecKeyPair.getPrivateKey(), Keys.PRIVATE_KEY_SIZE); - byte[] cipherText = - performCipherOperation(Cipher.ENCRYPT_MODE, iv, encryptKey, privateKeyBytes); + byte[] cipherText = + performCipherOperation(Cipher.ENCRYPT_MODE, iv, encryptKey, privateKeyBytes); - byte[] mac = generateMac(derivedKey, cipherText); + byte[] mac = generateMac(derivedKey, cipherText); - return createWalletFile(ecKeyPair, cipherText, iv, salt, mac, n, p); - } - - public static WalletFile createStandard(String password, ECKeyPair ecKeyPair) - throws CipherException { - return create(password, ecKeyPair, N_STANDARD, P_STANDARD); - } - - public static WalletFile createLight(String password, ECKeyPair ecKeyPair) - throws CipherException { - return create(password, ecKeyPair, N_LIGHT, P_LIGHT); - } - - private static WalletFile createWalletFile( - ECKeyPair ecKeyPair, byte[] cipherText, byte[] iv, byte[] salt, byte[] mac, int n, int p) { - - WalletFile walletFile = new WalletFile(); - walletFile.setAddress(Keys.getAddress(ecKeyPair)); - - WalletFile.Crypto crypto = new WalletFile.Crypto(); - crypto.setCipher(CIPHER); - crypto.setCiphertext(Numeric.toHexStringNoPrefix(cipherText)); - walletFile.setCrypto(crypto); - - WalletFile.CipherParams cipherParams = new WalletFile.CipherParams(); - cipherParams.setIv(Numeric.toHexStringNoPrefix(iv)); - crypto.setCipherparams(cipherParams); - - crypto.setKdf(SCRYPT); - WalletFile.ScryptKdfParams kdfParams = new WalletFile.ScryptKdfParams(); - kdfParams.setDklen(DKLEN); - kdfParams.setN(n); - kdfParams.setP(p); - kdfParams.setR(R); - kdfParams.setSalt(Numeric.toHexStringNoPrefix(salt)); - crypto.setKdfparams(kdfParams); - - crypto.setMac(Numeric.toHexStringNoPrefix(mac)); - walletFile.setCrypto(crypto); - walletFile.setId(UUID.randomUUID().toString()); - walletFile.setVersion(CURRENT_VERSION); - - return walletFile; - } - - private static byte[] generateDerivedScryptKey( - byte[] password, byte[] salt, int n, int r, int p, int dkLen) throws CipherException { - try { - return SCrypt.scrypt(password, salt, n, r, p, dkLen); - } catch (GeneralSecurityException e) { - throw new CipherException(e); + return createWalletFile(ecKeyPair, cipherText, iv, salt, mac, n, p); } - } - - private static byte[] generateAes128CtrDerivedKey(byte[] password, byte[] salt, int c, String prf) - throws CipherException { - if (!prf.equals("hmac-sha256")) { - throw new CipherException("Unsupported prf:" + prf); + public static WalletFile createStandard(String password, ECKeyPair ecKeyPair) + throws CipherException { + return create(password, ecKeyPair, N_STANDARD, P_STANDARD); } - // Java 8 supports this, but you have to convert the password to a character array, see - // http://stackoverflow.com/a/27928435/3211687 - - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); - gen.init(password, salt, c); - return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); - } - - private static byte[] performCipherOperation(int mode, byte[] iv, byte[] encryptKey, byte[] text) - throws CipherException { - - try { - IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); - - SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey, "AES"); - cipher.init(mode, secretKeySpec, ivParameterSpec); - return cipher.doFinal(text); - } catch (NoSuchPaddingException - | NoSuchAlgorithmException - | InvalidAlgorithmParameterException - | InvalidKeyException - | BadPaddingException - | IllegalBlockSizeException e) { - throw new CipherException("Error performing cipher operation", e); + public static WalletFile createLight(String password, ECKeyPair ecKeyPair) + throws CipherException { + return create(password, ecKeyPair, N_LIGHT, P_LIGHT); } - } - private static byte[] generateMac(byte[] derivedKey, byte[] cipherText) { - byte[] result = new byte[16 + cipherText.length]; + private static WalletFile createWalletFile( + ECKeyPair ecKeyPair, + byte[] cipherText, + byte[] iv, + byte[] salt, + byte[] mac, + int n, + int p) { + + WalletFile walletFile = new WalletFile(); + walletFile.setAddress(Keys.getAddress(ecKeyPair)); + + WalletFile.Crypto crypto = new WalletFile.Crypto(); + crypto.setCipher(CIPHER); + crypto.setCiphertext(Numeric.toHexStringNoPrefix(cipherText)); + walletFile.setCrypto(crypto); + + WalletFile.CipherParams cipherParams = new WalletFile.CipherParams(); + cipherParams.setIv(Numeric.toHexStringNoPrefix(iv)); + crypto.setCipherparams(cipherParams); + + crypto.setKdf(SCRYPT); + WalletFile.ScryptKdfParams kdfParams = new WalletFile.ScryptKdfParams(); + kdfParams.setDklen(DKLEN); + kdfParams.setN(n); + kdfParams.setP(p); + kdfParams.setR(R); + kdfParams.setSalt(Numeric.toHexStringNoPrefix(salt)); + crypto.setKdfparams(kdfParams); + + crypto.setMac(Numeric.toHexStringNoPrefix(mac)); + walletFile.setCrypto(crypto); + walletFile.setId(UUID.randomUUID().toString()); + walletFile.setVersion(CURRENT_VERSION); + + return walletFile; + } - System.arraycopy(derivedKey, 16, result, 0, 16); - System.arraycopy(cipherText, 0, result, 16, cipherText.length); + private static byte[] generateDerivedScryptKey( + byte[] password, byte[] salt, int n, int r, int p, int dkLen) throws CipherException { + try { + return SCrypt.scrypt(password, salt, n, r, p, dkLen); + } catch (GeneralSecurityException e) { + throw new CipherException(e); + } + } - return Hash.sha3(result); - } + private static byte[] generateAes128CtrDerivedKey( + byte[] password, byte[] salt, int c, String prf) throws CipherException { - public static ECKeyPair decrypt(String password, WalletFile walletFile) throws CipherException { + if (!prf.equals("hmac-sha256")) { + throw new CipherException("Unsupported prf:" + prf); + } - validate(walletFile); + // Java 8 supports this, but you have to convert the password to a character array, see + // http://stackoverflow.com/a/27928435/3211687 - WalletFile.Crypto crypto = walletFile.getCrypto(); + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); + gen.init(password, salt, c); + return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); + } - byte[] mac = Numeric.hexStringToByteArray(crypto.getMac()); - byte[] iv = Numeric.hexStringToByteArray(crypto.getCipherparams().getIv()); - byte[] cipherText = Numeric.hexStringToByteArray(crypto.getCiphertext()); + private static byte[] performCipherOperation( + int mode, byte[] iv, byte[] encryptKey, byte[] text) throws CipherException { + + try { + IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + + SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey, "AES"); + cipher.init(mode, secretKeySpec, ivParameterSpec); + return cipher.doFinal(text); + } catch (NoSuchPaddingException + | NoSuchAlgorithmException + | InvalidAlgorithmParameterException + | InvalidKeyException + | BadPaddingException + | IllegalBlockSizeException e) { + throw new CipherException("Error performing cipher operation", e); + } + } - byte[] derivedKey; + private static byte[] generateMac(byte[] derivedKey, byte[] cipherText) { + byte[] result = new byte[16 + cipherText.length]; - WalletFile.KdfParams kdfParams = crypto.getKdfparams(); - if (kdfParams instanceof WalletFile.ScryptKdfParams) { - WalletFile.ScryptKdfParams scryptKdfParams = - (WalletFile.ScryptKdfParams) crypto.getKdfparams(); - int dklen = scryptKdfParams.getDklen(); - int n = scryptKdfParams.getN(); - int p = scryptKdfParams.getP(); - int r = scryptKdfParams.getR(); - byte[] salt = Numeric.hexStringToByteArray(scryptKdfParams.getSalt()); - derivedKey = generateDerivedScryptKey(password.getBytes(UTF_8), salt, n, r, p, dklen); - } else if (kdfParams instanceof WalletFile.Aes128CtrKdfParams) { - WalletFile.Aes128CtrKdfParams aes128CtrKdfParams = - (WalletFile.Aes128CtrKdfParams) crypto.getKdfparams(); - int c = aes128CtrKdfParams.getC(); - String prf = aes128CtrKdfParams.getPrf(); - byte[] salt = Numeric.hexStringToByteArray(aes128CtrKdfParams.getSalt()); + System.arraycopy(derivedKey, 16, result, 0, 16); + System.arraycopy(cipherText, 0, result, 16, cipherText.length); - derivedKey = generateAes128CtrDerivedKey(password.getBytes(UTF_8), salt, c, prf); - } else { - throw new CipherException("Unable to deserialize params: " + crypto.getKdf()); + return Hash.sha3(result); } - byte[] derivedMac = generateMac(derivedKey, cipherText); - - if (!Arrays.equals(derivedMac, mac)) { - throw new CipherException("Invalid password provided"); + public static ECKeyPair decrypt(String password, WalletFile walletFile) throws CipherException { + + validate(walletFile); + + WalletFile.Crypto crypto = walletFile.getCrypto(); + + byte[] mac = Numeric.hexStringToByteArray(crypto.getMac()); + byte[] iv = Numeric.hexStringToByteArray(crypto.getCipherparams().getIv()); + byte[] cipherText = Numeric.hexStringToByteArray(crypto.getCiphertext()); + + byte[] derivedKey; + + WalletFile.KdfParams kdfParams = crypto.getKdfparams(); + if (kdfParams instanceof WalletFile.ScryptKdfParams) { + WalletFile.ScryptKdfParams scryptKdfParams = + (WalletFile.ScryptKdfParams) crypto.getKdfparams(); + int dklen = scryptKdfParams.getDklen(); + int n = scryptKdfParams.getN(); + int p = scryptKdfParams.getP(); + int r = scryptKdfParams.getR(); + byte[] salt = Numeric.hexStringToByteArray(scryptKdfParams.getSalt()); + derivedKey = generateDerivedScryptKey(password.getBytes(UTF_8), salt, n, r, p, dklen); + } else if (kdfParams instanceof WalletFile.Aes128CtrKdfParams) { + WalletFile.Aes128CtrKdfParams aes128CtrKdfParams = + (WalletFile.Aes128CtrKdfParams) crypto.getKdfparams(); + int c = aes128CtrKdfParams.getC(); + String prf = aes128CtrKdfParams.getPrf(); + byte[] salt = Numeric.hexStringToByteArray(aes128CtrKdfParams.getSalt()); + + derivedKey = generateAes128CtrDerivedKey(password.getBytes(UTF_8), salt, c, prf); + } else { + throw new CipherException("Unable to deserialize params: " + crypto.getKdf()); + } + + byte[] derivedMac = generateMac(derivedKey, cipherText); + + if (!Arrays.equals(derivedMac, mac)) { + throw new CipherException("Invalid password provided"); + } + + byte[] encryptKey = Arrays.copyOfRange(derivedKey, 0, 16); + byte[] privateKey = performCipherOperation(Cipher.DECRYPT_MODE, iv, encryptKey, cipherText); + return ECKeyPair.create(privateKey); } - byte[] encryptKey = Arrays.copyOfRange(derivedKey, 0, 16); - byte[] privateKey = performCipherOperation(Cipher.DECRYPT_MODE, iv, encryptKey, cipherText); - return ECKeyPair.create(privateKey); - } + static void validate(WalletFile walletFile) throws CipherException { + WalletFile.Crypto crypto = walletFile.getCrypto(); - static void validate(WalletFile walletFile) throws CipherException { - WalletFile.Crypto crypto = walletFile.getCrypto(); + if (walletFile.getVersion() != CURRENT_VERSION) { + throw new CipherException("Wallet version is not supported"); + } - if (walletFile.getVersion() != CURRENT_VERSION) { - throw new CipherException("Wallet version is not supported"); - } + if (!crypto.getCipher().equals(CIPHER)) { + throw new CipherException("Wallet cipher is not supported"); + } - if (!crypto.getCipher().equals(CIPHER)) { - throw new CipherException("Wallet cipher is not supported"); + if (!crypto.getKdf().equals(AES_128_CTR) && !crypto.getKdf().equals(SCRYPT)) { + throw new CipherException("KDF type is not supported"); + } } - if (!crypto.getKdf().equals(AES_128_CTR) && !crypto.getKdf().equals(SCRYPT)) { - throw new CipherException("KDF type is not supported"); + static byte[] generateRandomBytes(int size) { + byte[] bytes = new byte[size]; + SECURE_RANDOM.nextBytes(bytes); + return bytes; } - } - - static byte[] generateRandomBytes(int size) { - byte[] bytes = new byte[size]; - SECURE_RANDOM.nextBytes(bytes); - return bytes; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/WalletFile.java b/src/main/java/org/fisco/bcos/web3j/crypto/WalletFile.java index 5e02e6f93..191436747 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/WalletFile.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/WalletFile.java @@ -13,257 +13,258 @@ /** Ethereum wallet file. */ public class WalletFile { - private String address; - private Crypto crypto; - private String id; - private int version; + private String address; + private Crypto crypto; + private String id; + private int version; - public WalletFile() {} + public WalletFile() {} - public String getAddress() { - return address; - } + public String getAddress() { + return address; + } - public void setAddress(String address) { - this.address = address; - } + public void setAddress(String address) { + this.address = address; + } - public Crypto getCrypto() { - return crypto; - } + public Crypto getCrypto() { + return crypto; + } - @JsonSetter("crypto") - public void setCrypto(Crypto crypto) { - this.crypto = crypto; - } + @JsonSetter("crypto") + public void setCrypto(Crypto crypto) { + this.crypto = crypto; + } - @JsonSetter("Crypto") // older wallet files may have this attribute name - public void setCryptoV1(Crypto crypto) { - setCrypto(crypto); - } + @JsonSetter("Crypto") // older wallet files may have this attribute name + public void setCryptoV1(Crypto crypto) { + setCrypto(crypto); + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public void setId(String id) { - this.id = id; - } + public void setId(String id) { + this.id = id; + } - public int getVersion() { - return version; - } + public int getVersion() { + return version; + } - public void setVersion(int version) { - this.version = version; - } + public void setVersion(int version) { + this.version = version; + } - public static class Crypto { - private String cipher; - private String ciphertext; - private CipherParams cipherparams; + public static class Crypto { + private String cipher; + private String ciphertext; + private CipherParams cipherparams; - private String kdf; - private KdfParams kdfparams; + private String kdf; + private KdfParams kdfparams; - private String mac; + private String mac; - public Crypto() {} + public Crypto() {} - public String getCipher() { - return cipher; - } + public String getCipher() { + return cipher; + } - public void setCipher(String cipher) { - this.cipher = cipher; - } + public void setCipher(String cipher) { + this.cipher = cipher; + } - public String getCiphertext() { - return ciphertext; - } + public String getCiphertext() { + return ciphertext; + } - public void setCiphertext(String ciphertext) { - this.ciphertext = ciphertext; - } + public void setCiphertext(String ciphertext) { + this.ciphertext = ciphertext; + } - public CipherParams getCipherparams() { - return cipherparams; - } + public CipherParams getCipherparams() { + return cipherparams; + } - public void setCipherparams(CipherParams cipherparams) { - this.cipherparams = cipherparams; - } + public void setCipherparams(CipherParams cipherparams) { + this.cipherparams = cipherparams; + } - public String getKdf() { - return kdf; - } + public String getKdf() { + return kdf; + } - public void setKdf(String kdf) { - this.kdf = kdf; - } + public void setKdf(String kdf) { + this.kdf = kdf; + } - public KdfParams getKdfparams() { - return kdfparams; - } + public KdfParams getKdfparams() { + return kdfparams; + } - @JsonTypeInfo( - use = JsonTypeInfo.Id.NAME, - include = JsonTypeInfo.As.EXTERNAL_PROPERTY, - property = "kdf") - @JsonSubTypes({ - @JsonSubTypes.Type(value = Aes128CtrKdfParams.class, name = Wallet.AES_128_CTR), - @JsonSubTypes.Type(value = ScryptKdfParams.class, name = Wallet.SCRYPT) - }) - // To support my Ether Wallet keys uncomment this annotation & comment out the above - // @JsonDeserialize(using = KdfParamsDeserialiser.class) - // Also add the following to the ObjectMapperFactory - // objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); - public void setKdfparams(KdfParams kdfparams) { - this.kdfparams = kdfparams; - } + @JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXTERNAL_PROPERTY, + property = "kdf") + @JsonSubTypes({ + @JsonSubTypes.Type(value = Aes128CtrKdfParams.class, name = Wallet.AES_128_CTR), + @JsonSubTypes.Type(value = ScryptKdfParams.class, name = Wallet.SCRYPT) + }) + // To support my Ether Wallet keys uncomment this annotation & comment out the above + // @JsonDeserialize(using = KdfParamsDeserialiser.class) + // Also add the following to the ObjectMapperFactory + // objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); + public void setKdfparams(KdfParams kdfparams) { + this.kdfparams = kdfparams; + } - public String getMac() { - return mac; - } + public String getMac() { + return mac; + } - public void setMac(String mac) { - this.mac = mac; + public void setMac(String mac) { + this.mac = mac; + } } - } - public static class CipherParams { - private String iv; + public static class CipherParams { + private String iv; + + public CipherParams() {} - public CipherParams() {} + public String getIv() { + return iv; + } - public String getIv() { - return iv; + public void setIv(String iv) { + this.iv = iv; + } } - public void setIv(String iv) { - this.iv = iv; + interface KdfParams { + int getDklen(); + + String getSalt(); } - } - interface KdfParams { - int getDklen(); + public static class Aes128CtrKdfParams implements KdfParams { + private int dklen; + private int c; + private String prf; + private String salt; - String getSalt(); - } + public Aes128CtrKdfParams() {} - public static class Aes128CtrKdfParams implements KdfParams { - private int dklen; - private int c; - private String prf; - private String salt; + public int getDklen() { + return dklen; + } - public Aes128CtrKdfParams() {} + public void setDklen(int dklen) { + this.dklen = dklen; + } - public int getDklen() { - return dklen; - } + public int getC() { + return c; + } - public void setDklen(int dklen) { - this.dklen = dklen; - } + public void setC(int c) { + this.c = c; + } - public int getC() { - return c; - } + public String getPrf() { + return prf; + } - public void setC(int c) { - this.c = c; - } + public void setPrf(String prf) { + this.prf = prf; + } - public String getPrf() { - return prf; - } + public String getSalt() { + return salt; + } - public void setPrf(String prf) { - this.prf = prf; + public void setSalt(String salt) { + this.salt = salt; + } } - public String getSalt() { - return salt; - } + public static class ScryptKdfParams implements KdfParams { + private int dklen; + private int n; + private int p; + private int r; + private String salt; - public void setSalt(String salt) { - this.salt = salt; - } - } + public ScryptKdfParams() {} - public static class ScryptKdfParams implements KdfParams { - private int dklen; - private int n; - private int p; - private int r; - private String salt; + public int getDklen() { + return dklen; + } - public ScryptKdfParams() {} + public void setDklen(int dklen) { + this.dklen = dklen; + } - public int getDklen() { - return dklen; - } + public int getN() { + return n; + } - public void setDklen(int dklen) { - this.dklen = dklen; - } + public void setN(int n) { + this.n = n; + } - public int getN() { - return n; - } + public int getP() { + return p; + } - public void setN(int n) { - this.n = n; - } + public void setP(int p) { + this.p = p; + } - public int getP() { - return p; - } + public int getR() { + return r; + } - public void setP(int p) { - this.p = p; - } + public void setR(int r) { + this.r = r; + } - public int getR() { - return r; - } + public String getSalt() { + return salt; + } - public void setR(int r) { - this.r = r; + public void setSalt(String salt) { + this.salt = salt; + } } - public String getSalt() { - return salt; - } + // If we need to work with MyEtherWallet we'll need to use this deserializer, see the + // following issue https://github.com/kvhnuke/etherwallet/issues/269 + static class KdfParamsDeserialiser extends JsonDeserializer { - public void setSalt(String salt) { - this.salt = salt; - } - } - - // If we need to work with MyEtherWallet we'll need to use this deserializer, see the - // following issue https://github.com/kvhnuke/etherwallet/issues/269 - static class KdfParamsDeserialiser extends JsonDeserializer { - - @Override - public KdfParams deserialize( - JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { - - ObjectMapper objectMapper = (ObjectMapper) jsonParser.getCodec(); - ObjectNode root = objectMapper.readTree(jsonParser); - KdfParams kdfParams; - - // it would be preferable to detect the class to use based on the kdf parameter in the - // container object instance - JsonNode n = root.get("n"); - if (n == null) { - kdfParams = objectMapper.convertValue(root, Aes128CtrKdfParams.class); - } else { - kdfParams = objectMapper.convertValue(root, ScryptKdfParams.class); - } - - return kdfParams; + @Override + public KdfParams deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + + ObjectMapper objectMapper = (ObjectMapper) jsonParser.getCodec(); + ObjectNode root = objectMapper.readTree(jsonParser); + KdfParams kdfParams; + + // it would be preferable to detect the class to use based on the kdf parameter in the + // container object instance + JsonNode n = root.get("n"); + if (n == null) { + kdfParams = objectMapper.convertValue(root, Aes128CtrKdfParams.class); + } else { + kdfParams = objectMapper.convertValue(root, ScryptKdfParams.class); + } + + return kdfParams; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/WalletUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/WalletUtils.java index 6205abbfb..65fb25e54 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/WalletUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/WalletUtils.java @@ -18,101 +18,103 @@ /** Utility functions for working with Wallet files. */ public class WalletUtils { - public static String generateFullNewWalletFile(String password, File destinationDirectory) - throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, - CipherException, IOException { - - return generateNewWalletFile(password, destinationDirectory, true); - } - - public static String generateLightNewWalletFile(String password, File destinationDirectory) - throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, - CipherException, IOException { - - return generateNewWalletFile(password, destinationDirectory, false); - } - - public static String generateNewWalletFile( - String password, File destinationDirectory, boolean useFullScrypt) - throws CipherException, IOException, InvalidAlgorithmParameterException, - NoSuchAlgorithmException, NoSuchProviderException { - - ECKeyPair ecKeyPair = Keys.createEcKeyPair(); - return generateWalletFile(password, ecKeyPair, destinationDirectory, useFullScrypt); - } - - public static String generateWalletFile( - String password, ECKeyPair ecKeyPair, File destinationDirectory, boolean useFullScrypt) - throws CipherException, IOException { - - WalletFile walletFile; - if (useFullScrypt) { - walletFile = Wallet.createStandard(password, ecKeyPair); - } else { - walletFile = Wallet.createLight(password, ecKeyPair); + public static String generateFullNewWalletFile(String password, File destinationDirectory) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidAlgorithmParameterException, CipherException, IOException { + + return generateNewWalletFile(password, destinationDirectory, true); } - String fileName = getWalletFileName(walletFile); - File destination = new File(destinationDirectory, fileName); + public static String generateLightNewWalletFile(String password, File destinationDirectory) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidAlgorithmParameterException, CipherException, IOException { + + return generateNewWalletFile(password, destinationDirectory, false); + } - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - objectMapper.writeValue(destination, walletFile); + public static String generateNewWalletFile( + String password, File destinationDirectory, boolean useFullScrypt) + throws CipherException, IOException, InvalidAlgorithmParameterException, + NoSuchAlgorithmException, NoSuchProviderException { - return fileName; - } + ECKeyPair ecKeyPair = Keys.createEcKeyPair(); + return generateWalletFile(password, ecKeyPair, destinationDirectory, useFullScrypt); + } - public static Credentials loadCredentials(String password, String source) - throws IOException, CipherException { - return loadCredentials(password, new File(source)); - } + public static String generateWalletFile( + String password, ECKeyPair ecKeyPair, File destinationDirectory, boolean useFullScrypt) + throws CipherException, IOException { - public static Credentials loadCredentials(String password, File source) - throws IOException, CipherException { - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - WalletFile walletFile = objectMapper.readValue(source, WalletFile.class); - return Credentials.create(Wallet.decrypt(password, walletFile)); - } + WalletFile walletFile; + if (useFullScrypt) { + walletFile = Wallet.createStandard(password, ecKeyPair); + } else { + walletFile = Wallet.createLight(password, ecKeyPair); + } - private static String getWalletFileName(WalletFile walletFile) { - DateTimeFormatter format = DateTimeFormatter.ofPattern("'UTC--'yyyy-MM-dd'T'HH-mm-ss.nVV'--'"); - ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); + String fileName = getWalletFileName(walletFile); + File destination = new File(destinationDirectory, fileName); - return now.format(format) + walletFile.getAddress() + ".json"; - } + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + objectMapper.writeValue(destination, walletFile); - public static String getDefaultKeyDirectory() { - return getDefaultKeyDirectory(System.getProperty("os.name")); - } + return fileName; + } - static String getDefaultKeyDirectory(String osName1) { - String osName = osName1.toLowerCase(); + public static Credentials loadCredentials(String password, String source) + throws IOException, CipherException { + return loadCredentials(password, new File(source)); + } + + public static Credentials loadCredentials(String password, File source) + throws IOException, CipherException { + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + WalletFile walletFile = objectMapper.readValue(source, WalletFile.class); + return Credentials.create(Wallet.decrypt(password, walletFile)); + } + + private static String getWalletFileName(WalletFile walletFile) { + DateTimeFormatter format = + DateTimeFormatter.ofPattern("'UTC--'yyyy-MM-dd'T'HH-mm-ss.nVV'--'"); + ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); + + return now.format(format) + walletFile.getAddress() + ".json"; + } + + public static String getDefaultKeyDirectory() { + return getDefaultKeyDirectory(System.getProperty("os.name")); + } + + static String getDefaultKeyDirectory(String osName1) { + String osName = osName1.toLowerCase(); + + if (osName.startsWith("mac")) { + return String.format( + "%s%sLibrary%sEthereum", + System.getProperty("user.home"), File.separator, File.separator); + } else if (osName.startsWith("win")) { + return String.format("%s%sEthereum", System.getenv("APPDATA"), File.separator); + } else { + return String.format("%s%s.ethereum", System.getProperty("user.home"), File.separator); + } + } + + public static String getTestnetKeyDirectory() { + return String.format( + "%s%stestnet%skeystore", getDefaultKeyDirectory(), File.separator, File.separator); + } + + public static String getMainnetKeyDirectory() { + return String.format("%s%skeystore", getDefaultKeyDirectory(), File.separator); + } + + public static boolean isValidPrivateKey(String privateKey) { + String cleanPrivateKey = Numeric.cleanHexPrefix(privateKey); + return cleanPrivateKey.length() == PRIVATE_KEY_LENGTH_IN_HEX; + } - if (osName.startsWith("mac")) { - return String.format( - "%s%sLibrary%sEthereum", System.getProperty("user.home"), File.separator, File.separator); - } else if (osName.startsWith("win")) { - return String.format("%s%sEthereum", System.getenv("APPDATA"), File.separator); - } else { - return String.format("%s%s.ethereum", System.getProperty("user.home"), File.separator); + public static boolean isValidAddress(String address) { + String addressNoPrefix = Numeric.cleanHexPrefix(address); + return addressNoPrefix.length() == ADDRESS_LENGTH_IN_HEX; } - } - - public static String getTestnetKeyDirectory() { - return String.format( - "%s%stestnet%skeystore", getDefaultKeyDirectory(), File.separator, File.separator); - } - - public static String getMainnetKeyDirectory() { - return String.format("%s%skeystore", getDefaultKeyDirectory(), File.separator); - } - - public static boolean isValidPrivateKey(String privateKey) { - String cleanPrivateKey = Numeric.cleanHexPrefix(privateKey); - return cleanPrivateKey.length() == PRIVATE_KEY_LENGTH_IN_HEX; - } - - public static boolean isValidAddress(String address) { - String addressNoPrefix = Numeric.cleanHexPrefix(address); - return addressNoPrefix.length() == ADDRESS_LENGTH_IN_HEX; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenCredential.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenCredential.java index 63aeef88d..abb51c53e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenCredential.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenCredential.java @@ -14,103 +14,101 @@ import org.slf4j.LoggerFactory; public class GenCredential { - private static Logger logger = LoggerFactory.getLogger(GenCredential.class); + private static Logger logger = LoggerFactory.getLogger(GenCredential.class); - public static ECKeyPair createGuomiKeyPair() { - System.out.println("=====INIT GUOMI KEYPAIR ===="); - final SM2KeyGenerator generator = new SM2KeyGenerator(); - final KeyPair keyPairData = generator.generateKeyPair(); - if (keyPairData != null) return genEcPairFromKeyPair(keyPairData); - System.out.println("=====INIT GUOMI KEYPAIR FAILED ===="); - return null; - } + public static ECKeyPair createGuomiKeyPair() { + final SM2KeyGenerator generator = new SM2KeyGenerator(); + final KeyPair keyPairData = generator.generateKeyPair(); + if (keyPairData != null) return genEcPairFromKeyPair(keyPairData); + return null; + } - private static ECKeyPair genEcPairFromKeyPair(KeyPair keyPairData) { - try { - SM2PrivateKey vk = (SM2PrivateKey) keyPairData.getPrivate(); - SM2PublicKey pk = (SM2PublicKey) keyPairData.getPublic(); - final byte[] publicKey = pk.getEncoded(); - final byte[] privateKey = vk.getEncoded(); + private static ECKeyPair genEcPairFromKeyPair(KeyPair keyPairData) { + try { + SM2PrivateKey vk = (SM2PrivateKey) keyPairData.getPrivate(); + SM2PublicKey pk = (SM2PublicKey) keyPairData.getPublic(); + final byte[] publicKey = pk.getEncoded(); + final byte[] privateKey = vk.getEncoded(); - // System.out.println("===public:" + Hex.toHexString(publicKey)); - // System.out.println("===private:" + Hex.toHexString(privateKey)); - BigInteger biPublic = new BigInteger(Hex.toHexString(publicKey), 16); - BigInteger biPrivate = new BigInteger(Hex.toHexString(privateKey), 16); + // System.out.println("===public:" + Hex.toHexString(publicKey)); + // System.out.println("===private:" + Hex.toHexString(privateKey)); + BigInteger biPublic = new BigInteger(Hex.toHexString(publicKey), 16); + BigInteger biPrivate = new BigInteger(Hex.toHexString(privateKey), 16); - // System.out.println("---public:" + biPublic.toString(16)); - // System.out.println("---private:" + biPrivate.toString(16)); + // System.out.println("---public:" + biPublic.toString(16)); + // System.out.println("---private:" + biPrivate.toString(16)); - ECKeyPair keyPair = new ECKeyPair(biPrivate, biPublic); - return keyPair; - } catch (Exception e) { - logger.error("create ec_keypair of guomi failed, error msg:" + e.getMessage()); - return null; + ECKeyPair keyPair = new ECKeyPair(biPrivate, biPublic); + return keyPair; + } catch (Exception e) { + logger.error("create ec_keypair of guomi failed, error msg:" + e.getMessage()); + return null; + } } - } - private static ECKeyPair createGuomiKeyPair(String privKey) { - SM2KeyGenerator generator = new SM2KeyGenerator(); - final KeyPair keyPairData = generator.generateKeyPair(privKey); - if (keyPairData != null) return genEcPairFromKeyPair(keyPairData); - return null; - } + private static ECKeyPair createGuomiKeyPair(String privKey) { + SM2KeyGenerator generator = new SM2KeyGenerator(); + final KeyPair keyPairData = generator.generateKeyPair(privKey); + if (keyPairData != null) return genEcPairFromKeyPair(keyPairData); + return null; + } - private static ECKeyPair createECDSAKeyPair(String privKey) { - try { - BigInteger bigPrivKey = new BigInteger(privKey, 16); - ECKeyPair keyPair = ECKeyPair.create(bigPrivKey); - return keyPair; - } catch (Exception e) { - logger.error("create keypair of ECDSA failed, error msg:" + e.getMessage()); - return null; + private static ECKeyPair createECDSAKeyPair(String privKey) { + try { + BigInteger bigPrivKey = new BigInteger(privKey, 16); + ECKeyPair keyPair = ECKeyPair.create(bigPrivKey); + return keyPair; + } catch (Exception e) { + logger.error("create keypair of ECDSA failed, error msg:" + e.getMessage()); + return null; + } } - } - private static ECKeyPair createECDSAKeyPair() { - try { - ECKeyPair keyPair = Keys.createEcKeyPair(); - return keyPair; - } catch (Exception e) { - logger.error("create keypair of ECDSA failed, error msg:" + e.getMessage()); - return null; + private static ECKeyPair createECDSAKeyPair() { + try { + ECKeyPair keyPair = Keys.createEcKeyPair(); + return keyPair; + } catch (Exception e) { + logger.error("create keypair of ECDSA failed, error msg:" + e.getMessage()); + return null; + } } - } - private static ECKeyPair createKeyPair() { - // use guomi - if (EncryptType.encryptType == 1) return createGuomiKeyPair(); - return createECDSAKeyPair(); // default use ECDSA - } + private static ECKeyPair createKeyPair() { + // use guomi + if (EncryptType.encryptType == 1) return createGuomiKeyPair(); + return createECDSAKeyPair(); // default use ECDSA + } - private static ECKeyPair createKeyPair(String privKey) { - if (EncryptType.encryptType == 1) return createGuomiKeyPair(privKey); - return createECDSAKeyPair(privKey); - } + private static ECKeyPair createKeyPair(String privKey) { + if (EncryptType.encryptType == 1) return createGuomiKeyPair(privKey); + return createECDSAKeyPair(privKey); + } - public static Credentials create() { - try { - ECKeyPair keyPair = createKeyPair(); - if (keyPair == null) return null; + public static Credentials create() { + try { + ECKeyPair keyPair = createKeyPair(); + if (keyPair == null) return null; - Credentials credentials = Credentials.create(keyPair); - return credentials; - } catch (Exception e) { - System.out.println("init credential failed"); - logger.error("init credential failed, error msg:" + e.getMessage()); - return null; + Credentials credentials = Credentials.create(keyPair); + return credentials; + } catch (Exception e) { + System.out.println("init credential failed"); + logger.error("init credential failed, error msg:" + e.getMessage()); + return null; + } } - } - public static Credentials create(String privKey) { - try { - ECKeyPair keyPair = createKeyPair(privKey); - if (keyPair == null) return null; - Credentials credentials = Credentials.create(keyPair); - return credentials; - } catch (Exception e) { - System.out.println("init credential from private key failed "); - logger.error("init credential from private key failed, error msg:" + e.getMessage()); - return null; + public static Credentials create(String privKey) { + try { + ECKeyPair keyPair = createKeyPair(privKey); + if (keyPair == null) return null; + Credentials credentials = Credentials.create(keyPair); + return credentials; + } catch (Exception e) { + System.out.println("init credential from private key failed "); + logger.error("init credential from private key failed, error msg:" + e.getMessage()); + return null; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenGmAccount.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenGmAccount.java index 38cd65c42..41b03053f 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenGmAccount.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/GenGmAccount.java @@ -6,109 +6,111 @@ import org.fisco.bcos.web3j.utils.Numeric; public class GenGmAccount { - public static void main(String[] args) throws Exception { - if (args.length < 1) { - Usage(); - return; + public static void main(String[] args) throws Exception { + if (args.length < 1) { + Usage(); + return; + } + String opType = args[0]; + if (opType.equalsIgnoreCase("load")) { + if (args.length < 2) { + Usage(); + return; + } + LoadGuoMiKeyInfo(args[1]); + } else if (opType.equalsIgnoreCase("genkey")) { + String keyFile = "key.info"; + if (args.length > 1) keyFile = args[1]; + GenGuoMiKeyAndStore(keyFile); + } else { + System.out.println("UNKOWN OPTION"); + Usage(); + } } - String opType = args[0]; - if (opType.equalsIgnoreCase("load")) { - if (args.length < 2) { - Usage(); - return; - } - LoadGuoMiKeyInfo(args[1]); - } else if (opType.equalsIgnoreCase("genkey")) { - String keyFile = "key.info"; - if (args.length > 1) keyFile = args[1]; - GenGuoMiKeyAndStore(keyFile); - } else { - System.out.println("UNKOWN OPTION"); - Usage(); - } - } - private static void Usage() { - System.out.println("----Usage of GenGmAccount:"); - System.out.println( - "-------------------------------------------------------------------------------"); - System.out.println("==== load key information from specified file ===="); - System.out.println( - "java cp \'conf/:apps/*:lib/*\' org.bcos.contract.tools.GenGmAccount load ${keyFile}"); - System.out.println(""); - System.out.println( - "==== generate guomi private key/public key/account, store into specified file, default is key.info======="); - System.out.println( - "java cp \'conf/:apps/*:lib/*\' org.bcos.contract.tools.GenGmAccount genkey ${keyFile}"); - System.out.println( - "-------------------------------------------------------------------------------"); - } + private static void Usage() { + System.out.println("----Usage of GenGmAccount:"); + System.out.println( + "-------------------------------------------------------------------------------"); + System.out.println("==== load key information from specified file ===="); + System.out.println( + "java cp \'conf/:apps/*:lib/*\' org.bcos.contract.tools.GenGmAccount load ${keyFile}"); + System.out.println(""); + System.out.println( + "==== generate guomi private key/public key/account, store into specified file, default is key.info======="); + System.out.println( + "java cp \'conf/:apps/*:lib/*\' org.bcos.contract.tools.GenGmAccount genkey ${keyFile}"); + System.out.println( + "-------------------------------------------------------------------------------"); + } - /** - * @author: fisco-dev - * @function: load private/public key from specified file - * @param keyFile: file name that contains private/public/account info - */ - private static void LoadGuoMiKeyInfo(String keyFile) { - KeyInfo keyInfo = new KeyInfo(); - int ret = keyInfo.loadKeyInfo(keyFile); - if (ret == RetCode.success) - System.out.println("=== LOAD GUOMI KEY INFO FROM " + keyFile + " SUCCESS ==="); - else System.out.println("xxx LOAD GUOMI KEY INFO FROM " + keyFile + " FAILED xxx"); - } + /** + * @author: fisco-dev + * @function: load private/public key from specified file + * @param keyFile: file name that contains private/public/account info + */ + private static void LoadGuoMiKeyInfo(String keyFile) { + KeyInfo keyInfo = new KeyInfo(); + int ret = keyInfo.loadKeyInfo(keyFile); + if (ret == RetCode.success) + System.out.println("=== LOAD GUOMI KEY INFO FROM " + keyFile + " SUCCESS ==="); + else System.out.println("xxx LOAD GUOMI KEY INFO FROM " + keyFile + " FAILED xxx"); + } - /** - * @author: fisco-dev - * @function: generate private/public key with GuoMi algorithm - * @param keyFile: file name used to store private/public/account info - */ - private static void GenGuoMiKeyAndStore(String keyFile) { + /** + * @author: fisco-dev + * @function: generate private/public key with GuoMi algorithm + * @param keyFile: file name used to store private/public/account info + */ + private static void GenGuoMiKeyAndStore(String keyFile) { - System.out.println( - "-------------------------------------------------------------------------------"); - System.out.println( - "==========Generate (private key, public key, account) For Guomi randomly ======="); - ECKeyPair keyPair = GenCredential.createGuomiKeyPair(); - if (keyPair != null) { - // deduce account according to public key - String account = deduceAccountFromPublic(keyPair.getPublicKey()); - while (account == null || keyPair == null) { - keyPair = GenCredential.createGuomiKeyPair(); - account = deduceAccountFromPublic(keyPair.getPublicKey()); - } - System.out.println("===Generated Account:"); - System.out.println("* public key:" + (keyPair.getPublicKey().toString(16))); - System.out.println("* private key :" + (keyPair.getPrivateKey().toString(16))); - System.out.println("* account :" + account); - // save private/public/account result - System.out.println(""); - System.out.println("==== SAVE PRIVATE/PUBLIC/ACCOUNT INFO ==="); - KeyInfo keyInfo = - new KeyInfo( - keyPair.getPublicKey().toString(16), keyPair.getPrivateKey().toString(16), account); - int result = keyInfo.storeKeyInfo(keyFile); - if (result != RetCode.success) - System.out.println("xxx STORE PRIVATE/PUBLIC/ACCOUNT INFO FAILED xxx"); - else System.out.println("=== STORE PIVATE/PUBLIC/ACCOUNT SUCCEED ==="); - System.out.println( - "-------------------------------------------------------------------------------"); - } else { - System.out.println("==== generate private/public key with GuoMi algorithm failed ===="); + System.out.println( + "-------------------------------------------------------------------------------"); + System.out.println( + "==========Generate (private key, public key, account) For Guomi randomly ======="); + ECKeyPair keyPair = GenCredential.createGuomiKeyPair(); + if (keyPair != null) { + // deduce account according to public key + String account = deduceAccountFromPublic(keyPair.getPublicKey()); + while (account == null || keyPair == null) { + keyPair = GenCredential.createGuomiKeyPair(); + account = deduceAccountFromPublic(keyPair.getPublicKey()); + } + System.out.println("===Generated Account:"); + System.out.println("* public key:" + (keyPair.getPublicKey().toString(16))); + System.out.println("* private key :" + (keyPair.getPrivateKey().toString(16))); + System.out.println("* account :" + account); + // save private/public/account result + System.out.println(""); + System.out.println("==== SAVE PRIVATE/PUBLIC/ACCOUNT INFO ==="); + KeyInfo keyInfo = + new KeyInfo( + keyPair.getPublicKey().toString(16), + keyPair.getPrivateKey().toString(16), + account); + int result = keyInfo.storeKeyInfo(keyFile); + if (result != RetCode.success) + System.out.println("xxx STORE PRIVATE/PUBLIC/ACCOUNT INFO FAILED xxx"); + else System.out.println("=== STORE PIVATE/PUBLIC/ACCOUNT SUCCEED ==="); + System.out.println( + "-------------------------------------------------------------------------------"); + } else { + System.out.println("==== generate private/public key with GuoMi algorithm failed ===="); + } } - } - private static String deduceAccountFromPublic(BigInteger publicKey) { - try { - SM3Digest sm3Digest = new SM3Digest(); - System.out.println("===GEN COUNT :" + publicKey.toString(16)); - String publicKeyNoPrefix = Numeric.cleanHexPrefix(publicKey.toString(16)); - String hashSM3String = sm3Digest.hash(publicKeyNoPrefix); - String account = hashSM3String.substring(24); + private static String deduceAccountFromPublic(BigInteger publicKey) { + try { + SM3Digest sm3Digest = new SM3Digest(); + System.out.println("===GEN COUNT :" + publicKey.toString(16)); + String publicKeyNoPrefix = Numeric.cleanHexPrefix(publicKey.toString(16)); + String hashSM3String = sm3Digest.hash(publicKeyNoPrefix); + String account = hashSM3String.substring(24); - return "0x" + account; - } catch (Exception e) { - System.out.println("DeduceAccountFromPublic failed, error message:" + e.getMessage()); - return null; + return "0x" + account; + } catch (Exception e) { + System.out.println("DeduceAccountFromPublic failed, error message:" + e.getMessage()); + return null; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfo.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfo.java index 1e2ad52c2..1308b63c9 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfo.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfo.java @@ -6,164 +6,174 @@ import org.slf4j.LoggerFactory; public class KeyInfo implements KeyInfoInterface { - private static String privateKey; - private static String publicKey; - private static String account; - private static Logger logger = LoggerFactory.getLogger(KeyInfo.class); - - public static final String privJsonKey = "privateKey"; - public static final String pubJsonKey = "publicKey"; - public static final String accountJsonKey = "account"; - - KeyInfo(String publicKey, String privateKey, String account) { - this.privateKey = privateKey; - this.publicKey = publicKey; - this.account = account; - } - - KeyInfo() {} - - public void setPrivateKey(String privKey) { - this.privateKey = privKey; - } - - public String getPrivateKey() { - return this.privateKey; - } - - public void setPublicKey(String pubKey) { - this.publicKey = pubKey; - } - - public String getPublicKey() { - return this.publicKey; - } - - public void setAccount(String account) { - this.account = account; - } - - public String getAccount() { - return this.account; - } - - private static String readFile(String keyFile) { - InputStreamReader reader = null; - BufferedReader bufReader = null; - try { - File file = new File(keyFile); - reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); - if (reader != null) bufReader = new BufferedReader(reader); - String line = null; - String content = ""; - if (bufReader != null) { - while ((line = bufReader.readLine()) != null) { - content += line; - } - System.out.println("read file " + keyFile + ", result:" + content); - } - - return content; - } catch (Exception e) { - logger.error("read file " + keyFile + " failed, error message:" + e.getMessage()); - return null; - } finally { - ReleaseBufferedReader(bufReader); - ReleaseInputStream(reader); + private static String privateKey; + private static String publicKey; + private static String account; + private static Logger logger = LoggerFactory.getLogger(KeyInfo.class); + + public static final String privJsonKey = "privateKey"; + public static final String pubJsonKey = "publicKey"; + public static final String accountJsonKey = "account"; + + KeyInfo(String publicKey, String privateKey, String account) { + this.privateKey = privateKey; + this.publicKey = publicKey; + this.account = account; } - } - private static void ReleaseInputStream(InputStreamReader reader) { - try { - if (reader != null) reader.close(); - } catch (Exception e) { - logger.error("close InputStreamReader failed, error message:" + e.getMessage()); + KeyInfo() {} + + public void setPrivateKey(String privKey) { + this.privateKey = privKey; } - } - private static void ReleaseBufferedReader(BufferedReader bufReader) { - try { - if (bufReader != null) bufReader.close(); - } catch (Exception e) { - logger.error("close BufferedReader failed, error message: " + e.getMessage()); + public String getPrivateKey() { + return this.privateKey; } - } - - /** - * @author: fisco-dev - * @param keyFile: file that contains the key information - */ - @Override - public int loadKeyInfo(String keyFile) { - String keyInfoJsonStr = readFile(keyFile); - if (keyInfoJsonStr == null) { - System.out.println("load key information failed"); - logger.error("load key information failed"); - return RetCode.openFileFailed; + + public void setPublicKey(String pubKey) { + this.publicKey = pubKey; } - System.out.println(""); - System.out.println("===key info:" + keyInfoJsonStr); - try { - JSONObject keyInfoJsonObj = JSONObject.parseObject(keyInfoJsonStr); - if (keyInfoJsonObj == null) { - System.out.println("load json str from key info failed"); - logger.error("load json str from key info failed"); - return RetCode.parseJsonFailed; - } - if (keyInfoJsonObj.containsKey(privJsonKey)) - privateKey = keyInfoJsonObj.getString(privJsonKey); - if (keyInfoJsonObj.containsKey(pubJsonKey)) publicKey = keyInfoJsonObj.getString(pubJsonKey); - if (keyInfoJsonObj.containsKey(accountJsonKey)) - account = keyInfoJsonObj.getString(accountJsonKey); - System.out.println(""); - System.out.println("====LOADED KEY INFO ==="); - System.out.println("* private key:" + privateKey); - System.out.println("* public key :" + publicKey); - System.out.println("* account: " + account); - return RetCode.success; - } catch (Exception e) { - System.out.println( - "load private key from " + keyFile + " failed, error message:" + e.getMessage()); - return RetCode.loadKeyInfoFailed; + + public String getPublicKey() { + return this.publicKey; } - } - - private static int writeFile(String keyFile, String content) { - File file = null; - PrintStream ps = null; - try { - file = new File(keyFile); - ps = new PrintStream(new FileOutputStream(file)); - ps.println(content); - return RetCode.success; - } catch (Exception e) { - System.out.println("write " + content + " to " + keyFile + " failed"); - logger.error( - "write " + content + " to " + keyFile + " failed, error message: " + e.getMessage()); - } finally { - if (ps != null) ps.close(); + + public void setAccount(String account) { + this.account = account; + } + + public String getAccount() { + return this.account; + } + + private static String readFile(String keyFile) { + InputStreamReader reader = null; + BufferedReader bufReader = null; + try { + File file = new File(keyFile); + reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); + if (reader != null) bufReader = new BufferedReader(reader); + String line = null; + String content = ""; + if (bufReader != null) { + while ((line = bufReader.readLine()) != null) { + content += line; + } + System.out.println("read file " + keyFile + ", result:" + content); + } + + return content; + } catch (Exception e) { + logger.error("read file " + keyFile + " failed, error message:" + e.getMessage()); + return null; + } finally { + ReleaseBufferedReader(bufReader); + ReleaseInputStream(reader); + } + } + + private static void ReleaseInputStream(InputStreamReader reader) { + try { + if (reader != null) reader.close(); + } catch (Exception e) { + logger.error("close InputStreamReader failed, error message:" + e.getMessage()); + } } - return RetCode.storeKeyInfoFailed; - } - - /** @author: fisco-dev */ - @Override - public int storeKeyInfo(String keyFile) { - try { - // Map keyMap = new HashMap(); - JSONObject keyMapJson = new JSONObject(); - keyMapJson.put(privJsonKey, privateKey); - keyMapJson.put(pubJsonKey, publicKey); - keyMapJson.put(accountJsonKey, account); - - String keyJsonInfo = keyMapJson.toString(); - System.out.println("== SAVED KEY INFO: " + keyJsonInfo); - return writeFile(keyFile, keyJsonInfo); - } catch (Exception e) { - System.out.println( - "store keyInfo to " + keyFile + " failed, error message: " + e.getMessage()); - logger.error("store keyInfo to " + keyFile + " failed, error message: " + e.getMessage()); - return RetCode.storeKeyInfoFailed; + + private static void ReleaseBufferedReader(BufferedReader bufReader) { + try { + if (bufReader != null) bufReader.close(); + } catch (Exception e) { + logger.error("close BufferedReader failed, error message: " + e.getMessage()); + } + } + + /** + * @author: fisco-dev + * @param keyFile: file that contains the key information + */ + @Override + public int loadKeyInfo(String keyFile) { + String keyInfoJsonStr = readFile(keyFile); + if (keyInfoJsonStr == null) { + System.out.println("load key information failed"); + logger.error("load key information failed"); + return RetCode.openFileFailed; + } + System.out.println(""); + System.out.println("===key info:" + keyInfoJsonStr); + try { + JSONObject keyInfoJsonObj = JSONObject.parseObject(keyInfoJsonStr); + if (keyInfoJsonObj == null) { + System.out.println("load json str from key info failed"); + logger.error("load json str from key info failed"); + return RetCode.parseJsonFailed; + } + if (keyInfoJsonObj.containsKey(privJsonKey)) + privateKey = keyInfoJsonObj.getString(privJsonKey); + if (keyInfoJsonObj.containsKey(pubJsonKey)) + publicKey = keyInfoJsonObj.getString(pubJsonKey); + if (keyInfoJsonObj.containsKey(accountJsonKey)) + account = keyInfoJsonObj.getString(accountJsonKey); + System.out.println(""); + System.out.println("====LOADED KEY INFO ==="); + System.out.println("* private key:" + privateKey); + System.out.println("* public key :" + publicKey); + System.out.println("* account: " + account); + return RetCode.success; + } catch (Exception e) { + System.out.println( + "load private key from " + + keyFile + + " failed, error message:" + + e.getMessage()); + return RetCode.loadKeyInfoFailed; + } + } + + private static int writeFile(String keyFile, String content) { + File file = null; + PrintStream ps = null; + try { + file = new File(keyFile); + ps = new PrintStream(new FileOutputStream(file)); + ps.println(content); + return RetCode.success; + } catch (Exception e) { + System.out.println("write " + content + " to " + keyFile + " failed"); + logger.error( + "write " + + content + + " to " + + keyFile + + " failed, error message: " + + e.getMessage()); + } finally { + if (ps != null) ps.close(); + } + return RetCode.storeKeyInfoFailed; + } + + /** @author: fisco-dev */ + @Override + public int storeKeyInfo(String keyFile) { + try { + // Map keyMap = new HashMap(); + JSONObject keyMapJson = new JSONObject(); + keyMapJson.put(privJsonKey, privateKey); + keyMapJson.put(pubJsonKey, publicKey); + keyMapJson.put(accountJsonKey, account); + + String keyJsonInfo = keyMapJson.toString(); + System.out.println("== SAVED KEY INFO: " + keyJsonInfo); + return writeFile(keyFile, keyJsonInfo); + } catch (Exception e) { + System.out.println( + "store keyInfo to " + keyFile + " failed, error message: " + e.getMessage()); + logger.error( + "store keyInfo to " + keyFile + " failed, error message: " + e.getMessage()); + return RetCode.storeKeyInfoFailed; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfoInterface.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfoInterface.java index ef4073750..de26091e8 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfoInterface.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/KeyInfoInterface.java @@ -1,7 +1,7 @@ package org.fisco.bcos.web3j.crypto.gm; public interface KeyInfoInterface { - public int loadKeyInfo(String keyFile); + public int loadKeyInfo(String keyFile); - public int storeKeyInfo(String keyFile); + public int storeKeyInfo(String keyFile); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/RetCode.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/RetCode.java index 8bfb32482..996cc833b 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/RetCode.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/RetCode.java @@ -1,17 +1,17 @@ package org.fisco.bcos.web3j.crypto.gm; public class RetCode { - public static final int success = 0; - public static final int openFileFailed = 10000; - public static final int parseJsonFailed = 10001; - public static final int loadKeyInfoFailed = 10002; - public static final int storeKeyInfoFailed = 10003; + public static final int success = 0; + public static final int openFileFailed = 10000; + public static final int parseJsonFailed = 10001; + public static final int loadKeyInfoFailed = 10002; + public static final int storeKeyInfoFailed = 10003; - public static void msg(int retCode) { - if (retCode == success) System.out.println("===SUCCESS==="); - if (retCode == openFileFailed) System.out.println("===OPEN FILE FAILED==="); - if (retCode == parseJsonFailed) System.out.println("===PARSE JSON OBJECT FAILED ==="); - if (retCode == loadKeyInfoFailed) System.out.println("===LOAD KEY FROM FILE FAILED ==="); - if (retCode == storeKeyInfoFailed) System.out.println("====STORE KEY INFO FAILED===="); - } + public static void msg(int retCode) { + if (retCode == success) System.out.println("===SUCCESS==="); + if (retCode == openFileFailed) System.out.println("===OPEN FILE FAILED==="); + if (retCode == parseJsonFailed) System.out.println("===PARSE JSON OBJECT FAILED ==="); + if (retCode == loadKeyInfoFailed) System.out.println("===LOAD KEY FROM FILE FAILED ==="); + if (retCode == storeKeyInfoFailed) System.out.println("====STORE KEY INFO FAILED===="); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/SM2Sign.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/SM2Sign.java index 7bdd265a0..9d7426e9d 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/SM2Sign.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/SM2Sign.java @@ -17,47 +17,47 @@ /** Created by websterchen on 2018/3/22. */ public class SM2Sign implements SignInterface { - static Logger logger = LoggerFactory.getLogger(SM2Sign.class); + static Logger logger = LoggerFactory.getLogger(SM2Sign.class); - @Override - public Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair) { - return sign(message, keyPair); - } - - public static Sign.SignatureData sign(byte[] message, ECKeyPair ecKeyPair) { - SM3Digest sm3Digest = new SM3Digest(); - BigInteger[] rs = null; - byte[] r = null; - byte[] s = null; - byte[] pub = null; - byte v = 0; - byte[] messageHash = sm3Digest.hash(message); - try { - byte[] signByte = SM2Algorithm.sign(messageHash, ecKeyPair.getPrivateKey()); - logger.debug("signData:{}", signByte); - // System.out.println("signData:" + Hex.toHexString(signByte)); - ASN1Sequence as = (ASN1Sequence) ASN1Primitive.fromByteArray(signByte); - rs = - new BigInteger[] { - ((ASN1Integer) as.getObjectAt(0)).getValue(), - ((ASN1Integer) as.getObjectAt(1)).getValue() - }; - } catch (IOException ex) { - logger.error("SM2 Sign ERROR"); + @Override + public Sign.SignatureData signMessage(byte[] message, ECKeyPair keyPair) { + return sign(message, keyPair); } - if (rs != null) { - r = SM2Algorithm.getEncoded(rs[0]); - s = SM2Algorithm.getEncoded(rs[1]); - /*System.out.println("publicKey:" + Hex.toHexString(Numeric.toBytesPadded(ecKeyPair.getPublicKey(),64))); - System.out.println("publicKeyLen:" + ecKeyPair.getPublicKey().bitLength()); - System.out.println("privateKey:" + Hex.toHexString(Numeric.toBytesPadded(ecKeyPair.getPrivateKey(),32))); - System.out.println("privateKey:" + ecKeyPair.getPrivateKey().bitLength());*/ - pub = Numeric.toBytesPadded(ecKeyPair.getPublicKey(), 64); - logger.debug("SM2 SignPublic:{},SM2SignPublicLen:{}", Hex.toHexString(pub), pub.length); - logger.debug("SM2 SignR:{},SM2SignRLen{}", Hex.toHexString(r), r.length); - logger.debug("SM2 SignS:{},SM2SignSLen{}", Hex.toHexString(s), s.length); - // System.out.println("SM2 SignPublic:" + Hex.toHexString(pub)); + + public static Sign.SignatureData sign(byte[] message, ECKeyPair ecKeyPair) { + SM3Digest sm3Digest = new SM3Digest(); + BigInteger[] rs = null; + byte[] r = null; + byte[] s = null; + byte[] pub = null; + byte v = 0; + byte[] messageHash = sm3Digest.hash(message); + try { + byte[] signByte = SM2Algorithm.sign(messageHash, ecKeyPair.getPrivateKey()); + logger.debug("signData:{}", signByte); + // System.out.println("signData:" + Hex.toHexString(signByte)); + ASN1Sequence as = (ASN1Sequence) ASN1Primitive.fromByteArray(signByte); + rs = + new BigInteger[] { + ((ASN1Integer) as.getObjectAt(0)).getValue(), + ((ASN1Integer) as.getObjectAt(1)).getValue() + }; + } catch (IOException ex) { + logger.error("SM2 Sign ERROR"); + } + if (rs != null) { + r = SM2Algorithm.getEncoded(rs[0]); + s = SM2Algorithm.getEncoded(rs[1]); + /*System.out.println("publicKey:" + Hex.toHexString(Numeric.toBytesPadded(ecKeyPair.getPublicKey(),64))); + System.out.println("publicKeyLen:" + ecKeyPair.getPublicKey().bitLength()); + System.out.println("privateKey:" + Hex.toHexString(Numeric.toBytesPadded(ecKeyPair.getPrivateKey(),32))); + System.out.println("privateKey:" + ecKeyPair.getPrivateKey().bitLength());*/ + pub = Numeric.toBytesPadded(ecKeyPair.getPublicKey(), 64); + logger.debug("SM2 SignPublic:{},SM2SignPublicLen:{}", Hex.toHexString(pub), pub.length); + logger.debug("SM2 SignR:{},SM2SignRLen{}", Hex.toHexString(r), r.length); + logger.debug("SM2 SignS:{},SM2SignSLen{}", Hex.toHexString(s), s.length); + // System.out.println("SM2 SignPublic:" + Hex.toHexString(pub)); + } + return new Sign.SignatureData(v, r, s, pub); } - return new Sign.SignatureData(v, r, s, pub); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BlockCipher.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BlockCipher.java index 4b2e2b05c..14c1093f0 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BlockCipher.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BlockCipher.java @@ -2,46 +2,48 @@ /** Block cipher engines are expected to conform to this interface. */ public interface BlockCipher { - /** - * Initialise the cipher. - * - * @param forEncryption if true the cipher is initialised for encryption, if false for decryption. - * @param params the key and other data required by the cipher. - * @exception IllegalArgumentException if the params argument is inappropriate. - */ - public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException; + /** + * Initialise the cipher. + * + * @param forEncryption if true the cipher is initialised for encryption, if false for + * decryption. + * @param params the key and other data required by the cipher. + * @exception IllegalArgumentException if the params argument is inappropriate. + */ + public void init(boolean forEncryption, CipherParameters params) + throws IllegalArgumentException; - /** - * Return the name of the algorithm the cipher implements. - * - * @return the name of the algorithm the cipher implements. - */ - public String getAlgorithmName(); + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + public String getAlgorithmName(); - /** - * Return the block size for this cipher (in bytes). - * - * @return the block size for this cipher in bytes. - */ - public int getBlockSize(); + /** + * Return the block size for this cipher (in bytes). + * + * @return the block size for this cipher in bytes. + */ + public int getBlockSize(); - /** - * Process one block of input from the array in and write it to the out array. - * - * @param in the array containing the input data. - * @param inOff offset into the in array the data starts at. - * @param out the array the output data will be copied into. - * @param outOff the offset into the out array the output will start at. - * @exception DataLengthException if there isn't enough data in in, or space in out. - * @exception IllegalStateException if the cipher isn't initialised. - * @return the number of bytes processed and produced. - */ - public int processBlock(byte[] in, int inOff, byte[] out, int outOff) - throws DataLengthException, IllegalStateException; + /** + * Process one block of input from the array in and write it to the out array. + * + * @param in the array containing the input data. + * @param inOff offset into the in array the data starts at. + * @param out the array the output data will be copied into. + * @param outOff the offset into the out array the output will start at. + * @exception DataLengthException if there isn't enough data in in, or space in out. + * @exception IllegalStateException if the cipher isn't initialised. + * @return the number of bytes processed and produced. + */ + public int processBlock(byte[] in, int inOff, byte[] out, int outOff) + throws DataLengthException, IllegalStateException; - /** - * Reset the cipher. After resetting the cipher is in the same state as it was after the last init - * (if there was one). - */ - public void reset(); + /** + * Reset the cipher. After resetting the cipher is in the same state as it was after the last + * init (if there was one). + */ + public void reset(); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BufferedBlockCipher.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BufferedBlockCipher.java index c60a9baf6..eece73eb8 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BufferedBlockCipher.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/BufferedBlockCipher.java @@ -9,247 +9,249 @@ * block may not be a multiple of the block size. */ public class BufferedBlockCipher { - protected byte[] buf; - protected int bufOff; + protected byte[] buf; + protected int bufOff; - protected boolean forEncryption; - protected BlockCipher cipher; + protected boolean forEncryption; + protected BlockCipher cipher; - protected boolean partialBlockOkay; - protected boolean pgpCFB; + protected boolean partialBlockOkay; + protected boolean pgpCFB; - /** constructor for subclasses */ - protected BufferedBlockCipher() {} + /** constructor for subclasses */ + protected BufferedBlockCipher() {} - /** - * Create a buffered block cipher without padding. - * - * @param cipher the underlying block cipher this buffering object wraps. - */ - public BufferedBlockCipher(BlockCipher cipher) { - this.cipher = cipher; + /** + * Create a buffered block cipher without padding. + * + * @param cipher the underlying block cipher this buffering object wraps. + */ + public BufferedBlockCipher(BlockCipher cipher) { + this.cipher = cipher; - buf = new byte[cipher.getBlockSize()]; - bufOff = 0; + buf = new byte[cipher.getBlockSize()]; + bufOff = 0; - // - // check if we can handle partial blocks on doFinal. - // - String name = cipher.getAlgorithmName(); - int idx = name.indexOf('/') + 1; + // + // check if we can handle partial blocks on doFinal. + // + String name = cipher.getAlgorithmName(); + int idx = name.indexOf('/') + 1; - pgpCFB = (idx > 0 && name.startsWith("PGP", idx)); + pgpCFB = (idx > 0 && name.startsWith("PGP", idx)); - if (pgpCFB || cipher instanceof StreamCipher) { - partialBlockOkay = true; - } else { - partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx))); + if (pgpCFB || cipher instanceof StreamCipher) { + partialBlockOkay = true; + } else { + partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx))); + } } - } - - /** - * return the cipher this object wraps. - * - * @return the cipher this object wraps. - */ - public BlockCipher getUnderlyingCipher() { - return cipher; - } - - /** - * initialise the cipher. - * - * @param forEncryption if true the cipher is initialised for encryption, if false for decryption. - * @param params the key and other data required by the cipher. - * @exception IllegalArgumentException if the params argument is inappropriate. - */ - public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException { - this.forEncryption = forEncryption; - - reset(); - - cipher.init(forEncryption, params); - } - - /** - * return the blocksize for the underlying cipher. - * - * @return the blocksize for the underlying cipher. - */ - public int getBlockSize() { - return cipher.getBlockSize(); - } - - /** - * return the size of the output buffer required for an update an input of len bytes. - * - * @param len the length of the input. - * @return the space required to accommodate a call to update with len bytes of input. - */ - public int getUpdateOutputSize(int len) { - int total = len + bufOff; - int leftOver; - - if (pgpCFB) { - leftOver = total % buf.length - (cipher.getBlockSize() + 2); - } else { - leftOver = total % buf.length; + + /** + * return the cipher this object wraps. + * + * @return the cipher this object wraps. + */ + public BlockCipher getUnderlyingCipher() { + return cipher; } - return total - leftOver; - } - - /** - * return the size of the output buffer required for an update plus a doFinal with an input of - * 'length' bytes. - * - * @param length the length of the input. - * @return the space required to accommodate a call to update and doFinal with 'length' bytes of - * input. - */ - public int getOutputSize(int length) { - // Note: Can assume partialBlockOkay is true for purposes of this calculation - return length + bufOff; - } - - /** - * process a single byte, producing an output block if necessary. - * - * @param in the input byte. - * @param out the space for any output that might be produced. - * @param outOff the offset from which the output will be copied. - * @return the number of output bytes copied to out. - * @exception DataLengthException if there isn't enough space in out. - * @exception IllegalStateException if the cipher isn't initialised. - */ - public int processByte(byte in, byte[] out, int outOff) - throws DataLengthException, IllegalStateException { - int resultLen = 0; - - buf[bufOff++] = in; - - if (bufOff == buf.length) { - resultLen = cipher.processBlock(buf, 0, out, outOff); - bufOff = 0; + /** + * initialise the cipher. + * + * @param forEncryption if true the cipher is initialised for encryption, if false for + * decryption. + * @param params the key and other data required by the cipher. + * @exception IllegalArgumentException if the params argument is inappropriate. + */ + public void init(boolean forEncryption, CipherParameters params) + throws IllegalArgumentException { + this.forEncryption = forEncryption; + + reset(); + + cipher.init(forEncryption, params); } - return resultLen; - } - - /** - * process an array of bytes, producing output if necessary. - * - * @param in the input byte array. - * @param inOff the offset at which the input data starts. - * @param len the number of bytes to be copied out of the input array. - * @param out the space for any output that might be produced. - * @param outOff the offset from which the output will be copied. - * @return the number of output bytes copied to out. - * @exception DataLengthException if there isn't enough space in out. - * @exception IllegalStateException if the cipher isn't initialised. - */ - public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) - throws DataLengthException, IllegalStateException { - if (len < 0) { - throw new IllegalArgumentException("Can't have a negative input length!"); + /** + * return the blocksize for the underlying cipher. + * + * @return the blocksize for the underlying cipher. + */ + public int getBlockSize() { + return cipher.getBlockSize(); } - int blockSize = getBlockSize(); - int length = getUpdateOutputSize(len); + /** + * return the size of the output buffer required for an update an input of len bytes. + * + * @param len the length of the input. + * @return the space required to accommodate a call to update with len bytes of input. + */ + public int getUpdateOutputSize(int len) { + int total = len + bufOff; + int leftOver; + + if (pgpCFB) { + leftOver = total % buf.length - (cipher.getBlockSize() + 2); + } else { + leftOver = total % buf.length; + } + + return total - leftOver; + } - if (length > 0) { - if ((outOff + length) > out.length) { - throw new OutputLengthException("output buffer too short"); - } + /** + * return the size of the output buffer required for an update plus a doFinal with an input of + * 'length' bytes. + * + * @param length the length of the input. + * @return the space required to accommodate a call to update and doFinal with 'length' bytes of + * input. + */ + public int getOutputSize(int length) { + // Note: Can assume partialBlockOkay is true for purposes of this calculation + return length + bufOff; } - int resultLen = 0; - int gapLen = buf.length - bufOff; + /** + * process a single byte, producing an output block if necessary. + * + * @param in the input byte. + * @param out the space for any output that might be produced. + * @param outOff the offset from which the output will be copied. + * @return the number of output bytes copied to out. + * @exception DataLengthException if there isn't enough space in out. + * @exception IllegalStateException if the cipher isn't initialised. + */ + public int processByte(byte in, byte[] out, int outOff) + throws DataLengthException, IllegalStateException { + int resultLen = 0; + + buf[bufOff++] = in; + + if (bufOff == buf.length) { + resultLen = cipher.processBlock(buf, 0, out, outOff); + bufOff = 0; + } - if (len > gapLen) { - System.arraycopy(in, inOff, buf, bufOff, gapLen); + return resultLen; + } - resultLen += cipher.processBlock(buf, 0, out, outOff); + /** + * process an array of bytes, producing output if necessary. + * + * @param in the input byte array. + * @param inOff the offset at which the input data starts. + * @param len the number of bytes to be copied out of the input array. + * @param out the space for any output that might be produced. + * @param outOff the offset from which the output will be copied. + * @return the number of output bytes copied to out. + * @exception DataLengthException if there isn't enough space in out. + * @exception IllegalStateException if the cipher isn't initialised. + */ + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) + throws DataLengthException, IllegalStateException { + if (len < 0) { + throw new IllegalArgumentException("Can't have a negative input length!"); + } - bufOff = 0; - len -= gapLen; - inOff += gapLen; + int blockSize = getBlockSize(); + int length = getUpdateOutputSize(len); - while (len > buf.length) { - resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen); + if (length > 0) { + if ((outOff + length) > out.length) { + throw new OutputLengthException("output buffer too short"); + } + } - len -= blockSize; - inOff += blockSize; - } - } + int resultLen = 0; + int gapLen = buf.length - bufOff; - System.arraycopy(in, inOff, buf, bufOff, len); + if (len > gapLen) { + System.arraycopy(in, inOff, buf, bufOff, gapLen); - bufOff += len; + resultLen += cipher.processBlock(buf, 0, out, outOff); - if (bufOff == buf.length) { - resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); - bufOff = 0; - } + bufOff = 0; + len -= gapLen; + inOff += gapLen; - return resultLen; - } - - /** - * Process the last block in the buffer. - * - * @param out the array the block currently being held is copied into. - * @param outOff the offset at which the copying starts. - * @return the number of output bytes copied to out. - * @exception DataLengthException if there is insufficient space in out for the output, or the - * input is not block size aligned and should be. - * @exception IllegalStateException if the underlying cipher is not initialised. - * @exception InvalidCipherTextException if padding is expected and not found. - * @exception DataLengthException if the input is not block size aligned. - */ - public int doFinal(byte[] out, int outOff) - throws DataLengthException, IllegalStateException, InvalidCipherTextException { - try { - int resultLen = 0; - - if (outOff + bufOff > out.length) { - throw new OutputLengthException("output buffer too short for doFinal()"); - } - - if (bufOff != 0) { - if (!partialBlockOkay) { - throw new DataLengthException("data not block size aligned"); + while (len > buf.length) { + resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen); + + len -= blockSize; + inOff += blockSize; + } } - cipher.processBlock(buf, 0, buf, 0); - resultLen = bufOff; - bufOff = 0; - System.arraycopy(buf, 0, out, outOff, resultLen); - } + System.arraycopy(in, inOff, buf, bufOff, len); + + bufOff += len; - return resultLen; - } finally { - reset(); + if (bufOff == buf.length) { + resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); + bufOff = 0; + } + + return resultLen; } - } - - /** - * Reset the buffer and cipher. After resetting the object is in the same state as it was after - * the last init (if there was one). - */ - public void reset() { - // - // clean the buffer. - // - for (int i = 0; i < buf.length; i++) { - buf[i] = 0; + + /** + * Process the last block in the buffer. + * + * @param out the array the block currently being held is copied into. + * @param outOff the offset at which the copying starts. + * @return the number of output bytes copied to out. + * @exception DataLengthException if there is insufficient space in out for the output, or the + * input is not block size aligned and should be. + * @exception IllegalStateException if the underlying cipher is not initialised. + * @exception InvalidCipherTextException if padding is expected and not found. + * @exception DataLengthException if the input is not block size aligned. + */ + public int doFinal(byte[] out, int outOff) + throws DataLengthException, IllegalStateException, InvalidCipherTextException { + try { + int resultLen = 0; + + if (outOff + bufOff > out.length) { + throw new OutputLengthException("output buffer too short for doFinal()"); + } + + if (bufOff != 0) { + if (!partialBlockOkay) { + throw new DataLengthException("data not block size aligned"); + } + + cipher.processBlock(buf, 0, buf, 0); + resultLen = bufOff; + bufOff = 0; + System.arraycopy(buf, 0, out, outOff, resultLen); + } + + return resultLen; + } finally { + reset(); + } } - bufOff = 0; + /** + * Reset the buffer and cipher. After resetting the object is in the same state as it was after + * the last init (if there was one). + */ + public void reset() { + // + // clean the buffer. + // + for (int i = 0; i < buf.length; i++) { + buf[i] = 0; + } - // - // reset the underlying cipher. - // - cipher.reset(); - } + bufOff = 0; + + // + // reset the underlying cipher. + // + cipher.reset(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/CryptoException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/CryptoException.java index 99d2b20bc..98ffcb9b2 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/CryptoException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/CryptoException.java @@ -3,34 +3,34 @@ /** the foundation class for the hard exceptions thrown by the crypto packages. */ public class CryptoException extends Exception { - private static final long serialVersionUID = -5478692243351474439L; - private Throwable cause; + private static final long serialVersionUID = -5478692243351474439L; + private Throwable cause; - /** base constructor. */ - public CryptoException() {} + /** base constructor. */ + public CryptoException() {} - /** - * create a CryptoException with the given message. - * - * @param message the message to be carried with the exception. - */ - public CryptoException(String message) { - super(message); - } + /** + * create a CryptoException with the given message. + * + * @param message the message to be carried with the exception. + */ + public CryptoException(String message) { + super(message); + } - /** - * Create a CryptoException with the given message and underlying cause. - * - * @param message message describing exception. - * @param cause the throwable that was the underlying cause. - */ - public CryptoException(String message, Throwable cause) { - super(message); + /** + * Create a CryptoException with the given message and underlying cause. + * + * @param message message describing exception. + * @param cause the throwable that was the underlying cause. + */ + public CryptoException(String message, Throwable cause) { + super(message); - this.cause = cause; - } + this.cause = cause; + } - public Throwable getCause() { - return cause; - } + public Throwable getCause() { + return cause; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/DataLengthException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/DataLengthException.java index 888f392b2..19d096d87 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/DataLengthException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/DataLengthException.java @@ -7,17 +7,17 @@ */ public class DataLengthException extends RuntimeCryptoException { - private static final long serialVersionUID = -3632378156242665876L; + private static final long serialVersionUID = -3632378156242665876L; - /** base constructor. */ - public DataLengthException() {} + /** base constructor. */ + public DataLengthException() {} - /** - * create a DataLengthException with the given message. - * - * @param message the message to be carried with the exception. - */ - public DataLengthException(String message) { - super(message); - } + /** + * create a DataLengthException with the given message. + * + * @param message the message to be carried with the exception. + */ + public DataLengthException(String message) { + super(message); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/Digest.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/Digest.java index 3b1cb9ace..894ab1dd3 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/Digest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/Digest.java @@ -3,44 +3,44 @@ /** interface that a message digest conforms to. */ public interface Digest { - /** - * return the algorithm name - * - * @return the algorithm name - */ - public String getAlgorithmName(); + /** + * return the algorithm name + * + * @return the algorithm name + */ + public String getAlgorithmName(); - /** - * return the size, in bytes, of the digest produced by this message digest. - * - * @return the size, in bytes, of the digest produced by this message digest. - */ - public int getDigestSize(); + /** + * return the size, in bytes, of the digest produced by this message digest. + * + * @return the size, in bytes, of the digest produced by this message digest. + */ + public int getDigestSize(); - /** - * update the message digest with a single byte. - * - * @param in the input byte to be entered. - */ - public void update(byte in); + /** + * update the message digest with a single byte. + * + * @param in the input byte to be entered. + */ + public void update(byte in); - /** - * update the message digest with a block of bytes. - * - * @param in the byte array containing the data. - * @param inOff the offset into the byte array where the data starts. - * @param len the length of the data. - */ - public void update(byte[] in, int inOff, int len); + /** + * update the message digest with a block of bytes. + * + * @param in the byte array containing the data. + * @param inOff the offset into the byte array where the data starts. + * @param len the length of the data. + */ + public void update(byte[] in, int inOff, int len); - /** - * close the digest, producing the final digest value. The doFinal call leaves the digest reset. - * - * @param out the array the digest is to be copied into. - * @param outOff the offset into the out array the digest is to start at. - */ - public int doFinal(byte[] out, int outOff); + /** + * close the digest, producing the final digest value. The doFinal call leaves the digest reset. + * + * @param out the array the digest is to be copied into. + * @param outOff the offset into the out array the digest is to start at. + */ + public int doFinal(byte[] out, int outOff); - /** reset the digest back to it's initial state. */ - public void reset(); + /** reset the digest back to it's initial state. */ + public void reset(); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/ExtendedDigest.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/ExtendedDigest.java index 4ed73a180..587946ed9 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/ExtendedDigest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/ExtendedDigest.java @@ -2,11 +2,11 @@ public interface ExtendedDigest extends Digest { - /** - * Return the size in bytes of the internal buffer the digest applies it's compression function - * to. - * - * @return byte length of the digests internal buffer. - */ - public int getByteLength(); + /** + * Return the size in bytes of the internal buffer the digest applies it's compression function + * to. + * + * @return byte length of the digests internal buffer. + */ + public int getByteLength(); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/InvalidCipherTextException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/InvalidCipherTextException.java index 7fd73f004..cd7dbde41 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/InvalidCipherTextException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/InvalidCipherTextException.java @@ -3,27 +3,27 @@ /** this exception is thrown whenever we find something we don't expect in a message. */ public class InvalidCipherTextException extends CryptoException { - private static final long serialVersionUID = 5927402763633918686L; + private static final long serialVersionUID = 5927402763633918686L; - /** base constructor. */ - public InvalidCipherTextException() {} + /** base constructor. */ + public InvalidCipherTextException() {} - /** - * create a InvalidCipherTextException with the given message. - * - * @param message the message to be carried with the exception. - */ - public InvalidCipherTextException(String message) { - super(message); - } + /** + * create a InvalidCipherTextException with the given message. + * + * @param message the message to be carried with the exception. + */ + public InvalidCipherTextException(String message) { + super(message); + } - /** - * create a InvalidCipherTextException with the given message. - * - * @param message the message to be carried with the exception. - * @param cause the root cause of the exception. - */ - public InvalidCipherTextException(String message, Throwable cause) { - super(message, cause); - } + /** + * create a InvalidCipherTextException with the given message. + * + * @param message the message to be carried with the exception. + * @param cause the root cause of the exception. + */ + public InvalidCipherTextException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/OutputLengthException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/OutputLengthException.java index 29422d210..613782904 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/OutputLengthException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/OutputLengthException.java @@ -2,9 +2,9 @@ public class OutputLengthException extends DataLengthException { - private static final long serialVersionUID = -4797999475167434240L; + private static final long serialVersionUID = -4797999475167434240L; - public OutputLengthException(String msg) { - super(msg); - } + public OutputLengthException(String msg) { + super(msg); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/RuntimeCryptoException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/RuntimeCryptoException.java index 014667f23..8ee48bbcf 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/RuntimeCryptoException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/RuntimeCryptoException.java @@ -3,17 +3,17 @@ /** the foundation class for the exceptions thrown by the crypto packages. */ public class RuntimeCryptoException extends RuntimeException { - private static final long serialVersionUID = -560419554349052616L; + private static final long serialVersionUID = -560419554349052616L; - /** base constructor. */ - public RuntimeCryptoException() {} + /** base constructor. */ + public RuntimeCryptoException() {} - /** - * create a RuntimeCryptoException with the given message. - * - * @param message the message to be carried with the exception. - */ - public RuntimeCryptoException(String message) { - super(message); - } + /** + * create a RuntimeCryptoException with the given message. + * + * @param message the message to be carried with the exception. + */ + public RuntimeCryptoException(String message) { + super(message); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/StreamCipher.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/StreamCipher.java index 0f5d337fe..0cf474db2 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/StreamCipher.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/StreamCipher.java @@ -2,47 +2,49 @@ /** the interface stream ciphers conform to. */ public interface StreamCipher { - /** - * Initialise the cipher. - * - * @param forEncryption if true the cipher is initialised for encryption, if false for decryption. - * @param params the key and other data required by the cipher. - * @exception IllegalArgumentException if the params argument is inappropriate. - */ - public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException; + /** + * Initialise the cipher. + * + * @param forEncryption if true the cipher is initialised for encryption, if false for + * decryption. + * @param params the key and other data required by the cipher. + * @exception IllegalArgumentException if the params argument is inappropriate. + */ + public void init(boolean forEncryption, CipherParameters params) + throws IllegalArgumentException; - /** - * Return the name of the algorithm the cipher implements. - * - * @return the name of the algorithm the cipher implements. - */ - public String getAlgorithmName(); + /** + * Return the name of the algorithm the cipher implements. + * + * @return the name of the algorithm the cipher implements. + */ + public String getAlgorithmName(); - /** - * encrypt/decrypt a single byte returning the result. - * - * @param in the byte to be processed. - * @return the result of processing the input byte. - */ - public byte returnByte(byte in); + /** + * encrypt/decrypt a single byte returning the result. + * + * @param in the byte to be processed. + * @return the result of processing the input byte. + */ + public byte returnByte(byte in); - /** - * process a block of bytes from in putting the result into out. - * - * @param in the input byte array. - * @param inOff the offset into the in array where the data to be processed starts. - * @param len the number of bytes to be processed. - * @param out the output buffer the processed bytes go into. - * @param outOff the offset into the output byte array the processed data starts at. - * @return the number of bytes produced - should always be len. - * @exception DataLengthException if the output buffer is too small. - */ - public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) - throws DataLengthException; + /** + * process a block of bytes from in putting the result into out. + * + * @param in the input byte array. + * @param inOff the offset into the in array where the data to be processed starts. + * @param len the number of bytes to be processed. + * @param out the output buffer the processed bytes go into. + * @param outOff the offset into the output byte array the processed data starts at. + * @return the number of bytes produced - should always be len. + * @exception DataLengthException if the output buffer is too small. + */ + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) + throws DataLengthException; - /** - * reset the cipher. This leaves it in the same state it was at after the last init (if there was - * one). - */ - public void reset(); + /** + * reset the cipher. This leaves it in the same state it was at after the last init (if there + * was one). + */ + public void reset(); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2Algorithm.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2Algorithm.java index 351812daa..fbff02f15 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2Algorithm.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2Algorithm.java @@ -16,521 +16,525 @@ */ public class SM2Algorithm { - // SM2算法推荐曲线参数 - public static final BigInteger p = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16); - public static final BigInteger a = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16); - public static final BigInteger b = - new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16); - public static final BigInteger n = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); - public static final BigInteger gx = - new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); - public static final BigInteger gy = - new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); - - private static final ECCurve sm2Curve = new ECCurve.Fp(p, a, b); - private static final ECPoint sm2Point = sm2Curve.createPoint(gx, gy); - - /* - * SM2加密 - * @param pbk 公钥 - * @param data 待加密的数据 - * @return byte[] 加密后的数据 - */ - public static byte[] encrypt(SM2PublicKey pbk, byte[] data) { - String buf = KeyUtils.bcdhex_to_aschex(pbk.getEncoded()); - String pbX = buf.substring(0, 64); - String pbY = buf.substring(64, 128); - return encrypt(pbX, pbY, data); - } - - /* - * SM2解密 - * @param pvk 私钥 - * @param cipher 待解密的数据 - * @return byte[] 解密后的数据 - */ - public static byte[] decrypt(SM2PrivateKey pvk, byte[] cipher) { - String buf = KeyUtils.bcdhex_to_aschex(pvk.getEncoded()); - return decrypt(buf, cipher); - } - - /* - * SM2加密 - * @param pbX 公钥X成份(16进制格式) - * @param pbY 公钥Y成份(16进制格式) - * @param data 待加密的数据 - * @return byte[] 加密后的数据 - */ - public static byte[] encrypt(String pbkX, String pbkY, byte[] data) { - byte[] t = null; - ECPoint c1 = null; - BigInteger x2 = null; - BigInteger y2 = null; - BigInteger x1 = new BigInteger(pbkX, 16); - BigInteger y1 = new BigInteger(pbkY, 16); - while (isEmpty(t)) { - BigInteger k = generateRand(32); - c1 = calculateC1(k); - ECPoint s = calculateS(x1, y1, k); - x2 = calculateX2(s); - y2 = calculateY2(s); - if (x2.toByteArray().length >= 32 && y2.toByteArray().length >= 32) { - t = kdf(x2, y2, data.length); - } + // SM2算法推荐曲线参数 + public static final BigInteger p = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16); + public static final BigInteger a = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16); + public static final BigInteger b = + new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16); + public static final BigInteger n = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); + public static final BigInteger gx = + new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); + public static final BigInteger gy = + new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); + + private static final ECCurve sm2Curve = new ECCurve.Fp(p, a, b); + private static final ECPoint sm2Point = sm2Curve.createPoint(gx, gy); + + /* + * SM2加密 + * @param pbk 公钥 + * @param data 待加密的数据 + * @return byte[] 加密后的数据 + */ + public static byte[] encrypt(SM2PublicKey pbk, byte[] data) { + String buf = KeyUtils.bcdhex_to_aschex(pbk.getEncoded()); + String pbX = buf.substring(0, 64); + String pbY = buf.substring(64, 128); + return encrypt(pbX, pbY, data); } - byte[] c2 = calculateC2(data, t); - byte[] c3 = calculateC3(x2, data, y2); - - // // 调试用(旧标准) - // byte[] c = getC(c1, c2, c3); - - byte[] c = getC(c1, c3, c2); - return c; - } - - /* - * SM2解密 - * @param pk 私钥(16进制格式) - * @param cipher 待解密的数据 - * @param byte[] 解密后的数据 - */ - @SuppressWarnings("deprecation") - public static byte[] decrypt(String pvk, byte[] data) { - String hexCipher = KeyUtils.bcdhex_to_aschex(data); - String pbX = hexCipher.substring(0, 64); - String pbY = hexCipher.substring(64, 128); - - // // 调试用(旧标准) - // byte[] c2 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(128, hexCipher.length() - 64)); - // byte[] c3 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(hexCipher.length() - 64, - // hexCipher.length())); - - byte[] c3 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(128, 192)); - byte[] c2 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(192, hexCipher.length())); - - ECPoint s = - calculateS(new BigInteger(pbX, 16), new BigInteger(pbY, 16), new BigInteger(pvk, 16)); - BigInteger x2 = s.getX().toBigInteger(); - BigInteger y2 = s.getY().toBigInteger(); - - byte[] t = kdf(x2, y2, c2.length); - if (isEmpty(t)) { - return null; + + /* + * SM2解密 + * @param pvk 私钥 + * @param cipher 待解密的数据 + * @return byte[] 解密后的数据 + */ + public static byte[] decrypt(SM2PrivateKey pvk, byte[] cipher) { + String buf = KeyUtils.bcdhex_to_aschex(pvk.getEncoded()); + return decrypt(buf, cipher); } - byte[] m = calculateC2(t, c2); - if (m == null) return null; - byte[] cc3 = calculateC3(x2, m, y2); - - boolean sign = true; - for (int i = 0; i < c3.length; i++) { - if (c3.length != cc3.length) { - sign = false; - break; - } - if (c3[i] != cc3[i]) { - sign = false; - break; - } + /* + * SM2加密 + * @param pbX 公钥X成份(16进制格式) + * @param pbY 公钥Y成份(16进制格式) + * @param data 待加密的数据 + * @return byte[] 加密后的数据 + */ + public static byte[] encrypt(String pbkX, String pbkY, byte[] data) { + byte[] t = null; + ECPoint c1 = null; + BigInteger x2 = null; + BigInteger y2 = null; + BigInteger x1 = new BigInteger(pbkX, 16); + BigInteger y1 = new BigInteger(pbkY, 16); + while (isEmpty(t)) { + BigInteger k = generateRand(32); + c1 = calculateC1(k); + ECPoint s = calculateS(x1, y1, k); + x2 = calculateX2(s); + y2 = calculateY2(s); + if (x2.toByteArray().length >= 32 && y2.toByteArray().length >= 32) { + t = kdf(x2, y2, data.length); + } + } + byte[] c2 = calculateC2(data, t); + byte[] c3 = calculateC3(x2, data, y2); + + // // 调试用(旧标准) + // byte[] c = getC(c1, c2, c3); + + byte[] c = getC(c1, c3, c2); + return c; } - // if(Arrays.equals(c3, cc3)) { // JAVA可判断两个数组的值是否相等,android不行 - - - if (sign) { - return m; - } else { - return null; + /* + * SM2解密 + * @param pk 私钥(16进制格式) + * @param cipher 待解密的数据 + * @param byte[] 解密后的数据 + */ + @SuppressWarnings("deprecation") + public static byte[] decrypt(String pvk, byte[] data) { + String hexCipher = KeyUtils.bcdhex_to_aschex(data); + String pbX = hexCipher.substring(0, 64); + String pbY = hexCipher.substring(64, 128); + + // // 调试用(旧标准) + // byte[] c2 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(128, hexCipher.length() - + // 64)); + // byte[] c3 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(hexCipher.length() - 64, + // hexCipher.length())); + + byte[] c3 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(128, 192)); + byte[] c2 = KeyUtils.aschex_to_bcdhex(hexCipher.substring(192, hexCipher.length())); + + ECPoint s = + calculateS( + new BigInteger(pbX, 16), new BigInteger(pbY, 16), new BigInteger(pvk, 16)); + BigInteger x2 = s.getX().toBigInteger(); + BigInteger y2 = s.getY().toBigInteger(); + + byte[] t = kdf(x2, y2, c2.length); + if (isEmpty(t)) { + return null; + } + + byte[] m = calculateC2(t, c2); + if (m == null) return null; + byte[] cc3 = calculateC3(x2, m, y2); + + boolean sign = true; + for (int i = 0; i < c3.length; i++) { + if (c3.length != cc3.length) { + sign = false; + break; + } + if (c3[i] != cc3[i]) { + sign = false; + break; + } + } + + // if(Arrays.equals(c3, cc3)) { // JAVA可判断两个数组的值是否相等,android不行 - - + if (sign) { + return m; + } else { + return null; + } } - } - - /* - * 第1步:生成随机数 k∈[1, n-1] - * @param length 需要生成随机数的长度 - * @return BigInteger 生成的随机数 - */ - private static BigInteger generateRand(int length) { - if (length > 32) { - return null; + + /* + * 第1步:生成随机数 k∈[1, n-1] + * @param length 需要生成随机数的长度 + * @return BigInteger 生成的随机数 + */ + private static BigInteger generateRand(int length) { + if (length > 32) { + return null; + } + BigInteger k = BigInteger.ZERO; + SecureRandom secureRandom = new SecureRandom(); + byte[] buf = new byte[length]; + while (k.compareTo(BigInteger.ZERO) <= 0 || k.compareTo(n) >= 0) { + secureRandom.nextBytes(buf); // 生成随机数 + k = new BigInteger(1, buf); // 正数(无符号格式) + } + return k; } - BigInteger k = BigInteger.ZERO; - SecureRandom secureRandom = new SecureRandom(); - byte[] buf = new byte[length]; - while (k.compareTo(BigInteger.ZERO) <= 0 || k.compareTo(n) >= 0) { - secureRandom.nextBytes(buf); // 生成随机数 - k = new BigInteger(1, buf); // 正数(无符号格式) + + /* + * 第2步:计算椭圆曲线点 C1=[k]G=(x1,y1) + */ + private static ECPoint calculateC1(BigInteger k) { + return sm2Point.multiply(k); } - return k; - } - - /* - * 第2步:计算椭圆曲线点 C1=[k]G=(x1,y1) - */ - private static ECPoint calculateC1(BigInteger k) { - return sm2Point.multiply(k); - } - - /* - * 第3步:计算椭圆曲线点 S=[k]Pb(Pb为公钥) - */ - private static ECPoint calculateS(BigInteger x1, BigInteger y1, BigInteger k) { - return sm2Curve.createPoint(x1, y1).multiply(k); - } - - /* - * 第4步:计算 [k]Pb=(x2,y2) - */ - @SuppressWarnings("deprecation") - private static BigInteger calculateX2(ECPoint s) { - return s.getX().toBigInteger(); - } - - @SuppressWarnings("deprecation") - private static BigInteger calculateY2(ECPoint s) { - return s.getY().toBigInteger(); - } - - /* - * 第5步:计算 t = KDF(x2, y2, keyLen) - */ - private static byte[] kdf(BigInteger x2, BigInteger y2, int keyLen) { - byte[] t = new byte[keyLen]; - - SM3Digest sm3 = new SM3Digest(); - byte[] sm3Ret = new byte[32]; - int ct = 1; - - int value = keyLen / 32; - int remainder = keyLen % 32; - - byte[] x2Buf = padding(x2.toByteArray()); - byte[] y2Buf = padding(y2.toByteArray()); - - int offset = 0; - for (int i = 0; i < value; i++) { - sm3.update(x2Buf, 0, x2Buf.length); - sm3.update(y2Buf, 0, y2Buf.length); - sm3.update((byte) (ct >> 24 & 0x00ff)); - sm3.update((byte) (ct >> 16 & 0x00ff)); - sm3.update((byte) (ct >> 8 & 0x00ff)); - sm3.update((byte) (ct & 0x00ff)); - sm3.doFinal(t, offset); - offset += 32; - ct++; + + /* + * 第3步:计算椭圆曲线点 S=[k]Pb(Pb为公钥) + */ + private static ECPoint calculateS(BigInteger x1, BigInteger y1, BigInteger k) { + return sm2Curve.createPoint(x1, y1).multiply(k); } - if (remainder != 0) { - sm3.update(x2Buf, 0, x2Buf.length); - sm3.update(y2Buf, 0, y2Buf.length); - sm3.update((byte) (ct >> 24 & 0x00ff)); - sm3.update((byte) (ct >> 16 & 0x00ff)); - sm3.update((byte) (ct >> 8 & 0x00ff)); - sm3.update((byte) (ct & 0x00ff)); - sm3.doFinal(sm3Ret, 0); + + /* + * 第4步:计算 [k]Pb=(x2,y2) + */ + @SuppressWarnings("deprecation") + private static BigInteger calculateX2(ECPoint s) { + return s.getX().toBigInteger(); } - System.arraycopy(sm3Ret, 0, t, offset, remainder); - return t; - } - - /* - * 第6步:计算 C2 = M xor t - */ - private static byte[] calculateC2(byte[] m, byte[] t) { - if (m == null || m.length != t.length) { - return null; + + @SuppressWarnings("deprecation") + private static BigInteger calculateY2(ECPoint s) { + return s.getY().toBigInteger(); } - byte[] bufOut = new byte[m.length]; - for (int i = 0; i < m.length; i++) { - bufOut[i] = (byte) (m[i] ^ t[i]); + + /* + * 第5步:计算 t = KDF(x2, y2, keyLen) + */ + private static byte[] kdf(BigInteger x2, BigInteger y2, int keyLen) { + byte[] t = new byte[keyLen]; + + SM3Digest sm3 = new SM3Digest(); + byte[] sm3Ret = new byte[32]; + int ct = 1; + + int value = keyLen / 32; + int remainder = keyLen % 32; + + byte[] x2Buf = padding(x2.toByteArray()); + byte[] y2Buf = padding(y2.toByteArray()); + + int offset = 0; + for (int i = 0; i < value; i++) { + sm3.update(x2Buf, 0, x2Buf.length); + sm3.update(y2Buf, 0, y2Buf.length); + sm3.update((byte) (ct >> 24 & 0x00ff)); + sm3.update((byte) (ct >> 16 & 0x00ff)); + sm3.update((byte) (ct >> 8 & 0x00ff)); + sm3.update((byte) (ct & 0x00ff)); + sm3.doFinal(t, offset); + offset += 32; + ct++; + } + if (remainder != 0) { + sm3.update(x2Buf, 0, x2Buf.length); + sm3.update(y2Buf, 0, y2Buf.length); + sm3.update((byte) (ct >> 24 & 0x00ff)); + sm3.update((byte) (ct >> 16 & 0x00ff)); + sm3.update((byte) (ct >> 8 & 0x00ff)); + sm3.update((byte) (ct & 0x00ff)); + sm3.doFinal(sm3Ret, 0); + } + System.arraycopy(sm3Ret, 0, t, offset, remainder); + return t; } - return bufOut; - } - - /* - * 第7步:计算 C3 = Hash(X2 || M || Y2) - */ - private static byte[] calculateC3(BigInteger x2, byte[] m, BigInteger y2) { - SM3Digest sm3 = new SM3Digest(); - byte[] c3 = new byte[32]; - byte[] x2Buf = padding(x2.toByteArray()); - byte[] y2Buf = padding(y2.toByteArray()); - sm3.update(x2Buf, 0, x2Buf.length); - sm3.update(m, 0, m.length); - sm3.update(y2Buf, 0, y2Buf.length); - sm3.doFinal(c3, 0); - return c3; - } - - /* - * 第8步:输出密文 C = C1||C3||C2 - * @param c1 公钥部分 - * @param c2 算法加密部分 - * @param c3 消息摘要部分(校验) - */ - @SuppressWarnings("deprecation") - private static byte[] getC(ECPoint c1, byte[] c3, byte[] c2) { - byte[] c = new byte[64 + c3.length + c2.length]; - - byte[] c1xBuf = padding(c1.getX().toBigInteger().toByteArray()); - byte[] c1yBuf = padding(c1.getY().toBigInteger().toByteArray()); - - System.arraycopy(c1xBuf, 0, c, 0, 32); - System.arraycopy(c1yBuf, 0, c, 32, 32); - System.arraycopy(c3, 0, c, 64, c3.length); - System.arraycopy(c2, 0, c, 64 + c3.length, c2.length); - return c; - } - - private static boolean isEmpty(byte[] t) { - if (t != null) { - for (int i = 0; i < t.length; i++) { - if (t[i] != (byte) 0) { - return false; + + /* + * 第6步:计算 C2 = M xor t + */ + private static byte[] calculateC2(byte[] m, byte[] t) { + if (m == null || m.length != t.length) { + return null; } - } + byte[] bufOut = new byte[m.length]; + for (int i = 0; i < m.length; i++) { + bufOut[i] = (byte) (m[i] ^ t[i]); + } + return bufOut; } - return true; - } - - /* - * 填充数据 - */ - private static byte[] padding(byte[] bi) { - if (bi.length == 32) { - return bi; - } else if (bi.length > 32) { - byte[] dest = new byte[32]; - System.arraycopy(bi, bi.length - 32, dest, 0, 32); - return dest; - } else { - byte[] dest = new byte[32]; - for (int i = 0; i < 32 - bi.length; i++) { - dest[i] = 0x00; - } - System.arraycopy(bi, 0, dest, 32 - bi.length, bi.length); - return dest; + + /* + * 第7步:计算 C3 = Hash(X2 || M || Y2) + */ + private static byte[] calculateC3(BigInteger x2, byte[] m, BigInteger y2) { + SM3Digest sm3 = new SM3Digest(); + byte[] c3 = new byte[32]; + byte[] x2Buf = padding(x2.toByteArray()); + byte[] y2Buf = padding(y2.toByteArray()); + sm3.update(x2Buf, 0, x2Buf.length); + sm3.update(m, 0, m.length); + sm3.update(y2Buf, 0, y2Buf.length); + sm3.doFinal(c3, 0); + return c3; } - } - - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - - private static byte[] USER_ID = KeyUtils.hex2byte("31323334353637383132333435363738"); - private static int mFieldSizeInBytes; - private static ECCurve curve256; - private static ECPoint g256; - - // 初始化曲线G - static { - curve256 = new ECCurve.Fp(p, a, b); - // 这里算出椭圆曲线 - g256 = curve256.createPoint(gx, gy); - mFieldSizeInBytes = (p.bitLength() + 7 >> 3); - } - - /** - * SM2私钥签名 - * - * @param md 待签名数据 - * @param privateKeyS - * @return - * @author fisco-bcos - */ - private static BigInteger[] Sign(byte[] md, BigInteger privateKeyS) { - SM3Digest sm3 = new SM3Digest(); - byte[] z = sm2GetZ(USER_ID, g256.multiply(privateKeyS)); - sm3.update(z, 0, z.length); - byte[] p = md; - sm3.update(p, 0, p.length); - byte[] hashData = new byte[32]; - sm3.doFinal(hashData, 0); - return SignSm3(hashData, privateKeyS); - } - - /** - * SM2私钥签名 - * - * @param hash 32字节hash - * @param privateKeyS - * @return - * @date 2015年12月3日 - * @author fisco-bcos - */ - private static BigInteger[] SignSm3(byte[] hash, BigInteger privateKeyS) { - byte[] hashData = ByteUtils.copyBytes(hash); - BigInteger e = new BigInteger(1, hashData); - BigInteger k = null; - ECPoint kp = null; - BigInteger r = null; - BigInteger s = null; - BigInteger userD = privateKeyS; - do { - do { - k = createRandom(); - kp = g256.multiply(k); - r = e.add(kp.getX().toBigInteger()); - r = r.mod(n); - } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n)); - BigInteger da_1 = userD.add(BigInteger.ONE).modInverse(n); - s = r.multiply(userD); - s = k.subtract(s); - s = s.multiply(da_1); - s = s.mod(n); - } while (s.equals(BigInteger.ZERO)); - BigInteger[] retRS = {r, s}; - return retRS; - } - - /** - * SM2公钥验签 - * - * @param msg - * @param signData - * @param biX - * @param biY - * @return - * @author fisco-bcos - */ - private static boolean verify(byte[] msg, byte[] signData, BigInteger biX, BigInteger biY) { - ECPoint userKey = curve256.createPoint(biX, biY); - byte[] btRS = signData; - byte[] btR = ByteUtils.subByteArray(btRS, 0, btRS.length / 2); - byte[] btS = ByteUtils.subByteArray(btRS, btR.length, btRS.length - btR.length); - BigInteger r = new BigInteger(1, btR); - // 检验 r ′ ∈[1, n-1]是否成立,若不成立则验证不通过; - if (!checkValidateK(r)) return false; - BigInteger s = new BigInteger(1, btS); - // 检验 s ′ ∈[1, n-1]是否成立,若不成立则验证不通过; - if (!checkValidateK(s)) return false; - - SM3Digest sm3 = new SM3Digest(); - byte[] z = sm2GetZ(USER_ID, userKey); - sm3.update(z, 0, z.length); - byte[] p = msg; - sm3.update(p, 0, p.length); - byte[] hashData = new byte[32]; - sm3.doFinal(hashData, 0); - - BigInteger e = new BigInteger(1, hashData); - - BigInteger t = r.add(s).mod(n); - if (t.equals(BigInteger.ZERO)) return false; - ECPoint x1y1 = g256.multiply(s); - x1y1 = x1y1.add(userKey.multiply(t)); - BigInteger R = e.add(x1y1.getX().toBigInteger()).mod(n); - - return r.equals(R); - } - - /** * 用随机数发生器产生随机数k ∈[1,n-1] */ - private static BigInteger createRandom() { - SecureRandom random = new SecureRandom(); - byte[] r = new byte[32]; - BigInteger k; - do { - random.nextBytes(r); - k = new BigInteger(1, r); - } while (!checkValidateK(k)); - return k; - } - - private static boolean checkValidateK(BigInteger k) { // k ∈[1,n-1] - if (k.compareTo(new BigInteger("0")) > 0 && k.compareTo(n) < 0) { - return true; + + /* + * 第8步:输出密文 C = C1||C3||C2 + * @param c1 公钥部分 + * @param c2 算法加密部分 + * @param c3 消息摘要部分(校验) + */ + @SuppressWarnings("deprecation") + private static byte[] getC(ECPoint c1, byte[] c3, byte[] c2) { + byte[] c = new byte[64 + c3.length + c2.length]; + + byte[] c1xBuf = padding(c1.getX().toBigInteger().toByteArray()); + byte[] c1yBuf = padding(c1.getY().toBigInteger().toByteArray()); + + System.arraycopy(c1xBuf, 0, c, 0, 32); + System.arraycopy(c1yBuf, 0, c, 32, 32); + System.arraycopy(c3, 0, c, 64, c3.length); + System.arraycopy(c2, 0, c, 64 + c3.length, c2.length); + return c; } - return false; - } - - /** - * 计算Za - * - * @param userId - * @param publicKey - * @return - * @date 2015年12月4日 - * @author fisco-bcos - */ - private static byte[] sm2GetZ(byte[] userId, ECPoint publicKey) { - SM3Digest sm3 = new SM3Digest(); - int BitsLength = userId.length << 3; - sm3.update((byte) (BitsLength >> 8 & 0xFF)); - sm3.update((byte) (BitsLength & 0xFF)); - - sm3BlockUpdate(sm3, userId); - sm3BlockUpdate(sm3, getEncoded(a)); - sm3BlockUpdate(sm3, getEncoded(b)); - sm3BlockUpdate(sm3, getEncoded(gx)); - sm3BlockUpdate(sm3, getEncoded(gy)); - sm3BlockUpdate(sm3, getEncoded(publicKey.getX().toBigInteger())); - sm3BlockUpdate(sm3, getEncoded(publicKey.getY().toBigInteger())); - - byte[] md = new byte[sm3.getDigestSize()]; - sm3.doFinal(md, 0); - - return md; - } - - private static void sm3BlockUpdate(SM3Digest sm3, byte[] bytes) { - sm3.update(bytes, 0, bytes.length); - } - - public static byte[] getEncoded(BigInteger value) { - byte[] bytes = BigIntegers.asUnsignedByteArray(value); - if (bytes.length > mFieldSizeInBytes) { - byte[] tmp = new byte[mFieldSizeInBytes]; - System.arraycopy(bytes, bytes.length - mFieldSizeInBytes, tmp, 0, mFieldSizeInBytes); - return tmp; + + private static boolean isEmpty(byte[] t) { + if (t != null) { + for (int i = 0; i < t.length; i++) { + if (t[i] != (byte) 0) { + return false; + } + } + } + return true; + } + + /* + * 填充数据 + */ + private static byte[] padding(byte[] bi) { + if (bi.length == 32) { + return bi; + } else if (bi.length > 32) { + byte[] dest = new byte[32]; + System.arraycopy(bi, bi.length - 32, dest, 0, 32); + return dest; + } else { + byte[] dest = new byte[32]; + for (int i = 0; i < 32 - bi.length; i++) { + dest[i] = 0x00; + } + System.arraycopy(bi, 0, dest, 32 - bi.length, bi.length); + return dest; + } } - if (bytes.length < mFieldSizeInBytes) { - byte[] tmp = new byte[mFieldSizeInBytes]; - System.arraycopy(bytes, 0, tmp, mFieldSizeInBytes - bytes.length, bytes.length); - return tmp; + + //////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////// + + private static byte[] USER_ID = KeyUtils.hex2byte("31323334353637383132333435363738"); + private static int mFieldSizeInBytes; + private static ECCurve curve256; + private static ECPoint g256; + + // 初始化曲线G + static { + curve256 = new ECCurve.Fp(p, a, b); + // 这里算出椭圆曲线 + g256 = curve256.createPoint(gx, gy); + mFieldSizeInBytes = (p.bitLength() + 7 >> 3); + } + + /** + * SM2私钥签名 + * + * @param md 待签名数据 + * @param privateKeyS + * @return + * @author fisco-bcos + */ + private static BigInteger[] Sign(byte[] md, BigInteger privateKeyS) { + SM3Digest sm3 = new SM3Digest(); + byte[] z = sm2GetZ(USER_ID, g256.multiply(privateKeyS)); + sm3.update(z, 0, z.length); + byte[] p = md; + sm3.update(p, 0, p.length); + byte[] hashData = new byte[32]; + sm3.doFinal(hashData, 0); + return SignSm3(hashData, privateKeyS); } - return bytes; - } - - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - public static byte[] sign(byte[] data, SM2PrivateKey pvk) throws IOException { - // return sign(data,pvk.getPvkHex()); - return sign(data, pvk.getD()); - } - - public static byte[] sign(byte[] data, BigInteger privateKeyS) throws IOException { - // BigInteger privateKeyS = new BigInteger(hexPvk, 16); - BigInteger[] rs = Sign(data, privateKeyS); - // byte[] r = getEncoded(rs[0]); - // byte[] s = getEncoded(rs[1]); - - ASN1Integer[] ars = new ASN1Integer[] {new ASN1Integer(rs[0]), new ASN1Integer(rs[1])}; - return new DERSequence(ars).getEncoded(ASN1Encoding.DER); - } - - public static boolean verify(byte[] data, byte[] signData, SM2PublicKey pbk) throws IOException { - return verify(data, signData, pbk.getPbkxHex(), pbk.getPbkyHex()); - } - - public static boolean verify(byte[] data, byte[] signData, String hexPbkX, String hexPbkY) - throws IOException { - BigInteger biX = new BigInteger(hexPbkX, 16); - BigInteger biY = new BigInteger(hexPbkY, 16); - - ASN1Sequence as = (ASN1Sequence) ASN1Primitive.fromByteArray(signData); - BigInteger[] rs = - new BigInteger[] { - ((ASN1Integer) as.getObjectAt(0)).getValue(), ((ASN1Integer) as.getObjectAt(1)).getValue() - }; - - byte[] r = getEncoded(rs[0]); - byte[] s = getEncoded(rs[1]); - - byte[] rsBytes = new byte[r.length + s.length]; - System.arraycopy(r, 0, rsBytes, 0, r.length); - System.arraycopy(s, 0, rsBytes, r.length, s.length); - - return verify(data, rsBytes, biX, biY); - } + /** + * SM2私钥签名 + * + * @param hash 32字节hash + * @param privateKeyS + * @return + * @date 2015年12月3日 + * @author fisco-bcos + */ + private static BigInteger[] SignSm3(byte[] hash, BigInteger privateKeyS) { + byte[] hashData = ByteUtils.copyBytes(hash); + BigInteger e = new BigInteger(1, hashData); + BigInteger k = null; + ECPoint kp = null; + BigInteger r = null; + BigInteger s = null; + BigInteger userD = privateKeyS; + do { + do { + k = createRandom(); + kp = g256.multiply(k); + r = e.add(kp.getX().toBigInteger()); + r = r.mod(n); + } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n)); + BigInteger da_1 = userD.add(BigInteger.ONE).modInverse(n); + s = r.multiply(userD); + s = k.subtract(s); + s = s.multiply(da_1); + s = s.mod(n); + } while (s.equals(BigInteger.ZERO)); + BigInteger[] retRS = {r, s}; + return retRS; + } + + /** + * SM2公钥验签 + * + * @param msg + * @param signData + * @param biX + * @param biY + * @return + * @author fisco-bcos + */ + private static boolean verify(byte[] msg, byte[] signData, BigInteger biX, BigInteger biY) { + ECPoint userKey = curve256.createPoint(biX, biY); + byte[] btRS = signData; + byte[] btR = ByteUtils.subByteArray(btRS, 0, btRS.length / 2); + byte[] btS = ByteUtils.subByteArray(btRS, btR.length, btRS.length - btR.length); + BigInteger r = new BigInteger(1, btR); + // 检验 r ′ ∈[1, n-1]是否成立,若不成立则验证不通过; + if (!checkValidateK(r)) return false; + BigInteger s = new BigInteger(1, btS); + // 检验 s ′ ∈[1, n-1]是否成立,若不成立则验证不通过; + if (!checkValidateK(s)) return false; + + SM3Digest sm3 = new SM3Digest(); + byte[] z = sm2GetZ(USER_ID, userKey); + sm3.update(z, 0, z.length); + byte[] p = msg; + sm3.update(p, 0, p.length); + byte[] hashData = new byte[32]; + sm3.doFinal(hashData, 0); + + BigInteger e = new BigInteger(1, hashData); + + BigInteger t = r.add(s).mod(n); + if (t.equals(BigInteger.ZERO)) return false; + ECPoint x1y1 = g256.multiply(s); + x1y1 = x1y1.add(userKey.multiply(t)); + BigInteger R = e.add(x1y1.getX().toBigInteger()).mod(n); + + return r.equals(R); + } + + /** * 用随机数发生器产生随机数k ∈[1,n-1] */ + private static BigInteger createRandom() { + SecureRandom random = new SecureRandom(); + byte[] r = new byte[32]; + BigInteger k; + do { + random.nextBytes(r); + k = new BigInteger(1, r); + } while (!checkValidateK(k)); + return k; + } + + private static boolean checkValidateK(BigInteger k) { // k ∈[1,n-1] + if (k.compareTo(new BigInteger("0")) > 0 && k.compareTo(n) < 0) { + return true; + } + return false; + } + + /** + * 计算Za + * + * @param userId + * @param publicKey + * @return + * @date 2015年12月4日 + * @author fisco-bcos + */ + private static byte[] sm2GetZ(byte[] userId, ECPoint publicKey) { + SM3Digest sm3 = new SM3Digest(); + int BitsLength = userId.length << 3; + sm3.update((byte) (BitsLength >> 8 & 0xFF)); + sm3.update((byte) (BitsLength & 0xFF)); + + sm3BlockUpdate(sm3, userId); + sm3BlockUpdate(sm3, getEncoded(a)); + sm3BlockUpdate(sm3, getEncoded(b)); + sm3BlockUpdate(sm3, getEncoded(gx)); + sm3BlockUpdate(sm3, getEncoded(gy)); + sm3BlockUpdate(sm3, getEncoded(publicKey.getX().toBigInteger())); + sm3BlockUpdate(sm3, getEncoded(publicKey.getY().toBigInteger())); + + byte[] md = new byte[sm3.getDigestSize()]; + sm3.doFinal(md, 0); + + return md; + } + + private static void sm3BlockUpdate(SM3Digest sm3, byte[] bytes) { + sm3.update(bytes, 0, bytes.length); + } + + public static byte[] getEncoded(BigInteger value) { + byte[] bytes = BigIntegers.asUnsignedByteArray(value); + if (bytes.length > mFieldSizeInBytes) { + byte[] tmp = new byte[mFieldSizeInBytes]; + System.arraycopy(bytes, bytes.length - mFieldSizeInBytes, tmp, 0, mFieldSizeInBytes); + return tmp; + } + if (bytes.length < mFieldSizeInBytes) { + byte[] tmp = new byte[mFieldSizeInBytes]; + System.arraycopy(bytes, 0, tmp, mFieldSizeInBytes - bytes.length, bytes.length); + return tmp; + } + + return bytes; + } + + //////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////// + public static byte[] sign(byte[] data, SM2PrivateKey pvk) throws IOException { + // return sign(data,pvk.getPvkHex()); + return sign(data, pvk.getD()); + } + + public static byte[] sign(byte[] data, BigInteger privateKeyS) throws IOException { + // BigInteger privateKeyS = new BigInteger(hexPvk, 16); + BigInteger[] rs = Sign(data, privateKeyS); + // byte[] r = getEncoded(rs[0]); + // byte[] s = getEncoded(rs[1]); + + ASN1Integer[] ars = new ASN1Integer[] {new ASN1Integer(rs[0]), new ASN1Integer(rs[1])}; + return new DERSequence(ars).getEncoded(ASN1Encoding.DER); + } + + public static boolean verify(byte[] data, byte[] signData, SM2PublicKey pbk) + throws IOException { + return verify(data, signData, pbk.getPbkxHex(), pbk.getPbkyHex()); + } + + public static boolean verify(byte[] data, byte[] signData, String hexPbkX, String hexPbkY) + throws IOException { + BigInteger biX = new BigInteger(hexPbkX, 16); + BigInteger biY = new BigInteger(hexPbkY, 16); + + ASN1Sequence as = (ASN1Sequence) ASN1Primitive.fromByteArray(signData); + BigInteger[] rs = + new BigInteger[] { + ((ASN1Integer) as.getObjectAt(0)).getValue(), + ((ASN1Integer) as.getObjectAt(1)).getValue() + }; + + byte[] r = getEncoded(rs[0]); + byte[] s = getEncoded(rs[1]); + + byte[] rsBytes = new byte[r.length + s.length]; + System.arraycopy(r, 0, rsBytes, 0, r.length); + System.arraycopy(s, 0, rsBytes, r.length, s.length); + + return verify(data, rsBytes, biX, biY); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2KeyGenerator.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2KeyGenerator.java index 50de197d9..a4e6823c3 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2KeyGenerator.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2KeyGenerator.java @@ -14,102 +14,104 @@ public class SM2KeyGenerator { - // SM2算法推荐曲线参数 - public final BigInteger p = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16); - public final BigInteger a = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16); - public final BigInteger b = - new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16); - public final BigInteger n = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); - public final BigInteger gx = - new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); - public final BigInteger gy = - new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); + // SM2算法推荐曲线参数 + public final BigInteger p = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16); + public final BigInteger a = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16); + public final BigInteger b = + new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16); + public final BigInteger n = + new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); + public final BigInteger gx = + new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); + public final BigInteger gy = + new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); - private ECDomainParameters ecdp; + private ECDomainParameters ecdp; - @SuppressWarnings("deprecation") - public SM2KeyGenerator() { - ECCurve curve = new ECCurve.Fp(p, a, b); - ECFieldElement x = new Fp(p, gx); - ECFieldElement y = new Fp(p, gy); - ECPoint point = new ECPoint.Fp(curve, x, y); - ecdp = new ECDomainParameters(curve, point, n); - } + @SuppressWarnings("deprecation") + public SM2KeyGenerator() { + ECCurve curve = new ECCurve.Fp(p, a, b); + ECFieldElement x = new Fp(p, gx); + ECFieldElement y = new Fp(p, gy); + ECPoint point = new ECPoint.Fp(curve, x, y); + ecdp = new ECDomainParameters(curve, point, n); + } - /* - * 根据数据生成SM2私钥 - * - * @param imei 手机序列号 - * - * @param pin pin码 - * - * @param rand 随机数 - * - * @return String 私钥(16进制字符串,256bits) - */ - private SM2PrivateKey generatePrivateKey() { - SecureRandom random = new SecureRandom(); - byte[] r = new byte[32]; - BigInteger k; - do { - random.nextBytes(r); - k = new BigInteger(1, r); - } while (!checkValidateK(k)); + /* + * 根据数据生成SM2私钥 + * + * @param imei 手机序列号 + * + * @param pin pin码 + * + * @param rand 随机数 + * + * @return String 私钥(16进制字符串,256bits) + */ + private SM2PrivateKey generatePrivateKey() { + SecureRandom random = new SecureRandom(); + byte[] r = new byte[32]; + BigInteger k; + do { + random.nextBytes(r); + k = new BigInteger(1, r); + } while (!checkValidateK(k)); - byte[] in = k.toByteArray(); - SM3Digest digest = new SM3Digest(); - byte[] out = new byte[32]; - digest.update(in, 0, in.length); - digest.doFinal(out, 0); + byte[] in = k.toByteArray(); + SM3Digest digest = new SM3Digest(); + byte[] out = new byte[32]; + digest.update(in, 0, in.length); + digest.doFinal(out, 0); - String value = KeyUtils.bcdhex_to_aschex(out); - return new SM2PrivateKey(new BigInteger(value, 16)); - } + String value = KeyUtils.bcdhex_to_aschex(out); + return new SM2PrivateKey(new BigInteger(value, 16)); + } - /* - * 根据数据生成SM2密钥对 - * - * @param imei 手机序列号 - * - * @param pin pin码 - * - * @param rand 随机数 - * - * @return KeyPair 密钥对 - */ - public KeyPair generateKeyPair() { - SM2PrivateKey privateKey = generatePrivateKey(); - ECPoint g = ecdp.getG(); - ECPoint p = g.multiply(privateKey.getD()); - SM2PublicKey publicKey = new SM2PublicKey(p); - return new KeyPair(publicKey, privateKey); - } + /* + * 根据数据生成SM2密钥对 + * + * @param imei 手机序列号 + * + * @param pin pin码 + * + * @param rand 随机数 + * + * @return KeyPair 密钥对 + */ + public KeyPair generateKeyPair() { + SM2PrivateKey privateKey = generatePrivateKey(); + ECPoint g = ecdp.getG(); + ECPoint p = g.multiply(privateKey.getD()); + SM2PublicKey publicKey = new SM2PublicKey(p); + return new KeyPair(publicKey, privateKey); + } - public KeyPair generateKeyPair(String privKey) { - SM2PrivateKey privateKey = new SM2PrivateKey(new BigInteger(privKey, 16)); - byte[] privateKeyBytes = privateKey.getEncoded(); - privateKey.setD(new BigInteger(Hex.toHexString(privateKeyBytes), 16)); - try { - ECPoint g = ecdp.getG(); - ECPoint p = g.multiply(privateKey.getD()); - // System.out.println("===d:" + privateKey.getD().toString(16)); - SM2PublicKey publicKey = new SM2PublicKey(p); - return new KeyPair(publicKey, privateKey); - } catch (Exception e) { - System.out.println("====generate keypair from priv key failed, error msg:" + e.getMessage()); - return null; + public KeyPair generateKeyPair(String privKey) { + SM2PrivateKey privateKey = new SM2PrivateKey(new BigInteger(privKey, 16)); + byte[] privateKeyBytes = privateKey.getEncoded(); + privateKey.setD(new BigInteger(Hex.toHexString(privateKeyBytes), 16)); + try { + ECPoint g = ecdp.getG(); + ECPoint p = g.multiply(privateKey.getD()); + // System.out.println("===d:" + privateKey.getD().toString(16)); + SM2PublicKey publicKey = new SM2PublicKey(p); + return new KeyPair(publicKey, privateKey); + } catch (Exception e) { + System.out.println( + "====generate keypair from priv key failed, error msg:" + e.getMessage()); + return null; + } } - } - private static boolean checkValidateK(BigInteger k) { // k ∈[1,n-1] - BigInteger ecc_n = - new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); - if (k.compareTo(new BigInteger("0")) > 0 && k.compareTo(ecc_n) < 0) { - return true; + private static boolean checkValidateK(BigInteger k) { // k ∈[1,n-1] + BigInteger ecc_n = + new BigInteger( + "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); + if (k.compareTo(new BigInteger("0")) > 0 && k.compareTo(ecc_n) < 0) { + return true; + } + return false; } - return false; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PrivateKey.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PrivateKey.java index fd81bad1f..6e5c5c3c6 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PrivateKey.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PrivateKey.java @@ -6,55 +6,55 @@ public class SM2PrivateKey implements PrivateKey { - private static final long serialVersionUID = -8642664675083754692L; - - private final String ALGORITHM = "SM2"; - private BigInteger d; - - public SM2PrivateKey() {}; - - public SM2PrivateKey(BigInteger d) { - this.d = d; - } - - public String getAlgorithm() { - return ALGORITHM; - } - - public byte[] getEncoded() { - return padding(d.toByteArray(), 32); - } - - public String getPvkHex() { - return KeyUtils.bcdhex_to_aschex(getEncoded()); - } - - public String getFormat() { - return getPvkHex(); - } - - public BigInteger getD() { - return d; - } - - public void setD(BigInteger d) { - this.d = d; - } - - public byte[] padding(byte[] key, int length) { - if (key.length == length) { - return key; - } else if (key.length > length) { - byte[] dest = new byte[length]; - System.arraycopy(key, key.length - length, dest, 0, length); - return dest; - } else { - byte[] dest = new byte[length]; - for (int i = 0; i < length - key.length; i++) { - dest[i] = 0x00; - } - System.arraycopy(key, 0, dest, length - key.length, key.length); - return dest; - } - } + private static final long serialVersionUID = -8642664675083754692L; + + private final String ALGORITHM = "SM2"; + private BigInteger d; + + public SM2PrivateKey() {}; + + public SM2PrivateKey(BigInteger d) { + this.d = d; + } + + public String getAlgorithm() { + return ALGORITHM; + } + + public byte[] getEncoded() { + return padding(d.toByteArray(), 32); + } + + public String getPvkHex() { + return KeyUtils.bcdhex_to_aschex(getEncoded()); + } + + public String getFormat() { + return getPvkHex(); + } + + public BigInteger getD() { + return d; + } + + public void setD(BigInteger d) { + this.d = d; + } + + public byte[] padding(byte[] key, int length) { + if (key.length == length) { + return key; + } else if (key.length > length) { + byte[] dest = new byte[length]; + System.arraycopy(key, key.length - length, dest, 0, length); + return dest; + } else { + byte[] dest = new byte[length]; + for (int i = 0; i < length - key.length; i++) { + dest[i] = 0x00; + } + System.arraycopy(key, 0, dest, length - key.length, key.length); + return dest; + } + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PublicKey.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PublicKey.java index 9441995f5..3f11604d4 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PublicKey.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/asymmetric/SM2PublicKey.java @@ -7,77 +7,77 @@ public class SM2PublicKey implements PublicKey { - private static final long serialVersionUID = 6196280185307032043L; - - private final String ALGORITHM = "SM2"; - private BigInteger x; - private BigInteger y; - private ECPoint p; - - public SM2PublicKey() {} - - @SuppressWarnings("deprecation") - public SM2PublicKey(ECPoint p) { - this.p = p; - this.x = p.getX().toBigInteger(); - this.y = p.getY().toBigInteger(); - } - - public String getAlgorithm() { - return ALGORITHM; - } - - public byte[] getEncoded() { - byte[] xBuf = padding(this.x.toByteArray(), 32); - byte[] yBuf = padding(this.y.toByteArray(), 32); - byte[] encoded = new byte[xBuf.length + yBuf.length]; - System.arraycopy(xBuf, 0, encoded, 0, xBuf.length); - System.arraycopy(yBuf, 0, encoded, xBuf.length, yBuf.length); - return encoded; - } - - public String getPbkxHex() { - return KeyUtils.bcdhex_to_aschex(padding(x.toByteArray(), 32)); - } - - public String getPbkyHex() { - return KeyUtils.bcdhex_to_aschex(padding(y.toByteArray(), 32)); - } - - public String getFormat() { - return getPbkxHex() + getPbkyHex(); - } - - public BigInteger getX() { - return x; - } - - public BigInteger getY() { - return y; - } - - public ECPoint getP() { - return p; - } - - public void setP(ECPoint p) { - this.p = p; - } - - public byte[] padding(byte[] key, int length) { - if (key.length == length) { - return key; - } else if (key.length > length) { - byte[] dest = new byte[length]; - System.arraycopy(key, key.length - length, dest, 0, length); - return dest; - } else { - byte[] dest = new byte[length]; - for (int i = 0; i < length - key.length; i++) { - dest[i] = 0x00; - } - System.arraycopy(key, 0, dest, length - key.length, key.length); - return dest; + private static final long serialVersionUID = 6196280185307032043L; + + private final String ALGORITHM = "SM2"; + private BigInteger x; + private BigInteger y; + private ECPoint p; + + public SM2PublicKey() {} + + @SuppressWarnings("deprecation") + public SM2PublicKey(ECPoint p) { + this.p = p; + this.x = p.getX().toBigInteger(); + this.y = p.getY().toBigInteger(); + } + + public String getAlgorithm() { + return ALGORITHM; + } + + public byte[] getEncoded() { + byte[] xBuf = padding(this.x.toByteArray(), 32); + byte[] yBuf = padding(this.y.toByteArray(), 32); + byte[] encoded = new byte[xBuf.length + yBuf.length]; + System.arraycopy(xBuf, 0, encoded, 0, xBuf.length); + System.arraycopy(yBuf, 0, encoded, xBuf.length, yBuf.length); + return encoded; + } + + public String getPbkxHex() { + return KeyUtils.bcdhex_to_aschex(padding(x.toByteArray(), 32)); + } + + public String getPbkyHex() { + return KeyUtils.bcdhex_to_aschex(padding(y.toByteArray(), 32)); + } + + public String getFormat() { + return getPbkxHex() + getPbkyHex(); + } + + public BigInteger getX() { + return x; + } + + public BigInteger getY() { + return y; + } + + public ECPoint getP() { + return p; + } + + public void setP(ECPoint p) { + this.p = p; + } + + public byte[] padding(byte[] key, int length) { + if (key.length == length) { + return key; + } else if (key.length > length) { + byte[] dest = new byte[length]; + System.arraycopy(key, key.length - length, dest, 0, length); + return dest; + } else { + byte[] dest = new byte[length]; + for (int i = 0; i < length - key.length; i++) { + dest[i] = 0x00; + } + System.arraycopy(key, 0, dest, length - key.length, key.length); + return dest; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/GeneralDigest.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/GeneralDigest.java index 54088abd1..f0be2240f 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/GeneralDigest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/GeneralDigest.java @@ -9,122 +9,122 @@ * pages 344 - 347. */ public abstract class GeneralDigest implements ExtendedDigest, Memoable { - private static final int BYTE_LENGTH = 64; + private static final int BYTE_LENGTH = 64; - private final byte[] xBuf = new byte[4]; - private int xBufOff; + private final byte[] xBuf = new byte[4]; + private int xBufOff; - private long byteCount; + private long byteCount; - /** Standard constructor */ - protected GeneralDigest() { - xBufOff = 0; - } - - /** - * Copy constructor. We are using copy constructors in place of the Object.clone() interface as - * this interface is not supported by J2ME. - */ - protected GeneralDigest(GeneralDigest t) { - copyIn(t); - } - - protected GeneralDigest(byte[] encodedState) { - System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length); - xBufOff = Pack.bigEndianToInt(encodedState, 4); - byteCount = Pack.bigEndianToLong(encodedState, 8); - } + /** Standard constructor */ + protected GeneralDigest() { + xBufOff = 0; + } - protected void copyIn(GeneralDigest t) { - System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); + /** + * Copy constructor. We are using copy constructors in place of the Object.clone() interface as + * this interface is not supported by J2ME. + */ + protected GeneralDigest(GeneralDigest t) { + copyIn(t); + } - xBufOff = t.xBufOff; - byteCount = t.byteCount; - } + protected GeneralDigest(byte[] encodedState) { + System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length); + xBufOff = Pack.bigEndianToInt(encodedState, 4); + byteCount = Pack.bigEndianToLong(encodedState, 8); + } - public void update(byte in) { - xBuf[xBufOff++] = in; + protected void copyIn(GeneralDigest t) { + System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); - if (xBufOff == xBuf.length) { - processWord(xBuf, 0); - xBufOff = 0; + xBufOff = t.xBufOff; + byteCount = t.byteCount; } - byteCount++; - } + public void update(byte in) { + xBuf[xBufOff++] = in; - public void update(byte[] in, int inOff, int len) { - // - // fill the current word - // - while ((xBufOff != 0) && (len > 0)) { - update(in[inOff]); + if (xBufOff == xBuf.length) { + processWord(xBuf, 0); + xBufOff = 0; + } - inOff++; - len--; + byteCount++; } - // - // process whole words. - // - while (len > xBuf.length) { - processWord(in, inOff); - - inOff += xBuf.length; - len -= xBuf.length; - byteCount += xBuf.length; + public void update(byte[] in, int inOff, int len) { + // + // fill the current word + // + while ((xBufOff != 0) && (len > 0)) { + update(in[inOff]); + + inOff++; + len--; + } + + // + // process whole words. + // + while (len > xBuf.length) { + processWord(in, inOff); + + inOff += xBuf.length; + len -= xBuf.length; + byteCount += xBuf.length; + } + + // + // load in the remainder. + // + while (len > 0) { + update(in[inOff]); + + inOff++; + len--; + } } - // - // load in the remainder. - // - while (len > 0) { - update(in[inOff]); + public void finish() { + long bitLength = (byteCount << 3); - inOff++; - len--; - } - } + // + // add the pad bytes. + // + update((byte) 128); - public void finish() { - long bitLength = (byteCount << 3); + while (xBufOff != 0) { + update((byte) 0); + } - // - // add the pad bytes. - // - update((byte) 128); + processLength(bitLength); - while (xBufOff != 0) { - update((byte) 0); + processBlock(); } - processLength(bitLength); - - processBlock(); - } - - public void reset() { - byteCount = 0; + public void reset() { + byteCount = 0; - xBufOff = 0; - for (int i = 0; i < xBuf.length; i++) { - xBuf[i] = 0; + xBufOff = 0; + for (int i = 0; i < xBuf.length; i++) { + xBuf[i] = 0; + } } - } - protected void populateState(byte[] state) { - System.arraycopy(xBuf, 0, state, 0, xBufOff); - Pack.intToBigEndian(xBufOff, state, 4); - Pack.longToBigEndian(byteCount, state, 8); - } + protected void populateState(byte[] state) { + System.arraycopy(xBuf, 0, state, 0, xBufOff); + Pack.intToBigEndian(xBufOff, state, 4); + Pack.longToBigEndian(byteCount, state, 8); + } - public int getByteLength() { - return BYTE_LENGTH; - } + public int getByteLength() { + return BYTE_LENGTH; + } - protected abstract void processWord(byte[] in, int inOff); + protected abstract void processWord(byte[] in, int inOff); - protected abstract void processLength(long bitLength); + protected abstract void processLength(long bitLength); - protected abstract void processBlock(); + protected abstract void processBlock(); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/SM3Digest.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/SM3Digest.java index 9a19184c0..67271f5ba 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/SM3Digest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/digests/SM3Digest.java @@ -13,270 +13,270 @@ */ public class SM3Digest extends GeneralDigest { - private static final int DIGEST_LENGTH = 32; // bytes - private static final int BLOCK_SIZE = 64 / 4; // of 32 bit ints (16 ints) + private static final int DIGEST_LENGTH = 32; // bytes + private static final int BLOCK_SIZE = 64 / 4; // of 32 bit ints (16 ints) + + private int[] V = new int[DIGEST_LENGTH / 4]; // in 32 bit ints (8 ints) + private int[] inwords = new int[BLOCK_SIZE]; + private int xOff; + + // Work-bufs used within processBlock() + private int[] W = new int[68]; + private int[] W1 = new int[64]; + + // Round constant T for processBlock() which is 32 bit integer rolled left + // up to (63 MOD 32) bit positions. + private static final int[] T = new int[64]; + + static { + for (int i = 0; i < 16; ++i) { + int t = 0x79CC4519; + T[i] = (t << i) | (t >>> (32 - i)); + } + for (int i = 16; i < 64; ++i) { + int n = i % 32; + int t = 0x7A879D8A; + T[i] = (t << n) | (t >>> (32 - n)); + } + } + + /** Standard constructor */ + public SM3Digest() { + reset(); + } + + /** Copy constructor. This will copy the state of the provided message digest. */ + public SM3Digest(SM3Digest t) { + super(t); + + copyIn(t); + } - private int[] V = new int[DIGEST_LENGTH / 4]; // in 32 bit ints (8 ints) - private int[] inwords = new int[BLOCK_SIZE]; - private int xOff; + private void copyIn(SM3Digest t) { + System.arraycopy(t.V, 0, this.V, 0, this.V.length); + System.arraycopy(t.inwords, 0, this.inwords, 0, this.inwords.length); + xOff = t.xOff; + } + + public String getAlgorithmName() { + return "SM3"; + } - // Work-bufs used within processBlock() - private int[] W = new int[68]; - private int[] W1 = new int[64]; + public int getDigestSize() { + return DIGEST_LENGTH; + } + + public Memoable copy() { + return new SM3Digest(this); + } - // Round constant T for processBlock() which is 32 bit integer rolled left - // up to (63 MOD 32) bit positions. - private static final int[] T = new int[64]; + public void reset(Memoable other) { + SM3Digest d = (SM3Digest) other; - static { - for (int i = 0; i < 16; ++i) { - int t = 0x79CC4519; - T[i] = (t << i) | (t >>> (32 - i)); + super.copyIn(d); + copyIn(d); } - for (int i = 16; i < 64; ++i) { - int n = i % 32; - int t = 0x7A879D8A; - T[i] = (t << n) | (t >>> (32 - n)); + + /** reset the chaining variables */ + public void reset() { + super.reset(); + + this.V[0] = 0x7380166F; + this.V[1] = 0x4914B2B9; + this.V[2] = 0x172442D7; + this.V[3] = 0xDA8A0600; + this.V[4] = 0xA96F30BC; + this.V[5] = 0x163138AA; + this.V[6] = 0xE38DEE4D; + this.V[7] = 0xB0FB0E4E; + + this.xOff = 0; } - } - - /** Standard constructor */ - public SM3Digest() { - reset(); - } - - /** Copy constructor. This will copy the state of the provided message digest. */ - public SM3Digest(SM3Digest t) { - super(t); - - copyIn(t); - } - - private void copyIn(SM3Digest t) { - System.arraycopy(t.V, 0, this.V, 0, this.V.length); - System.arraycopy(t.inwords, 0, this.inwords, 0, this.inwords.length); - xOff = t.xOff; - } - - public String getAlgorithmName() { - return "SM3"; - } - - public int getDigestSize() { - return DIGEST_LENGTH; - } - - public Memoable copy() { - return new SM3Digest(this); - } - - public void reset(Memoable other) { - SM3Digest d = (SM3Digest) other; - - super.copyIn(d); - copyIn(d); - } - - /** reset the chaining variables */ - public void reset() { - super.reset(); - - this.V[0] = 0x7380166F; - this.V[1] = 0x4914B2B9; - this.V[2] = 0x172442D7; - this.V[3] = 0xDA8A0600; - this.V[4] = 0xA96F30BC; - this.V[5] = 0x163138AA; - this.V[6] = 0xE38DEE4D; - this.V[7] = 0xB0FB0E4E; - - this.xOff = 0; - } - - public int doFinal(byte[] out, int outOff) { - finish(); - - Pack.intToBigEndian(this.V[0], out, outOff + 0); - Pack.intToBigEndian(this.V[1], out, outOff + 4); - Pack.intToBigEndian(this.V[2], out, outOff + 8); - Pack.intToBigEndian(this.V[3], out, outOff + 12); - Pack.intToBigEndian(this.V[4], out, outOff + 16); - Pack.intToBigEndian(this.V[5], out, outOff + 20); - Pack.intToBigEndian(this.V[6], out, outOff + 24); - Pack.intToBigEndian(this.V[7], out, outOff + 28); - - reset(); - - return DIGEST_LENGTH; - } - - protected void processWord(byte[] in, int inOff) { - // Note: Inlined for performance - // this.inwords[xOff] = Pack.bigEndianToInt(in, inOff); - int n = - (((in[inOff] & 0xff) << 24) - | ((in[++inOff] & 0xff) << 16) - | ((in[++inOff] & 0xff) << 8) - | ((in[++inOff] & 0xff))); - - this.inwords[this.xOff] = n; - ++this.xOff; - - if (this.xOff >= 16) { - processBlock(); + + public int doFinal(byte[] out, int outOff) { + finish(); + + Pack.intToBigEndian(this.V[0], out, outOff + 0); + Pack.intToBigEndian(this.V[1], out, outOff + 4); + Pack.intToBigEndian(this.V[2], out, outOff + 8); + Pack.intToBigEndian(this.V[3], out, outOff + 12); + Pack.intToBigEndian(this.V[4], out, outOff + 16); + Pack.intToBigEndian(this.V[5], out, outOff + 20); + Pack.intToBigEndian(this.V[6], out, outOff + 24); + Pack.intToBigEndian(this.V[7], out, outOff + 28); + + reset(); + + return DIGEST_LENGTH; } - } - protected void processLength(long bitLength) { - if (this.xOff > (BLOCK_SIZE - 2)) { - // xOff == 15 --> can't fit the 64 bit length field at tail.. - this.inwords[this.xOff] = 0; // fill with zero - ++this.xOff; + protected void processWord(byte[] in, int inOff) { + // Note: Inlined for performance + // this.inwords[xOff] = Pack.bigEndianToInt(in, inOff); + int n = + (((in[inOff] & 0xff) << 24) + | ((in[++inOff] & 0xff) << 16) + | ((in[++inOff] & 0xff) << 8) + | ((in[++inOff] & 0xff))); + + this.inwords[this.xOff] = n; + ++this.xOff; + + if (this.xOff >= 16) { + processBlock(); + } + } - processBlock(); + protected void processLength(long bitLength) { + if (this.xOff > (BLOCK_SIZE - 2)) { + // xOff == 15 --> can't fit the 64 bit length field at tail.. + this.inwords[this.xOff] = 0; // fill with zero + ++this.xOff; + + processBlock(); + } + // Fill with zero words, until reach 2nd to last slot + while (this.xOff < (BLOCK_SIZE - 2)) { + this.inwords[this.xOff] = 0; + ++this.xOff; + } + + // Store input data length in BITS + this.inwords[this.xOff++] = (int) (bitLength >>> 32); + this.inwords[this.xOff++] = (int) (bitLength); } - // Fill with zero words, until reach 2nd to last slot - while (this.xOff < (BLOCK_SIZE - 2)) { - this.inwords[this.xOff] = 0; - ++this.xOff; + + /* + * + * 3.4.2. Constants + * + * + * Tj = 79cc4519 when 0 < = j < = 15 Tj = 7a879d8a when 16 < = j < = 63 + * + * 3.4.3. Boolean function + * + * + * FFj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15 = (X AND Y) OR (X AND Z) + * OR (Y AND Z) when 16 < = j < = 63 + * + * GGj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15 = (X AND Y) OR (NOT X AND + * Z) when 16 < = j < = 63 + * + * The X, Y, Z in the fomular are words!GBP + * + * 3.4.4. Permutation function + * + * + * P0(X) = X XOR (X <<< 9) XOR (X <<< 17) ## ROLL, not SHIFT P1(X) = X XOR + * (X <<< 15) XOR (X <<< 23) ## ROLL, not SHIFT + * + * The X in the fomular are a word. + * + * ---------- + * + * Each ROLL converted to Java expression: + * + * ROLL 9 : ((x << 9) | (x >>> (32-9)))) ROLL 17 : ((x << 17) | (x >>> + * (32-17))) ROLL 15 : ((x << 15) | (x >>> (32-15))) ROLL 23 : ((x << 23) | + * (x >>> (32-23))) + */ + + private int P0(final int x) { + final int r9 = ((x << 9) | (x >>> (32 - 9))); + final int r17 = ((x << 17) | (x >>> (32 - 17))); + return (x ^ r9 ^ r17); } - // Store input data length in BITS - this.inwords[this.xOff++] = (int) (bitLength >>> 32); - this.inwords[this.xOff++] = (int) (bitLength); - } - - /* - * - * 3.4.2. Constants - * - * - * Tj = 79cc4519 when 0 < = j < = 15 Tj = 7a879d8a when 16 < = j < = 63 - * - * 3.4.3. Boolean function - * - * - * FFj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15 = (X AND Y) OR (X AND Z) - * OR (Y AND Z) when 16 < = j < = 63 - * - * GGj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15 = (X AND Y) OR (NOT X AND - * Z) when 16 < = j < = 63 - * - * The X, Y, Z in the fomular are words!GBP - * - * 3.4.4. Permutation function - * - * - * P0(X) = X XOR (X <<< 9) XOR (X <<< 17) ## ROLL, not SHIFT P1(X) = X XOR - * (X <<< 15) XOR (X <<< 23) ## ROLL, not SHIFT - * - * The X in the fomular are a word. - * - * ---------- - * - * Each ROLL converted to Java expression: - * - * ROLL 9 : ((x << 9) | (x >>> (32-9)))) ROLL 17 : ((x << 17) | (x >>> - * (32-17))) ROLL 15 : ((x << 15) | (x >>> (32-15))) ROLL 23 : ((x << 23) | - * (x >>> (32-23))) - */ - - private int P0(final int x) { - final int r9 = ((x << 9) | (x >>> (32 - 9))); - final int r17 = ((x << 17) | (x >>> (32 - 17))); - return (x ^ r9 ^ r17); - } - - private int P1(final int x) { - final int r15 = ((x << 15) | (x >>> (32 - 15))); - final int r23 = ((x << 23) | (x >>> (32 - 23))); - return (x ^ r15 ^ r23); - } - - private int FF0(final int x, final int y, final int z) { - return (x ^ y ^ z); - } - - private int FF1(final int x, final int y, final int z) { - return ((x & y) | (x & z) | (y & z)); - } - - private int GG0(final int x, final int y, final int z) { - return (x ^ y ^ z); - } - - private int GG1(final int x, final int y, final int z) { - return ((x & y) | ((~x) & z)); - } - - protected void processBlock() { - for (int j = 0; j < 16; ++j) { - this.W[j] = this.inwords[j]; + private int P1(final int x) { + final int r15 = ((x << 15) | (x >>> (32 - 15))); + final int r23 = ((x << 23) | (x >>> (32 - 23))); + return (x ^ r15 ^ r23); } - for (int j = 16; j < 68; ++j) { - int wj3 = this.W[j - 3]; - int r15 = ((wj3 << 15) | (wj3 >>> (32 - 15))); - int wj13 = this.W[j - 13]; - int r7 = ((wj13 << 7) | (wj13 >>> (32 - 7))); - this.W[j] = P1(this.W[j - 16] ^ this.W[j - 9] ^ r15) ^ r7 ^ this.W[j - 6]; + + private int FF0(final int x, final int y, final int z) { + return (x ^ y ^ z); } - for (int j = 0; j < 64; ++j) { - this.W1[j] = this.W[j] ^ this.W[j + 4]; + + private int FF1(final int x, final int y, final int z) { + return ((x & y) | (x & z) | (y & z)); } - int A = this.V[0]; - int B = this.V[1]; - int C = this.V[2]; - int D = this.V[3]; - int E = this.V[4]; - int F = this.V[5]; - int G = this.V[6]; - int H = this.V[7]; - - for (int j = 0; j < 16; ++j) { - int a12 = ((A << 12) | (A >>> (32 - 12))); - int s1_ = a12 + E + T[j]; - int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7))); - int SS2 = SS1 ^ a12; - int TT1 = FF0(A, B, C) + D + SS2 + this.W1[j]; - int TT2 = GG0(E, F, G) + H + SS1 + this.W[j]; - D = C; - C = ((B << 9) | (B >>> (32 - 9))); - B = A; - A = TT1; - H = G; - G = ((F << 19) | (F >>> (32 - 19))); - F = E; - E = P0(TT2); + private int GG0(final int x, final int y, final int z) { + return (x ^ y ^ z); } - // Different FF,GG functions on rounds 16..63 - for (int j = 16; j < 64; ++j) { - int a12 = ((A << 12) | (A >>> (32 - 12))); - int s1_ = a12 + E + T[j]; - int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7))); - int SS2 = SS1 ^ a12; - int TT1 = FF1(A, B, C) + D + SS2 + this.W1[j]; - int TT2 = GG1(E, F, G) + H + SS1 + this.W[j]; - D = C; - C = ((B << 9) | (B >>> (32 - 9))); - B = A; - A = TT1; - H = G; - G = ((F << 19) | (F >>> (32 - 19))); - F = E; - E = P0(TT2); + private int GG1(final int x, final int y, final int z) { + return ((x & y) | ((~x) & z)); } - this.V[0] ^= A; - this.V[1] ^= B; - this.V[2] ^= C; - this.V[3] ^= D; - this.V[4] ^= E; - this.V[5] ^= F; - this.V[6] ^= G; - this.V[7] ^= H; - - this.xOff = 0; - } + protected void processBlock() { + for (int j = 0; j < 16; ++j) { + this.W[j] = this.inwords[j]; + } + for (int j = 16; j < 68; ++j) { + int wj3 = this.W[j - 3]; + int r15 = ((wj3 << 15) | (wj3 >>> (32 - 15))); + int wj13 = this.W[j - 13]; + int r7 = ((wj13 << 7) | (wj13 >>> (32 - 7))); + this.W[j] = P1(this.W[j - 16] ^ this.W[j - 9] ^ r15) ^ r7 ^ this.W[j - 6]; + } + for (int j = 0; j < 64; ++j) { + this.W1[j] = this.W[j] ^ this.W[j + 4]; + } + + int A = this.V[0]; + int B = this.V[1]; + int C = this.V[2]; + int D = this.V[3]; + int E = this.V[4]; + int F = this.V[5]; + int G = this.V[6]; + int H = this.V[7]; + + for (int j = 0; j < 16; ++j) { + int a12 = ((A << 12) | (A >>> (32 - 12))); + int s1_ = a12 + E + T[j]; + int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7))); + int SS2 = SS1 ^ a12; + int TT1 = FF0(A, B, C) + D + SS2 + this.W1[j]; + int TT2 = GG0(E, F, G) + H + SS1 + this.W[j]; + D = C; + C = ((B << 9) | (B >>> (32 - 9))); + B = A; + A = TT1; + H = G; + G = ((F << 19) | (F >>> (32 - 19))); + F = E; + E = P0(TT2); + } + + // Different FF,GG functions on rounds 16..63 + for (int j = 16; j < 64; ++j) { + int a12 = ((A << 12) | (A >>> (32 - 12))); + int s1_ = a12 + E + T[j]; + int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7))); + int SS2 = SS1 ^ a12; + int TT1 = FF1(A, B, C) + D + SS2 + this.W1[j]; + int TT2 = GG1(E, F, G) + H + SS1 + this.W[j]; + D = C; + C = ((B << 9) | (B >>> (32 - 9))); + B = A; + A = TT1; + H = G; + G = ((F << 19) | (F >>> (32 - 19))); + F = E; + E = P0(TT2); + } + + this.V[0] ^= A; + this.V[1] ^= B; + this.V[2] ^= C; + this.V[3] ^= D; + this.V[4] ^= E; + this.V[5] ^= F; + this.V[6] ^= G; + this.V[7] ^= H; + + this.xOff = 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ECDomainParameters.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ECDomainParameters.java index fac188f38..354fbac4e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ECDomainParameters.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ECDomainParameters.java @@ -7,45 +7,45 @@ import org.fisco.bcos.web3j.crypto.gm.sm2.util.Arrays; public class ECDomainParameters implements ECConstants { - private ECCurve curve; - private byte[] seed; - private ECPoint G; - private BigInteger n; - private BigInteger h; - - public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n) { - this(curve, G, n, ONE, null); - } - - public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n, BigInteger h) { - this(curve, G, n, h, null); - } - - public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) { - this.curve = curve; - this.G = G.normalize(); - this.n = n; - this.h = h; - this.seed = seed; - } - - public ECCurve getCurve() { - return curve; - } - - public ECPoint getG() { - return G; - } - - public BigInteger getN() { - return n; - } - - public BigInteger getH() { - return h; - } - - public byte[] getSeed() { - return Arrays.clone(seed); - } + private ECCurve curve; + private byte[] seed; + private ECPoint G; + private BigInteger n; + private BigInteger h; + + public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n) { + this(curve, G, n, ONE, null); + } + + public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n, BigInteger h) { + this(curve, G, n, h, null); + } + + public ECDomainParameters(ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) { + this.curve = curve; + this.G = G.normalize(); + this.n = n; + this.h = h; + this.seed = seed; + } + + public ECCurve getCurve() { + return curve; + } + + public ECPoint getG() { + return G; + } + + public BigInteger getN() { + return n; + } + + public BigInteger getH() { + return h; + } + + public byte[] getSeed() { + return Arrays.clone(seed); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/KeyParameter.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/KeyParameter.java index 7f8f36bb5..08e3b728e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/KeyParameter.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/KeyParameter.java @@ -4,19 +4,19 @@ public class KeyParameter implements CipherParameters { - private byte[] key; + private byte[] key; - public KeyParameter(byte[] key) { - this(key, 0, key.length); - } + public KeyParameter(byte[] key) { + this(key, 0, key.length); + } - public KeyParameter(byte[] key, int keyOff, int keyLen) { - this.key = new byte[keyLen]; + public KeyParameter(byte[] key, int keyOff, int keyLen) { + this.key = new byte[keyLen]; - System.arraycopy(key, keyOff, this.key, 0, keyLen); - } + System.arraycopy(key, keyOff, this.key, 0, keyLen); + } - public byte[] getKey() { - return key; - } + public byte[] getKey() { + return key; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithIV.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithIV.java index bb22b7847..317a4b68a 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithIV.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithIV.java @@ -4,25 +4,25 @@ public class ParametersWithIV implements CipherParameters { - private byte[] iv; - private CipherParameters parameters; + private byte[] iv; + private CipherParameters parameters; - public ParametersWithIV(CipherParameters parameters, byte[] iv) { - this(parameters, iv, 0, iv.length); - } + public ParametersWithIV(CipherParameters parameters, byte[] iv) { + this(parameters, iv, 0, iv.length); + } - public ParametersWithIV(CipherParameters parameters, byte[] iv, int ivOff, int ivLen) { - this.iv = new byte[ivLen]; - this.parameters = parameters; + public ParametersWithIV(CipherParameters parameters, byte[] iv, int ivOff, int ivLen) { + this.iv = new byte[ivLen]; + this.parameters = parameters; - System.arraycopy(iv, ivOff, this.iv, 0, ivLen); - } + System.arraycopy(iv, ivOff, this.iv, 0, ivLen); + } - public byte[] getIV() { - return iv; - } + public byte[] getIV() { + return iv; + } - public CipherParameters getParameters() { - return parameters; - } + public CipherParameters getParameters() { + return parameters; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithRandom.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithRandom.java index 04364e2f0..a4c293f34 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithRandom.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/crypto/params/ParametersWithRandom.java @@ -5,23 +5,23 @@ public class ParametersWithRandom implements CipherParameters { - private SecureRandom random; - private CipherParameters parameters; + private SecureRandom random; + private CipherParameters parameters; - public ParametersWithRandom(CipherParameters parameters, SecureRandom random) { - this.random = random; - this.parameters = parameters; - } + public ParametersWithRandom(CipherParameters parameters, SecureRandom random) { + this.random = random; + this.parameters = parameters; + } - public ParametersWithRandom(CipherParameters parameters) { - this(parameters, new SecureRandom()); - } + public ParametersWithRandom(CipherParameters parameters) { + this(parameters, new SecureRandom()); + } - public SecureRandom getRandom() { - return random; - } + public SecureRandom getRandom() { + return random; + } - public CipherParameters getParameters() { - return parameters; - } + public CipherParameters getParameters() { + return parameters; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Arrays.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Arrays.java index 584a67752..4fc80282e 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Arrays.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Arrays.java @@ -5,785 +5,786 @@ /** General array utilities. */ public final class Arrays { - private Arrays() { - // static class, hide constructor - } - - public static boolean areEqual(boolean[] a, boolean[] b) { - if (a == b) { - return true; - } - - if (a == null || b == null) { - return false; + private Arrays() { + // static class, hide constructor } - if (a.length != b.length) { - return false; - } + public static boolean areEqual(boolean[] a, boolean[] b) { + if (a == b) { + return true; + } - for (int i = 0; i != a.length; i++) { - if (a[i] != b[i]) { - return false; - } - } + if (a == null || b == null) { + return false; + } - return true; - } + if (a.length != b.length) { + return false; + } - public static boolean areEqual(char[] a, char[] b) { - if (a == b) { - return true; - } + for (int i = 0; i != a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } - if (a == null || b == null) { - return false; + return true; } - if (a.length != b.length) { - return false; - } + public static boolean areEqual(char[] a, char[] b) { + if (a == b) { + return true; + } - for (int i = 0; i != a.length; i++) { - if (a[i] != b[i]) { - return false; - } - } + if (a == null || b == null) { + return false; + } - return true; - } + if (a.length != b.length) { + return false; + } - public static boolean areEqual(byte[] a, byte[] b) { - if (a == b) { - return true; - } + for (int i = 0; i != a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } - if (a == null || b == null) { - return false; + return true; } - if (a.length != b.length) { - return false; - } + public static boolean areEqual(byte[] a, byte[] b) { + if (a == b) { + return true; + } - for (int i = 0; i != a.length; i++) { - if (a[i] != b[i]) { - return false; - } - } + if (a == null || b == null) { + return false; + } - return true; - } + if (a.length != b.length) { + return false; + } - /** - * A constant time equals comparison - does not terminate early if test will fail. - * - * @param a first array - * @param b second array - * @return true if arrays equal, false otherwise. - */ - public static boolean constantTimeAreEqual(byte[] a, byte[] b) { - if (a == b) { - return true; - } + for (int i = 0; i != a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } - if (a == null || b == null) { - return false; + return true; } - if (a.length != b.length) { - return false; - } + /** + * A constant time equals comparison - does not terminate early if test will fail. + * + * @param a first array + * @param b second array + * @return true if arrays equal, false otherwise. + */ + public static boolean constantTimeAreEqual(byte[] a, byte[] b) { + if (a == b) { + return true; + } - int nonEqual = 0; + if (a == null || b == null) { + return false; + } - for (int i = 0; i != a.length; i++) { - nonEqual |= (a[i] ^ b[i]); - } + if (a.length != b.length) { + return false; + } - return nonEqual == 0; - } + int nonEqual = 0; - public static boolean areEqual(int[] a, int[] b) { - if (a == b) { - return true; - } + for (int i = 0; i != a.length; i++) { + nonEqual |= (a[i] ^ b[i]); + } - if (a == null || b == null) { - return false; + return nonEqual == 0; } - if (a.length != b.length) { - return false; - } + public static boolean areEqual(int[] a, int[] b) { + if (a == b) { + return true; + } - for (int i = 0; i != a.length; i++) { - if (a[i] != b[i]) { - return false; - } - } + if (a == null || b == null) { + return false; + } - return true; - } + if (a.length != b.length) { + return false; + } - public static boolean areEqual(long[] a, long[] b) { - if (a == b) { - return true; - } + for (int i = 0; i != a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } - if (a == null || b == null) { - return false; + return true; } - if (a.length != b.length) { - return false; - } + public static boolean areEqual(long[] a, long[] b) { + if (a == b) { + return true; + } - for (int i = 0; i != a.length; i++) { - if (a[i] != b[i]) { - return false; - } - } + if (a == null || b == null) { + return false; + } - return true; - } + if (a.length != b.length) { + return false; + } - public static boolean areEqual(Object[] a, Object[] b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - if (a.length != b.length) { - return false; - } - for (int i = 0; i != a.length; i++) { - Object objA = a[i], objB = b[i]; - if (objA == null) { - if (objB != null) { - return false; + for (int i = 0; i != a.length; i++) { + if (a[i] != b[i]) { + return false; + } } - } else if (!objA.equals(objB)) { - return false; - } - } - return true; - } - public static boolean contains(short[] a, short n) { - for (int i = 0; i < a.length; ++i) { - if (a[i] == n) { return true; - } } - return false; - } - public static boolean contains(int[] a, int n) { - for (int i = 0; i < a.length; ++i) { - if (a[i] == n) { + public static boolean areEqual(Object[] a, Object[] b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a.length != b.length) { + return false; + } + for (int i = 0; i != a.length; i++) { + Object objA = a[i], objB = b[i]; + if (objA == null) { + if (objB != null) { + return false; + } + } else if (!objA.equals(objB)) { + return false; + } + } return true; - } } - return false; - } - public static void fill(byte[] array, byte value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; + public static boolean contains(short[] a, short n) { + for (int i = 0; i < a.length; ++i) { + if (a[i] == n) { + return true; + } + } + return false; } - } - public static void fill(char[] array, char value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; + public static boolean contains(int[] a, int n) { + for (int i = 0; i < a.length; ++i) { + if (a[i] == n) { + return true; + } + } + return false; } - } - public static void fill(long[] array, long value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; + public static void fill(byte[] array, byte value) { + for (int i = 0; i < array.length; i++) { + array[i] = value; + } } - } - public static void fill(short[] array, short value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; + public static void fill(char[] array, char value) { + for (int i = 0; i < array.length; i++) { + array[i] = value; + } } - } - public static void fill(int[] array, int value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; + public static void fill(long[] array, long value) { + for (int i = 0; i < array.length; i++) { + array[i] = value; + } } - } - public static int hashCode(byte[] data) { - if (data == null) { - return 0; + public static void fill(short[] array, short value) { + for (int i = 0; i < array.length; i++) { + array[i] = value; + } } - int i = data.length; - int hc = i + 1; - - while (--i >= 0) { - hc *= 257; - hc ^= data[i]; + public static void fill(int[] array, int value) { + for (int i = 0; i < array.length; i++) { + array[i] = value; + } } - return hc; - } + public static int hashCode(byte[] data) { + if (data == null) { + return 0; + } - public static int hashCode(byte[] data, int off, int len) { - if (data == null) { - return 0; - } + int i = data.length; + int hc = i + 1; - int i = len; - int hc = i + 1; + while (--i >= 0) { + hc *= 257; + hc ^= data[i]; + } - while (--i >= 0) { - hc *= 257; - hc ^= data[off + i]; + return hc; } - return hc; - } + public static int hashCode(byte[] data, int off, int len) { + if (data == null) { + return 0; + } - public static int hashCode(char[] data) { - if (data == null) { - return 0; - } + int i = len; + int hc = i + 1; - int i = data.length; - int hc = i + 1; + while (--i >= 0) { + hc *= 257; + hc ^= data[off + i]; + } - while (--i >= 0) { - hc *= 257; - hc ^= data[i]; + return hc; } - return hc; - } - - public static int hashCode(int[][] ints) { - int hc = 0; + public static int hashCode(char[] data) { + if (data == null) { + return 0; + } - for (int i = 0; i != ints.length; i++) { - hc = hc * 257 + hashCode(ints[i]); - } + int i = data.length; + int hc = i + 1; - return hc; - } + while (--i >= 0) { + hc *= 257; + hc ^= data[i]; + } - public static int hashCode(int[] data) { - if (data == null) { - return 0; + return hc; } - int i = data.length; - int hc = i + 1; + public static int hashCode(int[][] ints) { + int hc = 0; + + for (int i = 0; i != ints.length; i++) { + hc = hc * 257 + hashCode(ints[i]); + } - while (--i >= 0) { - hc *= 257; - hc ^= data[i]; + return hc; } - return hc; - } + public static int hashCode(int[] data) { + if (data == null) { + return 0; + } - public static int hashCode(int[] data, int off, int len) { - if (data == null) { - return 0; - } + int i = data.length; + int hc = i + 1; - int i = len; - int hc = i + 1; + while (--i >= 0) { + hc *= 257; + hc ^= data[i]; + } - while (--i >= 0) { - hc *= 257; - hc ^= data[off + i]; + return hc; } - return hc; - } + public static int hashCode(int[] data, int off, int len) { + if (data == null) { + return 0; + } + + int i = len; + int hc = i + 1; - public static int hashCode(short[][][] shorts) { - int hc = 0; + while (--i >= 0) { + hc *= 257; + hc ^= data[off + i]; + } - for (int i = 0; i != shorts.length; i++) { - hc = hc * 257 + hashCode(shorts[i]); + return hc; } - return hc; - } + public static int hashCode(short[][][] shorts) { + int hc = 0; - public static int hashCode(short[][] shorts) { - int hc = 0; + for (int i = 0; i != shorts.length; i++) { + hc = hc * 257 + hashCode(shorts[i]); + } - for (int i = 0; i != shorts.length; i++) { - hc = hc * 257 + hashCode(shorts[i]); + return hc; } - return hc; - } + public static int hashCode(short[][] shorts) { + int hc = 0; - public static int hashCode(short[] data) { - if (data == null) { - return 0; + for (int i = 0; i != shorts.length; i++) { + hc = hc * 257 + hashCode(shorts[i]); + } + + return hc; } - int i = data.length; - int hc = i + 1; + public static int hashCode(short[] data) { + if (data == null) { + return 0; + } - while (--i >= 0) { - hc *= 257; - hc ^= (data[i] & 0xff); - } + int i = data.length; + int hc = i + 1; - return hc; - } + while (--i >= 0) { + hc *= 257; + hc ^= (data[i] & 0xff); + } - public static int hashCode(Object[] data) { - if (data == null) { - return 0; + return hc; } - int i = data.length; - int hc = i + 1; + public static int hashCode(Object[] data) { + if (data == null) { + return 0; + } - while (--i >= 0) { - hc *= 257; - hc ^= data[i].hashCode(); - } + int i = data.length; + int hc = i + 1; - return hc; - } + while (--i >= 0) { + hc *= 257; + hc ^= data[i].hashCode(); + } - public static byte[] clone(byte[] data) { - if (data == null) { - return null; + return hc; } - byte[] copy = new byte[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); + public static byte[] clone(byte[] data) { + if (data == null) { + return null; + } + byte[] copy = new byte[data.length]; - return copy; - } + System.arraycopy(data, 0, copy, 0, data.length); - public static byte[] clone(byte[] data, byte[] existing) { - if (data == null) { - return null; + return copy; } - if ((existing == null) || (existing.length != data.length)) { - return clone(data); - } - System.arraycopy(data, 0, existing, 0, existing.length); - return existing; - } - public static byte[][] clone(byte[][] data) { - if (data == null) { - return null; + public static byte[] clone(byte[] data, byte[] existing) { + if (data == null) { + return null; + } + if ((existing == null) || (existing.length != data.length)) { + return clone(data); + } + System.arraycopy(data, 0, existing, 0, existing.length); + return existing; } - byte[][] copy = new byte[data.length][]; + public static byte[][] clone(byte[][] data) { + if (data == null) { + return null; + } - for (int i = 0; i != copy.length; i++) { - copy[i] = clone(data[i]); - } + byte[][] copy = new byte[data.length][]; - return copy; - } + for (int i = 0; i != copy.length; i++) { + copy[i] = clone(data[i]); + } - public static byte[][][] clone(byte[][][] data) { - if (data == null) { - return null; + return copy; } - byte[][][] copy = new byte[data.length][][]; + public static byte[][][] clone(byte[][][] data) { + if (data == null) { + return null; + } - for (int i = 0; i != copy.length; i++) { - copy[i] = clone(data[i]); - } + byte[][][] copy = new byte[data.length][][]; - return copy; - } + for (int i = 0; i != copy.length; i++) { + copy[i] = clone(data[i]); + } - public static int[] clone(int[] data) { - if (data == null) { - return null; + return copy; } - int[] copy = new int[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); + public static int[] clone(int[] data) { + if (data == null) { + return null; + } + int[] copy = new int[data.length]; - return copy; - } + System.arraycopy(data, 0, copy, 0, data.length); - public static long[] clone(long[] data) { - if (data == null) { - return null; + return copy; } - long[] copy = new long[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); + public static long[] clone(long[] data) { + if (data == null) { + return null; + } + long[] copy = new long[data.length]; - return copy; - } + System.arraycopy(data, 0, copy, 0, data.length); - public static long[] clone(long[] data, long[] existing) { - if (data == null) { - return null; - } - if ((existing == null) || (existing.length != data.length)) { - return clone(data); + return copy; } - System.arraycopy(data, 0, existing, 0, existing.length); - return existing; - } - public static short[] clone(short[] data) { - if (data == null) { - return null; + public static long[] clone(long[] data, long[] existing) { + if (data == null) { + return null; + } + if ((existing == null) || (existing.length != data.length)) { + return clone(data); + } + System.arraycopy(data, 0, existing, 0, existing.length); + return existing; } - short[] copy = new short[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); + public static short[] clone(short[] data) { + if (data == null) { + return null; + } + short[] copy = new short[data.length]; - return copy; - } + System.arraycopy(data, 0, copy, 0, data.length); - public static BigInteger[] clone(BigInteger[] data) { - if (data == null) { - return null; + return copy; } - BigInteger[] copy = new BigInteger[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); - - return copy; - } + public static BigInteger[] clone(BigInteger[] data) { + if (data == null) { + return null; + } + BigInteger[] copy = new BigInteger[data.length]; - public static byte[] copyOf(byte[] data, int newLength) { - byte[] tmp = new byte[newLength]; + System.arraycopy(data, 0, copy, 0, data.length); - if (newLength < data.length) { - System.arraycopy(data, 0, tmp, 0, newLength); - } else { - System.arraycopy(data, 0, tmp, 0, data.length); + return copy; } - return tmp; - } + public static byte[] copyOf(byte[] data, int newLength) { + byte[] tmp = new byte[newLength]; - public static char[] copyOf(char[] data, int newLength) { - char[] tmp = new char[newLength]; + if (newLength < data.length) { + System.arraycopy(data, 0, tmp, 0, newLength); + } else { + System.arraycopy(data, 0, tmp, 0, data.length); + } - if (newLength < data.length) { - System.arraycopy(data, 0, tmp, 0, newLength); - } else { - System.arraycopy(data, 0, tmp, 0, data.length); + return tmp; } - return tmp; - } + public static char[] copyOf(char[] data, int newLength) { + char[] tmp = new char[newLength]; - public static int[] copyOf(int[] data, int newLength) { - int[] tmp = new int[newLength]; + if (newLength < data.length) { + System.arraycopy(data, 0, tmp, 0, newLength); + } else { + System.arraycopy(data, 0, tmp, 0, data.length); + } - if (newLength < data.length) { - System.arraycopy(data, 0, tmp, 0, newLength); - } else { - System.arraycopy(data, 0, tmp, 0, data.length); + return tmp; } - return tmp; - } + public static int[] copyOf(int[] data, int newLength) { + int[] tmp = new int[newLength]; - public static long[] copyOf(long[] data, int newLength) { - long[] tmp = new long[newLength]; + if (newLength < data.length) { + System.arraycopy(data, 0, tmp, 0, newLength); + } else { + System.arraycopy(data, 0, tmp, 0, data.length); + } - if (newLength < data.length) { - System.arraycopy(data, 0, tmp, 0, newLength); - } else { - System.arraycopy(data, 0, tmp, 0, data.length); + return tmp; } - return tmp; - } + public static long[] copyOf(long[] data, int newLength) { + long[] tmp = new long[newLength]; - public static BigInteger[] copyOf(BigInteger[] data, int newLength) { - BigInteger[] tmp = new BigInteger[newLength]; + if (newLength < data.length) { + System.arraycopy(data, 0, tmp, 0, newLength); + } else { + System.arraycopy(data, 0, tmp, 0, data.length); + } - if (newLength < data.length) { - System.arraycopy(data, 0, tmp, 0, newLength); - } else { - System.arraycopy(data, 0, tmp, 0, data.length); + return tmp; } - return tmp; - } - - /** - * Make a copy of a range of bytes from the passed in data array. The range can extend beyond the - * end of the input array, in which case the return array will be padded with zeroes. - * - * @param data the array from which the data is to be copied. - * @param from the start index at which the copying should take place. - * @param to the final index of the range (exclusive). - * @return a new byte array containing the range given. - */ - public static byte[] copyOfRange(byte[] data, int from, int to) { - int newLength = getLength(from, to); + public static BigInteger[] copyOf(BigInteger[] data, int newLength) { + BigInteger[] tmp = new BigInteger[newLength]; - byte[] tmp = new byte[newLength]; + if (newLength < data.length) { + System.arraycopy(data, 0, tmp, 0, newLength); + } else { + System.arraycopy(data, 0, tmp, 0, data.length); + } - if (data.length - from < newLength) { - System.arraycopy(data, from, tmp, 0, data.length - from); - } else { - System.arraycopy(data, from, tmp, 0, newLength); + return tmp; } - return tmp; - } + /** + * Make a copy of a range of bytes from the passed in data array. The range can extend beyond + * the end of the input array, in which case the return array will be padded with zeroes. + * + * @param data the array from which the data is to be copied. + * @param from the start index at which the copying should take place. + * @param to the final index of the range (exclusive). + * @return a new byte array containing the range given. + */ + public static byte[] copyOfRange(byte[] data, int from, int to) { + int newLength = getLength(from, to); - public static int[] copyOfRange(int[] data, int from, int to) { - int newLength = getLength(from, to); + byte[] tmp = new byte[newLength]; - int[] tmp = new int[newLength]; + if (data.length - from < newLength) { + System.arraycopy(data, from, tmp, 0, data.length - from); + } else { + System.arraycopy(data, from, tmp, 0, newLength); + } - if (data.length - from < newLength) { - System.arraycopy(data, from, tmp, 0, data.length - from); - } else { - System.arraycopy(data, from, tmp, 0, newLength); + return tmp; } - return tmp; - } + public static int[] copyOfRange(int[] data, int from, int to) { + int newLength = getLength(from, to); - public static long[] copyOfRange(long[] data, int from, int to) { - int newLength = getLength(from, to); + int[] tmp = new int[newLength]; - long[] tmp = new long[newLength]; + if (data.length - from < newLength) { + System.arraycopy(data, from, tmp, 0, data.length - from); + } else { + System.arraycopy(data, from, tmp, 0, newLength); + } - if (data.length - from < newLength) { - System.arraycopy(data, from, tmp, 0, data.length - from); - } else { - System.arraycopy(data, from, tmp, 0, newLength); + return tmp; } - return tmp; - } + public static long[] copyOfRange(long[] data, int from, int to) { + int newLength = getLength(from, to); - public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to) { - int newLength = getLength(from, to); + long[] tmp = new long[newLength]; - BigInteger[] tmp = new BigInteger[newLength]; + if (data.length - from < newLength) { + System.arraycopy(data, from, tmp, 0, data.length - from); + } else { + System.arraycopy(data, from, tmp, 0, newLength); + } - if (data.length - from < newLength) { - System.arraycopy(data, from, tmp, 0, data.length - from); - } else { - System.arraycopy(data, from, tmp, 0, newLength); + return tmp; } - return tmp; - } + public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to) { + int newLength = getLength(from, to); - private static int getLength(int from, int to) { - int newLength = to - from; - if (newLength < 0) { - StringBuffer sb = new StringBuffer(from); - sb.append(" > ").append(to); - throw new IllegalArgumentException(sb.toString()); - } - return newLength; - } + BigInteger[] tmp = new BigInteger[newLength]; - public static byte[] append(byte[] a, byte b) { - if (a == null) { - return new byte[] {b}; - } + if (data.length - from < newLength) { + System.arraycopy(data, from, tmp, 0, data.length - from); + } else { + System.arraycopy(data, from, tmp, 0, newLength); + } - int length = a.length; - byte[] result = new byte[length + 1]; - System.arraycopy(a, 0, result, 0, length); - result[length] = b; - return result; - } + return tmp; + } - public static short[] append(short[] a, short b) { - if (a == null) { - return new short[] {b}; + private static int getLength(int from, int to) { + int newLength = to - from; + if (newLength < 0) { + StringBuffer sb = new StringBuffer(from); + sb.append(" > ").append(to); + throw new IllegalArgumentException(sb.toString()); + } + return newLength; } - int length = a.length; - short[] result = new short[length + 1]; - System.arraycopy(a, 0, result, 0, length); - result[length] = b; - return result; - } + public static byte[] append(byte[] a, byte b) { + if (a == null) { + return new byte[] {b}; + } - public static int[] append(int[] a, int b) { - if (a == null) { - return new int[] {b}; + int length = a.length; + byte[] result = new byte[length + 1]; + System.arraycopy(a, 0, result, 0, length); + result[length] = b; + return result; } - int length = a.length; - int[] result = new int[length + 1]; - System.arraycopy(a, 0, result, 0, length); - result[length] = b; - return result; - } + public static short[] append(short[] a, short b) { + if (a == null) { + return new short[] {b}; + } - public static byte[] concatenate(byte[] a, byte[] b) { - if (a != null && b != null) { - byte[] rv = new byte[a.length + b.length]; + int length = a.length; + short[] result = new short[length + 1]; + System.arraycopy(a, 0, result, 0, length); + result[length] = b; + return result; + } - System.arraycopy(a, 0, rv, 0, a.length); - System.arraycopy(b, 0, rv, a.length, b.length); + public static int[] append(int[] a, int b) { + if (a == null) { + return new int[] {b}; + } - return rv; - } else if (b != null) { - return clone(b); - } else { - return clone(a); + int length = a.length; + int[] result = new int[length + 1]; + System.arraycopy(a, 0, result, 0, length); + result[length] = b; + return result; } - } - public static byte[] concatenate(byte[] a, byte[] b, byte[] c) { - if (a != null && b != null && c != null) { - byte[] rv = new byte[a.length + b.length + c.length]; + public static byte[] concatenate(byte[] a, byte[] b) { + if (a != null && b != null) { + byte[] rv = new byte[a.length + b.length]; - System.arraycopy(a, 0, rv, 0, a.length); - System.arraycopy(b, 0, rv, a.length, b.length); - System.arraycopy(c, 0, rv, a.length + b.length, c.length); + System.arraycopy(a, 0, rv, 0, a.length); + System.arraycopy(b, 0, rv, a.length, b.length); - return rv; - } else if (b == null) { - return concatenate(a, c); - } else { - return concatenate(a, b); + return rv; + } else if (b != null) { + return clone(b); + } else { + return clone(a); + } } - } - public static byte[] concatenate(byte[] a, byte[] b, byte[] c, byte[] d) { - if (a != null && b != null && c != null && d != null) { - byte[] rv = new byte[a.length + b.length + c.length + d.length]; + public static byte[] concatenate(byte[] a, byte[] b, byte[] c) { + if (a != null && b != null && c != null) { + byte[] rv = new byte[a.length + b.length + c.length]; - System.arraycopy(a, 0, rv, 0, a.length); - System.arraycopy(b, 0, rv, a.length, b.length); - System.arraycopy(c, 0, rv, a.length + b.length, c.length); - System.arraycopy(d, 0, rv, a.length + b.length + c.length, d.length); + System.arraycopy(a, 0, rv, 0, a.length); + System.arraycopy(b, 0, rv, a.length, b.length); + System.arraycopy(c, 0, rv, a.length + b.length, c.length); - return rv; - } else if (d == null) { - return concatenate(a, b, c); - } else if (c == null) { - return concatenate(a, b, d); - } else if (b == null) { - return concatenate(a, c, d); - } else { - return concatenate(b, c, d); + return rv; + } else if (b == null) { + return concatenate(a, c); + } else { + return concatenate(a, b); + } } - } - public static int[] concatenate(int[] a, int[] b) { - if (a == null) { - return clone(b); - } - if (b == null) { - return clone(a); + public static byte[] concatenate(byte[] a, byte[] b, byte[] c, byte[] d) { + if (a != null && b != null && c != null && d != null) { + byte[] rv = new byte[a.length + b.length + c.length + d.length]; + + System.arraycopy(a, 0, rv, 0, a.length); + System.arraycopy(b, 0, rv, a.length, b.length); + System.arraycopy(c, 0, rv, a.length + b.length, c.length); + System.arraycopy(d, 0, rv, a.length + b.length + c.length, d.length); + + return rv; + } else if (d == null) { + return concatenate(a, b, c); + } else if (c == null) { + return concatenate(a, b, d); + } else if (b == null) { + return concatenate(a, c, d); + } else { + return concatenate(b, c, d); + } } - int[] c = new int[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } + public static int[] concatenate(int[] a, int[] b) { + if (a == null) { + return clone(b); + } + if (b == null) { + return clone(a); + } - public static byte[] prepend(byte[] a, byte b) { - if (a == null) { - return new byte[] {b}; + int[] c = new int[a.length + b.length]; + System.arraycopy(a, 0, c, 0, a.length); + System.arraycopy(b, 0, c, a.length, b.length); + return c; } - int length = a.length; - byte[] result = new byte[length + 1]; - System.arraycopy(a, 0, result, 1, length); - result[0] = b; - return result; - } + public static byte[] prepend(byte[] a, byte b) { + if (a == null) { + return new byte[] {b}; + } - public static short[] prepend(short[] a, short b) { - if (a == null) { - return new short[] {b}; + int length = a.length; + byte[] result = new byte[length + 1]; + System.arraycopy(a, 0, result, 1, length); + result[0] = b; + return result; } - int length = a.length; - short[] result = new short[length + 1]; - System.arraycopy(a, 0, result, 1, length); - result[0] = b; - return result; - } + public static short[] prepend(short[] a, short b) { + if (a == null) { + return new short[] {b}; + } - public static int[] prepend(int[] a, int b) { - if (a == null) { - return new int[] {b}; + int length = a.length; + short[] result = new short[length + 1]; + System.arraycopy(a, 0, result, 1, length); + result[0] = b; + return result; } - int length = a.length; - int[] result = new int[length + 1]; - System.arraycopy(a, 0, result, 1, length); - result[0] = b; - return result; - } + public static int[] prepend(int[] a, int b) { + if (a == null) { + return new int[] {b}; + } - public static byte[] reverse(byte[] a) { - if (a == null) { - return null; + int length = a.length; + int[] result = new int[length + 1]; + System.arraycopy(a, 0, result, 1, length); + result[0] = b; + return result; } - int p1 = 0, p2 = a.length; - byte[] result = new byte[p2]; + public static byte[] reverse(byte[] a) { + if (a == null) { + return null; + } - while (--p2 >= 0) { - result[p2] = a[p1++]; - } + int p1 = 0, p2 = a.length; + byte[] result = new byte[p2]; - return result; - } + while (--p2 >= 0) { + result[p2] = a[p1++]; + } - /** Iterator backed by a specific array. */ - public static class Iterator implements java.util.Iterator { - private final T[] dataArray; + return result; + } - private int position = 0; + /** Iterator backed by a specific array. */ + public static class Iterator implements java.util.Iterator { + private final T[] dataArray; - /** - * Base constructor. - * - *

Note: the array is not cloned, changes to it will affect the values returned by next(). - * - * @param dataArray array backing the iterator. - */ - public Iterator(T[] dataArray) { - this.dataArray = dataArray; - } + private int position = 0; - public boolean hasNext() { - return position < dataArray.length; - } + /** + * Base constructor. + * + *

Note: the array is not cloned, changes to it will affect the values returned by + * next(). + * + * @param dataArray array backing the iterator. + */ + public Iterator(T[] dataArray) { + this.dataArray = dataArray; + } - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return dataArray[position++]; - } + public boolean hasNext() { + return position < dataArray.length; + } - public void remove() { - throw new UnsupportedOperationException("Cannot remove element from an Array."); + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return dataArray[position++]; + } + + public void remove() { + throw new UnsupportedOperationException("Cannot remove element from an Array."); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/BigIntegers.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/BigIntegers.java index 62e0b8750..69fe6b135 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/BigIntegers.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/BigIntegers.java @@ -5,97 +5,97 @@ /** BigInteger utilities. */ public final class BigIntegers { - private static final int MAX_ITERATIONS = 1000; - private static final BigInteger ZERO = BigInteger.valueOf(0); + private static final int MAX_ITERATIONS = 1000; + private static final BigInteger ZERO = BigInteger.valueOf(0); - /** - * Return the passed in value as an unsigned byte array. - * - * @param value value to be converted. - * @return a byte array without a leading zero byte if present in the signed encoding. - */ - public static byte[] asUnsignedByteArray(BigInteger value) { - byte[] bytes = value.toByteArray(); + /** + * Return the passed in value as an unsigned byte array. + * + * @param value value to be converted. + * @return a byte array without a leading zero byte if present in the signed encoding. + */ + public static byte[] asUnsignedByteArray(BigInteger value) { + byte[] bytes = value.toByteArray(); - if (bytes[0] == 0) { - byte[] tmp = new byte[bytes.length - 1]; + if (bytes[0] == 0) { + byte[] tmp = new byte[bytes.length - 1]; - System.arraycopy(bytes, 1, tmp, 0, tmp.length); + System.arraycopy(bytes, 1, tmp, 0, tmp.length); - return tmp; - } - - return bytes; - } - - /** - * Return the passed in value as an unsigned byte array. - * - * @param value value to be converted. - * @return a byte array without a leading zero byte if present in the signed encoding. - */ - public static byte[] asUnsignedByteArray(int length, BigInteger value) { - byte[] bytes = value.toByteArray(); - if (bytes.length == length) { - return bytes; - } + return tmp; + } - int start = bytes[0] == 0 ? 1 : 0; - int count = bytes.length - start; - - if (count > length) { - throw new IllegalArgumentException("standard length exceeded for value"); + return bytes; } - byte[] tmp = new byte[length]; - System.arraycopy(bytes, start, tmp, tmp.length - count, count); - return tmp; - } - - /** - * Return a random BigInteger not less than 'min' and not greater than 'max' - * - * @param min the least value that may be generated - * @param max the greatest value that may be generated - * @param random the source of randomness - * @return a random BigInteger value in the range [min,max] - */ - public static BigInteger createRandomInRange( - BigInteger min, BigInteger max, SecureRandom random) { - int cmp = min.compareTo(max); - if (cmp >= 0) { - if (cmp > 0) { - throw new IllegalArgumentException("'min' may not be greater than 'max'"); - } - - return min; + /** + * Return the passed in value as an unsigned byte array. + * + * @param value value to be converted. + * @return a byte array without a leading zero byte if present in the signed encoding. + */ + public static byte[] asUnsignedByteArray(int length, BigInteger value) { + byte[] bytes = value.toByteArray(); + if (bytes.length == length) { + return bytes; + } + + int start = bytes[0] == 0 ? 1 : 0; + int count = bytes.length - start; + + if (count > length) { + throw new IllegalArgumentException("standard length exceeded for value"); + } + + byte[] tmp = new byte[length]; + System.arraycopy(bytes, start, tmp, tmp.length - count, count); + return tmp; } - if (min.bitLength() > max.bitLength() / 2) { - return createRandomInRange(ZERO, max.subtract(min), random).add(min); + /** + * Return a random BigInteger not less than 'min' and not greater than 'max' + * + * @param min the least value that may be generated + * @param max the greatest value that may be generated + * @param random the source of randomness + * @return a random BigInteger value in the range [min,max] + */ + public static BigInteger createRandomInRange( + BigInteger min, BigInteger max, SecureRandom random) { + int cmp = min.compareTo(max); + if (cmp >= 0) { + if (cmp > 0) { + throw new IllegalArgumentException("'min' may not be greater than 'max'"); + } + + return min; + } + + if (min.bitLength() > max.bitLength() / 2) { + return createRandomInRange(ZERO, max.subtract(min), random).add(min); + } + + for (int i = 0; i < MAX_ITERATIONS; ++i) { + BigInteger x = new BigInteger(max.bitLength(), random); + if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0) { + return x; + } + } + + // fall back to a faster (restricted) method + return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min); } - for (int i = 0; i < MAX_ITERATIONS; ++i) { - BigInteger x = new BigInteger(max.bitLength(), random); - if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0) { - return x; - } + public static BigInteger fromUnsignedByteArray(byte[] buf) { + return new BigInteger(1, buf); } - // fall back to a faster (restricted) method - return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min); - } - - public static BigInteger fromUnsignedByteArray(byte[] buf) { - return new BigInteger(1, buf); - } - - public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length) { - byte[] mag = buf; - if (off != 0 || length != buf.length) { - mag = new byte[length]; - System.arraycopy(buf, off, mag, 0, length); + public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length) { + byte[] mag = buf; + if (off != 0 || length != buf.length) { + mag = new byte[length]; + System.arraycopy(buf, off, mag, 0, length); + } + return new BigInteger(1, mag); } - return new BigInteger(1, mag); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/ByteUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/ByteUtils.java index 6782ae1ab..01a353d99 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/ByteUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/ByteUtils.java @@ -2,78 +2,78 @@ public class ByteUtils { - private ByteUtils() {}; + private ByteUtils() {}; - /** - * @param bytes1 - * @param bytes2 - * @return - * @author - */ - public static byte[] addByteArray(byte[] bytes1, byte[] bytes2) { - byte[] temp; - if (bytes1 == null) { - temp = new byte[bytes2.length]; - System.arraycopy(bytes2, 0, temp, 0, bytes2.length); - } else if (bytes2 == null) { - temp = new byte[bytes1.length]; - System.arraycopy(bytes1, 0, temp, 0, bytes1.length); - } else { - temp = new byte[bytes1.length + bytes2.length]; - System.arraycopy(bytes1, 0, temp, 0, bytes1.length); - System.arraycopy(bytes2, 0, temp, bytes1.length, bytes2.length); + /** + * @param bytes1 + * @param bytes2 + * @return + * @author + */ + public static byte[] addByteArray(byte[] bytes1, byte[] bytes2) { + byte[] temp; + if (bytes1 == null) { + temp = new byte[bytes2.length]; + System.arraycopy(bytes2, 0, temp, 0, bytes2.length); + } else if (bytes2 == null) { + temp = new byte[bytes1.length]; + System.arraycopy(bytes1, 0, temp, 0, bytes1.length); + } else { + temp = new byte[bytes1.length + bytes2.length]; + System.arraycopy(bytes1, 0, temp, 0, bytes1.length); + System.arraycopy(bytes2, 0, temp, bytes1.length, bytes2.length); + } + return temp; } - return temp; - } - /** - * @param bytes - * @return - * @author - */ - public static byte[] copyBytes(byte[] bytes) { - byte[] temp; - temp = new byte[bytes.length]; - System.arraycopy(bytes, 0, temp, 0, bytes.length); - return temp; - } + /** + * @param bytes + * @return + * @author + */ + public static byte[] copyBytes(byte[] bytes) { + byte[] temp; + temp = new byte[bytes.length]; + System.arraycopy(bytes, 0, temp, 0, bytes.length); + return temp; + } - /** - * @param bytes - * @param pos - * @param length - * @return - * @author fisco-bcos - */ - public static byte[] subByteArray(byte[] bytes, int pos, int length) { - byte[] retbs = new byte[length]; - System.arraycopy(bytes, pos, retbs, 0, length); - return retbs; - } + /** + * @param bytes + * @param pos + * @param length + * @return + * @author fisco-bcos + */ + public static byte[] subByteArray(byte[] bytes, int pos, int length) { + byte[] retbs = new byte[length]; + System.arraycopy(bytes, pos, retbs, 0, length); + return retbs; + } - /** - * @param bytes - * @return - * @author - */ - public static byte[] reverse(byte[] bytes) { - byte[] ret = new byte[bytes.length]; + /** + * @param bytes + * @return + * @author + */ + public static byte[] reverse(byte[] bytes) { + byte[] ret = new byte[bytes.length]; - int index = ret.length - 1; - for (int i = 0; i < bytes.length; i++) { - ret[index] = bytes[i]; - index--; - } + int index = ret.length - 1; + for (int i = 0; i < bytes.length; i++) { + ret[index] = bytes[i]; + index--; + } - return ret; - } + return ret; + } - /** - * @param bytes - * @return - * @author - */ - public static byte[] littleToBigEndian(byte[] bytes) { - return reverse(bytes); - } + /** + * @param bytes + * @return + * @author + */ + public static byte[] littleToBigEndian(byte[] bytes) { + return reverse(bytes); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Encodable.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Encodable.java index d4d8c5dbb..7d13ffc43 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Encodable.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Encodable.java @@ -4,11 +4,11 @@ /** Interface implemented by objects that can be converted into byte arrays. */ public interface Encodable { - /** - * Return a byte array representing the implementing object. - * - * @return a byte array representing the encoding. - * @throws IOException if an issue arises generation the encoding. - */ - byte[] getEncoded() throws IOException; + /** + * Return a byte array representing the implementing object. + * + * @return a byte array representing the encoding. + * @throws IOException if an issue arises generation the encoding. + */ + byte[] getEncoded() throws IOException; } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Integers.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Integers.java index c4eef8777..6c5fe1bfb 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Integers.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Integers.java @@ -1,15 +1,15 @@ package org.fisco.bcos.web3j.crypto.gm.sm2.util; public class Integers { - public static int rotateLeft(int i, int distance) { - return Integer.rotateLeft(i, distance); - } + public static int rotateLeft(int i, int distance) { + return Integer.rotateLeft(i, distance); + } - public static int rotateRight(int i, int distance) { - return Integer.rotateRight(i, distance); - } + public static int rotateRight(int i, int distance) { + return Integer.rotateRight(i, distance); + } - public static Integer valueOf(int value) { - return Integer.valueOf(value); - } + public static Integer valueOf(int value) { + return Integer.valueOf(value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/KeyUtils.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/KeyUtils.java index 515fd34b5..dabdb70c9 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/KeyUtils.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/KeyUtils.java @@ -8,396 +8,400 @@ import java.security.cert.Certificate; public class KeyUtils { - protected static final String DEFAUTL_CHARTSET = "ISO-8859-1"; + protected static final String DEFAUTL_CHARTSET = "ISO-8859-1"; - /** - * get key Object to p12 file - * - * @param storeType JKS or JCEKS - * @param storePath p12 film path - * @param keyTyep public or private - * @param password - * @return - */ - public static Key getKey(String storeType, String storePath, String keyTyep, String password) { - Key pvtKey = null; - FileInputStream fs = null; - try { - fs = new FileInputStream(storePath); - KeyStore keyStore = KeyStore.getInstance(storeType); - keyStore.load(fs, password.toCharArray()); - pvtKey = (Key) keyStore.getKey(keyTyep, password.toCharArray()); - if (fs != null) { + /** + * get key Object to p12 file + * + * @param storeType JKS or JCEKS + * @param storePath p12 film path + * @param keyTyep public or private + * @param password + * @return + */ + public static Key getKey(String storeType, String storePath, String keyTyep, String password) { + Key pvtKey = null; + FileInputStream fs = null; try { - fs.close(); - } catch (Exception e) { - System.out.println("close " + storePath + " Failed, error msg:" + e.getMessage()); - return pvtKey; + fs = new FileInputStream(storePath); + KeyStore keyStore = KeyStore.getInstance(storeType); + keyStore.load(fs, password.toCharArray()); + pvtKey = (Key) keyStore.getKey(keyTyep, password.toCharArray()); + if (fs != null) { + try { + fs.close(); + } catch (Exception e) { + System.out.println( + "close " + storePath + " Failed, error msg:" + e.getMessage()); + return pvtKey; + } + } + } catch (Exception ex) { + if (fs != null) { + try { + fs.close(); + } catch (Exception e) { + System.out.println( + "close " + storePath + " Failed, error msg:" + e.getMessage()); + return pvtKey; + } + } + ex.printStackTrace(); + return pvtKey; } - } - } catch (Exception ex) { - if (fs != null) { - try { - fs.close(); - } catch (Exception e) { - System.out.println("close " + storePath + " Failed, error msg:" + e.getMessage()); - return pvtKey; - } - } - ex.printStackTrace(); - return pvtKey; + return pvtKey; } - return pvtKey; - } - public static Certificate getCertificate( - String storeType, String storePath, String name, String password) { - Certificate cert = null; - FileInputStream storeFs = null; - try { - storeFs = new FileInputStream(storePath); - KeyStore keyStore = KeyStore.getInstance(storeType); - keyStore.load(storeFs, password.toCharArray()); - cert = keyStore.getCertificate(name); - if (storeFs != null) { - try { - storeFs.close(); - } catch (Exception e) { - System.out.println("close " + storePath + " Failed, error msg:" + e.getMessage()); - return cert; - } - } - } catch (Exception ex) { - if (storeFs != null) { + public static Certificate getCertificate( + String storeType, String storePath, String name, String password) { + Certificate cert = null; + FileInputStream storeFs = null; try { - storeFs.close(); - } catch (Exception e) { - System.out.println("close " + storePath + " Failed, error msg:" + e.getMessage()); - return cert; + storeFs = new FileInputStream(storePath); + KeyStore keyStore = KeyStore.getInstance(storeType); + keyStore.load(storeFs, password.toCharArray()); + cert = keyStore.getCertificate(name); + if (storeFs != null) { + try { + storeFs.close(); + } catch (Exception e) { + System.out.println( + "close " + storePath + " Failed, error msg:" + e.getMessage()); + return cert; + } + } + } catch (Exception ex) { + if (storeFs != null) { + try { + storeFs.close(); + } catch (Exception e) { + System.out.println( + "close " + storePath + " Failed, error msg:" + e.getMessage()); + return cert; + } + } + ex.printStackTrace(); + return cert; } - } - ex.printStackTrace(); - return cert; + return cert; } - return cert; - } - /** - * hex to ascii array - * - * @param aschex - * @return - */ - public static byte[] aschex_to_bcdhex(String aschex) { - byte[] aschexByte = aschex.getBytes(); - int j = 0; - if (aschexByte.length % 2 == 0) { - j = aschexByte.length / 2; - byte[] resTmp = new byte[j]; - for (int i = 0; i < j; i++) { - resTmp[i] = ascToHex(aschexByte[2 * i], aschexByte[2 * i + 1]); - } - return resTmp; + /** + * hex to ascii array + * + * @param aschex + * @return + */ + public static byte[] aschex_to_bcdhex(String aschex) { + byte[] aschexByte = aschex.getBytes(); + int j = 0; + if (aschexByte.length % 2 == 0) { + j = aschexByte.length / 2; + byte[] resTmp = new byte[j]; + for (int i = 0; i < j; i++) { + resTmp[i] = ascToHex(aschexByte[2 * i], aschexByte[2 * i + 1]); + } + return resTmp; - } else { - j = aschexByte.length / 2 + 1; - byte[] resTmp = new byte[j]; - for (int i = 0; i < j - 1; i++) { - resTmp[i] = ascToHex((byte) aschexByte[2 * i], (byte) aschexByte[2 * i + 1]); - } - resTmp[j - 1] = ascToHex((byte) aschexByte[2 * (j - 1)], (byte) 0); - return resTmp; + } else { + j = aschexByte.length / 2 + 1; + byte[] resTmp = new byte[j]; + for (int i = 0; i < j - 1; i++) { + resTmp[i] = ascToHex((byte) aschexByte[2 * i], (byte) aschexByte[2 * i + 1]); + } + resTmp[j - 1] = ascToHex((byte) aschexByte[2 * (j - 1)], (byte) 0); + return resTmp; + } } - } - - public static byte ascToHex(byte ch1, byte ch2) { - byte ch; - if (ch1 >= 'A') ch = (byte) ((ch1 - 0x37) << 4); - else ch = (byte) ((ch1 - '0') << 4); - if (ch2 >= 'A') ch |= (byte) (ch2 - 0x37); - else ch |= (byte) (ch2 - '0'); - return ch; - } - public static byte hexLowToAsc(byte xxc) { - xxc &= 0x0f; - if (xxc < 0x0a) xxc += '0'; - else xxc += 0x37; - return (byte) xxc; - } + public static byte ascToHex(byte ch1, byte ch2) { + byte ch; + if (ch1 >= 'A') ch = (byte) ((ch1 - 0x37) << 4); + else ch = (byte) ((ch1 - '0') << 4); + if (ch2 >= 'A') ch |= (byte) (ch2 - 0x37); + else ch |= (byte) (ch2 - '0'); + return ch; + } - public static byte hexHighToAsc(int xxc) { - xxc &= 0xf0; - xxc = xxc >> 4; - if (xxc < 0x0a) xxc += '0'; - else xxc += 0x37; - return (byte) xxc; - } + public static byte hexLowToAsc(byte xxc) { + xxc &= 0x0f; + if (xxc < 0x0a) xxc += '0'; + else xxc += 0x37; + return (byte) xxc; + } - /** - * * length to asn1 - * - * @param len - * @return asn1Len - */ - public static byte[] toAsn1Len(int len) { - int ret = 0; - byte[] buff = new byte[10]; - byte[] asn1Len = null; - if (len > 65535) { - return null; + public static byte hexHighToAsc(int xxc) { + xxc &= 0xf0; + xxc = xxc >> 4; + if (xxc < 0x0a) xxc += '0'; + else xxc += 0x37; + return (byte) xxc; } - if (len > 255) { - buff[0] = (byte) 0x82; - buff[1] = (byte) ((len & 0xFF00) >> 8); - buff[2] = (byte) (len & 0x00FF); - ret = 3; - } else { - if ((len & 0x80) != 0) { - buff[0] = (byte) 0x81; - buff[1] = (byte) len; - ret = 2; - } else { - buff[0] = (byte) len; - ret = 1; - } + + /** + * * length to asn1 + * + * @param len + * @return asn1Len + */ + public static byte[] toAsn1Len(int len) { + int ret = 0; + byte[] buff = new byte[10]; + byte[] asn1Len = null; + if (len > 65535) { + return null; + } + if (len > 255) { + buff[0] = (byte) 0x82; + buff[1] = (byte) ((len & 0xFF00) >> 8); + buff[2] = (byte) (len & 0x00FF); + ret = 3; + } else { + if ((len & 0x80) != 0) { + buff[0] = (byte) 0x81; + buff[1] = (byte) len; + ret = 2; + } else { + buff[0] = (byte) len; + ret = 1; + } + } + asn1Len = new byte[ret]; + System.arraycopy(buff, 0, asn1Len, 0, ret); + return asn1Len; } - asn1Len = new byte[ret]; - System.arraycopy(buff, 0, asn1Len, 0, ret); - return asn1Len; - } - /** - * hex bcd to hex asc - * - * @param bcdhex - * @return - */ - public static String bcdhex_to_aschex(byte[] bcdhex) { - byte[] aschex = {0, 0}; - String res = ""; - String tmp = ""; - for (int i = 0; i < bcdhex.length; i++) { - aschex[1] = hexLowToAsc(bcdhex[i]); - aschex[0] = hexHighToAsc(bcdhex[i]); - tmp = new String(aschex); - res += tmp; + /** + * hex bcd to hex asc + * + * @param bcdhex + * @return + */ + public static String bcdhex_to_aschex(byte[] bcdhex) { + byte[] aschex = {0, 0}; + String res = ""; + String tmp = ""; + for (int i = 0; i < bcdhex.length; i++) { + aschex[1] = hexLowToAsc(bcdhex[i]); + aschex[0] = hexHighToAsc(bcdhex[i]); + tmp = new String(aschex); + res += tmp; + } + return res; } - return res; - } - /** - * hex bcd to hex asc - * - * @param bcdhex - * @param len - * @return - */ - public static byte[] bcdhex_to_aschex(byte[] bcdhex, int len) { - byte[] aschex = new byte[len * 2]; + /** + * hex bcd to hex asc + * + * @param bcdhex + * @param len + * @return + */ + public static byte[] bcdhex_to_aschex(byte[] bcdhex, int len) { + byte[] aschex = new byte[len * 2]; - for (int i = 0; i < len; i++) { - aschex[2 * i] = hexHighToAsc(bcdhex[i]); - aschex[2 * i + 1] = hexLowToAsc(bcdhex[i]); + for (int i = 0; i < len; i++) { + aschex[2 * i] = hexHighToAsc(bcdhex[i]); + aschex[2 * i + 1] = hexLowToAsc(bcdhex[i]); + } + return aschex; } - return aschex; - } - /** - * hex bcd to hex asc - * - * @param aschex - * @param len - * @return - */ - public static byte[] aschex_to_bcdhex(byte[] aschex, int len) { - int i, j; - if (len % 2 == 0) { - j = len / 2; - } else { - j = len / 2 + 1; - } - byte[] bcdhex = new byte[j]; - for (i = 0; i < j; i++) { - bcdhex[i] = ascToHex(aschex[2 * i], aschex[2 * i + 1]); + /** + * hex bcd to hex asc + * + * @param aschex + * @param len + * @return + */ + public static byte[] aschex_to_bcdhex(byte[] aschex, int len) { + int i, j; + if (len % 2 == 0) { + j = len / 2; + } else { + j = len / 2 + 1; + } + byte[] bcdhex = new byte[j]; + for (i = 0; i < j; i++) { + bcdhex[i] = ascToHex(aschex[2 * i], aschex[2 * i + 1]); + } + return bcdhex; } - return bcdhex; - } - /** - * xor - * - * @param a - * @param b - * @return - */ - public static final String xor(String a, String b) { - if (a.length() != b.length()) return null; + /** + * xor + * + * @param a + * @param b + * @return + */ + public static final String xor(String a, String b) { + if (a.length() != b.length()) return null; - byte[] aBuf = aschex_to_bcdhex(a); - byte[] bBuf = aschex_to_bcdhex(b); + byte[] aBuf = aschex_to_bcdhex(a); + byte[] bBuf = aschex_to_bcdhex(b); - byte[] outBuf = new byte[aBuf.length]; - for (int j = 0; j < aBuf.length; j++) outBuf[j] = (byte) (aBuf[j] ^ bBuf[j]); + byte[] outBuf = new byte[aBuf.length]; + for (int j = 0; j < aBuf.length; j++) outBuf[j] = (byte) (aBuf[j] ^ bBuf[j]); - return bcdhex_to_aschex(outBuf); - } + return bcdhex_to_aschex(outBuf); + } - /** - * * sha1 - * - * @param inStr - * @return - */ - public static String sha1String(String inStr) { - MessageDigest md = null; - String outStr = null; - try { - md = MessageDigest.getInstance("SHA-1"); // 选择SHA-1 - byte[] data = null; - try { - data = inStr.getBytes(DEFAUTL_CHARTSET); - } catch (Exception e) { - data = inStr.getBytes(); - } - byte[] digest = md.digest(data); // 返回的是byet[],要转化为String存储比较方便 - outStr = bcdhex_to_aschex(digest); - } catch (NoSuchAlgorithmException nsae) { - nsae.printStackTrace(); + /** + * * sha1 + * + * @param inStr + * @return + */ + public static String sha1String(String inStr) { + MessageDigest md = null; + String outStr = null; + try { + md = MessageDigest.getInstance("SHA-1"); // 选择SHA-1 + byte[] data = null; + try { + data = inStr.getBytes(DEFAUTL_CHARTSET); + } catch (Exception e) { + data = inStr.getBytes(); + } + byte[] digest = md.digest(data); // 返回的是byet[],要转化为String存储比较方便 + outStr = bcdhex_to_aschex(digest); + } catch (NoSuchAlgorithmException nsae) { + nsae.printStackTrace(); + } + return outStr; } - return outStr; - } - /** - * md5 - * - * @param inStr - * @return - */ - public static String md5String(String inStr) { - MessageDigest md = null; - String outStr = null; - try { - md = MessageDigest.getInstance("MD5"); // 选择MD5 - byte[] data = null; - try { - data = inStr.getBytes(DEFAUTL_CHARTSET); - } catch (Exception e) { - data = inStr.getBytes(); - } - byte[] digest = md.digest(data); // 返回的是byet[],要转化为String存储比较方便 - outStr = bcdhex_to_aschex(digest); - } catch (NoSuchAlgorithmException nsae) { - nsae.printStackTrace(); + /** + * md5 + * + * @param inStr + * @return + */ + public static String md5String(String inStr) { + MessageDigest md = null; + String outStr = null; + try { + md = MessageDigest.getInstance("MD5"); // 选择MD5 + byte[] data = null; + try { + data = inStr.getBytes(DEFAUTL_CHARTSET); + } catch (Exception e) { + data = inStr.getBytes(); + } + byte[] digest = md.digest(data); // 返回的是byet[],要转化为String存储比较方便 + outStr = bcdhex_to_aschex(digest); + } catch (NoSuchAlgorithmException nsae) { + nsae.printStackTrace(); + } + return outStr; } - return outStr; - } - /** - * byte to hex - * - * @param b - * @return - */ - public static String byte2hex(byte[] b) { - String hs = ""; - String stmp = ""; - for (int n = 0; n < b.length; n++) { - stmp = (Integer.toHexString(b[n] & 0XFF)); - if (stmp.length() == 1) { - hs = hs + "0" + stmp; - } else { - hs = hs + stmp; - } - if (n < b.length - 1) { - hs = hs + ""; - } + /** + * byte to hex + * + * @param b + * @return + */ + public static String byte2hex(byte[] b) { + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = (Integer.toHexString(b[n] & 0XFF)); + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; + } + if (n < b.length - 1) { + hs = hs + ""; + } + } + return hs.toUpperCase(); } - return hs.toUpperCase(); - } - /** - * * hex to byte[] - * - * @param str - * @return - */ - public static byte[] hex2byte(String str) { - int len = str.length(); - String stmp = null; - byte bt[] = new byte[len / 2]; - for (int n = 0; n < len / 2; n++) { - stmp = str.substring(n * 2, n * 2 + 2); - bt[n] = (byte) (Integer.parseInt(stmp, 16)); + /** + * * hex to byte[] + * + * @param str + * @return + */ + public static byte[] hex2byte(String str) { + int len = str.length(); + String stmp = null; + byte bt[] = new byte[len / 2]; + for (int n = 0; n < len / 2; n++) { + stmp = str.substring(n * 2, n * 2 + 2); + bt[n] = (byte) (Integer.parseInt(stmp, 16)); + } + return bt; } - return bt; - } - /** - * character padding - * - * @param str - * @param padc padding character - * @param length - * @return - * @author fisco-bcos - */ - public static String paddingRightStr(String str, char padc, int length) { - if (str.length() > length) { - return str.substring(0, length); - } else { - int numc = length - str.length(); - StringBuffer rets = new StringBuffer(str); - for (int i = 0; i < numc; i++) { - rets.append(padc); - } - return rets.toString(); + /** + * character padding + * + * @param str + * @param padc padding character + * @param length + * @return + * @author fisco-bcos + */ + public static String paddingRightStr(String str, char padc, int length) { + if (str.length() > length) { + return str.substring(0, length); + } else { + int numc = length - str.length(); + StringBuffer rets = new StringBuffer(str); + for (int i = 0; i < numc; i++) { + rets.append(padc); + } + return rets.toString(); + } } - } - /** - * character padding - * - * @param str - * @param padc padding character - * @param length - * @return - * @author fisco-bcos - */ - public static String paddingLeftStr(String str, char padc, int length) { - if (str.length() > length) { - return str.substring(0, length); - } else { - int numc = length - str.length(); - StringBuffer rets = new StringBuffer(str); - for (int i = 0; i < numc; i++) { - rets.insert(0, padc); - } - return rets.toString(); + /** + * character padding + * + * @param str + * @param padc padding character + * @param length + * @return + * @author fisco-bcos + */ + public static String paddingLeftStr(String str, char padc, int length) { + if (str.length() > length) { + return str.substring(0, length); + } else { + int numc = length - str.length(); + StringBuffer rets = new StringBuffer(str); + for (int i = 0; i < numc; i++) { + rets.insert(0, padc); + } + return rets.toString(); + } } - } - /** - * byte[] add - * - * @param bytes1 - * @param bytes2 - * @return - * @author fisco-bcos - */ - public static byte[] addByteArray(byte[] bytes1, byte[] bytes2) { - byte[] temp; - if (bytes1 == null) { - temp = new byte[bytes2.length]; - System.arraycopy(bytes2, 0, temp, 0, bytes2.length); - } else if (bytes2 == null) { - temp = new byte[bytes1.length]; - System.arraycopy(bytes1, 0, temp, 0, bytes1.length); - } else { - temp = new byte[bytes1.length + bytes2.length]; - System.arraycopy(bytes1, 0, temp, 0, bytes1.length); - System.arraycopy(bytes2, 0, temp, bytes1.length, bytes2.length); + /** + * byte[] add + * + * @param bytes1 + * @param bytes2 + * @return + * @author fisco-bcos + */ + public static byte[] addByteArray(byte[] bytes1, byte[] bytes2) { + byte[] temp; + if (bytes1 == null) { + temp = new byte[bytes2.length]; + System.arraycopy(bytes2, 0, temp, 0, bytes2.length); + } else if (bytes2 == null) { + temp = new byte[bytes1.length]; + System.arraycopy(bytes1, 0, temp, 0, bytes1.length); + } else { + temp = new byte[bytes1.length + bytes2.length]; + System.arraycopy(bytes1, 0, temp, 0, bytes1.length); + System.arraycopy(bytes2, 0, temp, bytes1.length, bytes2.length); + } + return temp; } - return temp; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Memoable.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Memoable.java index 7259b41e2..c765d65b3 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Memoable.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Memoable.java @@ -1,24 +1,24 @@ package org.fisco.bcos.web3j.crypto.gm.sm2.util; public interface Memoable { - /** - * Produce a copy of this object with its configuration and in its current state. - * - *

The returned object may be used simply to store the state, or may be used as a similar - * object starting from the copied state. - */ - public Memoable copy(); + /** + * Produce a copy of this object with its configuration and in its current state. + * + *

The returned object may be used simply to store the state, or may be used as a similar + * object starting from the copied state. + */ + public Memoable copy(); - /** - * Restore a copied object state into this object. - * - *

Implementations of this method should try to avoid or minimise memory allocation to - * perform the reset. - * - * @param other an object originally {@link #copy() copied} from an object of the same type as - * this instance. - * @throws ClassCastException if the provided object is not of the correct type. if the - * other parameter is in some other way invalid. - */ - public void reset(Memoable other); + /** + * Restore a copied object state into this object. + * + *

Implementations of this method should try to avoid or minimise memory allocation + * to perform the reset. + * + * @param other an object originally {@link #copy() copied} from an object of the same type as + * this instance. + * @throws ClassCastException if the provided object is not of the correct type. if the + * other parameter is in some other way invalid. + */ + public void reset(Memoable other); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Pack.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Pack.java index 19c3b0507..30c1c652f 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Pack.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Pack.java @@ -2,166 +2,166 @@ public abstract class Pack { - public static int bigEndianToInt(byte[] bs, int off) { - int n = bs[off] << 24; - n |= (bs[++off] & 0xff) << 16; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff); - return n; - } - - public static void bigEndianToInt(byte[] bs, int off, int[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = bigEndianToInt(bs, off); - off += 4; - } - } - - public static byte[] intToBigEndian(int n) { - byte[] bs = new byte[4]; - intToBigEndian(n, bs, 0); - return bs; - } - - public static void intToBigEndian(int n, byte[] bs, int off) { - bs[off] = (byte) (n >>> 24); - bs[++off] = (byte) (n >>> 16); - bs[++off] = (byte) (n >>> 8); - bs[++off] = (byte) (n); - } - - public static byte[] intToBigEndian(int[] ns) { - byte[] bs = new byte[4 * ns.length]; - intToBigEndian(ns, bs, 0); - return bs; - } - - public static void intToBigEndian(int[] ns, byte[] bs, int off) { - for (int i = 0; i < ns.length; ++i) { - intToBigEndian(ns[i], bs, off); - off += 4; - } - } - - public static long bigEndianToLong(byte[] bs, int off) { - int hi = bigEndianToInt(bs, off); - int lo = bigEndianToInt(bs, off + 4); - return ((long) (hi & 0xffffffffL) << 32) | (long) (lo & 0xffffffffL); - } - - public static void bigEndianToLong(byte[] bs, int off, long[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = bigEndianToLong(bs, off); - off += 8; - } - } - - public static byte[] longToBigEndian(long n) { - byte[] bs = new byte[8]; - longToBigEndian(n, bs, 0); - return bs; - } - - public static void longToBigEndian(long n, byte[] bs, int off) { - intToBigEndian((int) (n >>> 32), bs, off); - intToBigEndian((int) (n & 0xffffffffL), bs, off + 4); - } - - public static byte[] longToBigEndian(long[] ns) { - byte[] bs = new byte[8 * ns.length]; - longToBigEndian(ns, bs, 0); - return bs; - } - - public static void longToBigEndian(long[] ns, byte[] bs, int off) { - for (int i = 0; i < ns.length; ++i) { - longToBigEndian(ns[i], bs, off); - off += 8; - } - } - - public static int littleEndianToInt(byte[] bs, int off) { - int n = bs[off] & 0xff; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff) << 16; - n |= bs[++off] << 24; - return n; - } - - public static void littleEndianToInt(byte[] bs, int off, int[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = littleEndianToInt(bs, off); - off += 4; - } - } - - public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) { - for (int i = 0; i < count; ++i) { - ns[nOff + i] = littleEndianToInt(bs, bOff); - bOff += 4; - } - } - - public static byte[] intToLittleEndian(int n) { - byte[] bs = new byte[4]; - intToLittleEndian(n, bs, 0); - return bs; - } - - public static void intToLittleEndian(int n, byte[] bs, int off) { - bs[off] = (byte) (n); - bs[++off] = (byte) (n >>> 8); - bs[++off] = (byte) (n >>> 16); - bs[++off] = (byte) (n >>> 24); - } - - public static byte[] intToLittleEndian(int[] ns) { - byte[] bs = new byte[4 * ns.length]; - intToLittleEndian(ns, bs, 0); - return bs; - } - - public static void intToLittleEndian(int[] ns, byte[] bs, int off) { - for (int i = 0; i < ns.length; ++i) { - intToLittleEndian(ns[i], bs, off); - off += 4; - } - } - - public static long littleEndianToLong(byte[] bs, int off) { - int lo = littleEndianToInt(bs, off); - int hi = littleEndianToInt(bs, off + 4); - return ((long) (hi & 0xffffffffL) << 32) | (long) (lo & 0xffffffffL); - } - - public static void littleEndianToLong(byte[] bs, int off, long[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = littleEndianToLong(bs, off); - off += 8; - } - } - - public static byte[] longToLittleEndian(long n) { - byte[] bs = new byte[8]; - longToLittleEndian(n, bs, 0); - return bs; - } - - public static void longToLittleEndian(long n, byte[] bs, int off) { - intToLittleEndian((int) (n & 0xffffffffL), bs, off); - intToLittleEndian((int) (n >>> 32), bs, off + 4); - } - - public static byte[] longToLittleEndian(long[] ns) { - byte[] bs = new byte[8 * ns.length]; - longToLittleEndian(ns, bs, 0); - return bs; - } - - public static void longToLittleEndian(long[] ns, byte[] bs, int off) { - for (int i = 0; i < ns.length; ++i) { - longToLittleEndian(ns[i], bs, off); - off += 8; - } - } + public static int bigEndianToInt(byte[] bs, int off) { + int n = bs[off] << 24; + n |= (bs[++off] & 0xff) << 16; + n |= (bs[++off] & 0xff) << 8; + n |= (bs[++off] & 0xff); + return n; + } + + public static void bigEndianToInt(byte[] bs, int off, int[] ns) { + for (int i = 0; i < ns.length; ++i) { + ns[i] = bigEndianToInt(bs, off); + off += 4; + } + } + + public static byte[] intToBigEndian(int n) { + byte[] bs = new byte[4]; + intToBigEndian(n, bs, 0); + return bs; + } + + public static void intToBigEndian(int n, byte[] bs, int off) { + bs[off] = (byte) (n >>> 24); + bs[++off] = (byte) (n >>> 16); + bs[++off] = (byte) (n >>> 8); + bs[++off] = (byte) (n); + } + + public static byte[] intToBigEndian(int[] ns) { + byte[] bs = new byte[4 * ns.length]; + intToBigEndian(ns, bs, 0); + return bs; + } + + public static void intToBigEndian(int[] ns, byte[] bs, int off) { + for (int i = 0; i < ns.length; ++i) { + intToBigEndian(ns[i], bs, off); + off += 4; + } + } + + public static long bigEndianToLong(byte[] bs, int off) { + int hi = bigEndianToInt(bs, off); + int lo = bigEndianToInt(bs, off + 4); + return ((long) (hi & 0xffffffffL) << 32) | (long) (lo & 0xffffffffL); + } + + public static void bigEndianToLong(byte[] bs, int off, long[] ns) { + for (int i = 0; i < ns.length; ++i) { + ns[i] = bigEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToBigEndian(long n) { + byte[] bs = new byte[8]; + longToBigEndian(n, bs, 0); + return bs; + } + + public static void longToBigEndian(long n, byte[] bs, int off) { + intToBigEndian((int) (n >>> 32), bs, off); + intToBigEndian((int) (n & 0xffffffffL), bs, off + 4); + } + + public static byte[] longToBigEndian(long[] ns) { + byte[] bs = new byte[8 * ns.length]; + longToBigEndian(ns, bs, 0); + return bs; + } + + public static void longToBigEndian(long[] ns, byte[] bs, int off) { + for (int i = 0; i < ns.length; ++i) { + longToBigEndian(ns[i], bs, off); + off += 8; + } + } + + public static int littleEndianToInt(byte[] bs, int off) { + int n = bs[off] & 0xff; + n |= (bs[++off] & 0xff) << 8; + n |= (bs[++off] & 0xff) << 16; + n |= bs[++off] << 24; + return n; + } + + public static void littleEndianToInt(byte[] bs, int off, int[] ns) { + for (int i = 0; i < ns.length; ++i) { + ns[i] = littleEndianToInt(bs, off); + off += 4; + } + } + + public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) { + for (int i = 0; i < count; ++i) { + ns[nOff + i] = littleEndianToInt(bs, bOff); + bOff += 4; + } + } + + public static byte[] intToLittleEndian(int n) { + byte[] bs = new byte[4]; + intToLittleEndian(n, bs, 0); + return bs; + } + + public static void intToLittleEndian(int n, byte[] bs, int off) { + bs[off] = (byte) (n); + bs[++off] = (byte) (n >>> 8); + bs[++off] = (byte) (n >>> 16); + bs[++off] = (byte) (n >>> 24); + } + + public static byte[] intToLittleEndian(int[] ns) { + byte[] bs = new byte[4 * ns.length]; + intToLittleEndian(ns, bs, 0); + return bs; + } + + public static void intToLittleEndian(int[] ns, byte[] bs, int off) { + for (int i = 0; i < ns.length; ++i) { + intToLittleEndian(ns[i], bs, off); + off += 4; + } + } + + public static long littleEndianToLong(byte[] bs, int off) { + int lo = littleEndianToInt(bs, off); + int hi = littleEndianToInt(bs, off + 4); + return ((long) (hi & 0xffffffffL) << 32) | (long) (lo & 0xffffffffL); + } + + public static void littleEndianToLong(byte[] bs, int off, long[] ns) { + for (int i = 0; i < ns.length; ++i) { + ns[i] = littleEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToLittleEndian(long n) { + byte[] bs = new byte[8]; + longToLittleEndian(n, bs, 0); + return bs; + } + + public static void longToLittleEndian(long n, byte[] bs, int off) { + intToLittleEndian((int) (n & 0xffffffffL), bs, off); + intToLittleEndian((int) (n >>> 32), bs, off + 4); + } + + public static byte[] longToLittleEndian(long[] ns) { + byte[] bs = new byte[8 * ns.length]; + longToLittleEndian(ns, bs, 0); + return bs; + } + + public static void longToLittleEndian(long[] ns, byte[] bs, int off) { + for (int i = 0; i < ns.length; ++i) { + longToLittleEndian(ns[i], bs, off); + off += 8; + } + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/StringList.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/StringList.java index c05f47be4..b95c80e2c 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/StringList.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/StringList.java @@ -2,21 +2,21 @@ public interface StringList extends Iterable { - boolean add(String s); + boolean add(String s); - String get(int index); + String get(int index); - int size(); + int size(); - String[] toStringArray(); + String[] toStringArray(); - /** - * Return a section of the contents of the list. If the list is too short the array is filled with - * nulls. - * - * @param from the initial index of the range to be copied, inclusive - * @param to the final index of the range to be copied, exclusive. - * @return an array of length to - from - */ - String[] toStringArray(int from, int to); + /** + * Return a section of the contents of the list. If the list is too short the array is filled + * with nulls. + * + * @param from the initial index of the range to be copied, inclusive + * @param to the final index of the range to be copied, exclusive. + * @return an array of length to - from + */ + String[] toStringArray(int from, int to); } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Strings.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Strings.java index cba88cf4c..15ddf70f6 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Strings.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/Strings.java @@ -7,293 +7,295 @@ import java.util.Vector; public final class Strings { - public static String fromUTF8ByteArray(byte[] bytes) { - int i = 0; - int length = 0; - - while (i < bytes.length) { - length++; - if ((bytes[i] & 0xf0) == 0xf0) { - // surrogate pair - length++; - i += 4; - } else if ((bytes[i] & 0xe0) == 0xe0) { - i += 3; - } else if ((bytes[i] & 0xc0) == 0xc0) { - i += 2; - } else { - i += 1; - } + public static String fromUTF8ByteArray(byte[] bytes) { + int i = 0; + int length = 0; + + while (i < bytes.length) { + length++; + if ((bytes[i] & 0xf0) == 0xf0) { + // surrogate pair + length++; + i += 4; + } else if ((bytes[i] & 0xe0) == 0xe0) { + i += 3; + } else if ((bytes[i] & 0xc0) == 0xc0) { + i += 2; + } else { + i += 1; + } + } + + char[] cs = new char[length]; + + i = 0; + length = 0; + + while (i < bytes.length) { + char ch; + + if ((bytes[i] & 0xf0) == 0xf0) { + int codePoint = + ((bytes[i] & 0x03) << 18) + | ((bytes[i + 1] & 0x3F) << 12) + | ((bytes[i + 2] & 0x3F) << 6) + | (bytes[i + 3] & 0x3F); + int U = codePoint - 0x10000; + char W1 = (char) (0xD800 | (U >> 10)); + char W2 = (char) (0xDC00 | (U & 0x3FF)); + cs[length++] = W1; + ch = W2; + i += 4; + } else if ((bytes[i] & 0xe0) == 0xe0) { + ch = + (char) + (((bytes[i] & 0x0f) << 12) + | ((bytes[i + 1] & 0x3f) << 6) + | (bytes[i + 2] & 0x3f)); + i += 3; + } else if ((bytes[i] & 0xd0) == 0xd0) { + ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); + i += 2; + } else if ((bytes[i] & 0xc0) == 0xc0) { + ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); + i += 2; + } else { + ch = (char) (bytes[i] & 0xff); + i += 1; + } + + cs[length++] = ch; + } + + return new String(cs); } - char[] cs = new char[length]; - - i = 0; - length = 0; - - while (i < bytes.length) { - char ch; - - if ((bytes[i] & 0xf0) == 0xf0) { - int codePoint = - ((bytes[i] & 0x03) << 18) - | ((bytes[i + 1] & 0x3F) << 12) - | ((bytes[i + 2] & 0x3F) << 6) - | (bytes[i + 3] & 0x3F); - int U = codePoint - 0x10000; - char W1 = (char) (0xD800 | (U >> 10)); - char W2 = (char) (0xDC00 | (U & 0x3FF)); - cs[length++] = W1; - ch = W2; - i += 4; - } else if ((bytes[i] & 0xe0) == 0xe0) { - ch = - (char) - (((bytes[i] & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); - i += 3; - } else if ((bytes[i] & 0xd0) == 0xd0) { - ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); - i += 2; - } else if ((bytes[i] & 0xc0) == 0xc0) { - ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); - i += 2; - } else { - ch = (char) (bytes[i] & 0xff); - i += 1; - } - - cs[length++] = ch; + public static byte[] toUTF8ByteArray(String string) { + return toUTF8ByteArray(string.toCharArray()); } - return new String(cs); - } + public static byte[] toUTF8ByteArray(char[] string) { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - public static byte[] toUTF8ByteArray(String string) { - return toUTF8ByteArray(string.toCharArray()); - } + try { + toUTF8ByteArray(string, bOut); + } catch (IOException e) { + throw new IllegalStateException("cannot encode string to byte array!"); + } - public static byte[] toUTF8ByteArray(char[] string) { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + return bOut.toByteArray(); + } - try { - toUTF8ByteArray(string, bOut); - } catch (IOException e) { - throw new IllegalStateException("cannot encode string to byte array!"); + public static void toUTF8ByteArray(char[] string, OutputStream sOut) throws IOException { + char[] c = string; + int i = 0; + + while (i < c.length) { + char ch = c[i]; + + if (ch < 0x0080) { + sOut.write(ch); + } else if (ch < 0x0800) { + sOut.write(0xc0 | (ch >> 6)); + sOut.write(0x80 | (ch & 0x3f)); + } + // surrogate pair + else if (ch >= 0xD800 && ch <= 0xDFFF) { + // in error - can only happen, if the Java String class has a + // bug. + if (i + 1 >= c.length) { + throw new IllegalStateException("invalid UTF-16 codepoint"); + } + char W1 = ch; + ch = c[++i]; + char W2 = ch; + // in error - can only happen, if the Java String class has a + // bug. + if (W1 > 0xDBFF) { + throw new IllegalStateException("invalid UTF-16 codepoint"); + } + int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000; + sOut.write(0xf0 | (codePoint >> 18)); + sOut.write(0x80 | ((codePoint >> 12) & 0x3F)); + sOut.write(0x80 | ((codePoint >> 6) & 0x3F)); + sOut.write(0x80 | (codePoint & 0x3F)); + } else { + sOut.write(0xe0 | (ch >> 12)); + sOut.write(0x80 | ((ch >> 6) & 0x3F)); + sOut.write(0x80 | (ch & 0x3F)); + } + + i++; + } } - return bOut.toByteArray(); - } - - public static void toUTF8ByteArray(char[] string, OutputStream sOut) throws IOException { - char[] c = string; - int i = 0; - - while (i < c.length) { - char ch = c[i]; - - if (ch < 0x0080) { - sOut.write(ch); - } else if (ch < 0x0800) { - sOut.write(0xc0 | (ch >> 6)); - sOut.write(0x80 | (ch & 0x3f)); - } - // surrogate pair - else if (ch >= 0xD800 && ch <= 0xDFFF) { - // in error - can only happen, if the Java String class has a - // bug. - if (i + 1 >= c.length) { - throw new IllegalStateException("invalid UTF-16 codepoint"); + /** + * A locale independent version of toUpperCase. + * + * @param string input to be converted + * @return a US Ascii uppercase version + */ + public static String toUpperCase(String string) { + boolean changed = false; + char[] chars = string.toCharArray(); + + for (int i = 0; i != chars.length; i++) { + char ch = chars[i]; + if ('a' <= ch && 'z' >= ch) { + changed = true; + chars[i] = (char) (ch - 'a' + 'A'); + } } - char W1 = ch; - ch = c[++i]; - char W2 = ch; - // in error - can only happen, if the Java String class has a - // bug. - if (W1 > 0xDBFF) { - throw new IllegalStateException("invalid UTF-16 codepoint"); + + if (changed) { + return new String(chars); } - int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000; - sOut.write(0xf0 | (codePoint >> 18)); - sOut.write(0x80 | ((codePoint >> 12) & 0x3F)); - sOut.write(0x80 | ((codePoint >> 6) & 0x3F)); - sOut.write(0x80 | (codePoint & 0x3F)); - } else { - sOut.write(0xe0 | (ch >> 12)); - sOut.write(0x80 | ((ch >> 6) & 0x3F)); - sOut.write(0x80 | (ch & 0x3F)); - } - - i++; - } - } - - /** - * A locale independent version of toUpperCase. - * - * @param string input to be converted - * @return a US Ascii uppercase version - */ - public static String toUpperCase(String string) { - boolean changed = false; - char[] chars = string.toCharArray(); - - for (int i = 0; i != chars.length; i++) { - char ch = chars[i]; - if ('a' <= ch && 'z' >= ch) { - changed = true; - chars[i] = (char) (ch - 'a' + 'A'); - } - } - if (changed) { - return new String(chars); + return string; } - return string; - } - - /** - * A locale independent version of toLowerCase. - * - * @param string input to be converted - * @return a US ASCII lowercase version - */ - public static String toLowerCase(String string) { - boolean changed = false; - char[] chars = string.toCharArray(); - - for (int i = 0; i != chars.length; i++) { - char ch = chars[i]; - if ('A' <= ch && 'Z' >= ch) { - changed = true; - chars[i] = (char) (ch - 'A' + 'a'); - } - } + /** + * A locale independent version of toLowerCase. + * + * @param string input to be converted + * @return a US ASCII lowercase version + */ + public static String toLowerCase(String string) { + boolean changed = false; + char[] chars = string.toCharArray(); + + for (int i = 0; i != chars.length; i++) { + char ch = chars[i]; + if ('A' <= ch && 'Z' >= ch) { + changed = true; + chars[i] = (char) (ch - 'A' + 'a'); + } + } - if (changed) { - return new String(chars); + if (changed) { + return new String(chars); + } + + return string; } - return string; - } + public static byte[] toByteArray(char[] chars) { + byte[] bytes = new byte[chars.length]; - public static byte[] toByteArray(char[] chars) { - byte[] bytes = new byte[chars.length]; + for (int i = 0; i != bytes.length; i++) { + bytes[i] = (byte) chars[i]; + } - for (int i = 0; i != bytes.length; i++) { - bytes[i] = (byte) chars[i]; + return bytes; } - return bytes; - } + public static byte[] toByteArray(String string) { + byte[] bytes = new byte[string.length()]; - public static byte[] toByteArray(String string) { - byte[] bytes = new byte[string.length()]; + for (int i = 0; i != bytes.length; i++) { + char ch = string.charAt(i); - for (int i = 0; i != bytes.length; i++) { - char ch = string.charAt(i); + bytes[i] = (byte) ch; + } - bytes[i] = (byte) ch; + return bytes; } - return bytes; - } - - public static int toByteArray(String s, byte[] buf, int off) { - int count = s.length(); - for (int i = 0; i < count; ++i) { - char c = s.charAt(i); - buf[off + i] = (byte) c; - } - return count; - } - - /** - * Convert an array of 8 bit characters into a string. - * - * @param bytes 8 bit characters. - * @return resulting String. - */ - public static String fromByteArray(byte[] bytes) { - return new String(asCharArray(bytes)); - } - - /** - * Do a simple conversion of an array of 8 bit characters into a string. - * - * @param bytes 8 bit characters. - * @return resulting String. - */ - public static char[] asCharArray(byte[] bytes) { - char[] chars = new char[bytes.length]; - - for (int i = 0; i != chars.length; i++) { - chars[i] = (char) (bytes[i] & 0xff); + public static int toByteArray(String s, byte[] buf, int off) { + int count = s.length(); + for (int i = 0; i < count; ++i) { + char c = s.charAt(i); + buf[off + i] = (byte) c; + } + return count; } - return chars; - } - - public static String[] split(String input, char delimiter) { - Vector v = new Vector(); - boolean moreTokens = true; - String subString; - - while (moreTokens) { - int tokenLocation = input.indexOf(delimiter); - if (tokenLocation > 0) { - subString = input.substring(0, tokenLocation); - v.addElement(subString); - input = input.substring(tokenLocation + 1); - } else { - moreTokens = false; - v.addElement(input); - } + /** + * Convert an array of 8 bit characters into a string. + * + * @param bytes 8 bit characters. + * @return resulting String. + */ + public static String fromByteArray(byte[] bytes) { + return new String(asCharArray(bytes)); } - String[] res = new String[v.size()]; + /** + * Do a simple conversion of an array of 8 bit characters into a string. + * + * @param bytes 8 bit characters. + * @return resulting String. + */ + public static char[] asCharArray(byte[] bytes) { + char[] chars = new char[bytes.length]; + + for (int i = 0; i != chars.length; i++) { + chars[i] = (char) (bytes[i] & 0xff); + } - for (int i = 0; i != res.length; i++) { - res[i] = (String) v.elementAt(i); + return chars; } - return res; - } - public static StringList newList() { - return new StringListImpl(); - } + public static String[] split(String input, char delimiter) { + Vector v = new Vector(); + boolean moreTokens = true; + String subString; + + while (moreTokens) { + int tokenLocation = input.indexOf(delimiter); + if (tokenLocation > 0) { + subString = input.substring(0, tokenLocation); + v.addElement(subString); + input = input.substring(tokenLocation + 1); + } else { + moreTokens = false; + v.addElement(input); + } + } - private static class StringListImpl extends ArrayList implements StringList { - public boolean add(String s) { - return super.add(s); - } + String[] res = new String[v.size()]; - public String set(int index, String element) { - return super.set(index, element); + for (int i = 0; i != res.length; i++) { + res[i] = (String) v.elementAt(i); + } + return res; } - public void add(int index, String element) { - super.add(index, element); + public static StringList newList() { + return new StringListImpl(); } - public String[] toStringArray() { - String[] strs = new String[this.size()]; + private static class StringListImpl extends ArrayList implements StringList { + public boolean add(String s) { + return super.add(s); + } + + public String set(int index, String element) { + return super.set(index, element); + } - for (int i = 0; i != strs.length; i++) { - strs[i] = this.get(i); - } + public void add(int index, String element) { + super.add(index, element); + } - return strs; - } + public String[] toStringArray() { + String[] strs = new String[this.size()]; - public String[] toStringArray(int from, int to) { - String[] strs = new String[to - from]; + for (int i = 0; i != strs.length; i++) { + strs[i] = this.get(i); + } - for (int i = from; i != this.size() && i != to; i++) { - strs[i - from] = this.get(i); - } + return strs; + } + + public String[] toStringArray(int from, int to) { + String[] strs = new String[to - from]; - return strs; + for (int i = from; i != this.size() && i != to; i++) { + strs[i - from] = this.get(i); + } + + return strs; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/DecoderException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/DecoderException.java index 478fd63e3..ba350f999 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/DecoderException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/DecoderException.java @@ -2,15 +2,15 @@ /** Exception thrown if an attempt is made to decode invalid data, or some other failure occurs. */ public class DecoderException extends IllegalStateException { - private Throwable cause; + private Throwable cause; - DecoderException(String msg, Throwable cause) { - super(msg); + DecoderException(String msg, Throwable cause) { + super(msg); - this.cause = cause; - } + this.cause = cause; + } - public Throwable getCause() { - return cause; - } + public Throwable getCause() { + return cause; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Encoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Encoder.java index 74e8a3858..0f50a35a8 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Encoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Encoder.java @@ -5,9 +5,9 @@ /** Encode and decode byte arrays (typically from binary to 7-bit ASCII encodings). */ public interface Encoder { - int encode(byte[] data, int off, int length, OutputStream out) throws IOException; + int encode(byte[] data, int off, int length, OutputStream out) throws IOException; - int decode(byte[] data, int off, int length, OutputStream out) throws IOException; + int decode(byte[] data, int off, int length, OutputStream out) throws IOException; - int decode(String data, OutputStream out) throws IOException; + int decode(String data, OutputStream out) throws IOException; } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/EncoderException.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/EncoderException.java index ecdc1ef76..afbc08076 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/EncoderException.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/EncoderException.java @@ -2,15 +2,15 @@ /** Exception thrown if an attempt is made to encode invalid data, or some other failure occurs. */ public class EncoderException extends IllegalStateException { - private Throwable cause; + private Throwable cause; - EncoderException(String msg, Throwable cause) { - super(msg); + EncoderException(String msg, Throwable cause) { + super(msg); - this.cause = cause; - } + this.cause = cause; + } - public Throwable getCause() { - return cause; - } + public Throwable getCause() { + return cause; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Hex.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Hex.java index 32bf47796..7c0b7b280 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Hex.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/Hex.java @@ -7,102 +7,103 @@ /** Utility class for converting hex data to bytes and back again. */ public class Hex { - private static final Encoder encoder = new HexEncoder(); - - public static String toHexString(byte[] data) { - return toHexString(data, 0, data.length); - } - - public static String toHexString(byte[] data, int off, int length) { - byte[] encoded = encode(data, off, length); - return Strings.fromByteArray(encoded); - } - - /** - * encode the input data producing a Hex encoded byte array. - * - * @return a byte array containing the Hex encoded data. - */ - public static byte[] encode(byte[] data) { - return encode(data, 0, data.length); - } - - /** - * encode the input data producing a Hex encoded byte array. - * - * @return a byte array containing the Hex encoded data. - */ - public static byte[] encode(byte[] data, int off, int length) { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - try { - encoder.encode(data, off, length, bOut); - } catch (Exception e) { - throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e); + private static final Encoder encoder = new HexEncoder(); + + public static String toHexString(byte[] data) { + return toHexString(data, 0, data.length); + } + + public static String toHexString(byte[] data, int off, int length) { + byte[] encoded = encode(data, off, length); + return Strings.fromByteArray(encoded); + } + + /** + * encode the input data producing a Hex encoded byte array. + * + * @return a byte array containing the Hex encoded data. + */ + public static byte[] encode(byte[] data) { + return encode(data, 0, data.length); + } + + /** + * encode the input data producing a Hex encoded byte array. + * + * @return a byte array containing the Hex encoded data. + */ + public static byte[] encode(byte[] data, int off, int length) { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + try { + encoder.encode(data, off, length, bOut); + } catch (Exception e) { + throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e); + } + + return bOut.toByteArray(); + } + + /** + * Hex encode the byte data writing it to the given output stream. + * + * @return the number of bytes produced. + */ + public static int encode(byte[] data, OutputStream out) throws IOException { + return encoder.encode(data, 0, data.length, out); } - return bOut.toByteArray(); - } - - /** - * Hex encode the byte data writing it to the given output stream. - * - * @return the number of bytes produced. - */ - public static int encode(byte[] data, OutputStream out) throws IOException { - return encoder.encode(data, 0, data.length, out); - } - - /** - * Hex encode the byte data writing it to the given output stream. - * - * @return the number of bytes produced. - */ - public static int encode(byte[] data, int off, int length, OutputStream out) throws IOException { - return encoder.encode(data, off, length, out); - } - - /** - * decode the Hex encoded input data. It is assumed the input data is valid. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode(byte[] data) { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - try { - encoder.decode(data, 0, data.length, bOut); - } catch (Exception e) { - throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e); + /** + * Hex encode the byte data writing it to the given output stream. + * + * @return the number of bytes produced. + */ + public static int encode(byte[] data, int off, int length, OutputStream out) + throws IOException { + return encoder.encode(data, off, length, out); } - return bOut.toByteArray(); - } - - /** - * decode the Hex encoded String data - whitespace will be ignored. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode(String data) { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - try { - encoder.decode(data, bOut); - } catch (Exception e) { - throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e); + /** + * decode the Hex encoded input data. It is assumed the input data is valid. + * + * @return a byte array representing the decoded data. + */ + public static byte[] decode(byte[] data) { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + try { + encoder.decode(data, 0, data.length, bOut); + } catch (Exception e) { + throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e); + } + + return bOut.toByteArray(); } - return bOut.toByteArray(); - } - - /** - * decode the Hex encoded String data writing it to the given output stream, whitespace characters - * will be ignored. - * - * @return the number of bytes produced. - */ - public static int decode(String data, OutputStream out) throws IOException { - return encoder.decode(data, out); - } + /** + * decode the Hex encoded String data - whitespace will be ignored. + * + * @return a byte array representing the decoded data. + */ + public static byte[] decode(String data) { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + try { + encoder.decode(data, bOut); + } catch (Exception e) { + throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e); + } + + return bOut.toByteArray(); + } + + /** + * decode the Hex encoded String data writing it to the given output stream, whitespace + * characters will be ignored. + * + * @return the number of bytes produced. + */ + public static int decode(String data, OutputStream out) throws IOException { + return encoder.decode(data, out); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/HexEncoder.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/HexEncoder.java index 49903b7fc..aa637e500 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/HexEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm2/util/encoders/HexEncoder.java @@ -5,146 +5,148 @@ /** A streaming Hex encoder. */ public class HexEncoder implements Encoder { - protected final byte[] encodingTable = { - (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', - (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' - }; - - /* - * set up the decoding table. - */ - protected final byte[] decodingTable = new byte[128]; - - protected void initialiseDecodingTable() { - for (int i = 0; i < decodingTable.length; i++) { - decodingTable[i] = (byte) 0xff; + protected final byte[] encodingTable = { + (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', + (byte) '7', + (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', + (byte) 'f' + }; + + /* + * set up the decoding table. + */ + protected final byte[] decodingTable = new byte[128]; + + protected void initialiseDecodingTable() { + for (int i = 0; i < decodingTable.length; i++) { + decodingTable[i] = (byte) 0xff; + } + + for (int i = 0; i < encodingTable.length; i++) { + decodingTable[encodingTable[i]] = (byte) i; + } + + decodingTable['A'] = decodingTable['a']; + decodingTable['B'] = decodingTable['b']; + decodingTable['C'] = decodingTable['c']; + decodingTable['D'] = decodingTable['d']; + decodingTable['E'] = decodingTable['e']; + decodingTable['F'] = decodingTable['f']; } - for (int i = 0; i < encodingTable.length; i++) { - decodingTable[encodingTable[i]] = (byte) i; + public HexEncoder() { + initialiseDecodingTable(); } - decodingTable['A'] = decodingTable['a']; - decodingTable['B'] = decodingTable['b']; - decodingTable['C'] = decodingTable['c']; - decodingTable['D'] = decodingTable['d']; - decodingTable['E'] = decodingTable['e']; - decodingTable['F'] = decodingTable['f']; - } - - public HexEncoder() { - initialiseDecodingTable(); - } - - /** - * encode the input data producing a Hex output stream. - * - * @return the number of bytes produced. - */ - public int encode(byte[] data, int off, int length, OutputStream out) throws IOException { - for (int i = off; i < (off + length); i++) { - int v = data[i] & 0xff; - - out.write(encodingTable[(v >>> 4)]); - out.write(encodingTable[v & 0xf]); + /** + * encode the input data producing a Hex output stream. + * + * @return the number of bytes produced. + */ + public int encode(byte[] data, int off, int length, OutputStream out) throws IOException { + for (int i = off; i < (off + length); i++) { + int v = data[i] & 0xff; + + out.write(encodingTable[(v >>> 4)]); + out.write(encodingTable[v & 0xf]); + } + + return length * 2; } - return length * 2; - } + private static boolean ignore(char c) { + return c == '\n' || c == '\r' || c == '\t' || c == ' '; + } - private static boolean ignore(char c) { - return c == '\n' || c == '\r' || c == '\t' || c == ' '; - } + /** + * decode the Hex encoded byte data writing it to the given output stream, whitespace characters + * will be ignored. + * + * @return the number of bytes produced. + */ + public int decode(byte[] data, int off, int length, OutputStream out) throws IOException { + byte b1, b2; + int outLen = 0; - /** - * decode the Hex encoded byte data writing it to the given output stream, whitespace characters - * will be ignored. - * - * @return the number of bytes produced. - */ - public int decode(byte[] data, int off, int length, OutputStream out) throws IOException { - byte b1, b2; - int outLen = 0; + int end = off + length; - int end = off + length; + while (end > off) { + if (!ignore((char) data[end - 1])) { + break; + } - while (end > off) { - if (!ignore((char) data[end - 1])) { - break; - } + end--; + } - end--; - } + int i = off; + while (i < end) { + while (i < end && ignore((char) data[i])) { + i++; + } - int i = off; - while (i < end) { - while (i < end && ignore((char) data[i])) { - i++; - } + b1 = decodingTable[data[i++]]; - b1 = decodingTable[data[i++]]; + while (i < end && ignore((char) data[i])) { + i++; + } - while (i < end && ignore((char) data[i])) { - i++; - } + b2 = decodingTable[data[i++]]; - b2 = decodingTable[data[i++]]; + if ((b1 | b2) < 0) { + throw new IOException("invalid characters encountered in Hex data"); + } - if ((b1 | b2) < 0) { - throw new IOException("invalid characters encountered in Hex data"); - } + out.write((b1 << 4) | (b2 & 0xff)); - out.write((b1 << 4) | (b2 & 0xff)); + outLen++; + } - outLen++; + return outLen; } - return outLen; - } + /** + * decode the Hex encoded String data writing it to the given output stream, whitespace + * characters will be ignored. + * + * @return the number of bytes produced. + */ + public int decode(String data, OutputStream out) throws IOException { + byte b1, b2; + int length = 0; - /** - * decode the Hex encoded String data writing it to the given output stream, whitespace characters - * will be ignored. - * - * @return the number of bytes produced. - */ - public int decode(String data, OutputStream out) throws IOException { - byte b1, b2; - int length = 0; + int end = data.length(); - int end = data.length(); + while (end > 0) { + if (!ignore(data.charAt(end - 1))) { + break; + } - while (end > 0) { - if (!ignore(data.charAt(end - 1))) { - break; - } + end--; + } - end--; - } + int i = 0; + while (i < end) { + while (i < end && ignore(data.charAt(i))) { + i++; + } - int i = 0; - while (i < end) { - while (i < end && ignore(data.charAt(i))) { - i++; - } + b1 = decodingTable[data.charAt(i++)]; - b1 = decodingTable[data.charAt(i++)]; + while (i < end && ignore(data.charAt(i))) { + i++; + } - while (i < end && ignore(data.charAt(i))) { - i++; - } + b2 = decodingTable[data.charAt(i++)]; - b2 = decodingTable[data.charAt(i++)]; + if ((b1 | b2) < 0) { + throw new IOException("invalid characters encountered in Hex string"); + } - if ((b1 | b2) < 0) { - throw new IOException("invalid characters encountered in Hex string"); - } + out.write((b1 << 4) | (b2 & 0xff)); - out.write((b1 << 4) | (b2 & 0xff)); + length++; + } - length++; + return length; } - - return length; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3.java index 913c5c7dc..b859d8943 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3.java @@ -1,345 +1,345 @@ package org.fisco.bcos.web3j.crypto.gm.sm3; public class SM3 { - /*public static final byte[] iv = { 0x2C, (byte) 0x91, (byte) 0xB4, 0x01, - (byte) 0xFC, 0x64, (byte) 0xB2, (byte) 0xCE, 0x7C, 0x4E, - (byte) 0xAE, (byte) 0xFB, (byte) 0xB1, 0x3B, (byte) 0xB6, - (byte) 0xD3, 0x17, 0x60, (byte) 0xB6, 0x35, (byte) 0xF3, 0x6F, - 0x13, (byte) 0xEB, (byte) 0xC8, 0x77, (byte) 0xE9, (byte) 0xA0, - (byte) 0xC2, 0x76, (byte) 0xA8, 0x17 };*/ - - public static final byte[] iv = { - 0x73, - (byte) 0x80, - 0x16, - 0x6f, - 0x49, - 0x14, - (byte) 0xb2, - (byte) 0xb9, - 0x17, - 0x24, - 0x42, - (byte) 0xd7, - (byte) 0xda, - (byte) 0x8a, - 0x06, - 0x00, - (byte) 0xa9, - 0x6f, - 0x30, - (byte) 0xbc, - (byte) 0x16, - 0x31, - 0x38, - (byte) 0xaa, - (byte) 0xe3, - (byte) 0x8d, - (byte) 0xee, - 0x4d, - (byte) 0xb0, - (byte) 0xfb, - 0x0e, - 0x4e - }; - - public static int[] Tj = new int[64]; - - static { - for (int i = 0; i < 16; i++) { - Tj[i] = 0x79cc4519; + /*public static final byte[] iv = { 0x2C, (byte) 0x91, (byte) 0xB4, 0x01, + (byte) 0xFC, 0x64, (byte) 0xB2, (byte) 0xCE, 0x7C, 0x4E, + (byte) 0xAE, (byte) 0xFB, (byte) 0xB1, 0x3B, (byte) 0xB6, + (byte) 0xD3, 0x17, 0x60, (byte) 0xB6, 0x35, (byte) 0xF3, 0x6F, + 0x13, (byte) 0xEB, (byte) 0xC8, 0x77, (byte) 0xE9, (byte) 0xA0, + (byte) 0xC2, 0x76, (byte) 0xA8, 0x17 };*/ + + public static final byte[] iv = { + 0x73, + (byte) 0x80, + 0x16, + 0x6f, + 0x49, + 0x14, + (byte) 0xb2, + (byte) 0xb9, + 0x17, + 0x24, + 0x42, + (byte) 0xd7, + (byte) 0xda, + (byte) 0x8a, + 0x06, + 0x00, + (byte) 0xa9, + 0x6f, + 0x30, + (byte) 0xbc, + (byte) 0x16, + 0x31, + 0x38, + (byte) 0xaa, + (byte) 0xe3, + (byte) 0x8d, + (byte) 0xee, + 0x4d, + (byte) 0xb0, + (byte) 0xfb, + 0x0e, + 0x4e + }; + + public static int[] Tj = new int[64]; + + static { + for (int i = 0; i < 16; i++) { + Tj[i] = 0x79cc4519; + } + + for (int i = 16; i < 64; i++) { + Tj[i] = 0x7a879d8a; + } } - for (int i = 16; i < 64; i++) { - Tj[i] = 0x7a879d8a; + public static byte[] CF(byte[] V, byte[] B) { + int[] v, b; + v = convert(V); + b = convert(B); + return convert(CF(v, b)); } - } - - public static byte[] CF(byte[] V, byte[] B) { - int[] v, b; - v = convert(V); - b = convert(B); - return convert(CF(v, b)); - } - - private static int[] convert(byte[] arr) { - int[] out = new int[arr.length / 4]; - byte[] tmp = new byte[4]; - for (int i = 0; i < arr.length; i += 4) { - System.arraycopy(arr, i, tmp, 0, 4); - out[i / 4] = bigEndianByteToInt(tmp); + + private static int[] convert(byte[] arr) { + int[] out = new int[arr.length / 4]; + byte[] tmp = new byte[4]; + for (int i = 0; i < arr.length; i += 4) { + System.arraycopy(arr, i, tmp, 0, 4); + out[i / 4] = bigEndianByteToInt(tmp); + } + return out; } - return out; - } - - private static byte[] convert(int[] arr) { - byte[] out = new byte[arr.length * 4]; - byte[] tmp = null; - for (int i = 0; i < arr.length; i++) { - tmp = bigEndianIntToByte(arr[i]); - System.arraycopy(tmp, 0, out, i * 4, 4); + + private static byte[] convert(int[] arr) { + byte[] out = new byte[arr.length * 4]; + byte[] tmp = null; + for (int i = 0; i < arr.length; i++) { + tmp = bigEndianIntToByte(arr[i]); + System.arraycopy(tmp, 0, out, i * 4, 4); + } + return out; } - return out; - } - - public static int[] CF(int[] V, int[] B) { - int a, b, c, d, e, f, g, h; - int ss1, ss2, tt1, tt2; - a = V[0]; - b = V[1]; - c = V[2]; - d = V[3]; - e = V[4]; - f = V[5]; - g = V[6]; - h = V[7]; - - /*System.out.println("IV: "); - System.out.print(Integer.toHexString(a)+" "); - System.out.print(Integer.toHexString(b)+" "); - System.out.print(Integer.toHexString(c)+" "); - System.out.print(Integer.toHexString(d)+" "); - System.out.print(Integer.toHexString(e)+" "); - System.out.print(Integer.toHexString(f)+" "); - System.out.print(Integer.toHexString(g)+" "); - System.out.print(Integer.toHexString(h)+" "); - System.out.println(""); - System.out.println(""); - - System.out.println("填充后的消息: "); - for(int i=0; i= 0 && j <= 15) { + return FF1j(X, Y, Z); + } else { + return FF2j(X, Y, Z); + } } - // System.out.println(""); - - int[] out = new int[8]; - out[0] = a ^ V[0]; - out[1] = b ^ V[1]; - out[2] = c ^ V[2]; - out[3] = d ^ V[3]; - out[4] = e ^ V[4]; - out[5] = f ^ V[5]; - out[6] = g ^ V[6]; - out[7] = h ^ V[7]; - - return out; - } - - private static int[][] expand(int[] B) { - int W[] = new int[68]; - int W1[] = new int[64]; - for (int i = 0; i < B.length; i++) { - W[i] = B[i]; + + private static int GGj(int X, int Y, int Z, int j) { + if (j >= 0 && j <= 15) { + return GG1j(X, Y, Z); + } else { + return GG2j(X, Y, Z); + } } - for (int i = 16; i < 68; i++) { - W[i] = - P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15)) - ^ bitCycleLeft(W[i - 13], 7) - ^ W[i - 6]; + // 逻辑位运算函数 + private static int FF1j(int X, int Y, int Z) { + int tmp = X ^ Y ^ Z; + return tmp; } - for (int i = 0; i < 64; i++) { - W1[i] = W[i] ^ W[i + 4]; + private static int FF2j(int X, int Y, int Z) { + int tmp = ((X & Y) | (X & Z) | (Y & Z)); + return tmp; } - int arr[][] = new int[][] {W, W1}; - return arr; - } + private static int GG1j(int X, int Y, int Z) { + int tmp = X ^ Y ^ Z; + return tmp; + } - private static byte[] bigEndianIntToByte(int num) { - return back(Util.intToBytes(num)); - } + private static int GG2j(int X, int Y, int Z) { + int tmp = (X & Y) | (~X & Z); + return tmp; + } - private static int bigEndianByteToInt(byte[] bytes) { - return Util.byteToInt(back(bytes)); - } + private static int P0(int X) { + int y = rotateLeft(X, 9); + y = bitCycleLeft(X, 9); + int z = rotateLeft(X, 17); + z = bitCycleLeft(X, 17); + int t = X ^ y ^ z; + return t; + } - private static int FFj(int X, int Y, int Z, int j) { - if (j >= 0 && j <= 15) { - return FF1j(X, Y, Z); - } else { - return FF2j(X, Y, Z); + private static int P1(int X) { + int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23); + return t; } - } - private static int GGj(int X, int Y, int Z, int j) { - if (j >= 0 && j <= 15) { - return GG1j(X, Y, Z); - } else { - return GG2j(X, Y, Z); + /** + * 对最后一个分组字节数据padding + * + * @param in + * @param bLen 分组个数 + * @return + */ + public static byte[] padding(byte[] in, int bLen) { + int k = 448 - (8 * in.length + 1) % 512; + if (k < 0) { + k = 960 - (8 * in.length + 1) % 512; + } + k += 1; + byte[] padd = new byte[k / 8]; + padd[0] = (byte) 0x80; + long n = in.length * 8L + bLen * 512L; + byte[] out = new byte[in.length + k / 8 + 64 / 8]; + int pos = 0; + System.arraycopy(in, 0, out, 0, in.length); + pos += in.length; + System.arraycopy(padd, 0, out, pos, padd.length); + pos += padd.length; + byte[] tmp = back(Util.longToBytes(n)); + System.arraycopy(tmp, 0, out, pos, tmp.length); + return out; } - } - - // 逻辑位运算函数 - private static int FF1j(int X, int Y, int Z) { - int tmp = X ^ Y ^ Z; - return tmp; - } - - private static int FF2j(int X, int Y, int Z) { - int tmp = ((X & Y) | (X & Z) | (Y & Z)); - return tmp; - } - - private static int GG1j(int X, int Y, int Z) { - int tmp = X ^ Y ^ Z; - return tmp; - } - - private static int GG2j(int X, int Y, int Z) { - int tmp = (X & Y) | (~X & Z); - return tmp; - } - - private static int P0(int X) { - int y = rotateLeft(X, 9); - y = bitCycleLeft(X, 9); - int z = rotateLeft(X, 17); - z = bitCycleLeft(X, 17); - int t = X ^ y ^ z; - return t; - } - - private static int P1(int X) { - int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23); - return t; - } - - /** - * 对最后一个分组字节数据padding - * - * @param in - * @param bLen 分组个数 - * @return - */ - public static byte[] padding(byte[] in, int bLen) { - int k = 448 - (8 * in.length + 1) % 512; - if (k < 0) { - k = 960 - (8 * in.length + 1) % 512; + + /** + * 字节数组逆序 + * + * @param in + * @return + */ + private static byte[] back(byte[] in) { + byte[] out = new byte[in.length]; + for (int i = 0; i < out.length; i++) { + out[i] = in[out.length - i - 1]; + } + + return out; } - k += 1; - byte[] padd = new byte[k / 8]; - padd[0] = (byte) 0x80; - long n = in.length * 8L + bLen * 512L; - byte[] out = new byte[in.length + k / 8 + 64 / 8]; - int pos = 0; - System.arraycopy(in, 0, out, 0, in.length); - pos += in.length; - System.arraycopy(padd, 0, out, pos, padd.length); - pos += padd.length; - byte[] tmp = back(Util.longToBytes(n)); - System.arraycopy(tmp, 0, out, pos, tmp.length); - return out; - } - - /** - * 字节数组逆序 - * - * @param in - * @return - */ - private static byte[] back(byte[] in) { - byte[] out = new byte[in.length]; - for (int i = 0; i < out.length; i++) { - out[i] = in[out.length - i - 1]; + + public static int rotateLeft(int x, int n) { + return (x << n) | (x >> (32 - n)); } - return out; - } + private static int bitCycleLeft(int n, int bitLen) { + bitLen %= 32; + byte[] tmp = bigEndianIntToByte(n); + int byteLen = bitLen / 8; + int len = bitLen % 8; + if (byteLen > 0) { + tmp = byteCycleLeft(tmp, byteLen); + } - public static int rotateLeft(int x, int n) { - return (x << n) | (x >> (32 - n)); - } + if (len > 0) { + tmp = bitSmall8CycleLeft(tmp, len); + } - private static int bitCycleLeft(int n, int bitLen) { - bitLen %= 32; - byte[] tmp = bigEndianIntToByte(n); - int byteLen = bitLen / 8; - int len = bitLen % 8; - if (byteLen > 0) { - tmp = byteCycleLeft(tmp, byteLen); + return bigEndianByteToInt(tmp); } - if (len > 0) { - tmp = bitSmall8CycleLeft(tmp, len); + private static byte[] bitSmall8CycleLeft(byte[] in, int len) { + byte[] tmp = new byte[in.length]; + int t1, t2, t3; + for (int i = 0; i < tmp.length; i++) { + t1 = (byte) ((in[i] & 0x000000ff) << len); + t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len)); + t3 = (byte) (t1 | t2); + tmp[i] = (byte) t3; + } + + return tmp; } - return bigEndianByteToInt(tmp); - } - - private static byte[] bitSmall8CycleLeft(byte[] in, int len) { - byte[] tmp = new byte[in.length]; - int t1, t2, t3; - for (int i = 0; i < tmp.length; i++) { - t1 = (byte) ((in[i] & 0x000000ff) << len); - t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len)); - t3 = (byte) (t1 | t2); - tmp[i] = (byte) t3; + private static byte[] byteCycleLeft(byte[] in, int byteLen) { + byte[] tmp = new byte[in.length]; + System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen); + System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen); + return tmp; } - return tmp; - } - - private static byte[] byteCycleLeft(byte[] in, int byteLen) { - byte[] tmp = new byte[in.length]; - System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen); - System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen); - return tmp; - } - - /*private static void print(int[] arr) - { - for (int i = 0; i < arr.length; i++) - { - System.out.print(Integer.toHexString(arr[i]) + " "); - if ((i + 1) % 16 == 0) - { - System.out.println(); - } - } - System.out.println(); - }*/ + /*private static void print(int[] arr) + { + for (int i = 0; i < arr.length; i++) + { + System.out.print(Integer.toHexString(arr[i]) + " "); + if ((i + 1) % 16 == 0) + { + System.out.println(); + } + } + System.out.println(); + }*/ } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3Digest.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3Digest.java index 24bab227f..b24e9b4b1 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3Digest.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/SM3Digest.java @@ -8,181 +8,181 @@ import org.slf4j.LoggerFactory; public class SM3Digest implements HashInterface { - static Logger logger = LoggerFactory.getLogger(SM3Digest.class); - /** SM3值的长度 */ - private static final int BYTE_LENGTH = 32; - - /** SM3分组长度 */ - private static final int BLOCK_LENGTH = 64; - - /** 缓冲区长度 */ - private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1; - - /** 缓冲区 */ - private byte[] xBuf = new byte[BUFFER_LENGTH]; - - /** 缓冲区偏移量 */ - private int xBufOff; - - /** 初始向量 */ - private byte[] V = SM3.iv.clone(); - - private int cntBlock = 0; - - @Override - public String hash(String hexInput) { - byte[] md = new byte[32]; - // hexInput = cleanHexPrefix(hexInput); - // byte[] msg = Hex.decode(hexInput); - byte[] msg = Numeric.hexStringToByteArray(hexInput); - logger.debug("sm3 hash origData:{}", hexInput); - SM3Digest sm3 = new SM3Digest(); - sm3.update(msg, 0, msg.length); - sm3.doFinal(md, 0); - logger.debug("sm3 hash data:{}", Hex.toHexString(md)); - return Numeric.toHexString(md); - } - - @Override - public byte[] hash(byte[] input, int offset, int length) { - byte[] md = new byte[32]; - logger.debug("sm3 hash origData:{}", input); - SM3Digest sm3 = new SM3Digest(); - sm3.update(input, offset, length); - sm3.doFinal(md, 0); - String s = new String(Hex.encode(md)); - logger.debug("sm3 hash data:{}", s); - return md; - } - - @Override - public byte[] hash(byte[] input) { - byte[] md = new byte[32]; - logger.debug("sm3 hash origData:{}", input); - SM3Digest sm3 = new SM3Digest(); - sm3.update(input, 0, input.length); - sm3.doFinal(md, 0); - String s = new String(Hex.encode(md)); - logger.debug("sm3 hash data:{}", s); - return md; - } - - public SM3Digest() {} - - public SM3Digest(SM3Digest t) { - System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length); - this.xBufOff = t.xBufOff; - System.arraycopy(t.V, 0, this.V, 0, t.V.length); - } - - /** - * SM3结果输出 - * - * @param out 保存SM3结构的缓冲区 - * @param outOff 缓冲区偏移量 - * @return - */ - public int doFinal(byte[] out, int outOff) { - byte[] tmp = doFinal(); - System.arraycopy(tmp, 0, out, 0, tmp.length); - return BYTE_LENGTH; - } - - public void reset() { - xBufOff = 0; - cntBlock = 0; - V = SM3.iv.clone(); - } - - /** - * 明文输入 - * - * @param in 明文输入缓冲区 - * @param inOff 缓冲区偏移量 - * @param len 明文长度 - */ - public void update(byte[] in, int inOff, int len) { - int partLen = BUFFER_LENGTH - xBufOff; - int inputLen = len; - int dPos = inOff; - if (partLen < inputLen) { - System.arraycopy(in, dPos, xBuf, xBufOff, partLen); - inputLen -= partLen; - dPos += partLen; - doUpdate(); - while (inputLen > BUFFER_LENGTH) { - System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH); - inputLen -= BUFFER_LENGTH; - dPos += BUFFER_LENGTH; - doUpdate(); - } + static Logger logger = LoggerFactory.getLogger(SM3Digest.class); + /** SM3值的长度 */ + private static final int BYTE_LENGTH = 32; + + /** SM3分组长度 */ + private static final int BLOCK_LENGTH = 64; + + /** 缓冲区长度 */ + private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1; + + /** 缓冲区 */ + private byte[] xBuf = new byte[BUFFER_LENGTH]; + + /** 缓冲区偏移量 */ + private int xBufOff; + + /** 初始向量 */ + private byte[] V = SM3.iv.clone(); + + private int cntBlock = 0; + + @Override + public String hash(String hexInput) { + byte[] md = new byte[32]; + // hexInput = cleanHexPrefix(hexInput); + // byte[] msg = Hex.decode(hexInput); + byte[] msg = Numeric.hexStringToByteArray(hexInput); + logger.debug("sm3 hash origData:{}", hexInput); + SM3Digest sm3 = new SM3Digest(); + sm3.update(msg, 0, msg.length); + sm3.doFinal(md, 0); + logger.debug("sm3 hash data:{}", Hex.toHexString(md)); + return Numeric.toHexString(md); } - System.arraycopy(in, dPos, xBuf, xBufOff, inputLen); - xBufOff += inputLen; - } + @Override + public byte[] hash(byte[] input, int offset, int length) { + byte[] md = new byte[32]; + logger.debug("sm3 hash origData:{}", input); + SM3Digest sm3 = new SM3Digest(); + sm3.update(input, offset, length); + sm3.doFinal(md, 0); + String s = new String(Hex.encode(md)); + logger.debug("sm3 hash data:{}", s); + return md; + } + + @Override + public byte[] hash(byte[] input) { + byte[] md = new byte[32]; + logger.debug("sm3 hash origData:{}", input); + SM3Digest sm3 = new SM3Digest(); + sm3.update(input, 0, input.length); + sm3.doFinal(md, 0); + String s = new String(Hex.encode(md)); + logger.debug("sm3 hash data:{}", s); + return md; + } + + public SM3Digest() {} + + public SM3Digest(SM3Digest t) { + System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length); + this.xBufOff = t.xBufOff; + System.arraycopy(t.V, 0, this.V, 0, t.V.length); + } + + /** + * SM3结果输出 + * + * @param out 保存SM3结构的缓冲区 + * @param outOff 缓冲区偏移量 + * @return + */ + public int doFinal(byte[] out, int outOff) { + byte[] tmp = doFinal(); + System.arraycopy(tmp, 0, out, 0, tmp.length); + return BYTE_LENGTH; + } + + public void reset() { + xBufOff = 0; + cntBlock = 0; + V = SM3.iv.clone(); + } + + /** + * 明文输入 + * + * @param in 明文输入缓冲区 + * @param inOff 缓冲区偏移量 + * @param len 明文长度 + */ + public void update(byte[] in, int inOff, int len) { + int partLen = BUFFER_LENGTH - xBufOff; + int inputLen = len; + int dPos = inOff; + if (partLen < inputLen) { + System.arraycopy(in, dPos, xBuf, xBufOff, partLen); + inputLen -= partLen; + dPos += partLen; + doUpdate(); + while (inputLen > BUFFER_LENGTH) { + System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH); + inputLen -= BUFFER_LENGTH; + dPos += BUFFER_LENGTH; + doUpdate(); + } + } + + System.arraycopy(in, dPos, xBuf, xBufOff, inputLen); + xBufOff += inputLen; + } - private void doUpdate() { - byte[] B = new byte[BLOCK_LENGTH]; - for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH) { - System.arraycopy(xBuf, i, B, 0, B.length); - doHash(B); + private void doUpdate() { + byte[] B = new byte[BLOCK_LENGTH]; + for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH) { + System.arraycopy(xBuf, i, B, 0, B.length); + doHash(B); + } + xBufOff = 0; } - xBufOff = 0; - } - - private void doHash(byte[] B) { - byte[] tmp = SM3.CF(V, B); - System.arraycopy(tmp, 0, V, 0, V.length); - cntBlock++; - } - - private byte[] doFinal() { - byte[] B = new byte[BLOCK_LENGTH]; - byte[] buffer = new byte[xBufOff]; - System.arraycopy(xBuf, 0, buffer, 0, buffer.length); - byte[] tmp = SM3.padding(buffer, cntBlock); - for (int i = 0; i < tmp.length; i += BLOCK_LENGTH) { - System.arraycopy(tmp, i, B, 0, B.length); - doHash(B); + + private void doHash(byte[] B) { + byte[] tmp = SM3.CF(V, B); + System.arraycopy(tmp, 0, V, 0, V.length); + cntBlock++; + } + + private byte[] doFinal() { + byte[] B = new byte[BLOCK_LENGTH]; + byte[] buffer = new byte[xBufOff]; + System.arraycopy(xBuf, 0, buffer, 0, buffer.length); + byte[] tmp = SM3.padding(buffer, cntBlock); + for (int i = 0; i < tmp.length; i += BLOCK_LENGTH) { + System.arraycopy(tmp, i, B, 0, B.length); + doHash(B); + } + return V; + } + + public void update(byte in) { + byte[] buffer = new byte[] {in}; + update(buffer, 0, 1); + } + + public int getDigestSize() { + return BYTE_LENGTH; + } + + public static void main(String[] args) { + byte[] md = new byte[32]; + String strMsg = "123456"; + String strHash = "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732"; + byte[] msg1 = strMsg.getBytes(); + System.out.println("签名原文:" + strMsg); + SM3Digest sm3 = new SM3Digest(); + sm3.update(msg1, 0, msg1.length); + sm3.doFinal(md, 0); + String s = new String(Hex.encode(md)); + System.out.println(s.toUpperCase().compareTo(strHash.toUpperCase())); } - return V; - } - - public void update(byte in) { - byte[] buffer = new byte[] {in}; - update(buffer, 0, 1); - } - - public int getDigestSize() { - return BYTE_LENGTH; - } - - public static void main(String[] args) { - byte[] md = new byte[32]; - String strMsg = "123456"; - String strHash = "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732"; - byte[] msg1 = strMsg.getBytes(); - System.out.println("签名原文:" + strMsg); - SM3Digest sm3 = new SM3Digest(); - sm3.update(msg1, 0, msg1.length); - sm3.doFinal(md, 0); - String s = new String(Hex.encode(md)); - System.out.println(s.toUpperCase().compareTo(strHash.toUpperCase())); - } - - public static String cleanHexPrefix(String input) { - if (containsHexPrefix(input)) { - return input.substring(2); - } else { - return input; + + public static String cleanHexPrefix(String input) { + if (containsHexPrefix(input)) { + return input.substring(2); + } else { + return input; + } + } + + public static boolean containsHexPrefix(String input) { + return !Strings.isEmpty(input) + && input.length() > 1 + && input.charAt(0) == '0' + && input.charAt(1) == 'x'; } - } - - public static boolean containsHexPrefix(String input) { - return !Strings.isEmpty(input) - && input.length() > 1 - && input.charAt(0) == '0' - && input.charAt(1) == 'x'; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/Util.java b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/Util.java index df4c3e455..bdfa4b11b 100644 --- a/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/Util.java +++ b/src/main/java/org/fisco/bcos/web3j/crypto/gm/sm3/Util.java @@ -3,539 +3,542 @@ import java.math.BigInteger; public class Util { - /** - * @param num - * @return - */ - public static byte[] intToBytes(int num) { - byte[] bytes = new byte[4]; - bytes[0] = (byte) (0xff & (num >> 0)); - bytes[1] = (byte) (0xff & (num >> 8)); - bytes[2] = (byte) (0xff & (num >> 16)); - bytes[3] = (byte) (0xff & (num >> 24)); - return bytes; - } - - /** - * @param bytes - * @return - */ - public static int byteToInt(byte[] bytes) { - int num = 0; - int temp; - temp = (0x000000ff & (bytes[0])); - num = num | temp; - temp = (0x000000ff & (bytes[1])) << 8; - num = num | temp; - temp = (0x000000ff & (bytes[2])) << 16; - num = num | temp; - temp = (0x000000ff & (bytes[3])) << 24; - num = num | temp; - return num; - } - - /** - * @param num - * @return - */ - public static byte[] longToBytes(long num) { - byte[] bytes = new byte[8]; - for (int i = 0; i < 8; i++) { - bytes[i] = (byte) (0xff & (num >> (i * 8))); - } - - return bytes; - } - - /** - * @param n - * @return - */ - public static byte[] byteConvert32Bytes(BigInteger n) { - byte tmpd[] = (byte[]) null; - if (n == null) { - return null; - } - - if (n.toByteArray().length == 33) { - tmpd = new byte[32]; - System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32); - } else if (n.toByteArray().length == 32) { - tmpd = n.toByteArray(); - } else { - tmpd = new byte[32]; - for (int i = 0; i < 32 - n.toByteArray().length; i++) { - tmpd[i] = 0; - } - System.arraycopy( - n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length); - } - return tmpd; - } - - /** - * @param b - * @return - */ - public static BigInteger byteConvertInteger(byte[] b) { - if (b[0] < 0) { - byte[] temp = new byte[b.length + 1]; - temp[0] = 0; - System.arraycopy(b, 0, temp, 1, b.length); - return new BigInteger(temp); - } - return new BigInteger(b); - } - - /** - * @param bytes - * @return - */ - public static String getHexString(byte[] bytes) { - return getHexString(bytes, true); - } - - /** - * @param bytes - * @param upperCase - * @return - */ - public static String getHexString(byte[] bytes, boolean upperCase) { - String ret = ""; - for (int i = 0; i < bytes.length; i++) { - ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1); - } - return upperCase ? ret.toUpperCase() : ret; - } - - /** @param bytes */ - public static void printHexString(byte[] bytes) { - for (int i = 0; i < bytes.length; i++) { - String hex = Integer.toHexString(bytes[i] & 0xFF); - if (hex.length() == 1) { - hex = '0' + hex; - } - System.out.print("0x" + hex.toUpperCase() + ","); - } - System.out.println(""); - } - - /** - * Convert hex string to byte[] - * - * @param hexString the hex string - * @return byte[] - */ - public static byte[] hexStringToBytes(String hexString) { - if (hexString == null || hexString.equals("")) { - return null; - } - - hexString = hexString.toUpperCase(); - int length = hexString.length() / 2; - char[] hexChars = hexString.toCharArray(); - byte[] d = new byte[length]; - for (int i = 0; i < length; i++) { - int pos = i * 2; - d[i] = (byte) (charToByte(hexChars[pos]) << 4 | (charToByte(hexChars[pos + 1]) & 0xff)); - } - return d; - } - - /** - * Convert char to byte - * - * @param c char - * @return byte - */ - public static byte charToByte(char c) { - return (byte) "0123456789ABCDEF".indexOf(c); - } - - /** */ - private static final char[] DIGITS_LOWER = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - /** */ - private static final char[] DIGITS_UPPER = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - /** - * @param data byte[] - * @return HEX char[] - */ - public static char[] encodeHex(byte[] data) { - return encodeHex(data, true); - } - - /** - * @param data byte[] - * @param toLowerCase - * @return char[] - */ - public static char[] encodeHex(byte[] data, boolean toLowerCase) { - return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); - } - - /** - * @param data byte[] - * @param toDigits char[] - * @return char[] - */ - protected static char[] encodeHex(byte[] data, char[] toDigits) { - int l = data.length; - char[] out = new char[l << 1]; - // two characters form the hex value. - for (int i = 0, j = 0; i < l; i++) { - out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; - out[j++] = toDigits[0x0F & data[i]]; - } - return out; - } - - /** - * @param data byte[] - * @return HEX String - */ - public static String encodeHexString(byte[] data) { - return encodeHexString(data, true); - } - - /** - * @param data byte[] - * @param toLowerCase truefalse - * @return HEX String - */ - public static String encodeHexString(byte[] data, boolean toLowerCase) { - return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); - } - - /** - * @param data byte[] - * @param toDigits - * @return String - */ - protected static String encodeHexString(byte[] data, char[] toDigits) { - return new String(encodeHex(data, toDigits)); - } - - /** - * @param data char[] - * @return byte[] - * @throws RuntimeException - */ - public static byte[] decodeHex(char[] data) { - int len = data.length; - - if ((len & 0x01) != 0) { - throw new RuntimeException("Odd number of characters."); - } - - byte[] out = new byte[len >> 1]; - - // two characters form the hex value. - for (int i = 0, j = 0; j < len; i++) { - int f = toDigit(data[j], j) << 4; - j++; - f = f | toDigit(data[j], j); - j++; - out[i] = (byte) (f & 0xFF); - } - - return out; - } - - /** - * @param ch - * @param index - * @return - * @throws RuntimeException - */ - protected static int toDigit(char ch, int index) { - int digit = Character.digit(ch, 16); - if (digit == -1) { - throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); - } - return digit; - } - - /** @return */ - public static String StringToAsciiString(String content) { - String result = ""; - int max = content.length(); - for (int i = 0; i < max; i++) { - char c = content.charAt(i); - String b = Integer.toHexString(c); - result = result + b; - } - return result; - } - - /** - * @param hexString - * @param encodeType - * @return - */ - public static String hexStringToString(String hexString, int encodeType) { - String result = ""; - int max = hexString.length() / encodeType; - for (int i = 0; i < max; i++) { - char c = - (char) hexStringToAlgorism(hexString.substring(i * encodeType, (i + 1) * encodeType)); - result += c; - } - return result; - } - - /** - * @param hex - * @return - */ - public static int hexStringToAlgorism(String hex) { - hex = hex.toUpperCase(); - int max = hex.length(); - int result = 0; - for (int i = max; i > 0; i--) { - char c = hex.charAt(i - 1); - int algorism = 0; - if (c >= '0' && c <= '9') { - algorism = c - '0'; - } else { - algorism = c - 55; - } - result += Math.pow(16, max - (double) i) * algorism; - } - return result; - } - - /** - * @param hex - * @return - */ - public static String hexStringToBinary(String hex) { - hex = hex.toUpperCase(); - String result = ""; - int max = hex.length(); - for (int i = 0; i < max; i++) { - char c = hex.charAt(i); - switch (c) { - case '0': - result += "0000"; - break; - case '1': - result += "0001"; - break; - case '2': - result += "0010"; - break; - case '3': - result += "0011"; - break; - case '4': - result += "0100"; - break; - case '5': - result += "0101"; - break; - case '6': - result += "0110"; - break; - case '7': - result += "0111"; - break; - case '8': - result += "1000"; - break; - case '9': - result += "1001"; - break; - case 'A': - result += "1010"; - break; - case 'B': - result += "1011"; - break; - case 'C': - result += "1100"; - break; - case 'D': - result += "1101"; - break; - case 'E': - result += "1110"; - break; - case 'F': - result += "1111"; - break; - } - } - return result; - } - - /** @return */ - public static String AsciiStringToString(String content) { - String result = ""; - int length = content.length() / 2; - for (int i = 0; i < length; i++) { - String c = content.substring(i * 2, i * 2 + 2); - int a = hexStringToAlgorism(c); - char b = (char) a; - String d = String.valueOf(b); - result += d; - } - return result; - } - - /** - * @param algorism int - * @param maxLength int - * @return String - */ - public static String algorismToHexString(int algorism, int maxLength) { - String result = ""; - result = Integer.toHexString(algorism); - - if (result.length() % 2 == 1) { - result = "0" + result; - } - return patchHexString(result.toUpperCase(), maxLength); - } - - /** - * @param bytearray byte[] - * @return String - */ - public static String byteToString(byte[] bytearray) { - String result = ""; - char temp; - - int length = bytearray.length; - for (int i = 0; i < length; i++) { - temp = (char) bytearray[i]; - result += temp; - } - return result; - } - - /** - * @param binary - * @return - */ - public static int binaryToAlgorism(String binary) { - int max = binary.length(); - int result = 0; - for (int i = max; i > 0; i--) { - char c = binary.charAt(i - 1); - int algorism = c - '0'; - result += Math.pow(2, max - (double) i) * algorism; - } - return result; - } - - /** - * @param algorism int - * @return String - */ - public static String algorismToHEXString(int algorism) { - String result = ""; - result = Integer.toHexString(algorism); - - if (result.length() % 2 == 1) { - result = "0" + result; - } - result = result.toUpperCase(); - - return result; - } - - /** - * @param str String - * @param maxLength int - * @return - */ - public static String patchHexString(String str, int maxLength) { - String temp = ""; - for (int i = 0; i < maxLength - str.length(); i++) { - temp = "0" + temp; - } - str = (temp + str).substring(0, maxLength); - return str; - } - - /** - * @param s String - * @param defaultInt int - * @param radix int - * @return int - */ - public static int parseToInt(String s, int defaultInt, int radix) { - int i = 0; - try { - i = Integer.parseInt(s, radix); - } catch (NumberFormatException ex) { - i = defaultInt; - } - return i; - } - - /** - * @param s - * @param defaultInt - * @return - */ - public static int parseToInt(String s, int defaultInt) { - int i = 0; - try { - i = Integer.parseInt(s); - } catch (NumberFormatException ex) { - i = defaultInt; - } - return i; - } - - /** @return the array of byte */ - public static byte[] hexToByte(String hex) throws IllegalArgumentException { - if (hex.length() % 2 != 0) { - throw new IllegalArgumentException(); - } - char[] arr = hex.toCharArray(); - byte[] b = new byte[hex.length() / 2]; - for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) { - String swap = "" + arr[i++] + arr[i]; - int byteint = Integer.parseInt(swap, 16) & 0xFF; - b[j] = (byte) byteint; - } - return b; - } - - /** - * @param b byte[] - * @return String - */ - public static String byteToHex(byte b[]) { - if (b == null) { - throw new IllegalArgumentException("Argument b ( byte array ) is null! "); - } - String hs = ""; - String stmp = ""; - for (int n = 0; n < b.length; n++) { - stmp = Integer.toHexString(b[n] & 0xff); - if (stmp.length() == 1) { - hs = hs + "0" + stmp; - } else { - hs = hs + stmp; - } - } - return hs.toUpperCase(); - } - - public static byte[] subByte(byte[] input, int startIndex, int length) { - byte[] bt = new byte[length]; - for (int i = 0; i < length; i++) { - bt[i] = input[i + startIndex]; - } - return bt; - } + /** + * @param num + * @return + */ + public static byte[] intToBytes(int num) { + byte[] bytes = new byte[4]; + bytes[0] = (byte) (0xff & (num >> 0)); + bytes[1] = (byte) (0xff & (num >> 8)); + bytes[2] = (byte) (0xff & (num >> 16)); + bytes[3] = (byte) (0xff & (num >> 24)); + return bytes; + } + + /** + * @param bytes + * @return + */ + public static int byteToInt(byte[] bytes) { + int num = 0; + int temp; + temp = (0x000000ff & (bytes[0])); + num = num | temp; + temp = (0x000000ff & (bytes[1])) << 8; + num = num | temp; + temp = (0x000000ff & (bytes[2])) << 16; + num = num | temp; + temp = (0x000000ff & (bytes[3])) << 24; + num = num | temp; + return num; + } + + /** + * @param num + * @return + */ + public static byte[] longToBytes(long num) { + byte[] bytes = new byte[8]; + for (int i = 0; i < 8; i++) { + bytes[i] = (byte) (0xff & (num >> (i * 8))); + } + + return bytes; + } + + /** + * @param n + * @return + */ + public static byte[] byteConvert32Bytes(BigInteger n) { + byte tmpd[] = (byte[]) null; + if (n == null) { + return null; + } + + if (n.toByteArray().length == 33) { + tmpd = new byte[32]; + System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32); + } else if (n.toByteArray().length == 32) { + tmpd = n.toByteArray(); + } else { + tmpd = new byte[32]; + for (int i = 0; i < 32 - n.toByteArray().length; i++) { + tmpd[i] = 0; + } + System.arraycopy( + n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length); + } + return tmpd; + } + + /** + * @param b + * @return + */ + public static BigInteger byteConvertInteger(byte[] b) { + if (b[0] < 0) { + byte[] temp = new byte[b.length + 1]; + temp[0] = 0; + System.arraycopy(b, 0, temp, 1, b.length); + return new BigInteger(temp); + } + return new BigInteger(b); + } + + /** + * @param bytes + * @return + */ + public static String getHexString(byte[] bytes) { + return getHexString(bytes, true); + } + + /** + * @param bytes + * @param upperCase + * @return + */ + public static String getHexString(byte[] bytes, boolean upperCase) { + String ret = ""; + for (int i = 0; i < bytes.length; i++) { + ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1); + } + return upperCase ? ret.toUpperCase() : ret; + } + + /** @param bytes */ + public static void printHexString(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + String hex = Integer.toHexString(bytes[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + System.out.print("0x" + hex.toUpperCase() + ","); + } + System.out.println(""); + } + + /** + * Convert hex string to byte[] + * + * @param hexString the hex string + * @return byte[] + */ + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | (charToByte(hexChars[pos + 1]) & 0xff)); + } + return d; + } + + /** + * Convert char to byte + * + * @param c char + * @return byte + */ + public static byte charToByte(char c) { + return (byte) "0123456789ABCDEF".indexOf(c); + } + + /** */ + private static final char[] DIGITS_LOWER = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + + /** */ + private static final char[] DIGITS_UPPER = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + /** + * @param data byte[] + * @return HEX char[] + */ + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + /** + * @param data byte[] + * @param toLowerCase + * @return char[] + */ + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * @param data byte[] + * @param toDigits char[] + * @return char[] + */ + protected static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; + out[j++] = toDigits[0x0F & data[i]]; + } + return out; + } + + /** + * @param data byte[] + * @return HEX String + */ + public static String encodeHexString(byte[] data) { + return encodeHexString(data, true); + } + + /** + * @param data byte[] + * @param toLowerCase truefalse + * @return HEX String + */ + public static String encodeHexString(byte[] data, boolean toLowerCase) { + return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * @param data byte[] + * @param toDigits + * @return String + */ + protected static String encodeHexString(byte[] data, char[] toDigits) { + return new String(encodeHex(data, toDigits)); + } + + /** + * @param data char[] + * @return byte[] + * @throws RuntimeException + */ + public static byte[] decodeHex(char[] data) { + int len = data.length; + + if ((len & 0x01) != 0) { + throw new RuntimeException("Odd number of characters."); + } + + byte[] out = new byte[len >> 1]; + + // two characters form the hex value. + for (int i = 0, j = 0; j < len; i++) { + int f = toDigit(data[j], j) << 4; + j++; + f = f | toDigit(data[j], j); + j++; + out[i] = (byte) (f & 0xFF); + } + + return out; + } + + /** + * @param ch + * @param index + * @return + * @throws RuntimeException + */ + protected static int toDigit(char ch, int index) { + int digit = Character.digit(ch, 16); + if (digit == -1) { + throw new RuntimeException( + "Illegal hexadecimal character " + ch + " at index " + index); + } + return digit; + } + + /** @return */ + public static String StringToAsciiString(String content) { + String result = ""; + int max = content.length(); + for (int i = 0; i < max; i++) { + char c = content.charAt(i); + String b = Integer.toHexString(c); + result = result + b; + } + return result; + } + + /** + * @param hexString + * @param encodeType + * @return + */ + public static String hexStringToString(String hexString, int encodeType) { + String result = ""; + int max = hexString.length() / encodeType; + for (int i = 0; i < max; i++) { + char c = + (char) + hexStringToAlgorism( + hexString.substring(i * encodeType, (i + 1) * encodeType)); + result += c; + } + return result; + } + + /** + * @param hex + * @return + */ + public static int hexStringToAlgorism(String hex) { + hex = hex.toUpperCase(); + int max = hex.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = hex.charAt(i - 1); + int algorism = 0; + if (c >= '0' && c <= '9') { + algorism = c - '0'; + } else { + algorism = c - 55; + } + result += Math.pow(16, max - (double) i) * algorism; + } + return result; + } + + /** + * @param hex + * @return + */ + public static String hexStringToBinary(String hex) { + hex = hex.toUpperCase(); + String result = ""; + int max = hex.length(); + for (int i = 0; i < max; i++) { + char c = hex.charAt(i); + switch (c) { + case '0': + result += "0000"; + break; + case '1': + result += "0001"; + break; + case '2': + result += "0010"; + break; + case '3': + result += "0011"; + break; + case '4': + result += "0100"; + break; + case '5': + result += "0101"; + break; + case '6': + result += "0110"; + break; + case '7': + result += "0111"; + break; + case '8': + result += "1000"; + break; + case '9': + result += "1001"; + break; + case 'A': + result += "1010"; + break; + case 'B': + result += "1011"; + break; + case 'C': + result += "1100"; + break; + case 'D': + result += "1101"; + break; + case 'E': + result += "1110"; + break; + case 'F': + result += "1111"; + break; + } + } + return result; + } + + /** @return */ + public static String AsciiStringToString(String content) { + String result = ""; + int length = content.length() / 2; + for (int i = 0; i < length; i++) { + String c = content.substring(i * 2, i * 2 + 2); + int a = hexStringToAlgorism(c); + char b = (char) a; + String d = String.valueOf(b); + result += d; + } + return result; + } + + /** + * @param algorism int + * @param maxLength int + * @return String + */ + public static String algorismToHexString(int algorism, int maxLength) { + String result = ""; + result = Integer.toHexString(algorism); + + if (result.length() % 2 == 1) { + result = "0" + result; + } + return patchHexString(result.toUpperCase(), maxLength); + } + + /** + * @param bytearray byte[] + * @return String + */ + public static String byteToString(byte[] bytearray) { + String result = ""; + char temp; + + int length = bytearray.length; + for (int i = 0; i < length; i++) { + temp = (char) bytearray[i]; + result += temp; + } + return result; + } + + /** + * @param binary + * @return + */ + public static int binaryToAlgorism(String binary) { + int max = binary.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = binary.charAt(i - 1); + int algorism = c - '0'; + result += Math.pow(2, max - (double) i) * algorism; + } + return result; + } + + /** + * @param algorism int + * @return String + */ + public static String algorismToHEXString(int algorism) { + String result = ""; + result = Integer.toHexString(algorism); + + if (result.length() % 2 == 1) { + result = "0" + result; + } + result = result.toUpperCase(); + + return result; + } + + /** + * @param str String + * @param maxLength int + * @return + */ + public static String patchHexString(String str, int maxLength) { + String temp = ""; + for (int i = 0; i < maxLength - str.length(); i++) { + temp = "0" + temp; + } + str = (temp + str).substring(0, maxLength); + return str; + } + + /** + * @param s String + * @param defaultInt int + * @param radix int + * @return int + */ + public static int parseToInt(String s, int defaultInt, int radix) { + int i = 0; + try { + i = Integer.parseInt(s, radix); + } catch (NumberFormatException ex) { + i = defaultInt; + } + return i; + } + + /** + * @param s + * @param defaultInt + * @return + */ + public static int parseToInt(String s, int defaultInt) { + int i = 0; + try { + i = Integer.parseInt(s); + } catch (NumberFormatException ex) { + i = defaultInt; + } + return i; + } + + /** @return the array of byte */ + public static byte[] hexToByte(String hex) throws IllegalArgumentException { + if (hex.length() % 2 != 0) { + throw new IllegalArgumentException(); + } + char[] arr = hex.toCharArray(); + byte[] b = new byte[hex.length() / 2]; + for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) { + String swap = "" + arr[i++] + arr[i]; + int byteint = Integer.parseInt(swap, 16) & 0xFF; + b[j] = (byte) byteint; + } + return b; + } + + /** + * @param b byte[] + * @return String + */ + public static String byteToHex(byte b[]) { + if (b == null) { + throw new IllegalArgumentException("Argument b ( byte array ) is null! "); + } + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = Integer.toHexString(b[n] & 0xff); + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; + } + } + return hs.toUpperCase(); + } + + public static byte[] subByte(byte[] input, int startIndex, int length) { + byte[] bt = new byte[length]; + for (int i = 0; i < length; i++) { + bt[i] = input[i + startIndex]; + } + return bt; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CNS.java b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CNS.java index 904796b90..5009f1ec5 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CNS.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CNS.java @@ -27,140 +27,144 @@ *

Generated with web3j version none. */ public class CNS extends Contract { - private static final String BINARY = ""; - - public static final String FUNC_SELECTBYNAME = "selectByName"; - - public static final String FUNC_SELECTBYNAMEANDVERSION = "selectByNameAndVersion"; - - public static final String FUNC_INSERT = "insert"; - - @Deprecated - protected CNS( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected CNS( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected CNS( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected CNS( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall selectByName(String name) { - final Function function = - new Function( - FUNC_SELECTBYNAME, - Arrays.asList(new Utf8String(name)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall selectByNameAndVersion(String name, String version) { - final Function function = - new Function( - FUNC_SELECTBYNAMEANDVERSION, - Arrays.asList(new Utf8String(name), new Utf8String(version)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall insert( - String name, String version, String addr, String abi) { - final Function function = - new Function( - FUNC_INSERT, - Arrays.asList( - new Utf8String(name), - new Utf8String(version), - new Utf8String(addr), - new Utf8String(abi)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - @Deprecated - public static CNS load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CNS(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static CNS load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new CNS(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static CNS load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new CNS(contractAddress, web3j, credentials, contractGasProvider); - } - - public static CNS load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new CNS(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(CNS.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(CNS.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(CNS.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(CNS.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } + private static final String BINARY = ""; + + public static final String FUNC_SELECTBYNAME = "selectByName"; + + public static final String FUNC_SELECTBYNAMEANDVERSION = "selectByNameAndVersion"; + + public static final String FUNC_INSERT = "insert"; + + @Deprecated + protected CNS( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected CNS( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected CNS( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected CNS( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall selectByName(String name) { + final Function function = + new Function( + FUNC_SELECTBYNAME, + Arrays.asList(new Utf8String(name)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall selectByNameAndVersion(String name, String version) { + final Function function = + new Function( + FUNC_SELECTBYNAMEANDVERSION, + Arrays.asList(new Utf8String(name), new Utf8String(version)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall insert( + String name, String version, String addr, String abi) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new Utf8String(name), + new Utf8String(version), + new Utf8String(addr), + new Utf8String(abi)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static CNS load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new CNS(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static CNS load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new CNS(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static CNS load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new CNS(contractAddress, web3j, credentials, contractGasProvider); + } + + public static CNS load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new CNS(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(CNS.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(CNS.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + CNS.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + CNS.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsInfo.java b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsInfo.java index 4d556fdee..0aa5efd67 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsInfo.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsInfo.java @@ -2,52 +2,52 @@ public class CnsInfo { - private String name; - private String version; - private String address; - private String abi; - - public CnsInfo() { - super(); - } - - public CnsInfo(String name, String version, String address, String abi) { - super(); - this.name = name; - this.version = version; - this.address = address; - this.abi = abi; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getAbi() { - return abi; - } - - public void setAbi(String abi) { - this.abi = abi; - } + private String name; + private String version; + private String address; + private String abi; + + public CnsInfo() { + super(); + } + + public CnsInfo(String name, String version, String address, String abi) { + super(); + this.name = name; + this.version = version; + this.address = address; + this.abi = abi; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getAbi() { + return abi; + } + + public void setAbi(String abi) { + this.abi = abi; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsResolutionException.java b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsResolutionException.java index 4e7e82927..1d9f9c59a 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsResolutionException.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsResolutionException.java @@ -2,11 +2,11 @@ /** ENS resolution exception. */ public class CnsResolutionException extends RuntimeException { - public CnsResolutionException(String message) { - super(message); - } + public CnsResolutionException(String message) { + super(message); + } - public CnsResolutionException(String message, Throwable cause) { - super(message, cause); - } + public CnsResolutionException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsService.java b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsService.java index fe6cd58f9..0d13036a1 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsService.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/cns/CnsService.java @@ -1,11 +1,12 @@ package org.fisco.bcos.web3j.precompile.cns; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.List; - import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.crypto.WalletUtils; import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; +import org.fisco.bcos.web3j.precompile.exception.PrecompileMessageException; import org.fisco.bcos.web3j.protocol.ObjectMapperFactory; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameterName; @@ -13,149 +14,159 @@ import org.fisco.bcos.web3j.protocol.core.methods.response.SyncStatus; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.fisco.bcos.web3j.tx.Contract; -import org.fisco.bcos.web3j.tx.RawTransactionManager; import org.fisco.bcos.web3j.tx.TransactionManager; import org.fisco.bcos.web3j.tx.gas.DefaultGasProvider; import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; - /** Resolution logic for contract addresses. */ public class CnsService { - private static Logger logger = LoggerFactory.getLogger(CnsService.class); - private static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3L; - public static final int MAX_VERSION_LENGTH = 40; + private static Logger logger = LoggerFactory.getLogger(CnsService.class); + private static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3L; + public static final int MAX_VERSION_LENGTH = 40; - private final Web3j web3j; - private final TransactionManager transactionManager; - private long syncThreshold; // non-final in case this value needs to be tweaked - private static String registryContract = "0x0000000000000000000000000000000000001004"; + private final Web3j web3j; + private final TransactionManager transactionManager; + private long syncThreshold; // non-final in case this value needs to be tweaked + private static String registryContract = "0x0000000000000000000000000000000000001004"; - private CNS cnsRegistry; + private CNS cnsRegistry; - public CnsService(Web3j web3j, long syncThreshold, Credentials credentials) { - this.web3j = web3j; - transactionManager = Contract.getTheTransactionManager(web3j,credentials); - this.syncThreshold = syncThreshold; - } + public CnsService(Web3j web3j, long syncThreshold, Credentials credentials) { + this.web3j = web3j; + transactionManager = Contract.getTheTransactionManager(web3j, credentials); + this.syncThreshold = syncThreshold; + } - public CnsService(Web3j web3j, Credentials credentials) { - this(web3j, DEFAULT_SYNC_THRESHOLD, credentials); - } + public CnsService(Web3j web3j, Credentials credentials) { + this(web3j, DEFAULT_SYNC_THRESHOLD, credentials); + } - public void setSyncThreshold(long syncThreshold) { - this.syncThreshold = syncThreshold; - } + public void setSyncThreshold(long syncThreshold) { + this.syncThreshold = syncThreshold; + } - public long getSyncThreshold() { - return syncThreshold; - } + public long getSyncThreshold() { + return syncThreshold; + } - public String getAddressByContractNameAndVersion(String contractNameAndVersion) { + public String getAddressByContractNameAndVersion(String contractNameAndVersion) { + + if (!isValidCnsName(contractNameAndVersion)) { + return contractNameAndVersion; + } + CNS cns; + cns = lookupResolver(); + String contractAddressInfo; + String address; + + try { + // if has version + if (contractNameAndVersion.contains(":")) { + String contractName = contractNameAndVersion.split(":")[0]; + String contractVersion = contractNameAndVersion.split(":")[1]; + contractAddressInfo = + cns.selectByNameAndVersion(contractName, contractVersion).send(); + if ("[\n]".equals(contractAddressInfo)) { + throw new PrecompileMessageException("The contract version does not exist."); + } + logger.debug("query contractName {}", contractAddressInfo); + List cNSInfos = jsonToCNSInfos(contractAddressInfo); + address = cNSInfos.get(0).getAddress(); + } else { + // only contract name + contractAddressInfo = cns.selectByName(contractNameAndVersion).send(); + if ("[\n]".equals(contractAddressInfo)) { + throw new PrecompileMessageException("The contract version does not exist."); + } + logger.debug("query contractName {} ", contractAddressInfo); + List CNSInfos = jsonToCNSInfos(contractAddressInfo); + CnsInfo c = CNSInfos.get(CNSInfos.size() - 1); + address = c.getAddress(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (!WalletUtils.isValidAddress(address)) { + throw new RuntimeException( + "Unable to resolve address for name: " + contractNameAndVersion); + } else { + return address; + } + } - if (!isValidCnsName(contractNameAndVersion)) { - return contractNameAndVersion; + public String registerCns(String name, String version, String address, String abi) + throws Exception { + CNS cns = lookupResolver(); + if (version.length() > MAX_VERSION_LENGTH) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.VersionExceeds); + } + TransactionReceipt receipt = cns.insert(name, version, address, abi).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); } - CNS cns; - cns = lookupResolver(); - String contractAddressInfo; - String address; - - try { - // if has version - if (contractNameAndVersion.contains(":")) { - String contractName = contractNameAndVersion.split(":")[0]; - String contractVersion = contractNameAndVersion.split(":")[1]; - - contractAddressInfo = cns.selectByNameAndVersion(contractName, contractVersion).send(); - logger.debug("get contractName ", contractAddressInfo); - List cNSInfos = jsonToCNSInfos(contractAddressInfo); - address = cNSInfos.get(0).getAddress(); - } else { - // only contract name - contractAddressInfo = cns.selectByName(contractNameAndVersion).send(); - logger.debug("get contractName ", contractAddressInfo); - List CNSInfos = jsonToCNSInfos(contractAddressInfo); - CnsInfo c = CNSInfos.get(CNSInfos.size() - 1); - address = c.getAddress(); - } - } catch (Exception e) { - throw new RuntimeException(e); + + public List queryCnsByName(String name) throws Exception { + CNS cns = lookupResolver(); + String cnsInfo = cns.selectByName(name).send(); + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + return objectMapper.readValue( + cnsInfo, + objectMapper.getTypeFactory().constructCollectionType(List.class, CnsInfo.class)); } - if (!WalletUtils.isValidAddress(address)) { - throw new RuntimeException("Unable to resolve address for name: " + contractNameAndVersion); - } else { - return address; + public List queryCnsByNameAndVersion(String name, String version) throws Exception { + CNS cns = lookupResolver(); + String cnsInfo = cns.selectByNameAndVersion(name, version).send(); + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + return objectMapper.readValue( + cnsInfo, + objectMapper.getTypeFactory().constructCollectionType(List.class, CnsInfo.class)); } - } - public String registerCns(String name, String version, String address, String abi) - throws Exception { - CNS cns = lookupResolver(); - if (version.length() > MAX_VERSION_LENGTH) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.VersionExceeds); + private List jsonToCNSInfos(String contractAddressInfo) throws IOException { + + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + List cnsInfo = + objectMapper.readValue( + contractAddressInfo, + objectMapper + .getTypeFactory() + .constructCollectionType(List.class, CnsInfo.class)); + return cnsInfo; } - TransactionReceipt receipt = cns.insert(name, version, address, abi).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - - public List queryCnsByName(String name) throws Exception { - CNS cns = lookupResolver(); - String cnsInfo = cns.selectByName(name).send(); - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - return objectMapper.readValue( - cnsInfo, objectMapper.getTypeFactory().constructCollectionType(List.class, CnsInfo.class)); - } - - public List queryCnsByNameAndVersion(String name, String version) throws Exception { - CNS cns = lookupResolver(); - String cnsInfo = cns.selectByNameAndVersion(name, version).send(); - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - return objectMapper.readValue( - cnsInfo, objectMapper.getTypeFactory().constructCollectionType(List.class, CnsInfo.class)); - } - - private List jsonToCNSInfos(String contractAddressInfo) throws IOException { - - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - List cnsInfo = - objectMapper.readValue( - contractAddressInfo, - objectMapper.getTypeFactory().constructCollectionType(List.class, CnsInfo.class)); - return cnsInfo; - } - - public CNS lookupResolver() { - - if (this.cnsRegistry == null) { - CNS cnsRegistry = - CNS.load( - registryContract, - web3j, - transactionManager, - new StaticGasProvider(DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT)); - this.cnsRegistry = cnsRegistry; + + public CNS lookupResolver() { + + if (this.cnsRegistry == null) { + CNS cnsRegistry = + CNS.load( + registryContract, + web3j, + transactionManager, + new StaticGasProvider( + DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT)); + this.cnsRegistry = cnsRegistry; + } + return this.cnsRegistry; } - return this.cnsRegistry; - } - - boolean isSynced() throws Exception { - SyncStatus ethSyncing = web3j.getSyncStatus().send(); - if (ethSyncing.isSyncing()) { - return false; - } else { - BcosBlock block = web3j.getBlockByNumber(DefaultBlockParameterName.LATEST, false).send(); - long timestamp = block.getBlock().getTimestamp().longValueExact() * 1000; - - return System.currentTimeMillis() - syncThreshold < timestamp; + + boolean isSynced() throws Exception { + SyncStatus ethSyncing = web3j.getSyncStatus().send(); + if (ethSyncing.isSyncing()) { + return false; + } else { + BcosBlock block = + web3j.getBlockByNumber(DefaultBlockParameterName.LATEST, false).send(); + long timestamp = block.getBlock().getTimestamp().longValueExact() * 1000; + + return System.currentTimeMillis() - syncThreshold < timestamp; + } } - } - public static boolean isValidCnsName(String input) { - return input != null // will be set to null on new Contract creation - && (input.contains(":") || !WalletUtils.isValidAddress(input)); - } + public static boolean isValidCnsName(String input) { + return input != null // will be set to null on new Contract creation + && (input.contains(":") || !WalletUtils.isValidAddress(input)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/cns/NameHash.java b/src/main/java/org/fisco/bcos/web3j/precompile/cns/NameHash.java index 09af2eda3..70ae144fa 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/cns/NameHash.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/cns/NameHash.java @@ -9,51 +9,51 @@ /** ENS name hash implementation. */ public class NameHash { - private static final byte[] EMPTY = new byte[32]; - - public static byte[] nameHashAsBytes(String ensName) { - return Numeric.hexStringToByteArray(nameHash(ensName)); - } - - public static String nameHash(String ensName) { - String normalisedEnsName = normalise(ensName); - return Numeric.toHexString(nameHash(normalisedEnsName.split("\\."))); - } - - private static byte[] nameHash(String[] labels) { - if (labels.length == 0 || labels[0].equals("")) { - return EMPTY; - } else { - String[] tail; - if (labels.length == 1) { - tail = new String[] {}; - } else { - tail = Arrays.copyOfRange(labels, 1, labels.length); - } - - byte[] remainderHash = nameHash(tail); - byte[] result = Arrays.copyOf(remainderHash, 64); - - byte[] labelHash = Hash.sha3(labels[0].getBytes(StandardCharsets.UTF_8)); - System.arraycopy(labelHash, 0, result, 32, labelHash.length); - - return Hash.sha3(result); + private static final byte[] EMPTY = new byte[32]; + + public static byte[] nameHashAsBytes(String ensName) { + return Numeric.hexStringToByteArray(nameHash(ensName)); + } + + public static String nameHash(String ensName) { + String normalisedEnsName = normalise(ensName); + return Numeric.toHexString(nameHash(normalisedEnsName.split("\\."))); } - } - - /** - * Normalise ENS name as per the specification. - * - * @param ensName our user input ENS name - * @return normalised ens name - * @throws CnsResolutionException if the name cannot be normalised - */ - public static String normalise(String ensName) { - try { - return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(); - } catch (IllegalArgumentException e) { - throw new CnsResolutionException("Invalid ENS name provided: " + ensName); + + private static byte[] nameHash(String[] labels) { + if (labels.length == 0 || labels[0].equals("")) { + return EMPTY; + } else { + String[] tail; + if (labels.length == 1) { + tail = new String[] {}; + } else { + tail = Arrays.copyOfRange(labels, 1, labels.length); + } + + byte[] remainderHash = nameHash(tail); + byte[] result = Arrays.copyOf(remainderHash, 64); + + byte[] labelHash = Hash.sha3(labels[0].getBytes(StandardCharsets.UTF_8)); + System.arraycopy(labelHash, 0, result, 32, labelHash.length); + + return Hash.sha3(result); + } + } + + /** + * Normalise ENS name as per the specification. + * + * @param ensName our user input ENS name + * @return normalised ens name + * @throws CnsResolutionException if the name cannot be normalised + */ + public static String normalise(String ensName) { + try { + return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(); + } catch (IllegalArgumentException e) { + throw new CnsResolutionException("Invalid ENS name provided: " + ensName); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledCommon.java b/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledCommon.java index a0492693b..923b85c0b 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledCommon.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledCommon.java @@ -1,134 +1,164 @@ package org.fisco.bcos.web3j.precompile.common; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; import java.math.BigInteger; - import org.fisco.bcos.web3j.protocol.ObjectMapperFactory; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.channel.StatusCode; +import org.fisco.bcos.web3j.protocol.core.methods.response.NodeVersion.Version; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.fisco.bcos.web3j.protocol.exceptions.TransactionException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - public class PrecompiledCommon { - // system table for authority control - public static final String SYSTABLE = "_sys_tables_"; - public static final String SYSTABLEACCESS = "_sys_table_access_"; - public static final String SYSCONSENSUS = "_sys_consensus_"; - public static final String SYSCNS = "_sys_cns_"; - public static final String SYSCONFIG = "_sys_config_"; - - public static final int Success = 0; - public static final int PermissionDenied = 50000; - public static final int TableNameAndAddressExist = 51000; - public static final int TableNameAndAddressNotExist = 51001; - public static final int InvalidNodeId = 51100; - public static final int LastSealer = 51101; - public static final int P2pNetwork = 51102; - public static final int GroupPeers = 51103; - public static final int SealerList = 51104; - public static final int ObserverList = 51105; - public static final int ContractNameAndVersionExist = 51200; - public static final int VersionExceeds = 51201; - public static final int InvalidKey = 51300; + public static final String BCOS_RC1 = "2.0.0-rc1"; + public static final String BCOS_RC2 = "2.0.0-rc2"; + public static final String BCOS_RC3 = "2.0.0-rc3"; + + // system table for authority control + public static final String USER_TABLE_PREFIX = "_user_"; + public static final String SYS_TABLE = "_sys_tables_"; + public static final String SYS_TABLE_ACCESS = "_sys_table_access_"; + public static final String SYS_CONSENSUS = "_sys_consensus_"; + public static final String SYS_CNS = "_sys_cns_"; + public static final String SYS_CONFIG = "_sys_config_"; - public static String transferToJson(int code) throws JsonProcessingException { - String msg = ""; - switch (code) { - case Success: - msg = "success"; - break; - case PermissionDenied: - msg = "permission denied"; - break; - case TableNameAndAddressExist: - msg = "table name and address already exist"; - break; - case TableNameAndAddressNotExist: - msg = "table name and address does not exist"; - break; - case InvalidNodeId: - msg = "invalid node ID"; - break; - case LastSealer: - msg = "the last sealer cannot be removed"; - break; - case P2pNetwork: - msg = "the node is not reachable"; - break; - case GroupPeers: - msg = "the node is not a group peer"; - break; - case SealerList: - msg = "the node is already in the sealer list"; - break; - case ObserverList: - msg = "the node is already in the observer list"; - break; - case ContractNameAndVersionExist: - msg = "contract name and version already exist"; - break; - case VersionExceeds: - msg = "version string length exceeds the maximum limit"; - break; - case InvalidKey: - msg = "invalid configuration entry"; - break; + public static final int Success = 0; + public static final int PermissionDenied_RC1 = 80; + public static final int PermissionDenied = 50000; + public static final int PermissionDenied_RC3 = -50000; + public static final int TableExist = 50001; + public static final int TableExist_RC3 = -50001; + public static final int TableNameAndAddressExist_RC1 = 56; + public static final int TableNameAndAddressExist = 51000; + public static final int TableNameAndAddressExist_RC3 = -51000; + public static final int TableNameAndAddressNotExist_RC1 = 57; + public static final int TableNameAndAddressNotExist = 51001; + public static final int TableNameAndAddressNotExist_RC3 = -51001; + public static final int InvalidNodeId = -51100; + public static final int LastSealer_RC1 = 100; + public static final int LastSealer = 51101; + public static final int LastSealer_RC3 = -51101; + public static final int P2pNetwork = -51102; + public static final int GroupPeers = -51103; + public static final int SealerList = -51104; + public static final int ObserverList = -51105; + public static final int ContractNameAndVersionExist = -51200; + public static final int VersionExceeds = -51201; + public static final int InvalidKey_RC1 = 157; + public static final int InvalidKey = 51300; + public static final int InvalidKey_RC3 = -51300; + + public static final int TABLE_KEY_MAX_LENGTH = 255; + + public static String BCOS_VERSION = ""; + + public static String transferToJson(int code) throws IOException { + // adapt fisco-bcos rc1 || rc2 || rc3 + String msg = ""; + if (BCOS_VERSION == null || BCOS_RC1.equals(BCOS_VERSION)) { + if (code == PermissionDenied_RC1) { + msg = "permission denied"; + } else if (code == TableNameAndAddressExist_RC1) { + msg = "table name and address already exist"; + } else if (code == TableNameAndAddressNotExist_RC1) { + msg = "table name and address does not exist"; + } else if (code == LastSealer_RC1) { + msg = "the last sealer cannot be removed"; + } else if (code == InvalidKey_RC1) { + msg = "invalid configuration entry"; + } + } else if (BCOS_RC2.equals(BCOS_VERSION)) { + if (code == PermissionDenied) { + msg = "permission denied"; + } else if (code == TableNameAndAddressExist) { + msg = "table name and address already exist"; + } else if (code == TableNameAndAddressNotExist) { + msg = "table name and address does not exist"; + } else if (code == LastSealer) { + msg = "the last sealer cannot be removed"; + } else if (code == TableExist) { + msg = "table already exist"; + } else if (code == InvalidKey) { + msg = "invalid configuration entry"; + } + } else { + if (code == PermissionDenied_RC3) { + msg = "permission denied"; + } else if (code == TableNameAndAddressExist_RC3) { + msg = "table name and address already exist"; + } else if (code == TableNameAndAddressNotExist_RC3) { + msg = "table name and address does not exist"; + } else if (code == LastSealer_RC3) { + msg = "the last sealer cannot be removed"; + } else if (code == TableExist_RC3) { + msg = "table already exist"; + } else if (code == InvalidKey_RC3) { + msg = "invalid configuration entry"; + } + } + if (code == Success) { + msg = "success"; + } else if (code == InvalidNodeId) { + msg = "invalid node ID"; + } else if (code == P2pNetwork) { + msg = "the node is not reachable"; + } else if (code == GroupPeers) { + msg = "the node is not a group peer"; + } else if (code == SealerList) { + msg = "the node is already in the sealer list"; + } else if (code == ObserverList) { + msg = "the node is already in the observer list"; + } else if (code == ContractNameAndVersionExist) { + msg = "contract name and version already exist"; + } else if (code == VersionExceeds) { + msg = "version string length exceeds the maximum limit"; + } + ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); + return mapper.writeValueAsString(new PrecompiledResponse(code, msg)); } - ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); - return mapper.writeValueAsString(new PrecompiledResponse(code, msg)); - } - public static String getJsonStr(String output) throws JsonProcessingException { - try { - int code = 0; - code = new BigInteger(output.substring(2, output.length()), 16).intValue(); - if(code == 1) - { - code = Success; - } - if(code == 56) - { - code = TableNameAndAddressExist; - } - if(code == 57) - { - code = TableNameAndAddressNotExist; - } - if(code == 80) - { - code = PermissionDenied; - } - if(code == 100) - { - code = InvalidKey; - } - if(code == 157) - { - code = LastSealer; - } - return transferToJson(code); - } catch (NumberFormatException e) { - return "The call function does not exist."; + public static String getJsonStr(String output, Web3j web3j) throws IOException { + try { + Version nodeVersion = web3j.getNodeVersion().send().getNodeVersion(); + BCOS_VERSION = nodeVersion.getSupportedVersion(); + int code = 0; + code = new BigInteger(output.substring(2, output.length()), 16).intValue(); + if (code == 1) { + code = Success; + } + return transferToJson(code); + } catch (NumberFormatException e) { + return "The call function does not exist."; + } } - } - - public static String handleTransactionReceipt(TransactionReceipt receipt) - throws TransactionException, JsonProcessingException { - if("Receipt timeout".equals(receipt.getStatus())) - { - throw new TransactionException("Transaction receipt timeout."); + + public static int handleTransactionReceiptForCRUD(TransactionReceipt receipt) + throws TransactionException { + String status = receipt.getStatus(); + if (!"0x0".equals(receipt.getStatus())) { + throw new TransactionException(StatusCode.getStatusMessage(receipt.getStatus())); + } + String output = receipt.getOutput(); + if (!"0x".equals(output)) { + return new BigInteger(output.substring(2, output.length()), 16).intValue(); + } else { + throw new TransactionException("Transaction is handled failure."); + } } - else - { - if(receipt.getOutput() != null) - { - return PrecompiledCommon.getJsonStr(receipt.getOutput()); - } - else - { - throw new TransactionException("Transaction is handled failure."); - } + + public static String handleTransactionReceipt(TransactionReceipt receipt, Web3j web3j) + throws TransactionException, IOException { + String status = receipt.getStatus(); + if (!"0x0".equals(status)) { + throw new TransactionException(StatusCode.getStatusMessage(receipt.getStatus())); + } else { + if (receipt.getOutput() != null) { + return PrecompiledCommon.getJsonStr(receipt.getOutput(), web3j); + } else { + throw new TransactionException("Transaction is handled failure."); + } + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledResponse.java b/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledResponse.java index 0d7d24375..76205c07f 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledResponse.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/common/PrecompiledResponse.java @@ -2,33 +2,33 @@ public class PrecompiledResponse { - private int code; - private String msg; - - public PrecompiledResponse() { - super(); - // TODO Auto-generated constructor stub - } - - public PrecompiledResponse(int code, String msg) { - super(); - this.code = code; - this.msg = msg; - } - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } + private int code; + private String msg; + + public PrecompiledResponse() { + super(); + // TODO Auto-generated constructor stub + } + + public PrecompiledResponse(int code, String msg) { + super(); + this.code = code; + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/config/EnumKey.java b/src/main/java/org/fisco/bcos/web3j/precompile/config/EnumKey.java new file mode 100644 index 000000000..c5ca280a7 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/config/EnumKey.java @@ -0,0 +1,6 @@ +package org.fisco.bcos.web3j.precompile.config; + +public enum EnumKey { + tx_count_limit, + tx_gas_limit; +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfig.java b/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfig.java index 42622d56c..b46c4de96 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfig.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfig.java @@ -26,118 +26,121 @@ *

Generated with web3j version none. */ public class SystemConfig extends Contract { - private static final String BINARY = ""; - - public static final String FUNC_SETVALUEBYKEY = "setValueByKey"; - - @Deprecated - protected SystemConfig( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected SystemConfig( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected SystemConfig( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected SystemConfig( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall setValueByKey(String key, String value) { - final Function function = - new Function( - FUNC_SETVALUEBYKEY, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(value)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - @Deprecated - public static SystemConfig load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new SystemConfig(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static SystemConfig load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new SystemConfig(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static SystemConfig load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new SystemConfig(contractAddress, web3j, credentials, contractGasProvider); - } - - public static SystemConfig load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new SystemConfig(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - SystemConfig.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(SystemConfig.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - SystemConfig.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - SystemConfig.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } + private static final String BINARY = ""; + + public static final String FUNC_SETVALUEBYKEY = "setValueByKey"; + + @Deprecated + protected SystemConfig( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected SystemConfig( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected SystemConfig( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected SystemConfig( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall setValueByKey(String key, String value) { + final Function function = + new Function( + FUNC_SETVALUEBYKEY, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(value)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static SystemConfig load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new SystemConfig(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static SystemConfig load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new SystemConfig(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static SystemConfig load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new SystemConfig(contractAddress, web3j, credentials, contractGasProvider); + } + + public static SystemConfig load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new SystemConfig(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + SystemConfig.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + SystemConfig.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + SystemConfig.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + SystemConfig.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigSerivce.java b/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigSerivce.java deleted file mode 100644 index db202864c..000000000 --- a/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigSerivce.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.fisco.bcos.web3j.precompile.config; - -import java.math.BigInteger; - -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; -import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; - -public class SystemConfigSerivce { - private static BigInteger gasPrice = new BigInteger("300000000"); - private static BigInteger gasLimit = new BigInteger("300000000"); - private static String systemConfigPrecompileAddress = - "0x0000000000000000000000000000000000001000"; - private SystemConfig systemConfig; - - public SystemConfigSerivce(Web3j web3j, Credentials credentials) { - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - systemConfig = - SystemConfig.load(systemConfigPrecompileAddress, web3j, credentials, contractGasProvider); - } - - public String setValueByKey(String key, String value) throws Exception { - TransactionReceipt receipt = systemConfig.setValueByKey(key, value).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } -} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigService.java b/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigService.java new file mode 100644 index 000000000..9becbc603 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/config/SystemConfigService.java @@ -0,0 +1,31 @@ +package org.fisco.bcos.web3j.precompile.config; + +import java.math.BigInteger; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; +import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; + +public class SystemConfigService { + private static BigInteger gasPrice = new BigInteger("300000000"); + private static BigInteger gasLimit = new BigInteger("300000000"); + private static String systemConfigPrecompileAddress = + "0x0000000000000000000000000000000000001000"; + private SystemConfig systemConfig; + private Web3j web3j; + + public SystemConfigService(Web3j web3j, Credentials credentials) { + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + systemConfig = + SystemConfig.load( + systemConfigPrecompileAddress, web3j, credentials, contractGasProvider); + this.web3j = web3j; + } + + public String setValueByKey(String key, String value) throws Exception { + TransactionReceipt receipt = systemConfig.setValueByKey(key, value).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/consensus/Consensus.java b/src/main/java/org/fisco/bcos/web3j/precompile/consensus/Consensus.java index a03378cb4..106a6f171 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/consensus/Consensus.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/consensus/Consensus.java @@ -27,164 +27,174 @@ *

Generated with web3j version none. */ public class Consensus extends Contract { - private static final String BINARY = ""; - - public static final String FUNC_ADDOBSERVER = "addObserver"; - - public static final String FUNC_REMOVE = "remove"; - - public static final String FUNC_ADDSEALER = "addSealer"; - - @Deprecated - protected Consensus( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected Consensus( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected Consensus( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected Consensus( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall addObserver(String nodeID) { - final Function function = - new Function( - FUNC_ADDOBSERVER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void addObserver(String nodeID, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_ADDOBSERVER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall remove(String nodeID) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void remove(String nodeID, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall addSealer(String nodeID) { - final Function function = - new Function( - FUNC_ADDSEALER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void addSealer(String nodeID, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_ADDSEALER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - @Deprecated - public static Consensus load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Consensus(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static Consensus load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Consensus(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static Consensus load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new Consensus(contractAddress, web3j, credentials, contractGasProvider); - } - - public static Consensus load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new Consensus(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Consensus.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(Consensus.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - Consensus.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - Consensus.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } + private static final String BINARY = ""; + + public static final String FUNC_ADDOBSERVER = "addObserver"; + + public static final String FUNC_REMOVE = "remove"; + + public static final String FUNC_ADDSEALER = "addSealer"; + + @Deprecated + protected Consensus( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected Consensus( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected Consensus( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected Consensus( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall addObserver(String nodeID) { + final Function function = + new Function( + FUNC_ADDOBSERVER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void addObserver(String nodeID, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_ADDOBSERVER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall remove(String nodeID) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void remove(String nodeID, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall addSealer(String nodeID) { + final Function function = + new Function( + FUNC_ADDSEALER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void addSealer(String nodeID, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_ADDSEALER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(nodeID)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + @Deprecated + public static Consensus load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Consensus(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static Consensus load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Consensus(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static Consensus load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new Consensus(contractAddress, web3j, credentials, contractGasProvider); + } + + public static Consensus load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new Consensus(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Consensus.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + Consensus.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Consensus.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + Consensus.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/consensus/ConsensusService.java b/src/main/java/org/fisco/bcos/web3j/precompile/consensus/ConsensusService.java index ace9f123b..bf259c5dd 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/consensus/ConsensusService.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/consensus/ConsensusService.java @@ -1,9 +1,9 @@ package org.fisco.bcos.web3j.precompile.consensus; +import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; import java.math.BigInteger; import java.util.List; - import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; import org.fisco.bcos.web3j.protocol.Web3j; @@ -11,76 +11,74 @@ import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; -import com.fasterxml.jackson.core.JsonProcessingException; - public class ConsensusService { - private static BigInteger gasPrice = new BigInteger("300000000"); - private static BigInteger gasLimit = new BigInteger("300000000"); - private static String ConsensusPrecompileAddress = "0x0000000000000000000000000000000000001003"; - private Web3j web3j; - private Consensus consensus; + private static BigInteger gasPrice = new BigInteger("300000000"); + private static BigInteger gasLimit = new BigInteger("300000000"); + private static String ConsensusPrecompileAddress = "0x0000000000000000000000000000000000001003"; + private Web3j web3j; + private Consensus consensus; - public ConsensusService(Web3j web3j, Credentials credentials) { - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - this.web3j = web3j; - consensus = Consensus.load(ConsensusPrecompileAddress, web3j, credentials, contractGasProvider); - } - - public String addSealer(String nodeID) throws Exception { - if (!isValidNodeID(nodeID)) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.P2pNetwork); - } - List sealerList = web3j.getSealerList().send().getResult(); - if (sealerList.contains(nodeID)) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.SealerList); + public ConsensusService(Web3j web3j, Credentials credentials) { + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + this.web3j = web3j; + consensus = + Consensus.load(ConsensusPrecompileAddress, web3j, credentials, contractGasProvider); } - TransactionReceipt receipt = consensus.addSealer(nodeID).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - public String addObserver(String nodeID) throws Exception { - if (!isValidNodeID(nodeID)) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.P2pNetwork); + public String addSealer(String nodeID) throws Exception { + if (!isValidNodeID(nodeID)) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.P2pNetwork); + } + List sealerList = web3j.getSealerList().send().getResult(); + if (sealerList.contains(nodeID)) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.SealerList); + } + TransactionReceipt receipt = consensus.addSealer(nodeID).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); } - List observerList = web3j.getObserverList().send().getResult(); - if (observerList.contains(nodeID)) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.ObserverList); - } - TransactionReceipt receipt = consensus.addObserver(nodeID).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - public String removeNode(String nodeId) throws Exception { - List groupPeers = web3j.getGroupPeers().send().getResult(); - if (!groupPeers.contains(nodeId)) { - return PrecompiledCommon.transferToJson(PrecompiledCommon.GroupPeers); + public String addObserver(String nodeID) throws Exception { + if (!isValidNodeID(nodeID)) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.P2pNetwork); + } + List observerList = web3j.getObserverList().send().getResult(); + if (observerList.contains(nodeID)) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.ObserverList); + } + TransactionReceipt receipt = consensus.addObserver(nodeID).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); } - TransactionReceipt receipt = new TransactionReceipt(); - try { - receipt = consensus.remove(nodeId).send(); - } catch (RuntimeException e) { - // firstly remove node that sdk connected to the node, return the request that present - // susscces - // because the exception is throwed by getTransactionReceipt, we need ignore it. - if (e.getMessage() - .contains("Don't send requests to this group")) { - return PrecompiledCommon.transferToJson(0); - } else { - throw e; - } + + public String removeNode(String nodeId) throws Exception { + List groupPeers = web3j.getGroupPeers().send().getResult(); + if (!groupPeers.contains(nodeId)) { + return PrecompiledCommon.transferToJson(PrecompiledCommon.GroupPeers); + } + TransactionReceipt receipt = new TransactionReceipt(); + try { + receipt = consensus.remove(nodeId).send(); + } catch (RuntimeException e) { + // firstly remove node that sdk connected to the node, return the request that present + // susscces + // because the exception is throwed by getTransactionReceipt, we need ignore it. + if (e.getMessage().contains("Don't send requests to this group")) { + return PrecompiledCommon.transferToJson(0); + } else { + throw e; + } + } + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); } - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - private boolean isValidNodeID(String _nodeID) throws IOException, JsonProcessingException { - boolean flag = false; - List nodeIDs = web3j.getNodeIDList().send().getResult(); - for (String nodeID : nodeIDs) { - if (_nodeID.equals(nodeID)) { - flag = true; - break; - } + private boolean isValidNodeID(String _nodeID) throws IOException, JsonProcessingException { + boolean flag = false; + List nodeIDs = web3j.getNodeIDList().send().getResult(); + for (String nodeID : nodeIDs) { + if (_nodeID.equals(nodeID)) { + flag = true; + break; + } + } + return flag; } - return flag; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.java new file mode 100644 index 000000000..de915fb03 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.java @@ -0,0 +1,255 @@ +package org.fisco.bcos.web3j.precompile.crud; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collections; +import org.fisco.bcos.channel.client.TransactionSucCallback; +import org.fisco.bcos.web3j.abi.TypeReference; +import org.fisco.bcos.web3j.abi.datatypes.Function; +import org.fisco.bcos.web3j.abi.datatypes.Type; +import org.fisco.bcos.web3j.abi.datatypes.Utf8String; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.core.RemoteCall; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.Contract; +import org.fisco.bcos.web3j.tx.TransactionManager; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; + +/** + * Auto generated code. + * + *

Do not modify! + * + *

Please use the web3j command line tools, + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. + * + *

Generated with web3j version none. + */ +@SuppressWarnings("unchecked") +public class CRUD extends Contract { + private static final String BINARY = ""; + + public static final String FUNC_UPDATE = "update"; + + public static final String FUNC_SELECT = "select"; + + public static final String FUNC_INSERT = "insert"; + + public static final String FUNC_REMOVE = "remove"; + + @Deprecated + protected CRUD( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected CRUD( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected CRUD( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected CRUD( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall update( + String tableName, String key, String entry, String condition, String optional) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(entry), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(condition), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void update( + String tableName, + String key, + String entry, + String condition, + String optional, + TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(entry), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(condition), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall select( + String tableName, String key, String condition, String optional) { + final Function function = + new Function( + FUNC_SELECT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(condition), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall insert( + String tableName, String key, String entry, String optional) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(entry), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void insert( + String tableName, + String key, + String entry, + String optional, + TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(entry), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall remove( + String tableName, String key, String condition, String optional) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(condition), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void remove( + String tableName, + String key, + String condition, + String optional, + TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(condition), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(optional)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + @Deprecated + public static CRUD load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new CRUD(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static CRUD load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new CRUD(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static CRUD load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new CRUD(contractAddress, web3j, credentials, contractGasProvider); + } + + public static CRUD load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new CRUD(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(CRUD.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(CRUD.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + CRUD.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + CRUD.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.sol b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.sol new file mode 100644 index 000000000..e3e37a559 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUD.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.2; + +contract CRUD +{ + function insert(string tableName, string key, string entry, string optional) public returns(int); + function update(string tableName, string key, string entry, string condition, string optional) public returns(int); + function remove(string tableName, string key, string condition, string optional) public returns(int); + function select(string tableName, string key, string condition, string optional) public constant returns(string); +} \ No newline at end of file diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUDSerivce.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUDSerivce.java new file mode 100644 index 000000000..731babafc --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/CRUDSerivce.java @@ -0,0 +1,144 @@ +package org.fisco.bcos.web3j.precompile.crud; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigInteger; +import java.util.List; +import java.util.Map; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; +import org.fisco.bcos.web3j.precompile.exception.PrecompileMessageException; +import org.fisco.bcos.web3j.protocol.ObjectMapperFactory; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; +import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; + +public class CRUDSerivce { + private static BigInteger gasPrice = new BigInteger("300000000"); + private static BigInteger gasLimit = new BigInteger("300000000"); + private static final String TableFactoryPrecompileAddress = + "0x0000000000000000000000000000000000001001"; + private static final String CRUDPrecompileAddress = + "0x0000000000000000000000000000000000001002"; + private TableFactory tableFactory; + private CRUD crud; + + public CRUDSerivce(Web3j web3j, Credentials credentials) { + + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + tableFactory = + TableFactory.load( + TableFactoryPrecompileAddress, web3j, credentials, contractGasProvider); + crud = CRUD.load(CRUDPrecompileAddress, web3j, credentials, contractGasProvider); + } + + public int createTable(Table table) throws Exception { + + TransactionReceipt receipt = + tableFactory + .createTable(table.getTableName(), table.getKey(), table.getValueFields()) + .send(); + return PrecompiledCommon.handleTransactionReceiptForCRUD(receipt); + } + + public int insert(Table table, Entry entry) throws Exception { + + if (table.getKey().length() > PrecompiledCommon.TABLE_KEY_MAX_LENGTH) { + throw new PrecompileMessageException( + "The value of the table key exceeds the maximum limit(" + + PrecompiledCommon.TABLE_KEY_MAX_LENGTH + + ")."); + } + String entryJsonStr = + ObjectMapperFactory.getObjectMapper().writeValueAsString(entry.getFields()); + + TransactionReceipt receipt = + crud.insert(table.getTableName(), table.getKey(), entryJsonStr, table.getOptional()) + .send(); + return PrecompiledCommon.handleTransactionReceiptForCRUD(receipt); + } + + public int update(Table table, Entry entry, Condition condition) throws Exception { + + if (table.getKey().length() > PrecompiledCommon.TABLE_KEY_MAX_LENGTH) { + throw new PrecompileMessageException( + "The value of the table key exceeds the maximum limit(" + + PrecompiledCommon.TABLE_KEY_MAX_LENGTH + + ")."); + } + String entryJsonStr = + ObjectMapperFactory.getObjectMapper().writeValueAsString(entry.getFields()); + String conditionStr = + ObjectMapperFactory.getObjectMapper().writeValueAsString(condition.getConditions()); + TransactionReceipt receipt = + crud.update( + table.getTableName(), + table.getKey(), + entryJsonStr, + conditionStr, + table.getOptional()) + .send(); + return PrecompiledCommon.handleTransactionReceiptForCRUD(receipt); + } + + public int remove(Table table, Condition condition) throws Exception { + + if (table.getKey().length() > PrecompiledCommon.TABLE_KEY_MAX_LENGTH) { + throw new PrecompileMessageException( + "The value of the table key exceeds the maximum limit(" + + PrecompiledCommon.TABLE_KEY_MAX_LENGTH + + ")."); + } + String conditionStr = + ObjectMapperFactory.getObjectMapper().writeValueAsString(condition.getConditions()); + TransactionReceipt receipt = + crud.remove(table.getTableName(), table.getKey(), conditionStr, table.getOptional()) + .send(); + return PrecompiledCommon.handleTransactionReceiptForCRUD(receipt); + } + + @SuppressWarnings("unchecked") + public List> select(Table table, Condition condition) throws Exception { + + if (table.getKey().length() > PrecompiledCommon.TABLE_KEY_MAX_LENGTH) { + throw new PrecompileMessageException( + "The value of the table key exceeds the maximum limit(" + + PrecompiledCommon.TABLE_KEY_MAX_LENGTH + + ")."); + } + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + String conditionJsonStr = objectMapper.writeValueAsString(condition.getConditions()); + String resultStr = + crud.select( + table.getTableName(), + table.getKey(), + conditionJsonStr, + table.getOptional()) + .send(); + List> result = + (List>) + objectMapper.readValue( + resultStr, + objectMapper + .getTypeFactory() + .constructCollectionType(List.class, Map.class)); + return result; + } + + public Table desc(String tableName) throws Exception { + Table table = new Table(); + table.setTableName(PrecompiledCommon.SYS_TABLE); + table.setKey(PrecompiledCommon.USER_TABLE_PREFIX + tableName); + Condition condition = table.getCondition(); + List> userTable = select(table, condition); + Table tableInfo = new Table(); + if (userTable.size() != 0) { + tableInfo.setTableName(tableName); + tableInfo.setKey(userTable.get(0).get("key_field")); + tableInfo.setValueFields(userTable.get(0).get("value_field")); + } else { + throw new PrecompileMessageException("The table '" + tableName + "' does not exist."); + } + return tableInfo; + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/Condition.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Condition.java new file mode 100644 index 000000000..6a343f080 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Condition.java @@ -0,0 +1,73 @@ +package org.fisco.bcos.web3j.precompile.crud; + +import java.util.HashMap; +import java.util.Map; + +public class Condition { + + private Map> conditions; + + public Condition() { + conditions = new HashMap<>(); + } + + public void EQ(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.eq, value); + conditions.put(key, map); + } + + public void NE(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.ne, value); + conditions.put(key, map); + } + + public void GT(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.gt, value); + conditions.put(key, map); + } + + public void GE(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.ge, value); + conditions.put(key, map); + } + + public void LT(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.lt, value); + conditions.put(key, map); + } + + public void LE(String key, String value) { + HashMap map = new HashMap(); + map.put(EnumOP.le, value); + conditions.put(key, map); + } + + public void Limit(int count) { + Limit(0, count); + } + + public void Limit(int offset, int count) { + HashMap map = new HashMap(); + if (offset < 0) { + offset = 0; + } + if (count < 0) { + count = 0; + } + map.put(EnumOP.limit, offset + "," + count); + conditions.put("limit", map); + } + + public Map> getConditions() { + return conditions; + } + + public void setConditions(Map> conditions) { + this.conditions = conditions; + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/Entry.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Entry.java new file mode 100644 index 000000000..640f477a4 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Entry.java @@ -0,0 +1,28 @@ +package org.fisco.bcos.web3j.precompile.crud; + +import java.util.HashMap; +import java.util.Map; + +public class Entry { + private Map fields; + + public Map getFields() { + return fields; + } + + public void setFields(Map fields) { + this.fields = fields; + } + + public Entry() { + fields = new HashMap<>(); + } + + public void put(String key, String value) { + fields.put(key, value); + } + + public String get(String key) { + return fields.get(key); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/EnumOP.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/EnumOP.java new file mode 100644 index 000000000..7528f524c --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/EnumOP.java @@ -0,0 +1,11 @@ +package org.fisco.bcos.web3j.precompile.crud; + +public enum EnumOP { + eq, + ne, + gt, + ge, + lt, + le, + limit; +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/Table.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Table.java new file mode 100644 index 000000000..2b8b7fa7b --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/Table.java @@ -0,0 +1,70 @@ +package org.fisco.bcos.web3j.precompile.crud; + +public class Table { + + private String tableName; + private String key; + private String valueFields; + private String optional = ""; + + public Table() {} + + public Table(String tableName, String key) { + this.tableName = tableName; + this.key = key; + } + + public Table(String tableName, String key, String valueFields) { + this.tableName = tableName; + this.key = key; + this.valueFields = valueFields; + } + + public Table(String tableName, String key, String valueFields, String optional) { + super(); + this.tableName = tableName; + this.key = key; + this.valueFields = valueFields; + this.optional = optional; + } + + public String getTableName() { + return tableName; + } + + public String getKey() { + return key; + } + + public String getValueFields() { + return valueFields; + } + + public String getOptional() { + return optional; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public void setKey(String key) { + this.key = key; + } + + public void setValueFields(String valueFields) { + this.valueFields = valueFields; + } + + public void setOptional(String optional) { + this.optional = optional; + } + + public Entry getEntry() { + return new Entry(); + } + + public Condition getCondition() { + return new Condition(); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.java b/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.java new file mode 100644 index 000000000..137ee1c8f --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.java @@ -0,0 +1,163 @@ +package org.fisco.bcos.web3j.precompile.crud; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collections; +import org.fisco.bcos.channel.client.TransactionSucCallback; +import org.fisco.bcos.web3j.abi.TypeReference; +import org.fisco.bcos.web3j.abi.datatypes.Function; +import org.fisco.bcos.web3j.abi.datatypes.Type; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.core.RemoteCall; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.tx.Contract; +import org.fisco.bcos.web3j.tx.TransactionManager; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; + +/** + * Auto generated code. + * + *

Do not modify! + * + *

Please use the web3j command line tools, + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. + * + *

Generated with web3j version none. + */ +@SuppressWarnings("unchecked") +public class TableFactory extends Contract { + private static final String BINARY = ""; + + public static final String FUNC_CREATETABLE = "createTable"; + + @Deprecated + protected TableFactory( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected TableFactory( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected TableFactory( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected TableFactory( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall createTable( + String tableName, String key, String valueField) { + final Function function = + new Function( + FUNC_CREATETABLE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(valueField)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void createTable( + String tableName, String key, String valueField, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_CREATETABLE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(tableName), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(key), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(valueField)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + @Deprecated + public static TableFactory load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new TableFactory(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static TableFactory load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new TableFactory(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static TableFactory load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new TableFactory(contractAddress, web3j, credentials, contractGasProvider); + } + + public static TableFactory load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new TableFactory(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + TableFactory.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + TableFactory.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + TableFactory.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + TableFactory.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.sol b/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.sol new file mode 100644 index 000000000..4709d20ed --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/crud/TableFactory.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.4.2; + +contract TableFactory { + function createTable(string tableName, string key, string valueField) public returns (int); +} \ No newline at end of file diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/exception/PrecompileMessageException.java b/src/main/java/org/fisco/bcos/web3j/precompile/exception/PrecompileMessageException.java new file mode 100644 index 000000000..de54af841 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/precompile/exception/PrecompileMessageException.java @@ -0,0 +1,24 @@ +package org.fisco.bcos.web3j.precompile.exception; + +import java.io.IOException; + +public class PrecompileMessageException extends IOException { + + private static final long serialVersionUID = 1L; + + public PrecompileMessageException() { + super(); + } + + public PrecompileMessageException(String message, Throwable cause) { + super(message, cause); + } + + public PrecompileMessageException(String message) { + super(message); + } + + public PrecompileMessageException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/permission/Permission.java b/src/main/java/org/fisco/bcos/web3j/precompile/permission/Permission.java index f7d71cc9b..b28dca875 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/permission/Permission.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/permission/Permission.java @@ -27,137 +27,141 @@ *

Generated with web3j version none. */ public class Permission extends Contract { - private static final String BINARY = ""; - - public static final String FUNC_INSERT = "insert"; - - public static final String FUNC_QUERYBYNAME = "queryByName"; - - public static final String FUNC_REMOVE = "remove"; - - @Deprecated - protected Permission( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected Permission( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected Permission( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected Permission( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall insert(String table_name, String addr) { - final Function function = - new Function( - FUNC_INSERT, - Arrays.asList(new Utf8String(table_name), new Utf8String(addr)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall queryByName(String table_name) { - final Function function = - new Function( - FUNC_QUERYBYNAME, - Arrays.asList(new Utf8String(table_name)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall remove(String table_name, String addr) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList(new Utf8String(table_name), new Utf8String(addr)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - @Deprecated - public static Permission load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Permission(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static Permission load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Permission(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static Permission load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new Permission(contractAddress, web3j, credentials, contractGasProvider); - } - - public static Permission load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new Permission(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Permission.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(Permission.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - Permission.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - Permission.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } + private static final String BINARY = ""; + + public static final String FUNC_INSERT = "insert"; + + public static final String FUNC_QUERYBYNAME = "queryByName"; + + public static final String FUNC_REMOVE = "remove"; + + @Deprecated + protected Permission( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected Permission( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected Permission( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected Permission( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall insert(String table_name, String addr) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList(new Utf8String(table_name), new Utf8String(addr)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall queryByName(String table_name) { + final Function function = + new Function( + FUNC_QUERYBYNAME, + Arrays.asList(new Utf8String(table_name)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall remove(String table_name, String addr) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList(new Utf8String(table_name), new Utf8String(addr)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static Permission load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Permission(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static Permission load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Permission(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static Permission load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new Permission(contractAddress, web3j, credentials, contractGasProvider); + } + + public static Permission load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new Permission(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Permission.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + Permission.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Permission.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + Permission.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionInfo.java b/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionInfo.java index 1b934619c..e9d875b54 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionInfo.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionInfo.java @@ -4,35 +4,35 @@ public class PermissionInfo { - @JsonProperty("table_name") - private String tableName; + @JsonProperty("table_name") + private String tableName; - private String address; + private String address; - @JsonProperty("enable_num") - private String enableNum; + @JsonProperty("enable_num") + private String enableNum; - public String getTableName() { - return tableName; - } + public String getTableName() { + return tableName; + } - public void setTableName(String tableName) { - this.tableName = tableName; - } + public void setTableName(String tableName) { + this.tableName = tableName; + } - public String getAddress() { - return address; - } + public String getAddress() { + return address; + } - public void setAddress(String address) { - this.address = address; - } + public void setAddress(String address) { + this.address = address; + } - public String getEnableNum() { - return enableNum; - } + public String getEnableNum() { + return enableNum; + } - public void setEnableNum(String enableNum) { - this.enableNum = enableNum; - } + public void setEnableNum(String enableNum) { + this.enableNum = enableNum; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionService.java b/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionService.java index adbde57bf..1b27b79bb 100644 --- a/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionService.java +++ b/src/main/java/org/fisco/bcos/web3j/precompile/permission/PermissionService.java @@ -1,117 +1,126 @@ package org.fisco.bcos.web3j.precompile.permission; +import com.fasterxml.jackson.databind.ObjectMapper; import java.math.BigInteger; import java.util.List; - import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; +import org.fisco.bcos.web3j.precompile.crud.CRUDSerivce; import org.fisco.bcos.web3j.protocol.ObjectMapperFactory; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; -import com.fasterxml.jackson.databind.ObjectMapper; - public class PermissionService { - private static BigInteger gasPrice = new BigInteger("300000000"); - private static BigInteger gasLimit = new BigInteger("300000000"); - private static String PermissionPrecompileAddress = "0x0000000000000000000000000000000000001005"; - private Permission permission; - - public PermissionService(Web3j web3j, Credentials credentials) { - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - permission = - Permission.load(PermissionPrecompileAddress, web3j, credentials, contractGasProvider); - } - - public String grantUserTableManager(String tableName, String grantress) throws Exception { - return grant(tableName, grantress); - } - - public String revokeUserTableManager(String tableName, String grantress) throws Exception { - return revoke(tableName, grantress); - } - - public List listUserTableManager(String tableName) throws Exception { - return list(tableName); - } - - public String grantDeployAndCreateManager(String grantress) throws Exception { - return grant(PrecompiledCommon.SYSTABLE, grantress); - } - - public String revokeDeployAndCreateManager(String grantress) throws Exception { - return revoke(PrecompiledCommon.SYSTABLE, grantress); - } - - public List listDeployAndCreateManager() throws Exception { - return list(PrecompiledCommon.SYSTABLE); - } - - public String grantPermissionManager(String grantress) throws Exception { - return grant(PrecompiledCommon.SYSTABLEACCESS, grantress); - } - - public String revokePermissionManager(String grantress) throws Exception { - return revoke(PrecompiledCommon.SYSTABLEACCESS, grantress); - } - - public List listPermissionManager() throws Exception { - return list(PrecompiledCommon.SYSTABLEACCESS); - } - - public String grantNodeManager(String grantress) throws Exception { - return grant(PrecompiledCommon.SYSCONSENSUS, grantress); - } - - public String revokeNodeManager(String grantress) throws Exception { - return revoke(PrecompiledCommon.SYSCONSENSUS, grantress); - } - - public List listNodeManager() throws Exception { - return list(PrecompiledCommon.SYSCONSENSUS); - } - - public String grantCNSManager(String grantress) throws Exception { - return grant(PrecompiledCommon.SYSCNS, grantress); - } - - public String revokeCNSManager(String grantress) throws Exception { - return revoke(PrecompiledCommon.SYSCNS, grantress); - } - - public List listCNSManager() throws Exception { - return list(PrecompiledCommon.SYSCNS); - } - - public String grantSysConfigManager(String grantress) throws Exception { - return grant(PrecompiledCommon.SYSCONFIG, grantress); - } - - public String revokeSysConfigManager(String grantress) throws Exception { - return revoke(PrecompiledCommon.SYSCONFIG, grantress); - } - - public List listSysConfigManager() throws Exception { - return list(PrecompiledCommon.SYSCONFIG); - } - - private String grant(String tableName, String grantress) throws Exception { - TransactionReceipt receipt = permission.insert(tableName, grantress).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - - private String revoke(String tableName, String address) throws Exception { - TransactionReceipt receipt = permission.remove(tableName, address).send(); - return PrecompiledCommon.handleTransactionReceipt(receipt); - } - - private List list(String tableName) throws Exception { - String permissionyInfo = permission.queryByName(tableName).send(); - ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - return objectMapper.readValue( - permissionyInfo, - objectMapper.getTypeFactory().constructCollectionType(List.class, PermissionInfo.class)); - } + private static BigInteger gasPrice = new BigInteger("300000000"); + private static BigInteger gasLimit = new BigInteger("300000000"); + private static String PermissionPrecompileAddress = + "0x0000000000000000000000000000000000001005"; + private Permission permission; + private Web3j web3j; + private Credentials credentials; + + public PermissionService(Web3j web3j, Credentials credentials) { + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + permission = + Permission.load( + PermissionPrecompileAddress, web3j, credentials, contractGasProvider); + this.web3j = web3j; + this.credentials = credentials; + } + + public String grantUserTableManager(String tableName, String grantress) throws Exception { + CRUDSerivce crudSerivce = new CRUDSerivce(web3j, credentials); + crudSerivce.desc(tableName); + return grant(tableName, grantress); + } + + public String revokeUserTableManager(String tableName, String grantress) throws Exception { + return revoke(tableName, grantress); + } + + public List listUserTableManager(String tableName) throws Exception { + return list(tableName); + } + + public String grantDeployAndCreateManager(String grantress) throws Exception { + return grant(PrecompiledCommon.SYS_TABLE, grantress); + } + + public String revokeDeployAndCreateManager(String grantress) throws Exception { + return revoke(PrecompiledCommon.SYS_TABLE, grantress); + } + + public List listDeployAndCreateManager() throws Exception { + return list(PrecompiledCommon.SYS_TABLE); + } + + public String grantPermissionManager(String grantress) throws Exception { + return grant(PrecompiledCommon.SYS_TABLE_ACCESS, grantress); + } + + public String revokePermissionManager(String grantress) throws Exception { + return revoke(PrecompiledCommon.SYS_TABLE_ACCESS, grantress); + } + + public List listPermissionManager() throws Exception { + return list(PrecompiledCommon.SYS_TABLE_ACCESS); + } + + public String grantNodeManager(String grantress) throws Exception { + return grant(PrecompiledCommon.SYS_CONSENSUS, grantress); + } + + public String revokeNodeManager(String grantress) throws Exception { + return revoke(PrecompiledCommon.SYS_CONSENSUS, grantress); + } + + public List listNodeManager() throws Exception { + return list(PrecompiledCommon.SYS_CONSENSUS); + } + + public String grantCNSManager(String grantress) throws Exception { + return grant(PrecompiledCommon.SYS_CNS, grantress); + } + + public String revokeCNSManager(String grantress) throws Exception { + return revoke(PrecompiledCommon.SYS_CNS, grantress); + } + + public List listCNSManager() throws Exception { + return list(PrecompiledCommon.SYS_CNS); + } + + public String grantSysConfigManager(String grantress) throws Exception { + return grant(PrecompiledCommon.SYS_CONFIG, grantress); + } + + public String revokeSysConfigManager(String grantress) throws Exception { + return revoke(PrecompiledCommon.SYS_CONFIG, grantress); + } + + public List listSysConfigManager() throws Exception { + return list(PrecompiledCommon.SYS_CONFIG); + } + + private String grant(String tableName, String grantress) throws Exception { + TransactionReceipt receipt = permission.insert(tableName, grantress).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); + } + + private String revoke(String tableName, String address) throws Exception { + TransactionReceipt receipt = permission.remove(tableName, address).send(); + return PrecompiledCommon.handleTransactionReceipt(receipt, web3j); + } + + private List list(String tableName) throws Exception { + String permissionyInfo = permission.queryByName(tableName).send(); + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + return objectMapper.readValue( + permissionyInfo, + objectMapper + .getTypeFactory() + .constructCollectionType(List.class, PermissionInfo.class)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ObjectMapperFactory.java b/src/main/java/org/fisco/bcos/web3j/protocol/ObjectMapperFactory.java index 92d50f73a..307c576fd 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ObjectMapperFactory.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ObjectMapperFactory.java @@ -15,53 +15,53 @@ /** Factory for managing our ObjectMapper instances. */ public class ObjectMapperFactory { - private static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper(); + private static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper(); - static { - configureObjectMapper(DEFAULT_OBJECT_MAPPER, false); - } - - public static ObjectMapper getObjectMapper() { - return getObjectMapper(false); - } + static { + configureObjectMapper(DEFAULT_OBJECT_MAPPER, false); + } - public static ObjectMapper getObjectMapper(boolean shouldIncludeRawResponses) { - if (!shouldIncludeRawResponses) { - return DEFAULT_OBJECT_MAPPER; + public static ObjectMapper getObjectMapper() { + return getObjectMapper(false); } - return configureObjectMapper(new ObjectMapper(), true); - } + public static ObjectMapper getObjectMapper(boolean shouldIncludeRawResponses) { + if (!shouldIncludeRawResponses) { + return DEFAULT_OBJECT_MAPPER; + } - public static ObjectReader getObjectReader() { - return DEFAULT_OBJECT_MAPPER.reader(); - } + return configureObjectMapper(new ObjectMapper(), true); + } - private static ObjectMapper configureObjectMapper( - ObjectMapper objectMapper, boolean shouldIncludeRawResponses) { - if (shouldIncludeRawResponses) { - SimpleModule module = new SimpleModule(); - module.setDeserializerModifier( - new BeanDeserializerModifier() { - @Override - public JsonDeserializer modifyDeserializer( - DeserializationConfig config, - BeanDescription beanDesc, - JsonDeserializer deserializer) { - if (Response.class.isAssignableFrom(beanDesc.getBeanClass())) { - return new RawResponseDeserializer(deserializer); - } + public static ObjectReader getObjectReader() { + return DEFAULT_OBJECT_MAPPER.reader(); + } - return deserializer; - } - }); + private static ObjectMapper configureObjectMapper( + ObjectMapper objectMapper, boolean shouldIncludeRawResponses) { + if (shouldIncludeRawResponses) { + SimpleModule module = new SimpleModule(); + module.setDeserializerModifier( + new BeanDeserializerModifier() { + @Override + public JsonDeserializer modifyDeserializer( + DeserializationConfig config, + BeanDescription beanDesc, + JsonDeserializer deserializer) { + if (Response.class.isAssignableFrom(beanDesc.getBeanClass())) { + return new RawResponseDeserializer(deserializer); + } - objectMapper.registerModule(module); - } + return deserializer; + } + }); + + objectMapper.registerModule(module); + } - objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - return objectMapper; - } + return objectMapper; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/Service.java b/src/main/java/org/fisco/bcos/web3j/protocol/Service.java index a888ee31e..e7aa4befa 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/Service.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/Service.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.reactivex.Flowable; +import java.io.IOException; import java.util.concurrent.CompletableFuture; import org.fisco.bcos.web3j.protocol.core.Request; import org.fisco.bcos.web3j.protocol.core.Response; @@ -11,23 +12,27 @@ /** Base service implementation. */ public abstract class Service implements Web3jService { - protected final ObjectMapper objectMapper; + protected final ObjectMapper objectMapper; - public Service(boolean includeRawResponses) { - objectMapper = ObjectMapperFactory.getObjectMapper(includeRawResponses); - } + public Service(boolean includeRawResponses) { + objectMapper = ObjectMapperFactory.getObjectMapper(includeRawResponses); + } - @Override - public CompletableFuture sendAsync( - Request jsonRpc20Request, Class responseType) { - return Async.run(() -> send(jsonRpc20Request, responseType)); - } + @Override + public CompletableFuture sendAsync( + Request jsonRpc20Request, Class responseType) { + return Async.run(() -> send(jsonRpc20Request, responseType)); + } - @Override - public > Flowable subscribe( - Request request, String unsubscribeMethod, Class responseType) { - throw new UnsupportedOperationException( - String.format( - "Service %s does not support subscriptions", this.getClass().getSimpleName())); - } + @Override + public void sendOnly(Request request) throws IOException {} + + @Override + public > Flowable subscribe( + Request request, String unsubscribeMethod, Class responseType) { + throw new UnsupportedOperationException( + String.format( + "Service %s does not support subscriptions", + this.getClass().getSimpleName())); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/Web3j.java b/src/main/java/org/fisco/bcos/web3j/protocol/Web3j.java index e19089a5e..327183d67 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/Web3j.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/Web3j.java @@ -7,19 +7,20 @@ /** JSON-RPC Request object building factory. */ public interface Web3j extends Ethereum, Web3jRx { - static Web3j build(Web3jService web3jService) { - return new JsonRpc2_0Web3j(web3jService); - } + static Web3j build(Web3jService web3jService) { + return new JsonRpc2_0Web3j(web3jService); + } - static Web3j build( - Web3jService web3jService, - long pollingInterval, - ScheduledExecutorService scheduledExecutorService, - int groupId) { - return new JsonRpc2_0Web3j(web3jService, pollingInterval, scheduledExecutorService, groupId); - } + static Web3j build( + Web3jService web3jService, + long pollingInterval, + ScheduledExecutorService scheduledExecutorService, + int groupId) { + return new JsonRpc2_0Web3j( + web3jService, pollingInterval, scheduledExecutorService, groupId); + } - static Web3j build(Web3jService web3jService, int groupId) { - return new JsonRpc2_0Web3j(web3jService, groupId); - } + static Web3j build(Web3jService web3jService, int groupId) { + return new JsonRpc2_0Web3j(web3jService, groupId); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/Web3jService.java b/src/main/java/org/fisco/bcos/web3j/protocol/Web3jService.java index 5cf4c5fb6..91b7f2ea1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/Web3jService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/Web3jService.java @@ -9,33 +9,35 @@ /** Services API. */ public interface Web3jService { - T send(Request request, Class responseType) throws IOException; + T send(Request request, Class responseType) throws IOException; - CompletableFuture sendAsync(Request request, Class responseType); + void sendOnly(Request request) throws IOException; - /** - * Subscribe to a stream of notifications. A stream of notifications is opened by by performing a - * specified JSON-RPC request and is closed by calling the unsubscribe method. Different WebSocket - * implementations use different pair of subscribe/unsubscribe methods. - * - *

This method creates an Flowable that can be used to subscribe to new notifications. When a - * client unsubscribes from this Flowable the service unsubscribes from the underlying stream of - * events. - * - * @param request JSON-RPC request that will be send to subscribe to a stream of events - * @param unsubscribeMethod method that will be called to unsubscribe from a stream of - * notifications - * @param responseType class of incoming events objects in a stream - * @param type of incoming event objects - * @return a {@link Flowable} instance that emits incoming events - */ - > Flowable subscribe( - Request request, String unsubscribeMethod, Class responseType); + CompletableFuture sendAsync(Request request, Class responseType); - /** - * Closes resources used by the service. - * - * @throws IOException thrown if a service failed to close all resources - */ - void close() throws IOException; + /** + * Subscribe to a stream of notifications. A stream of notifications is opened by by performing + * a specified JSON-RPC request and is closed by calling the unsubscribe method. Different + * WebSocket implementations use different pair of subscribe/unsubscribe methods. + * + *

This method creates an Flowable that can be used to subscribe to new notifications. When a + * client unsubscribes from this Flowable the service unsubscribes from the underlying stream of + * events. + * + * @param request JSON-RPC request that will be send to subscribe to a stream of events + * @param unsubscribeMethod method that will be called to unsubscribe from a stream of + * notifications + * @param responseType class of incoming events objects in a stream + * @param type of incoming event objects + * @return a {@link Flowable} instance that emits incoming events + */ + > Flowable subscribe( + Request request, String unsubscribeMethod, Class responseType); + + /** + * Closes resources used by the service. + * + * @throws IOException thrown if a service failed to close all resources + */ + void close() throws IOException; } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/channel/ChannelEthereumService.java b/src/main/java/org/fisco/bcos/web3j/protocol/channel/ChannelEthereumService.java index c00d57b81..6b7d564ba 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/channel/ChannelEthereumService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/channel/ChannelEthereumService.java @@ -1,137 +1,237 @@ package org.fisco.bcos.web3j.protocol.channel; import java.io.IOException; +import org.fisco.bcos.channel.client.BcosResponseCallback; import org.fisco.bcos.channel.client.Service; -import org.fisco.bcos.channel.dto.FiscoRequest; -import org.fisco.bcos.channel.dto.FiscoResponse; +import org.fisco.bcos.channel.dto.BcosRequest; +import org.fisco.bcos.channel.dto.BcosResponse; import org.fisco.bcos.web3j.protocol.core.Request; import org.fisco.bcos.web3j.protocol.core.Response; +import org.fisco.bcos.web3j.protocol.core.methods.response.Call.CallOutput; import org.fisco.bcos.web3j.protocol.exceptions.MessageDecodingException; +import org.fisco.bcos.web3j.tx.exceptions.ContractCallException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Channel implementation of our services API. */ public class ChannelEthereumService extends org.fisco.bcos.web3j.protocol.Service { - private static Logger logger = LoggerFactory.getLogger(ChannelEthereumService.class); - - private Service channelService; - - public ChannelEthereumService(boolean includeRawResponses) { - super(includeRawResponses); - } - public ChannelEthereumService() { - super(false); - } - private Integer timeout=0; - - @Override - public T send(Request request, Class responseType) throws IOException { - byte[] payload = objectMapper.writeValueAsBytes(request); - - FiscoRequest fiscoRequest = new FiscoRequest(); - fiscoRequest.setKeyID(channelService.getOrgID()); - fiscoRequest.setBankNO(""); - fiscoRequest.setContent(new String(payload)); - fiscoRequest.setMessageID(channelService.newSeq()); - - if (timeout != 0) { - fiscoRequest.setTimeout(timeout); + private static Logger logger = LoggerFactory.getLogger(ChannelEthereumService.class); + + private Service channelService; + + public ChannelEthereumService(boolean includeRawResponses) { + super(includeRawResponses); } - FiscoResponse response; - if (!request.isNeedTransCallback()) { - response = channelService.sendEthereumMessage(fiscoRequest); - } else { - response = - channelService.sendEthereumMessage(fiscoRequest, request.getTransactionSucCallback()); + public ChannelEthereumService() { + super(false); } - logger.debug( - "fisco Request:{} {}", - fiscoRequest.getMessageID(), - objectMapper.writeValueAsString(request)); - logger.debug( - "fisco Response:{} {} {}", - fiscoRequest.getMessageID(), - response.getErrorCode(), - response.getContent()); - if (response.getErrorCode() == 0) { - try { - T t = objectMapper.readValue(response.getContent(), responseType); - if (t.getError() != null) { - throw new IOException(t.getError().getMessage()); + private Integer timeout = 0; + + @Override + public T send(Request request, Class responseType) throws IOException { + byte[] payload = objectMapper.writeValueAsBytes(request); + + BcosRequest bcosRequest = new BcosRequest(); + if (channelService.getOrgID() != null) { + bcosRequest.setKeyID(channelService.getOrgID()); + } else { + bcosRequest.setKeyID(channelService.getAgencyName()); + } + bcosRequest.setBankNO(""); + bcosRequest.setContent(new String(payload)); + bcosRequest.setMessageID(channelService.newSeq()); + + if (timeout != 0) { + bcosRequest.setTimeout(timeout); + } + + BcosResponse response; + if (!request.isNeedTransCallback()) { + response = channelService.sendEthereumMessage(bcosRequest); + } else { + response = + channelService.sendEthereumMessage( + bcosRequest, request.getTransactionSucCallback()); + } + logger.info( + "bcos request, seq:{}, method:{}", bcosRequest.getMessageID(), request.getMethod()); + logger.debug( + "bcos request:{} {}", + bcosRequest.getMessageID(), + objectMapper.writeValueAsString(request)); + logger.trace( + "bcos request:{} {}", + bcosRequest.getMessageID(), + objectMapper.writeValueAsString(request)); + logger.trace( + "bcos response:{} {} {}", + bcosRequest.getMessageID(), + response.getErrorCode(), + response.getContent()); + if (response.getErrorCode() == 0) { + try { + T t = objectMapper.readValue(response.getContent(), responseType); + if (t.getError() != null) { + throw new IOException(t.getError().getMessage()); + } + if (t.getResult() instanceof CallOutput) { + CallOutput callResult = (CallOutput) t.getResult(); + if (StatusCode.RevertInstruction.equals(callResult.getStatus())) { + throw new ContractCallException( + "The execution of the contract rolled back."); + } + if (StatusCode.CallAddressError.equals(callResult.getStatus())) { + throw new ContractCallException("The contract address is incorrect."); + } + } + return t; + } catch (ContractCallException e) { + throw e; + } catch (Exception e) { + throw new MessageDecodingException(response.getContent()); + } + } else { + throw new IOException(response.getErrorMessage()); } - return t; - } catch (Exception e) { - throw new MessageDecodingException(response.getContent()); - } - } else { - throw new IOException(response.getErrorMessage()); } - } - public String sendSpecial(Request request) throws IOException { - byte[] payload = objectMapper.writeValueAsBytes(request); + @Override + public void sendOnly(Request request) throws IOException { + byte[] payload = objectMapper.writeValueAsBytes(request); - FiscoRequest fiscoRequest = new FiscoRequest(); - fiscoRequest.setKeyID(channelService.getOrgID()); - fiscoRequest.setBankNO(""); - fiscoRequest.setContent(new String(payload)); - fiscoRequest.setMessageID(channelService.newSeq()); + BcosRequest fiscoRequest = new BcosRequest(); + fiscoRequest.setKeyID(channelService.getOrgID()); + fiscoRequest.setBankNO(""); + fiscoRequest.setContent(new String(payload)); + fiscoRequest.setMessageID(channelService.newSeq()); - if (timeout != 0) { - fiscoRequest.setTimeout(timeout); - } + if (timeout != 0) { + fiscoRequest.setTimeout(timeout); + } - FiscoResponse response; - if (!request.isNeedTransCallback()) { - response = channelService.sendEthereumMessage(fiscoRequest); - } else { - response = - channelService.sendEthereumMessage(fiscoRequest, request.getTransactionSucCallback()); + BcosResponse response; + if (!request.isNeedTransCallback()) { + channelService.asyncSendEthereumMessage( + fiscoRequest, + new BcosResponseCallback() { + @Override + public void onResponse(BcosResponse response) { + try { + logger.debug( + "fisco Request:{} {}", + fiscoRequest.getMessageID(), + objectMapper.writeValueAsString(request)); + logger.debug( + "fisco Response:{} {} {}", + fiscoRequest.getMessageID(), + response.getErrorCode(), + response.getContent()); + + if (response.getErrorCode() != 0) { + logger.error("Error: " + response.getErrorCode()); + } + } catch (Exception e) { + logger.error("Error: ", e); + } + } + }); + } else { + channelService.asyncSendEthereumMessage( + fiscoRequest, + new BcosResponseCallback() { + @Override + public void onResponse(BcosResponse response) { + try { + logger.debug( + "fisco Request:{} {}", + fiscoRequest.getMessageID(), + objectMapper.writeValueAsString(request)); + logger.debug( + "fisco Response:{} {} {}", + fiscoRequest.getMessageID(), + response.getErrorCode(), + response.getContent()); + + if (response.getErrorCode() != 0) { + logger.error("Error: " + response.getErrorCode()); + } + } catch (Exception e) { + logger.error("Error: ", e); + } + } + }, + request.getTransactionSucCallback()); + } } - logger.debug( - "fisco Request:{} {}", - fiscoRequest.getMessageID(), - objectMapper.writeValueAsString(request)); - logger.debug( - "fisco Response:{} {} {}", - fiscoRequest.getMessageID(), - response.getErrorCode(), - response.getContent()); - if (response.getErrorCode() == 0) { - if (response.getContent().contains("error")) { - Response t = objectMapper.readValue(response.getContent(), Response.class); - throw new ResponseExcepiton(t.getError().getCode(), t.getError().getMessage()); - } else { - String[] resultArray = response.getContent().split("result"); - String resultStr = resultArray[1]; - if ("\"".equals(resultStr.substring(2, 3))) - return resultStr.substring(3, resultStr.length() - 3); - else return resultStr.substring(2, resultStr.length() - 2); - } - } else { - throw new IOException(response.getErrorMessage()); + public String sendSpecial(Request request) throws IOException { + byte[] payload = objectMapper.writeValueAsBytes(request); + + BcosRequest bcosRequest = new BcosRequest(); + if (channelService.getOrgID() != null) { + bcosRequest.setKeyID(channelService.getOrgID()); + } else { + bcosRequest.setKeyID(channelService.getAgencyName()); + } + bcosRequest.setBankNO(""); + bcosRequest.setContent(new String(payload)); + bcosRequest.setMessageID(channelService.newSeq()); + + if (timeout != 0) { + bcosRequest.setTimeout(timeout); + } + + BcosResponse response; + if (!request.isNeedTransCallback()) { + response = channelService.sendEthereumMessage(bcosRequest); + } else { + response = + channelService.sendEthereumMessage( + bcosRequest, request.getTransactionSucCallback()); + } + logger.trace( + "bcos request:{} {}", + bcosRequest.getMessageID(), + objectMapper.writeValueAsString(request)); + logger.trace( + "bcos response:{} {} {}", + bcosRequest.getMessageID(), + response.getErrorCode(), + response.getContent()); + if (response.getErrorCode() == 0) { + if (response.getContent().contains("error")) { + Response t = objectMapper.readValue(response.getContent(), Response.class); + throw new ResponseExcepiton(t.getError().getCode(), t.getError().getMessage()); + } else { + String[] resultArray = response.getContent().split("result"); + String resultStr = resultArray[1]; + if ("\"".equals(resultStr.substring(2, 3))) + return resultStr.substring(3, resultStr.length() - 3); + else return resultStr.substring(2, resultStr.length() - 2); + } + } else { + throw new IOException(response.getErrorMessage()); + } } - } - public Service getChannelService() { - return channelService; - } + public Service getChannelService() { + return channelService; + } - public void setChannelService(Service channelService) { - this.channelService = channelService; - } + public void setChannelService(Service channelService) { + this.channelService = channelService; + } - public Integer getTimeout() { - return timeout; - } + public Integer getTimeout() { + return timeout; + } - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } - @Override - public void close() throws IOException {} + @Override + public void close() throws IOException {} } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/channel/ResponseExcepiton.java b/src/main/java/org/fisco/bcos/web3j/protocol/channel/ResponseExcepiton.java index 53902162c..50be0ff44 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/channel/ResponseExcepiton.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/channel/ResponseExcepiton.java @@ -4,30 +4,30 @@ public class ResponseExcepiton extends IOException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public ResponseExcepiton(int code, String message) { - super(); - this.code = code; - this.message = message; - } + public ResponseExcepiton(int code, String message) { + super(); + this.code = code; + this.message = message; + } - private int code; - private String message; + private int code; + private String message; - public int getCode() { - return code; - } + public int getCode() { + return code; + } - public void setCode(int code) { - this.code = code; - } + public void setCode(int code) { + this.code = code; + } - public String getMessage() { - return message; - } + public String getMessage() { + return message; + } - public void setMessage(String message) { - this.message = message; - } + public void setMessage(String message) { + this.message = message; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/channel/StatusCode.java b/src/main/java/org/fisco/bcos/web3j/protocol/channel/StatusCode.java new file mode 100644 index 000000000..a658046d8 --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/protocol/channel/StatusCode.java @@ -0,0 +1,124 @@ +package org.fisco.bcos.web3j.protocol.channel; + +public class StatusCode { + + public static final String Success = "0x0"; + public static final String Unknown = "0x1"; + public static final String BadRLP = "0x2"; + public static final String InvalidFormat = "0x3"; + public static final String OutOfGasIntrinsic = "0x4"; + public static final String InvalidSignature = "0x5"; + public static final String InvalidNonce = "0x6"; + public static final String NotEnoughCash = "0x7"; + public static final String OutOfGasBase = "0x8"; + public static final String BlockGasLimitReached = "0x9"; + public static final String BadInstruction = "0xa"; + public static final String BadJumpDestination = "0xb"; + public static final String OutOfGas = "0xc"; + public static final String OutOfStack = "0xd"; + public static final String StackUnderflow = "0xe"; + public static final String NonceCheckFail = "0xf"; + public static final String BlockLimitCheckFail = "0x10"; + public static final String FilterCheckFail = "0x11"; + public static final String NoDeployPermission = "0x12"; + public static final String NoCallPermission = "0x13"; + public static final String NoTxPermission = "0x14"; + public static final String PrecompiledError = "0x15"; + public static final String RevertInstruction = "0x16"; + public static final String InvalidZeroSignatureFormat = "0x17"; + public static final String AddressAlreadyUsed = "0x18"; + public static final String PermissionDenied = "0x19"; + public static final String CallAddressError = "0x1a"; + + public static String getStatusMessage(String status) { + String message = ""; + switch (status) { + case Success: + message = "success"; + break; + case Unknown: + message = "unknown"; + break; + case BadRLP: + message = "bad RLP"; + break; + case InvalidFormat: + message = "invalid format"; + break; + case OutOfGasIntrinsic: + message = "out of gas intrinsic"; + break; + case InvalidSignature: + message = "invalid signature"; + break; + case InvalidNonce: + message = "invalid nonce"; + break; + case NotEnoughCash: + message = "not enough cash"; + break; + case OutOfGasBase: + message = "out of gas base"; + break; + case BlockGasLimitReached: + message = "block gas limit reached"; + break; + case BadInstruction: + message = "bad instruction"; + break; + case BadJumpDestination: + message = "bad jump destination"; + break; + case OutOfGas: + message = "out of gas"; + break; + case OutOfStack: + message = "out of stack"; + break; + case StackUnderflow: + message = "stack underflow"; + break; + case NonceCheckFail: + message = "nonce check fail"; + break; + case BlockLimitCheckFail: + message = "block limit check fail"; + break; + case FilterCheckFail: + message = "filter check fail"; + break; + case NoDeployPermission: + message = "no deploy permission"; + break; + case NoCallPermission: + message = "no call permission"; + break; + case NoTxPermission: + message = "no tx permission"; + break; + case PrecompiledError: + message = "precompiled error"; + break; + case RevertInstruction: + message = "revert instruction"; + break; + case InvalidZeroSignatureFormat: + message = "invalid zero signature format"; + break; + case AddressAlreadyUsed: + message = "address already used"; + break; + case PermissionDenied: + message = "permission denied"; + break; + case CallAddressError: + message = "call address error"; + break; + default: + message = status; + break; + } + + return message; + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameter.java index 88ee87369..47fd4c758 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameter.java @@ -9,13 +9,13 @@ * specification for further information. */ public interface DefaultBlockParameter { - static DefaultBlockParameter valueOf(BigInteger blockNumber) { - return new DefaultBlockParameterNumber(blockNumber); - } + static DefaultBlockParameter valueOf(BigInteger blockNumber) { + return new DefaultBlockParameterNumber(blockNumber); + } - static DefaultBlockParameter valueOf(String blockName) { - return DefaultBlockParameterName.fromString(blockName); - } + static DefaultBlockParameter valueOf(String blockName) { + return DefaultBlockParameterName.fromString(blockName); + } - String getValue(); + String getValue(); } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterName.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterName.java index 9173aa45e..814566c5c 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterName.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterName.java @@ -4,31 +4,31 @@ /** https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter */ public enum DefaultBlockParameterName implements DefaultBlockParameter { - EARLIEST("earliest"), - LATEST("latest"), - PENDING("pending"); + EARLIEST("earliest"), + LATEST("latest"), + PENDING("pending"); - private String name; + private String name; - DefaultBlockParameterName(String name) { - this.name = name; - } + DefaultBlockParameterName(String name) { + this.name = name; + } - @JsonValue - @Override - public String getValue() { - return name; - } + @JsonValue + @Override + public String getValue() { + return name; + } - public static DefaultBlockParameterName fromString(String name) { - if (name != null) { - for (DefaultBlockParameterName defaultBlockParameterName : - DefaultBlockParameterName.values()) { - if (name.equalsIgnoreCase(defaultBlockParameterName.name)) { - return defaultBlockParameterName; + public static DefaultBlockParameterName fromString(String name) { + if (name != null) { + for (DefaultBlockParameterName defaultBlockParameterName : + DefaultBlockParameterName.values()) { + if (name.equalsIgnoreCase(defaultBlockParameterName.name)) { + return defaultBlockParameterName; + } + } } - } + return valueOf(name); } - return valueOf(name); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterNumber.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterNumber.java index 6247447d1..a4f36d000 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterNumber.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/DefaultBlockParameterNumber.java @@ -7,23 +7,23 @@ /** DefaultBlockParameter implementation that takes a numeric value. */ public class DefaultBlockParameterNumber implements DefaultBlockParameter { - private BigInteger blockNumber; + private BigInteger blockNumber; - public DefaultBlockParameterNumber(BigInteger blockNumber) { - this.blockNumber = blockNumber; - } + public DefaultBlockParameterNumber(BigInteger blockNumber) { + this.blockNumber = blockNumber; + } - public DefaultBlockParameterNumber(long blockNumber) { - this(BigInteger.valueOf(blockNumber)); - } + public DefaultBlockParameterNumber(long blockNumber) { + this(BigInteger.valueOf(blockNumber)); + } - @Override - @JsonValue - public String getValue() { - return Numeric.encodeQuantity(blockNumber); - } + @Override + @JsonValue + public String getValue() { + return Numeric.encodeQuantity(blockNumber); + } - public BigInteger getBlockNumber() { - return blockNumber; - } + public BigInteger getBlockNumber() { + return blockNumber; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/Ethereum.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/Ethereum.java index 4de88ac15..48b0d3d33 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/Ethereum.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/Ethereum.java @@ -6,72 +6,72 @@ /** Core FISCO BCOS JSON-RPC API. */ public interface Ethereum { - Request getNodeVersion(); + Request getNodeVersion(); - Request getBlockNumber(); + Request getBlockNumber(); - Request getPbftView(); + Request getPbftView(); - Request getSealerList(); + Request getSealerList(); - Request getObserverList(); + Request getObserverList(); - Request getNodeIDList(); + Request getNodeIDList(); - Request getGroupList(); + Request getGroupList(); - Request getGroupPeers(); + Request getGroupPeers(); - Request getPeers(); + Request getPeers(); - Request getConsensusStatus(); + Request getConsensusStatus(); - Request getSyncStatus(); + Request getSyncStatus(); - Request getSystemConfigByKey(String key); + Request getSystemConfigByKey(String key); - Request getCode(String address, DefaultBlockParameter defaultBlockParameter); + Request getCode(String address, DefaultBlockParameter defaultBlockParameter); - Request getTotalTransactionCount(); + Request getTotalTransactionCount(); - Request getBlockByHash(String blockHash, boolean returnFullTransactionObjects); + Request getBlockByHash(String blockHash, boolean returnFullTransactionObjects); - Request getBlockByNumber( - DefaultBlockParameter defaultBlockParameter, boolean returnFullTransactionObjects); + Request getBlockByNumber( + DefaultBlockParameter defaultBlockParameter, boolean returnFullTransactionObjects); - Request getBlockHashByNumber(DefaultBlockParameter defaultBlockParameter); + Request getBlockHashByNumber(DefaultBlockParameter defaultBlockParameter); - Request getTransactionByHash(String transactionHash); + Request getTransactionByHash(String transactionHash); - Request getTransactionByBlockHashAndIndex( - String blockHash, BigInteger transactionIndex); + Request getTransactionByBlockHashAndIndex( + String blockHash, BigInteger transactionIndex); - Request getTransactionByBlockNumberAndIndex( - DefaultBlockParameter defaultBlockParameter, BigInteger transactionIndex); + Request getTransactionByBlockNumberAndIndex( + DefaultBlockParameter defaultBlockParameter, BigInteger transactionIndex); - Request getTransactionReceipt(String transactionHash); + Request getTransactionReceipt(String transactionHash); - Request getPendingTransaction(); + Request getPendingTransaction(); - BigInteger getBlockNumberCache(); + BigInteger getBlockNumberCache(); - Request getPendingTxSize(); + Request getPendingTxSize(); - Request call( - org.fisco.bcos.web3j.protocol.core.methods.request.Transaction transaction, - DefaultBlockParameter defaultBlockParameter); + Request call( + org.fisco.bcos.web3j.protocol.core.methods.request.Transaction transaction, + DefaultBlockParameter defaultBlockParameter); - Request sendRawTransaction(String signedTransactionData); + Request sendRawTransaction(String signedTransactionData); - // TODO - Request newPendingTransactionFilter(); + // TODO + Request newPendingTransactionFilter(); - Request newBlockFilter(); + Request newBlockFilter(); - Request getFilterChanges(BigInteger filterId); + Request getFilterChanges(BigInteger filterId); - Request getUninstallFilter(BigInteger filterId); + Request getUninstallFilter(BigInteger filterId); - Request newFilter( - org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter); + Request newFilter( + org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter); } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/JsonRpc2_0Web3j.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/JsonRpc2_0Web3j.java index 7e506d4bf..870155375 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/JsonRpc2_0Web3j.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/JsonRpc2_0Web3j.java @@ -1,6 +1,10 @@ package org.fisco.bcos.web3j.protocol.core; import io.reactivex.Flowable; +import java.io.IOException; +import java.math.BigInteger; +import java.util.*; +import java.util.concurrent.ScheduledExecutorService; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.Web3jService; import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; @@ -14,422 +18,444 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.math.BigInteger; -import java.util.*; -import java.util.concurrent.ScheduledExecutorService; - /** JSON-RPC 2.0 factory implementation. */ public class JsonRpc2_0Web3j implements Web3j { - static Logger logger = LoggerFactory.getLogger(JsonRpc2_0Web3j.class); - protected static final long ID = 1; - public static final int BLOCK_TIME = 15 * 100; - public static final int DEFAULT_BLOCK_TIME = 15 * 1000; - protected final Web3jService web3jService; - private final JsonRpc2_0Rx web3jRx; - private final long blockTime; - private final ScheduledExecutorService scheduledExecutorService; - - - private int groupId = 1; - - public Web3jService web3jService() { - return web3jService; - } - - public BigInteger getLocalBlockNumber() { - return ((ChannelEthereumService) web3jService).getChannelService().getNumber(); - } - - public synchronized void setBlockNumber(BigInteger blockNumber) { - if (blockNumber.compareTo( - ((ChannelEthereumService) web3jService).getChannelService().getNumber()) - > 0) { - ((ChannelEthereumService) web3jService).getChannelService().setNumber(blockNumber); - } - } - - public JsonRpc2_0Web3j(Web3jService web3jService) { - this(web3jService, DEFAULT_BLOCK_TIME, Async.defaultExecutorService(), 1); - } - - public JsonRpc2_0Web3j(Web3jService web3jService, int groupId) { - this(web3jService, DEFAULT_BLOCK_TIME, Async.defaultExecutorService(), groupId); - this.groupId = groupId; - } - - public JsonRpc2_0Web3j( - Web3jService web3jService, - long pollingInterval, - ScheduledExecutorService scheduledExecutorService, - int groupId) { - this.web3jService = web3jService; - this.web3jRx = new JsonRpc2_0Rx(this, scheduledExecutorService); - this.blockTime = pollingInterval; - this.scheduledExecutorService = scheduledExecutorService; - this.groupId = groupId; - } - - @Override - public Request getNodeVersion() { - return new Request<>("getClientVersion", Arrays.asList(), web3jService, NodeVersion.class); - } - - @Override - public synchronized Request getBlockNumber() { - return new Request<>("getBlockNumber", Arrays.asList(groupId), web3jService, BlockNumber.class); - } - - @Override - public BigInteger getBlockNumberCache() { - if (getLocalBlockNumber().intValue() == 1) { - try { - BlockNumber blockNumber = getBlockNumber().sendAsync().get(); - setBlockNumber(blockNumber.getBlockNumber()); - } catch (Exception e) { - logger.error("Exception: " + e); - } - } - return getLocalBlockNumber().add(new BigInteger(BlockLimit.blockLimit.toString())); - } - - @Override - public Request getGroupList() { - return new Request<>("getGroupList", Arrays.asList(), web3jService, GroupList.class); - } - - @Override - public Request getSealerList() { - return new Request<>("getSealerList", Arrays.asList(groupId), web3jService, SealerList.class); - } - - @Override - public Request getObserverList() { - return new Request<>( - "getObserverList", Arrays.asList(groupId), web3jService, ObserverList.class); - } - - @Override - public Request getPeers() { - return new Request<>("getPeers", Arrays.asList(groupId), web3jService, Peers.class); - } - - @Override - public Request getNodeIDList() { - return new Request<>("getNodeIDList", Arrays.asList(groupId), web3jService, NodeIDList.class); - } - - @Override - public Request getSystemConfigByKey(String key) { - return new Request<>( - "getSystemConfigByKey", Arrays.asList(groupId, key), web3jService, SystemConfig.class); - } - - @Override - public Request getSyncStatus() { - return new Request<>("getSyncStatus", Arrays.asList(groupId), web3jService, SyncStatus.class); - } - - @Override - public Request getPbftView() { - return new Request<>("getPbftView", Arrays.asList(groupId), web3jService, PbftView.class); - } - - @Override - public Request getConsensusStatus() { - return new Request<>( - "getConsensusStatus", - Arrays.asList(groupId), - (ChannelEthereumService) web3jService, - ConsensusStatus.class); - } - - @Override - public Request getCode(String address, DefaultBlockParameter defaultBlockParameter) { - return new Request<>("getCode", Arrays.asList(groupId, address), web3jService, Code.class); - } - - @Override - public Request getTotalTransactionCount() { - return new Request<>( - "getTotalTransactionCount", - Arrays.asList(groupId), - web3jService, - TotalTransactionCount.class); - } - - @Override - public Request call( - org.fisco.bcos.web3j.protocol.core.methods.request.Transaction transaction, - DefaultBlockParameter defaultBlockParameter) { - return new Request<>("call", Arrays.asList(groupId, transaction), web3jService, Call.class); - } - - @Override - public Request getBlockByHash( - String blockHash, boolean returnFullTransactionObjects) { - return new Request<>( - "getBlockByHash", - Arrays.asList(groupId, blockHash, returnFullTransactionObjects), - web3jService, - BcosBlock.class); - } - - @Override - public Request getBlockByNumber( - DefaultBlockParameter defaultBlockParameter, boolean returnFullTransactionObjects) { - return new Request<>( - "getBlockByNumber", - Arrays.asList(groupId, defaultBlockParameter.getValue(), returnFullTransactionObjects), - web3jService, - BcosBlock.class); - } - - @Override - public Request getBlockHashByNumber(DefaultBlockParameter defaultBlockParameter) { - return new Request<>( - "getBlockHashByNumber", - Arrays.asList(groupId, defaultBlockParameter.getValue()), - web3jService, - BlockHash.class); - } - - @Override - public Request getTransactionByHash(String transactionHash) { - return new Request<>( - "getTransactionByHash", - Arrays.asList(groupId, transactionHash), - web3jService, - BcosTransaction.class); - } - - @Override - public Request getTransactionByBlockHashAndIndex( - String blockHash, BigInteger transactionIndex) { - return new Request<>( - "getTransactionByBlockHashAndIndex", - Arrays.asList(groupId, blockHash, Numeric.encodeQuantity(transactionIndex)), - web3jService, - BcosTransaction.class); - } - - @Override - public Request getTransactionByBlockNumberAndIndex( - DefaultBlockParameter defaultBlockParameter, BigInteger transactionIndex) { - return new Request<>( - "getTransactionByBlockNumberAndIndex", - Arrays.asList( - groupId, defaultBlockParameter.getValue(), Numeric.encodeQuantity(transactionIndex)), - web3jService, - BcosTransaction.class); - } - - @Override - public Request getTransactionReceipt(String transactionHash) { - return new Request<>( - "getTransactionReceipt", - Arrays.asList(groupId, transactionHash), - web3jService, - BcosTransactionReceipt.class); - } - - @Override - public Request getPendingTransaction() { - return new Request<>( - "getPendingTransactions", Arrays.asList(groupId), web3jService, PendingTransactions.class); - } - - @Override - public Request getPendingTxSize() { - return new Request<>( - "getPendingTxSize", Arrays.asList(groupId), web3jService, PendingTxSize.class); - } - - @Override - public Request sendRawTransaction(String signedTransactionData) { - return new Request<>( - "sendRawTransaction", - Arrays.asList(groupId, signedTransactionData), - web3jService, - SendTransaction.class); - } - - @Override - public Request getGroupPeers() { - return new Request<>("getGroupPeers", Arrays.asList(groupId), web3jService, GroupPeers.class); - } - - @Override - public Request newPendingTransactionFilter() { - return new Request<>( - "newPendingTransactionFilter", Arrays.asList(groupId), web3jService, BcosFilter.class); - } - - @Override - public Request newBlockFilter() { - return new Request<>("newBlockFilter", Arrays.asList(groupId), web3jService, BcosFilter.class); - } - - @Override - public Request getFilterChanges(BigInteger filterId) { - return new Request<>( - "getFilterChanges", - Arrays.asList(groupId, Numeric.toHexStringWithPrefixSafe(filterId)), - web3jService, - BcosLog.class); - } - - @Override - public Request getUninstallFilter(BigInteger filterId) { - return new Request<>( - "getUninstallFilter", - Arrays.asList(groupId, Numeric.toHexStringWithPrefixSafe(filterId)), - web3jService, - UninstallFilter.class); - } - - @Override - public Request newFilter( - org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter filter) { - return new Request<>( - "newFilter", Arrays.asList(groupId, filter), web3jService, BcosFilter.class); - } - - @Override - public Flowable newHeadsNotifications() { - return web3jService.subscribe( - new Request<>( - "subscribe", Collections.singletonList("newHeads"), web3jService, BcosSubscribe.class), - "unsubscribe", - NewHeadsNotification.class); - } - - @Override - public Flowable logsNotifications(List addresses, List topics) { - - Map params = createLogsParams(addresses, topics); - - return web3jService.subscribe( - new Request<>( - "subscribe", Arrays.asList(groupId, "logs", params), web3jService, BcosSubscribe.class), - "unsubscribe", - LogNotification.class); - } - - private Map createLogsParams(List addresses, List topics) { - Map params = new HashMap<>(); - if (!addresses.isEmpty()) { - params.put("address", addresses); - } - if (!topics.isEmpty()) { - params.put("topics", topics); - } - return params; - } - - @Override - public Flowable blockHashFlowable() { - return web3jRx.blockHashFlowable(blockTime); - } - - @Override - public Flowable pendingTransactionHashFlowable() { - return web3jRx.pendingTransactionHashFlowable(blockTime); - } - - @Override - public Flowable logFlowable( - org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter filter) { - return web3jRx.logFlowable(filter, blockTime); - } - - @Override - public Flowable - transactionFlowable() { - return web3jRx.transactionFlowable(blockTime); - } - - @Override - public Flowable - pendingTransactionFlowable() { - return web3jRx.pendingTransactionFlowable(blockTime); - } - - @Override - public Flowable blockFlowable(boolean fullTransactionObjects) { - return web3jRx.blockFlowable(fullTransactionObjects, blockTime); - } - - @Override - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects) { - return web3jRx.replayBlocksFlowable(startBlock, endBlock, fullTransactionObjects); - } - - @Override - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects, - boolean ascending) { - return web3jRx.replayBlocksFlowable(startBlock, endBlock, fullTransactionObjects, ascending); - } - - @Override - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - boolean fullTransactionObjects, - Flowable onCompleteFlowable) { - return web3jRx.replayPastBlocksFlowable(startBlock, fullTransactionObjects, onCompleteFlowable); - } - - @Override - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects) { - return web3jRx.replayPastBlocksFlowable(startBlock, fullTransactionObjects); - } - - @Override - public Flowable - replayPastTransactionsFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - return web3jRx.replayTransactionsFlowable(startBlock, endBlock); - } - - @Override - public Flowable - replayPastTransactionsFlowable(DefaultBlockParameter startBlock) { - return web3jRx.replayPastTransactionsFlowable(startBlock); - } - - @Override - public Flowable replayPastAndFutureBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects) { - return web3jRx.replayPastAndFutureBlocksFlowable(startBlock, fullTransactionObjects, blockTime); - } - - @Override - public Flowable - replayPastAndFutureTransactionsFlowable(DefaultBlockParameter startBlock) { - return web3jRx.replayPastAndFutureTransactionsFlowable(startBlock, blockTime); - } - - public int getGroupId() { - return groupId; - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - public void shutdown() { - scheduledExecutorService.shutdown(); - try { - web3jService.close(); - } catch (IOException e) { - throw new RuntimeException("Failed to close web3j service", e); - } - } + static Logger logger = LoggerFactory.getLogger(JsonRpc2_0Web3j.class); + protected static final long ID = 1; + public static final int BLOCK_TIME = 15 * 100; + public static final int DEFAULT_BLOCK_TIME = 15 * 1000; + protected final Web3jService web3jService; + private final JsonRpc2_0Rx web3jRx; + private final long blockTime; + private final ScheduledExecutorService scheduledExecutorService; + + private int groupId = 1; + + public Web3jService web3jService() { + return web3jService; + } + + public BigInteger getLocalBlockNumber() { + return ((ChannelEthereumService) web3jService).getChannelService().getNumber(); + } + + public synchronized void setBlockNumber(BigInteger blockNumber) { + if (blockNumber.compareTo( + ((ChannelEthereumService) web3jService).getChannelService().getNumber()) + > 0) { + ((ChannelEthereumService) web3jService).getChannelService().setNumber(blockNumber); + } + } + + public JsonRpc2_0Web3j(Web3jService web3jService) { + this(web3jService, DEFAULT_BLOCK_TIME, Async.defaultExecutorService(), 1); + } + + public JsonRpc2_0Web3j(Web3jService web3jService, int groupId) { + this(web3jService, DEFAULT_BLOCK_TIME, Async.defaultExecutorService(), groupId); + this.groupId = groupId; + } + + public JsonRpc2_0Web3j( + Web3jService web3jService, + long pollingInterval, + ScheduledExecutorService scheduledExecutorService, + int groupId) { + this.web3jService = web3jService; + this.web3jRx = new JsonRpc2_0Rx(this, scheduledExecutorService); + this.blockTime = pollingInterval; + this.scheduledExecutorService = scheduledExecutorService; + this.groupId = groupId; + } + + @Override + public Request getNodeVersion() { + return new Request<>("getClientVersion", Arrays.asList(), web3jService, NodeVersion.class); + } + + @Override + public synchronized Request getBlockNumber() { + return new Request<>( + "getBlockNumber", Arrays.asList(groupId), web3jService, BlockNumber.class); + } + + @Override + public BigInteger getBlockNumberCache() { + if (getLocalBlockNumber().intValue() == 1) { + try { + BlockNumber blockNumber = getBlockNumber().sendAsync().get(); + setBlockNumber(blockNumber.getBlockNumber()); + } catch (Exception e) { + logger.error("Exception: " + e); + } + } + return getLocalBlockNumber().add(new BigInteger(BlockLimit.blockLimit.toString())); + } + + @Override + public Request getGroupList() { + return new Request<>("getGroupList", Arrays.asList(), web3jService, GroupList.class); + } + + @Override + public Request getSealerList() { + return new Request<>( + "getSealerList", Arrays.asList(groupId), web3jService, SealerList.class); + } + + @Override + public Request getObserverList() { + return new Request<>( + "getObserverList", Arrays.asList(groupId), web3jService, ObserverList.class); + } + + @Override + public Request getPeers() { + return new Request<>("getPeers", Arrays.asList(groupId), web3jService, Peers.class); + } + + @Override + public Request getNodeIDList() { + return new Request<>( + "getNodeIDList", Arrays.asList(groupId), web3jService, NodeIDList.class); + } + + @Override + public Request getSystemConfigByKey(String key) { + return new Request<>( + "getSystemConfigByKey", + Arrays.asList(groupId, key), + web3jService, + SystemConfig.class); + } + + @Override + public Request getSyncStatus() { + return new Request<>( + "getSyncStatus", Arrays.asList(groupId), web3jService, SyncStatus.class); + } + + @Override + public Request getPbftView() { + return new Request<>("getPbftView", Arrays.asList(groupId), web3jService, PbftView.class); + } + + @Override + public Request getConsensusStatus() { + return new Request<>( + "getConsensusStatus", + Arrays.asList(groupId), + (ChannelEthereumService) web3jService, + ConsensusStatus.class); + } + + @Override + public Request getCode(String address, DefaultBlockParameter defaultBlockParameter) { + return new Request<>("getCode", Arrays.asList(groupId, address), web3jService, Code.class); + } + + @Override + public Request getTotalTransactionCount() { + return new Request<>( + "getTotalTransactionCount", + Arrays.asList(groupId), + web3jService, + TotalTransactionCount.class); + } + + @Override + public Request call( + org.fisco.bcos.web3j.protocol.core.methods.request.Transaction transaction, + DefaultBlockParameter defaultBlockParameter) { + return new Request<>("call", Arrays.asList(groupId, transaction), web3jService, Call.class); + } + + @Override + public Request getBlockByHash( + String blockHash, boolean returnFullTransactionObjects) { + return new Request<>( + "getBlockByHash", + Arrays.asList(groupId, blockHash, returnFullTransactionObjects), + web3jService, + BcosBlock.class); + } + + @Override + public Request getBlockByNumber( + DefaultBlockParameter defaultBlockParameter, boolean returnFullTransactionObjects) { + return new Request<>( + "getBlockByNumber", + Arrays.asList( + groupId, defaultBlockParameter.getValue(), returnFullTransactionObjects), + web3jService, + BcosBlock.class); + } + + @Override + public Request getBlockHashByNumber(DefaultBlockParameter defaultBlockParameter) { + return new Request<>( + "getBlockHashByNumber", + Arrays.asList(groupId, defaultBlockParameter.getValue()), + web3jService, + BlockHash.class); + } + + @Override + public Request getTransactionByHash(String transactionHash) { + return new Request<>( + "getTransactionByHash", + Arrays.asList(groupId, transactionHash), + web3jService, + BcosTransaction.class); + } + + @Override + public Request getTransactionByBlockHashAndIndex( + String blockHash, BigInteger transactionIndex) { + return new Request<>( + "getTransactionByBlockHashAndIndex", + Arrays.asList(groupId, blockHash, Numeric.encodeQuantity(transactionIndex)), + web3jService, + BcosTransaction.class); + } + + @Override + public Request getTransactionByBlockNumberAndIndex( + DefaultBlockParameter defaultBlockParameter, BigInteger transactionIndex) { + return new Request<>( + "getTransactionByBlockNumberAndIndex", + Arrays.asList( + groupId, + defaultBlockParameter.getValue(), + Numeric.encodeQuantity(transactionIndex)), + web3jService, + BcosTransaction.class); + } + + @Override + public Request getTransactionReceipt(String transactionHash) { + return new Request<>( + "getTransactionReceipt", + Arrays.asList(groupId, transactionHash), + web3jService, + BcosTransactionReceipt.class); + } + + @Override + public Request getPendingTransaction() { + return new Request<>( + "getPendingTransactions", + Arrays.asList(groupId), + web3jService, + PendingTransactions.class); + } + + @Override + public Request getPendingTxSize() { + return new Request<>( + "getPendingTxSize", Arrays.asList(groupId), web3jService, PendingTxSize.class); + } + + @Override + public Request sendRawTransaction(String signedTransactionData) { + return new Request<>( + "sendRawTransaction", + Arrays.asList(groupId, signedTransactionData), + web3jService, + SendTransaction.class); + } + + @Override + public Request getGroupPeers() { + return new Request<>( + "getGroupPeers", Arrays.asList(groupId), web3jService, GroupPeers.class); + } + + @Override + public Request newPendingTransactionFilter() { + return new Request<>( + "newPendingTransactionFilter", + Arrays.asList(groupId), + web3jService, + BcosFilter.class); + } + + @Override + public Request newBlockFilter() { + return new Request<>( + "newBlockFilter", Arrays.asList(groupId), web3jService, BcosFilter.class); + } + + @Override + public Request getFilterChanges(BigInteger filterId) { + return new Request<>( + "getFilterChanges", + Arrays.asList(groupId, Numeric.toHexStringWithPrefixSafe(filterId)), + web3jService, + BcosLog.class); + } + + @Override + public Request getUninstallFilter(BigInteger filterId) { + return new Request<>( + "getUninstallFilter", + Arrays.asList(groupId, Numeric.toHexStringWithPrefixSafe(filterId)), + web3jService, + UninstallFilter.class); + } + + @Override + public Request newFilter( + org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter filter) { + return new Request<>( + "newFilter", Arrays.asList(groupId, filter), web3jService, BcosFilter.class); + } + + @Override + public Flowable newHeadsNotifications() { + return web3jService.subscribe( + new Request<>( + "subscribe", + Collections.singletonList("newHeads"), + web3jService, + BcosSubscribe.class), + "unsubscribe", + NewHeadsNotification.class); + } + + @Override + public Flowable logsNotifications( + List addresses, List topics) { + + Map params = createLogsParams(addresses, topics); + + return web3jService.subscribe( + new Request<>( + "subscribe", + Arrays.asList(groupId, "logs", params), + web3jService, + BcosSubscribe.class), + "unsubscribe", + LogNotification.class); + } + + private Map createLogsParams(List addresses, List topics) { + Map params = new HashMap<>(); + if (!addresses.isEmpty()) { + params.put("address", addresses); + } + if (!topics.isEmpty()) { + params.put("topics", topics); + } + return params; + } + + @Override + public Flowable blockHashFlowable() { + return web3jRx.blockHashFlowable(blockTime); + } + + @Override + public Flowable pendingTransactionHashFlowable() { + return web3jRx.pendingTransactionHashFlowable(blockTime); + } + + @Override + public Flowable logFlowable( + org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter filter) { + return web3jRx.logFlowable(filter, blockTime); + } + + @Override + public Flowable + transactionFlowable() { + return web3jRx.transactionFlowable(blockTime); + } + + @Override + public Flowable + pendingTransactionFlowable() { + return web3jRx.pendingTransactionFlowable(blockTime); + } + + @Override + public Flowable blockFlowable(boolean fullTransactionObjects) { + return web3jRx.blockFlowable(fullTransactionObjects, blockTime); + } + + @Override + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects) { + return web3jRx.replayBlocksFlowable(startBlock, endBlock, fullTransactionObjects); + } + + @Override + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects, + boolean ascending) { + return web3jRx.replayBlocksFlowable( + startBlock, endBlock, fullTransactionObjects, ascending); + } + + @Override + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + boolean fullTransactionObjects, + Flowable onCompleteFlowable) { + return web3jRx.replayPastBlocksFlowable( + startBlock, fullTransactionObjects, onCompleteFlowable); + } + + @Override + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, boolean fullTransactionObjects) { + return web3jRx.replayPastBlocksFlowable(startBlock, fullTransactionObjects); + } + + @Override + public Flowable + replayPastTransactionsFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3jRx.replayTransactionsFlowable(startBlock, endBlock); + } + + @Override + public Flowable + replayPastTransactionsFlowable(DefaultBlockParameter startBlock) { + return web3jRx.replayPastTransactionsFlowable(startBlock); + } + + @Override + public Flowable replayPastAndFutureBlocksFlowable( + DefaultBlockParameter startBlock, boolean fullTransactionObjects) { + return web3jRx.replayPastAndFutureBlocksFlowable( + startBlock, fullTransactionObjects, blockTime); + } + + @Override + public Flowable + replayPastAndFutureTransactionsFlowable(DefaultBlockParameter startBlock) { + return web3jRx.replayPastAndFutureTransactionsFlowable(startBlock, blockTime); + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public void shutdown() { + scheduledExecutorService.shutdown(); + try { + web3jService.close(); + } catch (IOException e) { + throw new RuntimeException("Failed to close web3j service", e); + } + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/RemoteCall.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/RemoteCall.java index cbce31094..561de456c 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/RemoteCall.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/RemoteCall.java @@ -12,37 +12,37 @@ */ public class RemoteCall { - private Callable callable; + private Callable callable; - public RemoteCall(Callable callable) { - this.callable = callable; - } + public RemoteCall(Callable callable) { + this.callable = callable; + } - /** - * Perform request synchronously. - * - * @return result of enclosed function - * @throws Exception if the function throws an exception - */ - public T send() throws Exception { - return callable.call(); - } + /** + * Perform request synchronously. + * + * @return result of enclosed function + * @throws Exception if the function throws an exception + */ + public T send() throws Exception { + return callable.call(); + } - /** - * Perform request asynchronously with a future. - * - * @return a future containing our function - */ - public CompletableFuture sendAsync() { - return Async.run(this::send); - } + /** + * Perform request asynchronously with a future. + * + * @return a future containing our function + */ + public CompletableFuture sendAsync() { + return Async.run(this::send); + } - /** - * Provide an flowable to emit result from our function. - * - * @return an flowable - */ - public Flowable flowable() { - return Flowable.fromCallable(this::send); - } + /** + * Provide an flowable to emit result from our function. + * + * @return an flowable + */ + public Flowable flowable() { + return Flowable.fromCallable(this::send); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/Request.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/Request.java index ae40b14f7..eeff67ef7 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/Request.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/Request.java @@ -11,103 +11,107 @@ import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; public class Request { - private static AtomicLong nextId = new AtomicLong(0); - private String jsonrpc = "2.0"; - private String method; - private List params; - private long id; - private TransactionSucCallback callback; - - private Web3jService web3jService; - - // Unfortunately require an instance of the type too, see - // http://stackoverflow.com/a/3437930/3211687 - private Class responseType; - - // 添加属性支持交易回调 - @JsonIgnore private boolean needTransCallback; - @JsonIgnore private TransactionSucCallback transactionSucCallback; - - public boolean isNeedTransCallback() { - return needTransCallback; - } - - public void setNeedTransCallback(boolean needTransCallback) { - this.needTransCallback = needTransCallback; - } - - public void setTransactionSucCallback(TransactionSucCallback transactionSucCallback) { - this.transactionSucCallback = transactionSucCallback; - } - - public TransactionSucCallback getTransactionSucCallback() { - return transactionSucCallback; - } - - public Request() {} - - public Request(String method, List params, Web3jService web3jService, Class type) { - this.method = method; - this.params = params; - this.id = nextId.getAndIncrement(); - this.web3jService = web3jService; - this.responseType = type; - } - - public String getJsonrpc() { - return jsonrpc; - } - - public void setJsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - } - - public String getMethod() { - return method; - } - - public void setMethod(String method) { - this.method = method; - } - - public List getParams() { - return params; - } - - public void setParams(List params) { - this.params = params; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public T send() throws IOException { - return web3jService.send(this, responseType); - } - - public String sendForReturnString() throws IOException { - ChannelEthereumService channelEthereumService = (ChannelEthereumService) web3jService; - return channelEthereumService.sendSpecial(this); - } - - public CompletableFuture sendAsync() { - return web3jService.sendAsync(this, responseType); - } - - public Flowable flowable() { - return new RemoteCall<>(this::send).flowable(); - } - - public TransactionSucCallback getCallback() { - return callback; - } - - public void setCallback(TransactionSucCallback callback) { - this.callback = callback; - } + private static AtomicLong nextId = new AtomicLong(0); + private String jsonrpc = "2.0"; + private String method; + private List params; + private long id; + private TransactionSucCallback callback; + + private Web3jService web3jService; + + // Unfortunately require an instance of the type too, see + // http://stackoverflow.com/a/3437930/3211687 + private Class responseType; + + // 添加属性支持交易回调 + @JsonIgnore private boolean needTransCallback; + @JsonIgnore private TransactionSucCallback transactionSucCallback; + + public boolean isNeedTransCallback() { + return needTransCallback; + } + + public void setNeedTransCallback(boolean needTransCallback) { + this.needTransCallback = needTransCallback; + } + + public void setTransactionSucCallback(TransactionSucCallback transactionSucCallback) { + this.transactionSucCallback = transactionSucCallback; + } + + public TransactionSucCallback getTransactionSucCallback() { + return transactionSucCallback; + } + + public Request() {} + + public Request(String method, List params, Web3jService web3jService, Class type) { + this.method = method; + this.params = params; + this.id = nextId.getAndIncrement(); + this.web3jService = web3jService; + this.responseType = type; + } + + public String getJsonrpc() { + return jsonrpc; + } + + public void setJsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public T send() throws IOException { + return web3jService.send(this, responseType); + } + + public void sendOnly() throws IOException { + web3jService.sendOnly(this); + } + + public String sendForReturnString() throws IOException { + ChannelEthereumService channelEthereumService = (ChannelEthereumService) web3jService; + return channelEthereumService.sendSpecial(this); + } + + public CompletableFuture sendAsync() { + return web3jService.sendAsync(this, responseType); + } + + public Flowable flowable() { + return new RemoteCall<>(this::send).flowable(); + } + + public TransactionSucCallback getCallback() { + return callback; + } + + public void setCallback(TransactionSucCallback callback) { + this.callback = callback; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/Response.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/Response.java index 45ece085f..c85151185 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/Response.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/Response.java @@ -4,122 +4,122 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Response { - private long id; - private String jsonrpc; - private T result; - private Error error; - private String rawResponse; + private long id; + private String jsonrpc; + private T result; + private Error error; + private String rawResponse; - public Response() {} + public Response() {} - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getJsonrpc() { - return jsonrpc; - } - - public void setJsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - } - - public T getResult() { - return result; - } - - public void setResult(T result) { - this.result = result; - } - - public Error getError() { - return error; - } - - public void setError(Error error) { - this.error = error; - } - - public boolean hasError() { - return error != null; - } - - public String getRawResponse() { - return rawResponse; - } - - public void setRawResponse(String rawResponse) { - this.rawResponse = rawResponse; - } + public long getId() { + return id; + } - public static class Error { - private int code; - private String message; - private String data; + public void setId(long id) { + this.id = id; + } - public Error() {} + public String getJsonrpc() { + return jsonrpc; + } - public Error(int code, String message) { - this.code = code; - this.message = message; + public void setJsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; } - public int getCode() { - return code; + public T getResult() { + return result; } - public void setCode(int code) { - this.code = code; + public void setResult(T result) { + this.result = result; } - public String getMessage() { - return message; + public Error getError() { + return error; } - public void setMessage(String message) { - this.message = message; + public void setError(Error error) { + this.error = error; } - public String getData() { - return data; + public boolean hasError() { + return error != null; } - public void setData(String data) { - this.data = data; + public String getRawResponse() { + return rawResponse; } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Error)) { - return false; - } - - Error error = (Error) o; - - if (getCode() != error.getCode()) { - return false; - } - if (getMessage() != null - ? !getMessage().equals(error.getMessage()) - : error.getMessage() != null) { - return false; - } - return getData() != null ? getData().equals(error.getData()) : error.getData() == null; + public void setRawResponse(String rawResponse) { + this.rawResponse = rawResponse; } - @Override - public int hashCode() { - int result = getCode(); - result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0); - result = 31 * result + (getData() != null ? getData().hashCode() : 0); - return result; + public static class Error { + private int code; + private String message; + private String data; + + public Error() {} + + public Error(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Error)) { + return false; + } + + Error error = (Error) o; + + if (getCode() != error.getCode()) { + return false; + } + if (getMessage() != null + ? !getMessage().equals(error.getMessage()) + : error.getMessage() != null) { + return false; + } + return getData() != null ? getData().equals(error.getData()) : error.getData() == null; + } + + @Override + public int hashCode() { + int result = getCode(); + result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0); + result = 31 * result + (getData() != null ? getData().hashCode() : 0); + return result; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/ResponseSpecial.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/ResponseSpecial.java index 6c7587d36..b7917fd55 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/ResponseSpecial.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/ResponseSpecial.java @@ -5,122 +5,122 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ResponseSpecial { - private long id; - private String jsonrpc; - @JsonIgnore private T result; - private Error error; - private String rawResponse; + private long id; + private String jsonrpc; + @JsonIgnore private T result; + private Error error; + private String rawResponse; - public ResponseSpecial() {} + public ResponseSpecial() {} - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getJsonrpc() { - return jsonrpc; - } - - public void setJsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - } - - public T getResult() { - return result; - } - - public void setResult(T result) { - this.result = result; - } - - public Error getError() { - return error; - } - - public void setError(Error error) { - this.error = error; - } - - public boolean hasError() { - return error != null; - } - - public String getRawResponse() { - return rawResponse; - } - - public void setRawResponse(String rawResponse) { - this.rawResponse = rawResponse; - } + public long getId() { + return id; + } - public static class Error { - private int code; - private String message; - private String data; + public void setId(long id) { + this.id = id; + } - public Error() {} + public String getJsonrpc() { + return jsonrpc; + } - public Error(int code, String message) { - this.code = code; - this.message = message; + public void setJsonrpc(String jsonrpc) { + this.jsonrpc = jsonrpc; } - public int getCode() { - return code; + public T getResult() { + return result; } - public void setCode(int code) { - this.code = code; + public void setResult(T result) { + this.result = result; } - public String getMessage() { - return message; + public Error getError() { + return error; } - public void setMessage(String message) { - this.message = message; + public void setError(Error error) { + this.error = error; } - public String getData() { - return data; + public boolean hasError() { + return error != null; } - public void setData(String data) { - this.data = data; + public String getRawResponse() { + return rawResponse; } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Error)) { - return false; - } - - Error error = (Error) o; - - if (getCode() != error.getCode()) { - return false; - } - if (getMessage() != null - ? !getMessage().equals(error.getMessage()) - : error.getMessage() != null) { - return false; - } - return getData() != null ? getData().equals(error.getData()) : error.getData() == null; + public void setRawResponse(String rawResponse) { + this.rawResponse = rawResponse; } - @Override - public int hashCode() { - int result = getCode(); - result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0); - result = 31 * result + (getData() != null ? getData().hashCode() : 0); - return result; + public static class Error { + private int code; + private String message; + private String data; + + public Error() {} + + public Error(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Error)) { + return false; + } + + Error error = (Error) o; + + if (getCode() != error.getCode()) { + return false; + } + if (getMessage() != null + ? !getMessage().equals(error.getMessage()) + : error.getMessage() != null) { + return false; + } + return getData() != null ? getData().equals(error.getData()) : error.getData() == null; + } + + @Override + public int hashCode() { + int result = getCode(); + result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0); + result = 31 * result + (getData() != null ? getData().hashCode() : 0); + return result; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/BlockFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/BlockFilter.java index 6be40f02a..ab93319a0 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/BlockFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/BlockFilter.java @@ -12,36 +12,37 @@ /** Handler for working with block filter requests. */ public class BlockFilter extends Filter { - public BlockFilter(Web3j web3j, Callback callback) { - super(web3j, callback); - } + public BlockFilter(Web3j web3j, Callback callback) { + super(web3j, callback); + } - @Override - BcosFilter sendRequest() throws IOException { - return web3j.newBlockFilter().send(); - } + @Override + BcosFilter sendRequest() throws IOException { + return web3j.newBlockFilter().send(); + } - @Override - void process(List logResults) { - for (BcosLog.LogResult logResult : logResults) { - if (logResult instanceof BcosLog.Hash) { - String blockHash = ((BcosLog.Hash) logResult).get(); - callback.onEvent(blockHash); - } else { - throw new FilterException("Unexpected result type: " + logResult.get() + ", required Hash"); - } + @Override + void process(List logResults) { + for (BcosLog.LogResult logResult : logResults) { + if (logResult instanceof BcosLog.Hash) { + String blockHash = ((BcosLog.Hash) logResult).get(); + callback.onEvent(blockHash); + } else { + throw new FilterException( + "Unexpected result type: " + logResult.get() + ", required Hash"); + } + } } - } - /** - * Since the block filter does not support historic filters, the filterId is ignored and an empty - * optional is returned - * - * @param filterId Id of the filter for which the historic log should be retrieved - * @return Optional.empty() - */ - @Override - protected Optional> getFilterLogs(BigInteger filterId) { - return Optional.empty(); - } + /** + * Since the block filter does not support historic filters, the filterId is ignored and an + * empty optional is returned + * + * @param filterId Id of the filter for which the historic log should be retrieved + * @return Optional.empty() + */ + @Override + protected Optional> getFilterLogs(BigInteger filterId) { + return Optional.empty(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Callback.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Callback.java index 21675427e..f673d9502 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Callback.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Callback.java @@ -2,5 +2,5 @@ /** Filter callback interface. */ public interface Callback { - void onEvent(T value); + void onEvent(T value); } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Filter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Filter.java index eb419d61f..16992775a 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Filter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/Filter.java @@ -18,104 +18,104 @@ /** Class for creating managed filter requests with callbacks. */ public abstract class Filter { - final Web3j web3j; - final Callback callback; + final Web3j web3j; + final Callback callback; - private volatile BigInteger filterId; + private volatile BigInteger filterId; - private ScheduledFuture schedule; + private ScheduledFuture schedule; - public Filter(Web3j web3j, Callback callback) { - this.web3j = web3j; - this.callback = callback; - } + public Filter(Web3j web3j, Callback callback) { + this.web3j = web3j; + this.callback = callback; + } - public void run(ScheduledExecutorService scheduledExecutorService, long blockTime) { - try { - BcosFilter ethFilter = sendRequest(); - if (ethFilter.hasError()) { - throwException(ethFilter.getError()); - } + public void run(ScheduledExecutorService scheduledExecutorService, long blockTime) { + try { + BcosFilter ethFilter = sendRequest(); + if (ethFilter.hasError()) { + throwException(ethFilter.getError()); + } - filterId = ethFilter.getFilterId(); + filterId = ethFilter.getFilterId(); - scheduledExecutorService.submit(this::getInitialFilterLogs); + scheduledExecutorService.submit(this::getInitialFilterLogs); - schedule = - scheduledExecutorService.scheduleAtFixedRate( - () -> this.pollFilter(ethFilter), 0, blockTime, TimeUnit.MILLISECONDS); + schedule = + scheduledExecutorService.scheduleAtFixedRate( + () -> this.pollFilter(ethFilter), 0, blockTime, TimeUnit.MILLISECONDS); - } catch (IOException e) { - throwException(e); - } - } - - private void getInitialFilterLogs() { - try { - Optional> maybeRequest = this.getFilterLogs(this.filterId); - BcosLog ethLog; - if (maybeRequest.isPresent()) { - ethLog = maybeRequest.get().send(); - } else { - ethLog = new BcosLog(); - ethLog.setResult(Collections.emptyList()); - } - process(ethLog.getLogs()); - } catch (IOException e) { - throwException(e); + } catch (IOException e) { + throwException(e); + } } - } - - private void pollFilter(BcosFilter ethFilter) { - BcosLog ethLog = null; - try { - ethLog = web3j.getFilterChanges(filterId).send(); - } catch (IOException e) { - throwException(e); + + private void getInitialFilterLogs() { + try { + Optional> maybeRequest = this.getFilterLogs(this.filterId); + BcosLog ethLog; + if (maybeRequest.isPresent()) { + ethLog = maybeRequest.get().send(); + } else { + ethLog = new BcosLog(); + ethLog.setResult(Collections.emptyList()); + } + process(ethLog.getLogs()); + } catch (IOException e) { + throwException(e); + } } - if (ethLog.hasError()) { - throwException(ethFilter.getError()); + + private void pollFilter(BcosFilter ethFilter) { + BcosLog ethLog = null; + try { + ethLog = web3j.getFilterChanges(filterId).send(); + } catch (IOException e) { + throwException(e); + } + if (ethLog.hasError()) { + throwException(ethFilter.getError()); + } + process(ethLog.getLogs()); } - process(ethLog.getLogs()); - } - abstract BcosFilter sendRequest() throws IOException; + abstract BcosFilter sendRequest() throws IOException; + + abstract void process(List logResults); + + public void cancel() { + schedule.cancel(false); - abstract void process(List logResults); + UninstallFilter ethUninstallFilter = null; + try { + ethUninstallFilter = web3j.getUninstallFilter(filterId).send(); + } catch (IOException e) { + throwException(e); + } - public void cancel() { - schedule.cancel(false); + if (ethUninstallFilter.hasError()) { + throwException(ethUninstallFilter.getError()); + } - UninstallFilter ethUninstallFilter = null; - try { - ethUninstallFilter = web3j.getUninstallFilter(filterId).send(); - } catch (IOException e) { - throwException(e); + if (!ethUninstallFilter.isUninstalled()) { + throwException(ethUninstallFilter.getError()); + } } - if (ethUninstallFilter.hasError()) { - throwException(ethUninstallFilter.getError()); + /** + * Retrieves historic filters for the filter with the given id. Getting historic logs is not + * supported by all filters. If not the method should return an empty EthLog object + * + * @param filterId Id of the filter for which the historic log should be retrieved + * @return Historic logs, or an empty optional if the filter cannot retrieve historic logs + */ + protected abstract Optional> getFilterLogs(BigInteger filterId); + + void throwException(Response.Error error) { + throw new FilterException("Invalid request: " + error.getMessage()); } - if (!ethUninstallFilter.isUninstalled()) { - throwException(ethUninstallFilter.getError()); + void throwException(Throwable cause) { + throw new FilterException("Error sending request", cause); } - } - - /** - * Retrieves historic filters for the filter with the given id. Getting historic logs is not - * supported by all filters. If not the method should return an empty EthLog object - * - * @param filterId Id of the filter for which the historic log should be retrieved - * @return Historic logs, or an empty optional if the filter cannot retrieve historic logs - */ - protected abstract Optional> getFilterLogs(BigInteger filterId); - - void throwException(Response.Error error) { - throw new FilterException("Invalid request: " + error.getMessage()); - } - - void throwException(Throwable cause) { - throw new FilterException("Error sending request", cause); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/FilterException.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/FilterException.java index 273a4fbb4..d1adb287e 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/FilterException.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/FilterException.java @@ -3,11 +3,11 @@ /** Filter exception wrapper. */ public class FilterException extends RuntimeException { - public FilterException(String message) { - super(message); - } + public FilterException(String message) { + super(message); + } - public FilterException(String message, Throwable cause) { - super(message, cause); - } + public FilterException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/LogFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/LogFilter.java index 67915d285..597248efc 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/LogFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/LogFilter.java @@ -12,36 +12,37 @@ /** Log filter handler. */ public class LogFilter extends Filter { - private final org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter; + private final org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter; - public LogFilter( - Web3j web3j, - Callback callback, - org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter) { - super(web3j, callback); - this.ethFilter = ethFilter; - } + public LogFilter( + Web3j web3j, + Callback callback, + org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter ethFilter) { + super(web3j, callback); + this.ethFilter = ethFilter; + } - @Override - org.fisco.bcos.web3j.protocol.core.methods.response.BcosFilter sendRequest() throws IOException { - return web3j.newFilter(ethFilter).send(); - } + @Override + org.fisco.bcos.web3j.protocol.core.methods.response.BcosFilter sendRequest() + throws IOException { + return web3j.newFilter(ethFilter).send(); + } - @Override - void process(List logResults) { - for (BcosLog.LogResult logResult : logResults) { - if (logResult instanceof BcosLog.LogObject) { - Log log = ((BcosLog.LogObject) logResult).get(); - callback.onEvent(log); - } else { - throw new FilterException( - "Unexpected result type: " + logResult.get() + " required LogObject"); - } + @Override + void process(List logResults) { + for (BcosLog.LogResult logResult : logResults) { + if (logResult instanceof BcosLog.LogObject) { + Log log = ((BcosLog.LogObject) logResult).get(); + callback.onEvent(log); + } else { + throw new FilterException( + "Unexpected result type: " + logResult.get() + " required LogObject"); + } + } } - } - @Override - protected Optional> getFilterLogs(BigInteger filterId) { - return Optional.empty(); - } + @Override + protected Optional> getFilterLogs(BigInteger filterId) { + return Optional.empty(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/PendingTransactionFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/PendingTransactionFilter.java index c62615d90..e458e3106 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/PendingTransactionFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/filters/PendingTransactionFilter.java @@ -12,36 +12,37 @@ /** Handler for working with transaction filter requests. */ public class PendingTransactionFilter extends Filter { - public PendingTransactionFilter(Web3j web3j, Callback callback) { - super(web3j, callback); - } + public PendingTransactionFilter(Web3j web3j, Callback callback) { + super(web3j, callback); + } - @Override - BcosFilter sendRequest() throws IOException { - return web3j.newPendingTransactionFilter().send(); - } + @Override + BcosFilter sendRequest() throws IOException { + return web3j.newPendingTransactionFilter().send(); + } - @Override - void process(List logResults) { - for (BcosLog.LogResult logResult : logResults) { - if (logResult instanceof BcosLog.Hash) { - String blockHash = ((BcosLog.Hash) logResult).get(); - callback.onEvent(blockHash); - } else { - throw new FilterException("Unexpected result type: " + logResult.get() + ", required Hash"); - } + @Override + void process(List logResults) { + for (BcosLog.LogResult logResult : logResults) { + if (logResult instanceof BcosLog.Hash) { + String blockHash = ((BcosLog.Hash) logResult).get(); + callback.onEvent(blockHash); + } else { + throw new FilterException( + "Unexpected result type: " + logResult.get() + ", required Hash"); + } + } } - } - /** - * Since the pending transaction filter does not support historic filters, the filterId is ignored - * and an empty optional is returned - * - * @param filterId Id of the filter for which the historic log should be retrieved - * @return Optional.empty() - */ - @Override - protected Optional> getFilterLogs(BigInteger filterId) { - return Optional.empty(); - } + /** + * Since the pending transaction filter does not support historic filters, the filterId is + * ignored and an empty optional is returned + * + * @param filterId Id of the filter for which the historic log should be retrieved + * @return Optional.empty() + */ + @Override + protected Optional> getFilterLogs(BigInteger filterId) { + return Optional.empty(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/BcosFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/BcosFilter.java index c61e30aa2..5b50f20c1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/BcosFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/BcosFilter.java @@ -9,41 +9,41 @@ * href="/ethereum/wiki/wiki/JSON-RPC#eth_newfilter">docs. */ public class BcosFilter extends Filter { - private DefaultBlockParameter fromBlock; // optional, params - defaults to latest for both - private DefaultBlockParameter toBlock; - private List address; // spec. implies this can be single address as string or list - - public BcosFilter() { - super(); - } - - public BcosFilter( - DefaultBlockParameter fromBlock, DefaultBlockParameter toBlock, List address) { - super(); - this.fromBlock = fromBlock; - this.toBlock = toBlock; - this.address = address; - } - - public BcosFilter( - DefaultBlockParameter fromBlock, DefaultBlockParameter toBlock, String address) { - this(fromBlock, toBlock, Arrays.asList(address)); - } - - public DefaultBlockParameter getFromBlock() { - return fromBlock; - } - - public DefaultBlockParameter getToBlock() { - return toBlock; - } - - public List getAddress() { - return address; - } - - @Override - Filter getThis() { - return this; - } + private DefaultBlockParameter fromBlock; // optional, params - defaults to latest for both + private DefaultBlockParameter toBlock; + private List address; // spec. implies this can be single address as string or list + + public BcosFilter() { + super(); + } + + public BcosFilter( + DefaultBlockParameter fromBlock, DefaultBlockParameter toBlock, List address) { + super(); + this.fromBlock = fromBlock; + this.toBlock = toBlock; + this.address = address; + } + + public BcosFilter( + DefaultBlockParameter fromBlock, DefaultBlockParameter toBlock, String address) { + this(fromBlock, toBlock, Arrays.asList(address)); + } + + public DefaultBlockParameter getFromBlock() { + return fromBlock; + } + + public DefaultBlockParameter getToBlock() { + return toBlock; + } + + public List getAddress() { + return address; + } + + @Override + Filter getThis() { + return this; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Filter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Filter.java index fa691eaec..1c199eecf 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Filter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Filter.java @@ -12,76 +12,76 @@ @JsonInclude(JsonInclude.Include.NON_NULL) public abstract class Filter { - private T thisObj; - private List topics; + private T thisObj; + private List topics; - Filter() { - thisObj = getThis(); - topics = new ArrayList<>(); - } + Filter() { + thisObj = getThis(); + topics = new ArrayList<>(); + } - public T addSingleTopic(String topic) { - topics.add(new SingleTopic(topic)); - return getThis(); - } + public T addSingleTopic(String topic) { + topics.add(new SingleTopic(topic)); + return getThis(); + } - public T addNullTopic() { - topics.add(new SingleTopic()); - return getThis(); - } + public T addNullTopic() { + topics.add(new SingleTopic()); + return getThis(); + } - // how to pass in null topic? - public T addOptionalTopics(String... optionalTopics) { - topics.add(new ListTopic(optionalTopics)); - return getThis(); - } + // how to pass in null topic? + public T addOptionalTopics(String... optionalTopics) { + topics.add(new ListTopic(optionalTopics)); + return getThis(); + } - public List getTopics() { - return topics; - } + public List getTopics() { + return topics; + } - abstract T getThis(); + abstract T getThis(); - public interface FilterTopic { - @JsonValue - T getValue(); - } + public interface FilterTopic { + @JsonValue + T getValue(); + } - public static class SingleTopic implements FilterTopic { + public static class SingleTopic implements FilterTopic { - private String topic; + private String topic; - public SingleTopic() { - this.topic = null; // null topic - } + public SingleTopic() { + this.topic = null; // null topic + } - public SingleTopic(String topic) { - this.topic = topic; - } + public SingleTopic(String topic) { + this.topic = topic; + } - @Override - public String getValue() { - return topic; - } - } - - public static class ListTopic implements FilterTopic> { - private List topics; - - public ListTopic(String... optionalTopics) { - topics = new ArrayList<>(); - for (String topic : optionalTopics) { - if (topic != null) { - topics.add(new SingleTopic(topic)); - } else { - topics.add(new SingleTopic()); + @Override + public String getValue() { + return topic; } - } } - @Override - public List getValue() { - return topics; + public static class ListTopic implements FilterTopic> { + private List topics; + + public ListTopic(String... optionalTopics) { + topics = new ArrayList<>(); + for (String topic : optionalTopics) { + if (topic != null) { + topics.add(new SingleTopic(topic)); + } else { + topics.add(new SingleTopic()); + } + } + } + + @Override + public List getValue() { + return topics; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ProofMerkle.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ProofMerkle.java index 49da71256..a5d5438a3 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ProofMerkle.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ProofMerkle.java @@ -2,27 +2,27 @@ /** Created by suyuhui on 17/9/28. */ public class ProofMerkle { - private String blockHash; - private String transactionIndex; + private String blockHash; + private String transactionIndex; - public ProofMerkle(String blockHash, String transactionIndex) { - this.blockHash = blockHash; - this.transactionIndex = transactionIndex; - } + public ProofMerkle(String blockHash, String transactionIndex) { + this.blockHash = blockHash; + this.transactionIndex = transactionIndex; + } - public String getBlockHash() { - return blockHash; - } + public String getBlockHash() { + return blockHash; + } - public void setBlockHash(String blockHash) { - this.blockHash = blockHash; - } + public void setBlockHash(String blockHash) { + this.blockHash = blockHash; + } - public String getTransactionIndex() { - return transactionIndex; - } + public String getTransactionIndex() { + return transactionIndex; + } - public void setTransactionIndex(String transactionIndex) { - this.transactionIndex = transactionIndex; - } + public void setTransactionIndex(String transactionIndex) { + this.transactionIndex = transactionIndex; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhFilter.java index 2a673986c..a43796186 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhFilter.java @@ -5,19 +5,19 @@ * href="/ethereum/wiki/wiki/JSON-RPC#eth_newfilter">docs */ public class ShhFilter extends Filter { - private String to; + private String to; - public ShhFilter(String to) { - super(); - this.to = to; - } + public ShhFilter(String to) { + super(); + this.to = to; + } - public String getTo() { - return to; - } + public String getTo() { + return to; + } - @Override - Filter getThis() { - return this; - } + @Override + Filter getThis() { + return this; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhPost.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhPost.java index bd6696d64..ef2205f63 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhPost.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/ShhPost.java @@ -8,64 +8,64 @@ /** https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post */ @JsonInclude(JsonInclude.Include.NON_NULL) public class ShhPost { - private String from; - private String to; - private List topics; - private String payload; - private BigInteger priority; - private BigInteger ttl; + private String from; + private String to; + private List topics; + private String payload; + private BigInteger priority; + private BigInteger ttl; - public ShhPost(List topics, String payload, BigInteger priority, BigInteger ttl) { - this.topics = topics; - this.payload = payload; - this.priority = priority; - this.ttl = ttl; - } + public ShhPost(List topics, String payload, BigInteger priority, BigInteger ttl) { + this.topics = topics; + this.payload = payload; + this.priority = priority; + this.ttl = ttl; + } - public ShhPost( - String from, - String to, - List topics, - String payload, - BigInteger priority, - BigInteger ttl) { - this.from = from; - this.to = to; - this.topics = topics; - this.payload = payload; - this.priority = priority; - this.ttl = ttl; - } + public ShhPost( + String from, + String to, + List topics, + String payload, + BigInteger priority, + BigInteger ttl) { + this.from = from; + this.to = to; + this.topics = topics; + this.payload = payload; + this.priority = priority; + this.ttl = ttl; + } - public String getFrom() { - return from; - } + public String getFrom() { + return from; + } - public String getTo() { - return to; - } + public String getTo() { + return to; + } - public List getTopics() { - return topics; - } + public List getTopics() { + return topics; + } - public String getPayload() { - return payload; - } + public String getPayload() { + return payload; + } - public String getPriority() { - return convert(priority); - } + public String getPriority() { + return convert(priority); + } - public String getTtl() { - return convert(ttl); - } + public String getTtl() { + return convert(ttl); + } - private String convert(BigInteger value) { - if (value != null) { - return Numeric.encodeQuantity(value); - } else { - return null; + private String convert(BigInteger value) { + if (value != null) { + return Numeric.encodeQuantity(value); + } else { + return null; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Transaction.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Transaction.java index 264993ace..17d8c48a2 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Transaction.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/request/Transaction.java @@ -15,144 +15,144 @@ */ @JsonInclude(JsonInclude.Include.NON_NULL) public class Transaction { - // default as per https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction - public static final BigInteger DEFAULT_GAS = BigInteger.valueOf(9000); - - private String from; - private String to; - private BigInteger gas; - private BigInteger gasPrice; - private BigInteger value; - private String data; - private BigInteger nonce; // nonce field is not present on eth_call/eth_estimateGas - private BigInteger type; // 0 new合约,1 call - // private BigInteger version = TransactionConstant.version; - private String contractName; - - public Transaction( - String from, - BigInteger nonce, - BigInteger gasPrice, - BigInteger gasLimit, - String to, - BigInteger value, - String data) { - this.from = from; - this.to = to; - this.gas = gasLimit; - this.gasPrice = gasPrice; - this.value = value; - - if (data != null) { - if (this.to != null && this.to != "") { - this.data = Numeric.prependHexPrefix(data); - } else { - this.data = data; - } - } - - this.nonce = nonce; - } - - public static Transaction createContractTransaction( - String from, - BigInteger nonce, - BigInteger gasPrice, - BigInteger gasLimit, - BigInteger value, - String init) { - - return new Transaction(from, nonce, gasPrice, gasLimit, null, value, init); - } - - public static Transaction createContractTransaction( - String from, BigInteger nonce, BigInteger gasPrice, String init) { - - return createContractTransaction(from, nonce, gasPrice, null, null, init); - } - - public static Transaction createEtherTransaction( - String from, - BigInteger nonce, - BigInteger gasPrice, - BigInteger gasLimit, - String to, - BigInteger value) { - - return new Transaction(from, nonce, gasPrice, gasLimit, to, value, null); - } - - public static Transaction createFunctionCallTransaction( - String from, - BigInteger nonce, - BigInteger gasPrice, - BigInteger gasLimit, - String to, - BigInteger value, - String data) { - - return new Transaction(from, nonce, gasPrice, gasLimit, to, value, data); - } - - public static Transaction createFunctionCallTransaction( - String from, - BigInteger nonce, - BigInteger gasPrice, - BigInteger gasLimit, - String to, - String data) { - - return new Transaction(from, nonce, gasPrice, gasLimit, to, null, data); - } - - public static Transaction createEthCallTransaction(String from, String to, String data) { - - return new Transaction(from, null, null, null, to, null, data); - } - - public String getFrom() { - return from; - } - - public String getTo() { - return to; - } - - public String getGas() { - return convert(gas); - } - - public String getGasPrice() { - return convert(gasPrice); - } - - public String getValue() { - return convert(value); - } - - public String getData() { - return data; - } - - public String getNonce() { - return convert(nonce); - } - - public String getContractName() { - return contractName; - } - - public String getType() { - return convert(type); - } - - // public String getVersion() {return convert(version); } - - private static String convert(BigInteger value) { - if (value != null) { - return Numeric.encodeQuantity(value); - } else { - return null; // we don't want the field to be encoded if not present - } - } + // default as per https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction + public static final BigInteger DEFAULT_GAS = BigInteger.valueOf(9000); + + private String from; + private String to; + private BigInteger gas; + private BigInteger gasPrice; + private BigInteger value; + private String data; + private BigInteger nonce; // nonce field is not present on eth_call/eth_estimateGas + private BigInteger type; // 0 new合约,1 call + // private BigInteger version = TransactionConstant.version; + private String contractName; + + public Transaction( + String from, + BigInteger nonce, + BigInteger gasPrice, + BigInteger gasLimit, + String to, + BigInteger value, + String data) { + this.from = from; + this.to = to; + this.gas = gasLimit; + this.gasPrice = gasPrice; + this.value = value; + + if (data != null) { + if (this.to != null && this.to != "") { + this.data = Numeric.prependHexPrefix(data); + } else { + this.data = data; + } + } + + this.nonce = nonce; + } + + public static Transaction createContractTransaction( + String from, + BigInteger nonce, + BigInteger gasPrice, + BigInteger gasLimit, + BigInteger value, + String init) { + + return new Transaction(from, nonce, gasPrice, gasLimit, null, value, init); + } + + public static Transaction createContractTransaction( + String from, BigInteger nonce, BigInteger gasPrice, String init) { + + return createContractTransaction(from, nonce, gasPrice, null, null, init); + } + + public static Transaction createEtherTransaction( + String from, + BigInteger nonce, + BigInteger gasPrice, + BigInteger gasLimit, + String to, + BigInteger value) { + + return new Transaction(from, nonce, gasPrice, gasLimit, to, value, null); + } + + public static Transaction createFunctionCallTransaction( + String from, + BigInteger nonce, + BigInteger gasPrice, + BigInteger gasLimit, + String to, + BigInteger value, + String data) { + + return new Transaction(from, nonce, gasPrice, gasLimit, to, value, data); + } + + public static Transaction createFunctionCallTransaction( + String from, + BigInteger nonce, + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data) { + + return new Transaction(from, nonce, gasPrice, gasLimit, to, null, data); + } + + public static Transaction createEthCallTransaction(String from, String to, String data) { + + return new Transaction(from, null, null, null, to, null, data); + } + + public String getFrom() { + return from; + } + + public String getTo() { + return to; + } + + public String getGas() { + return convert(gas); + } + + public String getGasPrice() { + return convert(gasPrice); + } + + public String getValue() { + return convert(value); + } + + public String getData() { + return data; + } + + public String getNonce() { + return convert(nonce); + } + + public String getContractName() { + return contractName; + } + + public String getType() { + return convert(type); + } + + // public String getVersion() {return convert(version); } + + private static String convert(BigInteger value) { + if (value != null) { + return Numeric.encodeQuantity(value); + } else { + return null; // we don't want the field to be encoded if not present + } + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/AbiDefinition.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/AbiDefinition.java index adf842936..901e69acd 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/AbiDefinition.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/AbiDefinition.java @@ -6,225 +6,227 @@ /** AbiDefinition wrapper. */ @JsonIgnoreProperties(ignoreUnknown = true) public class AbiDefinition { - private boolean constant; - private List inputs; - private String name; - private List outputs; - private String type; - private boolean payable; - - private String stateMutability; - - public AbiDefinition() {} - - public AbiDefinition( - boolean constant, - List inputs, - String name, - List outputs, - String type, - boolean payable) { - this(constant, inputs, name, outputs, type, payable, null); - } - - public AbiDefinition( - boolean constant, - List inputs, - String name, - List outputs, - String type, - boolean payable, - String stateMutability) { - this.constant = constant; - this.inputs = inputs; - this.name = name; - this.outputs = outputs; - this.type = type; - this.payable = payable; - this.stateMutability = stateMutability; - } - - public boolean isConstant() { - return constant; - } - - public void setConstant(boolean constant) { - this.constant = constant; - } - - public List getInputs() { - return inputs; - } - - public void setInputs(List inputs) { - this.inputs = inputs; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getOutputs() { - return outputs; - } - - public boolean hasOutputs() { - return !outputs.isEmpty(); - } - - public void setOutputs(List outputs) { - this.outputs = outputs; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public boolean isPayable() { - return payable; - } - - public void setPayable(boolean payable) { - this.payable = payable; - } - - public String getStateMutability() { - return stateMutability; - } - - public void setStateMutability(String stateMutability) { - this.stateMutability = stateMutability; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof AbiDefinition)) { - return false; - } - - AbiDefinition that = (AbiDefinition) o; - - if (isConstant() != that.isConstant()) { - return false; - } - if (isPayable() != that.isPayable()) { - return false; - } - if (getInputs() != null ? !getInputs().equals(that.getInputs()) : that.getInputs() != null) { - return false; - } - if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) { - return false; - } - if (getOutputs() != null - ? !getOutputs().equals(that.getOutputs()) - : that.getOutputs() != null) { - return false; - } - if (getStateMutability() != null - ? !getStateMutability().equals(that.getStateMutability()) - : that.getStateMutability() != null) { - return false; - } - return getType() != null ? getType().equals(that.getType()) : that.getType() == null; - } - - @Override - public int hashCode() { - int result = (isConstant() ? 1 : 0); - result = 31 * result + (getInputs() != null ? getInputs().hashCode() : 0); - result = 31 * result + (getName() != null ? getName().hashCode() : 0); - result = 31 * result + (getOutputs() != null ? getOutputs().hashCode() : 0); - result = 31 * result + (getType() != null ? getType().hashCode() : 0); - result = 31 * result + (isPayable() ? 1 : 0); - result = 31 * result + (getStateMutability() != null ? getStateMutability().hashCode() : 0); - return result; - } - - public static class NamedType { + private boolean constant; + private List inputs; private String name; + private List outputs; private String type; - private boolean indexed; + private boolean payable; + + private String stateMutability; + + public AbiDefinition() {} + + public AbiDefinition( + boolean constant, + List inputs, + String name, + List outputs, + String type, + boolean payable) { + this(constant, inputs, name, outputs, type, payable, null); + } - public NamedType() {} + public AbiDefinition( + boolean constant, + List inputs, + String name, + List outputs, + String type, + boolean payable, + String stateMutability) { + this.constant = constant; + this.inputs = inputs; + this.name = name; + this.outputs = outputs; + this.type = type; + this.payable = payable; + this.stateMutability = stateMutability; + } + + public boolean isConstant() { + return constant; + } - public NamedType(String name, String type) { - this.name = name; - this.type = type; + public void setConstant(boolean constant) { + this.constant = constant; } - public NamedType(String name, String type, boolean indexed) { - this.name = name; - this.type = type; - this.indexed = indexed; + public List getInputs() { + return inputs; + } + + public void setInputs(List inputs) { + this.inputs = inputs; } public String getName() { - return name; + return name; } public void setName(String name) { - this.name = name; + this.name = name; + } + + public List getOutputs() { + return outputs; + } + + public boolean hasOutputs() { + return !outputs.isEmpty(); + } + + public void setOutputs(List outputs) { + this.outputs = outputs; } public String getType() { - return type; + return type; } public void setType(String type) { - this.type = type; + this.type = type; } - public boolean isIndexed() { - return indexed; + public boolean isPayable() { + return payable; } - public void setIndexed(boolean indexed) { - this.indexed = indexed; + public void setPayable(boolean payable) { + this.payable = payable; } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof NamedType)) { - return false; - } - - NamedType namedType = (NamedType) o; + public String getStateMutability() { + return stateMutability; + } - if (isIndexed() != namedType.isIndexed()) { - return false; - } + public void setStateMutability(String stateMutability) { + this.stateMutability = stateMutability; + } - if (getName() != null - ? !getName().equals(namedType.getName()) - : namedType.getName() != null) { - return false; - } - return getType() != null - ? getType().equals(namedType.getType()) - : namedType.getType() == null; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AbiDefinition)) { + return false; + } + + AbiDefinition that = (AbiDefinition) o; + + if (isConstant() != that.isConstant()) { + return false; + } + if (isPayable() != that.isPayable()) { + return false; + } + if (getInputs() != null + ? !getInputs().equals(that.getInputs()) + : that.getInputs() != null) { + return false; + } + if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) { + return false; + } + if (getOutputs() != null + ? !getOutputs().equals(that.getOutputs()) + : that.getOutputs() != null) { + return false; + } + if (getStateMutability() != null + ? !getStateMutability().equals(that.getStateMutability()) + : that.getStateMutability() != null) { + return false; + } + return getType() != null ? getType().equals(that.getType()) : that.getType() == null; } @Override public int hashCode() { - int result = getName() != null ? getName().hashCode() : 0; - result = 31 * result + (getType() != null ? getType().hashCode() : 0); - result = 31 * result + (isIndexed() ? 1 : 0); - return result; + int result = (isConstant() ? 1 : 0); + result = 31 * result + (getInputs() != null ? getInputs().hashCode() : 0); + result = 31 * result + (getName() != null ? getName().hashCode() : 0); + result = 31 * result + (getOutputs() != null ? getOutputs().hashCode() : 0); + result = 31 * result + (getType() != null ? getType().hashCode() : 0); + result = 31 * result + (isPayable() ? 1 : 0); + result = 31 * result + (getStateMutability() != null ? getStateMutability().hashCode() : 0); + return result; + } + + public static class NamedType { + private String name; + private String type; + private boolean indexed; + + public NamedType() {} + + public NamedType(String name, String type) { + this.name = name; + this.type = type; + } + + public NamedType(String name, String type, boolean indexed) { + this.name = name; + this.type = type; + this.indexed = indexed; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isIndexed() { + return indexed; + } + + public void setIndexed(boolean indexed) { + this.indexed = indexed; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof NamedType)) { + return false; + } + + NamedType namedType = (NamedType) o; + + if (isIndexed() != namedType.isIndexed()) { + return false; + } + + if (getName() != null + ? !getName().equals(namedType.getName()) + : namedType.getName() != null) { + return false; + } + return getType() != null + ? getType().equals(namedType.getType()) + : namedType.getType() == null; + } + + @Override + public int hashCode() { + int result = getName() != null ? getName().hashCode() : 0; + result = 31 * result + (getType() != null ? getType().hashCode() : 0); + result = 31 * result + (isIndexed() ? 1 : 0); + return result; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosBlock.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosBlock.java index 50f245783..3134c2951 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosBlock.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosBlock.java @@ -17,630 +17,566 @@ public class BcosBlock extends Response { - @Override - @JsonDeserialize(using = BcosBlock.ResponseDeserialiser.class) - public void setResult(Block result) { - super.setResult(result); - } - - public Block getBlock() { - return getResult(); - } - - public static class Block { - private String number; - private String hash; - private String parentHash; - private String nonce; - private String sha3Uncles; - private String logsBloom; - private String transactionsRoot; - private String stateRoot; - private String receiptsRoot; - private String author; - private String sealer; - private String mixHash; - private String difficulty; - private String totalDifficulty; - private List extraData; - private String size; - private String gasLimit; - private String gasUsed; - private String timestamp; - private List transactions; - private List uncles; - private List sealFields; - - public Block() {} - @Override - public String toString() { - return "Block [number=" - + number - + ", hash=" - + hash - + ", parentHash=" - + parentHash - + ", nonce=" - + nonce - + ", sha3Uncles=" - + sha3Uncles - + ", logsBloom=" - + logsBloom - + ", transactionsRoot=" - + transactionsRoot - + ", stateRoot=" - + stateRoot - + ", receiptsRoot=" - + receiptsRoot - + ", author=" - + author - + ", sealer=" - + sealer - + ", mixHash=" - + mixHash - + ", difficulty=" - + difficulty - + ", totalDifficulty=" - + totalDifficulty - + ", extraData=" - + extraData - + ", size=" - + size - + ", gasLimit=" - + gasLimit - + ", gasUsed=" - + gasUsed - + ", timestamp=" - + timestamp - + ", transactions=" - + transactions - + ", uncles=" - + uncles - + ", sealFields=" - + sealFields - + "]"; - } - - public Block( - String number, - String hash, - String parentHash, - String nonce, - String sha3Uncles, - String logsBloom, - String transactionsRoot, - String stateRoot, - String receiptsRoot, - String author, - String sealer, - String mixHash, - String difficulty, - String totalDifficulty, - List extraData, - String size, - String gasLimit, - String gasUsed, - String timestamp, - List transactions, - List uncles, - List sealFields) { - this.number = number; - this.hash = hash; - this.parentHash = parentHash; - this.nonce = nonce; - this.sha3Uncles = sha3Uncles; - this.logsBloom = logsBloom; - this.transactionsRoot = transactionsRoot; - this.stateRoot = stateRoot; - this.receiptsRoot = receiptsRoot; - this.author = author; - this.sealer = sealer; - this.mixHash = mixHash; - this.difficulty = difficulty; - this.totalDifficulty = totalDifficulty; - this.extraData = extraData; - this.size = size; - this.gasLimit = gasLimit; - this.gasUsed = gasUsed; - this.timestamp = timestamp; - this.transactions = transactions; - this.uncles = uncles; - this.sealFields = sealFields; - } - - public BigInteger getNumber() { - return Numeric.decodeQuantity(number); - } - - public String getNumberRaw() { - return number; - } - - public void setNumber(String number) { - this.number = number; - } - - public String getHash() { - return hash; - } + @JsonDeserialize(using = BcosBlock.ResponseDeserialiser.class) + public void setResult(Block result) { + super.setResult(result); + } + + public Block getBlock() { + return getResult(); + } + + public static class Block { + private String number; + private String hash; + private String parentHash; + private String nonce; + private String sha3Uncles; + private String logsBloom; + private String transactionsRoot; + private String stateRoot; + private String receiptsRoot; + private String author; + private String sealer; + private String mixHash; + private List extraData; + private String gasLimit; + private String gasUsed; + private String timestamp; + private List transactions; + private List uncles; + private List sealFields; + + public Block() {} + + @Override + public String toString() { + return "Block [number=" + + number + + ", hash=" + + hash + + ", parentHash=" + + parentHash + + ", nonce=" + + nonce + + ", sha3Uncles=" + + sha3Uncles + + ", logsBloom=" + + logsBloom + + ", transactionsRoot=" + + transactionsRoot + + ", stateRoot=" + + stateRoot + + ", receiptsRoot=" + + receiptsRoot + + ", author=" + + author + + ", sealer=" + + sealer + + ", mixHash=" + + mixHash + + ", extraData=" + + extraData + + ", gasLimit=" + + gasLimit + + ", gasUsed=" + + gasUsed + + ", timestamp=" + + timestamp + + ", transactions=" + + transactions + + ", uncles=" + + uncles + + ", sealFields=" + + sealFields + + "]"; + } - public void setHash(String hash) { - this.hash = hash; - } + public Block( + String number, + String hash, + String parentHash, + String nonce, + String sha3Uncles, + String logsBloom, + String transactionsRoot, + String stateRoot, + String receiptsRoot, + String author, + String sealer, + String mixHash, + List extraData, + String gasLimit, + String gasUsed, + String timestamp, + List transactions, + List uncles, + List sealFields) { + this.number = number; + this.hash = hash; + this.parentHash = parentHash; + this.nonce = nonce; + this.sha3Uncles = sha3Uncles; + this.logsBloom = logsBloom; + this.transactionsRoot = transactionsRoot; + this.stateRoot = stateRoot; + this.receiptsRoot = receiptsRoot; + this.author = author; + this.sealer = sealer; + this.mixHash = mixHash; + this.extraData = extraData; + this.gasLimit = gasLimit; + this.gasUsed = gasUsed; + this.timestamp = timestamp; + this.transactions = transactions; + this.uncles = uncles; + this.sealFields = sealFields; + } - public String getParentHash() { - return parentHash; - } + public BigInteger getNumber() { + return Numeric.decodeQuantity(number); + } - public void setParentHash(String parentHash) { - this.parentHash = parentHash; - } + public String getNumberRaw() { + return number; + } - public BigInteger getNonce() { - if (nonce == null) return new BigInteger("0"); - return Numeric.decodeQuantity(nonce); - } + public void setNumber(String number) { + this.number = number; + } - public String getNonceRaw() { - return nonce; - } + public String getHash() { + return hash; + } - public void setNonce(String nonce) { - this.nonce = nonce; - } + public void setHash(String hash) { + this.hash = hash; + } - public String getSha3Uncles() { - return sha3Uncles; - } + public String getParentHash() { + return parentHash; + } - public void setSha3Uncles(String sha3Uncles) { - this.sha3Uncles = sha3Uncles; - } + public void setParentHash(String parentHash) { + this.parentHash = parentHash; + } - public String getLogsBloom() { - return logsBloom; - } + public BigInteger getNonce() { + if (nonce == null) return new BigInteger("0"); + return Numeric.decodeQuantity(nonce); + } - public void setLogsBloom(String logsBloom) { - this.logsBloom = logsBloom; - } + public String getNonceRaw() { + return nonce; + } - public String getTransactionsRoot() { - return transactionsRoot; - } + public void setNonce(String nonce) { + this.nonce = nonce; + } - public void setTransactionsRoot(String transactionsRoot) { - this.transactionsRoot = transactionsRoot; - } + public String getSha3Uncles() { + return sha3Uncles; + } - public String getStateRoot() { - return stateRoot; - } + public void setSha3Uncles(String sha3Uncles) { + this.sha3Uncles = sha3Uncles; + } - public void setStateRoot(String stateRoot) { - this.stateRoot = stateRoot; - } + public String getLogsBloom() { + return logsBloom; + } - public String getReceiptsRoot() { - return receiptsRoot; - } + public void setLogsBloom(String logsBloom) { + this.logsBloom = logsBloom; + } - public void setReceiptsRoot(String receiptsRoot) { - this.receiptsRoot = receiptsRoot; - } + public String getTransactionsRoot() { + return transactionsRoot; + } - public String getAuthor() { - return author; - } + public void setTransactionsRoot(String transactionsRoot) { + this.transactionsRoot = transactionsRoot; + } - public void setAuthor(String author) { - this.author = author; - } + public String getStateRoot() { + return stateRoot; + } - public String getSealer() { - return sealer; - } + public void setStateRoot(String stateRoot) { + this.stateRoot = stateRoot; + } - public void setSealer(String sealer) { - this.sealer = sealer; - } + public String getReceiptsRoot() { + return receiptsRoot; + } - public String getMixHash() { - return mixHash; - } + public void setReceiptsRoot(String receiptsRoot) { + this.receiptsRoot = receiptsRoot; + } - public void setMixHash(String mixHash) { - this.mixHash = mixHash; - } + public String getAuthor() { + return author; + } - public BigInteger getDifficulty() { - return Numeric.decodeQuantity(difficulty); - } + public void setAuthor(String author) { + this.author = author; + } - public String getDifficultyRaw() { - return difficulty; - } + public String getSealer() { + return sealer; + } - public void setDifficulty(String difficulty) { - this.difficulty = difficulty; - } + public void setSealer(String sealer) { + this.sealer = sealer; + } - public BigInteger getTotalDifficulty() { - return Numeric.decodeQuantity(totalDifficulty); - } + public String getMixHash() { + return mixHash; + } - public String getTotalDifficultyRaw() { - return totalDifficulty; - } + public void setMixHash(String mixHash) { + this.mixHash = mixHash; + } - public void setTotalDifficulty(String totalDifficulty) { - this.totalDifficulty = totalDifficulty; - } + public List getExtraData() { + return extraData; + } - public List getExtraData() { - return extraData; - } + public void setExtraData(List extraData) { + this.extraData = extraData; + } - public void setExtraData(List extraData) { - this.extraData = extraData; - } + public BigInteger getGasLimit() { + return Numeric.decodeQuantity(gasLimit); + } - public BigInteger getSize() { - return Numeric.decodeQuantity(size); - } + public String getGasLimitRaw() { + return gasLimit; + } - public String getSizeRaw() { - return size; - } + public void setGasLimit(String gasLimit) { + this.gasLimit = gasLimit; + } - public void setSize(String size) { - this.size = size; - } + public BigInteger getGasUsed() { + return Numeric.decodeQuantity(gasUsed); + } - public BigInteger getGasLimit() { - return Numeric.decodeQuantity(gasLimit); - } + public String getGasUsedRaw() { + return gasUsed; + } - public String getGasLimitRaw() { - return gasLimit; - } + public void setGasUsed(String gasUsed) { + this.gasUsed = gasUsed; + } - public void setGasLimit(String gasLimit) { - this.gasLimit = gasLimit; - } + public BigInteger getTimestamp() { + return Numeric.decodeQuantity(timestamp); + } - public BigInteger getGasUsed() { - return Numeric.decodeQuantity(gasUsed); - } + public String getTimestampRaw() { + return timestamp; + } - public String getGasUsedRaw() { - return gasUsed; - } + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } - public void setGasUsed(String gasUsed) { - this.gasUsed = gasUsed; - } + public List getTransactions() { + return transactions; + } - public BigInteger getTimestamp() { - return Numeric.decodeQuantity(timestamp); - } + @JsonDeserialize(using = ResultTransactionDeserialiser.class) + public void setTransactions(List transactions) { + this.transactions = transactions; + } - public String getTimestampRaw() { - return timestamp; - } + public List getUncles() { + return uncles; + } - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } + public void setUncles(List uncles) { + this.uncles = uncles; + } - public List getTransactions() { - return transactions; - } + public List getSealFields() { + return sealFields; + } - @JsonDeserialize(using = ResultTransactionDeserialiser.class) - public void setTransactions(List transactions) { - this.transactions = transactions; - } + public void setSealFields(List sealFields) { + this.sealFields = sealFields; + } - public List getUncles() { - return uncles; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Block)) { + return false; + } + + Block block = (Block) o; + + if (getNumberRaw() != null + ? !getNumberRaw().equals(block.getNumberRaw()) + : block.getNumberRaw() != null) { + return false; + } + if (getHash() != null ? !getHash().equals(block.getHash()) : block.getHash() != null) { + return false; + } + if (getParentHash() != null + ? !getParentHash().equals(block.getParentHash()) + : block.getParentHash() != null) { + return false; + } + if (getNonceRaw() != null + ? !getNonceRaw().equals(block.getNonceRaw()) + : block.getNonceRaw() != null) { + return false; + } + if (getSha3Uncles() != null + ? !getSha3Uncles().equals(block.getSha3Uncles()) + : block.getSha3Uncles() != null) { + return false; + } + if (getLogsBloom() != null + ? !getLogsBloom().equals(block.getLogsBloom()) + : block.getLogsBloom() != null) { + return false; + } + if (getTransactionsRoot() != null + ? !getTransactionsRoot().equals(block.getTransactionsRoot()) + : block.getTransactionsRoot() != null) { + return false; + } + if (getStateRoot() != null + ? !getStateRoot().equals(block.getStateRoot()) + : block.getStateRoot() != null) { + return false; + } + if (getReceiptsRoot() != null + ? !getReceiptsRoot().equals(block.getReceiptsRoot()) + : block.getReceiptsRoot() != null) { + return false; + } + if (getAuthor() != null + ? !getAuthor().equals(block.getAuthor()) + : block.getAuthor() != null) { + return false; + } + if (getSealer() != null + ? !getSealer().equals(block.getSealer()) + : block.getSealer() != null) { + return false; + } + if (getMixHash() != null + ? !getMixHash().equals(block.getMixHash()) + : block.getMixHash() != null) { + return false; + } + if (getExtraData() != null + ? !getExtraData().equals(block.getExtraData()) + : block.getExtraData() != null) { + return false; + } + if (getGasLimitRaw() != null + ? !getGasLimitRaw().equals(block.getGasLimitRaw()) + : block.getGasLimitRaw() != null) { + return false; + } + if (getGasUsedRaw() != null + ? !getGasUsedRaw().equals(block.getGasUsedRaw()) + : block.getGasUsedRaw() != null) { + return false; + } + if (getTimestampRaw() != null + ? !getTimestampRaw().equals(block.getTimestampRaw()) + : block.getTimestampRaw() != null) { + return false; + } + if (getTransactions() != null + ? !getTransactions().equals(block.getTransactions()) + : block.getTransactions() != null) { + return false; + } + if (getUncles() != null + ? !getUncles().equals(block.getUncles()) + : block.getUncles() != null) { + return false; + } + return getSealFields() != null + ? getSealFields().equals(block.getSealFields()) + : block.getSealFields() == null; + } - public void setUncles(List uncles) { - this.uncles = uncles; + @Override + public int hashCode() { + int result = getNumberRaw() != null ? getNumberRaw().hashCode() : 0; + result = 31 * result + (getHash() != null ? getHash().hashCode() : 0); + result = 31 * result + (getParentHash() != null ? getParentHash().hashCode() : 0); + result = 31 * result + (getNonceRaw() != null ? getNonceRaw().hashCode() : 0); + result = 31 * result + (getSha3Uncles() != null ? getSha3Uncles().hashCode() : 0); + result = 31 * result + (getLogsBloom() != null ? getLogsBloom().hashCode() : 0); + result = + 31 * result + + (getTransactionsRoot() != null + ? getTransactionsRoot().hashCode() + : 0); + result = 31 * result + (getStateRoot() != null ? getStateRoot().hashCode() : 0); + result = 31 * result + (getReceiptsRoot() != null ? getReceiptsRoot().hashCode() : 0); + result = 31 * result + (getAuthor() != null ? getAuthor().hashCode() : 0); + result = 31 * result + (getSealer() != null ? getSealer().hashCode() : 0); + result = 31 * result + (getMixHash() != null ? getMixHash().hashCode() : 0); + result = 31 * result + (getExtraData() != null ? getExtraData().hashCode() : 0); + result = 31 * result + (getGasLimitRaw() != null ? getGasLimitRaw().hashCode() : 0); + result = 31 * result + (getGasUsedRaw() != null ? getGasUsedRaw().hashCode() : 0); + result = 31 * result + (getTimestampRaw() != null ? getTimestampRaw().hashCode() : 0); + result = 31 * result + (getTransactions() != null ? getTransactions().hashCode() : 0); + result = 31 * result + (getUncles() != null ? getUncles().hashCode() : 0); + result = 31 * result + (getSealFields() != null ? getSealFields().hashCode() : 0); + return result; + } } - public List getSealFields() { - return sealFields; + public interface TransactionResult { + T get(); } - public void setSealFields(List sealFields) { - this.sealFields = sealFields; - } + public static class TransactionHash implements TransactionResult { + private String value; - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Block)) { - return false; - } - - Block block = (Block) o; - - if (getNumberRaw() != null - ? !getNumberRaw().equals(block.getNumberRaw()) - : block.getNumberRaw() != null) { - return false; - } - if (getHash() != null ? !getHash().equals(block.getHash()) : block.getHash() != null) { - return false; - } - if (getParentHash() != null - ? !getParentHash().equals(block.getParentHash()) - : block.getParentHash() != null) { - return false; - } - if (getNonceRaw() != null - ? !getNonceRaw().equals(block.getNonceRaw()) - : block.getNonceRaw() != null) { - return false; - } - if (getSha3Uncles() != null - ? !getSha3Uncles().equals(block.getSha3Uncles()) - : block.getSha3Uncles() != null) { - return false; - } - if (getLogsBloom() != null - ? !getLogsBloom().equals(block.getLogsBloom()) - : block.getLogsBloom() != null) { - return false; - } - if (getTransactionsRoot() != null - ? !getTransactionsRoot().equals(block.getTransactionsRoot()) - : block.getTransactionsRoot() != null) { - return false; - } - if (getStateRoot() != null - ? !getStateRoot().equals(block.getStateRoot()) - : block.getStateRoot() != null) { - return false; - } - if (getReceiptsRoot() != null - ? !getReceiptsRoot().equals(block.getReceiptsRoot()) - : block.getReceiptsRoot() != null) { - return false; - } - if (getAuthor() != null - ? !getAuthor().equals(block.getAuthor()) - : block.getAuthor() != null) { - return false; - } - if (getSealer() != null - ? !getSealer().equals(block.getSealer()) - : block.getSealer() != null) { - return false; - } - if (getMixHash() != null - ? !getMixHash().equals(block.getMixHash()) - : block.getMixHash() != null) { - return false; - } - if (getDifficultyRaw() != null - ? !getDifficultyRaw().equals(block.getDifficultyRaw()) - : block.getDifficultyRaw() != null) { - return false; - } - if (getTotalDifficultyRaw() != null - ? !getTotalDifficultyRaw().equals(block.getTotalDifficultyRaw()) - : block.getTotalDifficultyRaw() != null) { - return false; - } - if (getExtraData() != null - ? !getExtraData().equals(block.getExtraData()) - : block.getExtraData() != null) { - return false; - } - if (getSizeRaw() != null - ? !getSizeRaw().equals(block.getSizeRaw()) - : block.getSizeRaw() != null) { - return false; - } - if (getGasLimitRaw() != null - ? !getGasLimitRaw().equals(block.getGasLimitRaw()) - : block.getGasLimitRaw() != null) { - return false; - } - if (getGasUsedRaw() != null - ? !getGasUsedRaw().equals(block.getGasUsedRaw()) - : block.getGasUsedRaw() != null) { - return false; - } - if (getTimestampRaw() != null - ? !getTimestampRaw().equals(block.getTimestampRaw()) - : block.getTimestampRaw() != null) { - return false; - } - if (getTransactions() != null - ? !getTransactions().equals(block.getTransactions()) - : block.getTransactions() != null) { - return false; - } - if (getUncles() != null - ? !getUncles().equals(block.getUncles()) - : block.getUncles() != null) { - return false; - } - return getSealFields() != null - ? getSealFields().equals(block.getSealFields()) - : block.getSealFields() == null; - } + public TransactionHash() {} - @Override - public int hashCode() { - int result = getNumberRaw() != null ? getNumberRaw().hashCode() : 0; - result = 31 * result + (getHash() != null ? getHash().hashCode() : 0); - result = 31 * result + (getParentHash() != null ? getParentHash().hashCode() : 0); - result = 31 * result + (getNonceRaw() != null ? getNonceRaw().hashCode() : 0); - result = 31 * result + (getSha3Uncles() != null ? getSha3Uncles().hashCode() : 0); - result = 31 * result + (getLogsBloom() != null ? getLogsBloom().hashCode() : 0); - result = 31 * result + (getTransactionsRoot() != null ? getTransactionsRoot().hashCode() : 0); - result = 31 * result + (getStateRoot() != null ? getStateRoot().hashCode() : 0); - result = 31 * result + (getReceiptsRoot() != null ? getReceiptsRoot().hashCode() : 0); - result = 31 * result + (getAuthor() != null ? getAuthor().hashCode() : 0); - result = 31 * result + (getSealer() != null ? getSealer().hashCode() : 0); - result = 31 * result + (getMixHash() != null ? getMixHash().hashCode() : 0); - result = 31 * result + (getDifficultyRaw() != null ? getDifficultyRaw().hashCode() : 0); - result = - 31 * result + (getTotalDifficultyRaw() != null ? getTotalDifficultyRaw().hashCode() : 0); - result = 31 * result + (getExtraData() != null ? getExtraData().hashCode() : 0); - result = 31 * result + (getSizeRaw() != null ? getSizeRaw().hashCode() : 0); - result = 31 * result + (getGasLimitRaw() != null ? getGasLimitRaw().hashCode() : 0); - result = 31 * result + (getGasUsedRaw() != null ? getGasUsedRaw().hashCode() : 0); - result = 31 * result + (getTimestampRaw() != null ? getTimestampRaw().hashCode() : 0); - result = 31 * result + (getTransactions() != null ? getTransactions().hashCode() : 0); - result = 31 * result + (getUncles() != null ? getUncles().hashCode() : 0); - result = 31 * result + (getSealFields() != null ? getSealFields().hashCode() : 0); - return result; - } - } + public TransactionHash(String value) { + this.value = value; + } - public interface TransactionResult { - T get(); - } + @Override + public String get() { + return value; + } - public static class TransactionHash implements TransactionResult { - private String value; + public void setValue(String value) { + this.value = value; + } - public TransactionHash() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TransactionHash)) { + return false; + } - public TransactionHash(String value) { - this.value = value; - } + TransactionHash that = (TransactionHash) o; - @Override - public String get() { - return value; - } + return value != null ? value.equals(that.value) : that.value == null; + } - public void setValue(String value) { - this.value = value; + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; + } } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof TransactionHash)) { - return false; - } - - TransactionHash that = (TransactionHash) o; - - return value != null ? value.equals(that.value) : that.value == null; - } + public static class TransactionObject extends Transaction + implements TransactionResult { + public TransactionObject() {} + + public TransactionObject( + String hash, + String nonce, + String blockHash, + String blockNumber, + String transactionIndex, + String from, + String to, + String value, + String gasPrice, + String gas, + String input, + String creates, + String publicKey, + String raw, + String r, + String s, + int v) { + super( + hash, + nonce, + blockHash, + blockNumber, + transactionIndex, + from, + to, + value, + gasPrice, + gas, + input, + creates, + publicKey, + raw, + r, + s, + v); + } - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } - - public static class TransactionObject extends Transaction - implements TransactionResult { - public TransactionObject() {} - - public TransactionObject( - String hash, - String nonce, - String blockHash, - String blockNumber, - String transactionIndex, - String from, - String to, - String value, - String gasPrice, - String gas, - String input, - String creates, - String publicKey, - String raw, - String r, - String s, - int v) { - super( - hash, - nonce, - blockHash, - blockNumber, - transactionIndex, - from, - to, - value, - gasPrice, - gas, - input, - creates, - publicKey, - raw, - r, - s, - v); + @Override + public Transaction get() { + return this; + } } - @Override - public Transaction get() { - return this; - } - } + public static class ResultTransactionDeserialiser + extends JsonDeserializer> { - public static class ResultTransactionDeserialiser - extends JsonDeserializer> { + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + @Override + public List deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { - @Override - public List deserialize( - JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + List transactionResults = new ArrayList<>(); + JsonToken nextToken = jsonParser.nextToken(); - List transactionResults = new ArrayList<>(); - JsonToken nextToken = jsonParser.nextToken(); + if (nextToken == JsonToken.START_OBJECT) { + Iterator transactionObjectIterator = + objectReader.readValues(jsonParser, TransactionObject.class); + while (transactionObjectIterator.hasNext()) { + transactionResults.add(transactionObjectIterator.next()); + } + } else if (nextToken == JsonToken.VALUE_STRING) { + jsonParser.getValueAsString(); - if (nextToken == JsonToken.START_OBJECT) { - Iterator transactionObjectIterator = - objectReader.readValues(jsonParser, TransactionObject.class); - while (transactionObjectIterator.hasNext()) { - transactionResults.add(transactionObjectIterator.next()); - } - } else if (nextToken == JsonToken.VALUE_STRING) { - jsonParser.getValueAsString(); + Iterator transactionHashIterator = + objectReader.readValues(jsonParser, TransactionHash.class); + while (transactionHashIterator.hasNext()) { + transactionResults.add(transactionHashIterator.next()); + } + } - Iterator transactionHashIterator = - objectReader.readValues(jsonParser, TransactionHash.class); - while (transactionHashIterator.hasNext()) { - transactionResults.add(transactionHashIterator.next()); + return transactionResults; } - } - - return transactionResults; } - } - public static class ResponseDeserialiser extends JsonDeserializer { + public static class ResponseDeserialiser extends JsonDeserializer { - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); - @Override - public Block deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { - return objectReader.readValue(jsonParser, Block.class); - } else { - return null; // null is wrapped by Optional in above getter - } + @Override + public Block deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { + return objectReader.readValue(jsonParser, Block.class); + } else { + return null; // null is wrapped by Optional in above getter + } + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosFilter.java index 6f66682e3..33ce48edf 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosFilter.java @@ -6,7 +6,7 @@ /** newBlockFilter */ public class BcosFilter extends Response { - public BigInteger getFilterId() { - return Numeric.decodeQuantity(getResult()); - } + public BigInteger getFilterId() { + return Numeric.decodeQuantity(getResult()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosLog.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosLog.java index 56109bf25..5227f514d 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosLog.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosLog.java @@ -27,118 +27,120 @@ */ public class BcosLog extends Response> { - @Override - @JsonDeserialize(using = LogResultDeserialiser.class) - public void setResult(List result) { - super.setResult(result); - } - - public List getLogs() { - return getResult(); - } - - public interface LogResult { - T get(); - } - - public static class LogObject extends Log implements LogResult { - - public LogObject() {} - - public LogObject( - boolean removed, - String logIndex, - String transactionIndex, - String transactionHash, - String blockHash, - String blockNumber, - String address, - String data, - String type, - List topics) { - super( - removed, - logIndex, - transactionIndex, - transactionHash, - blockHash, - blockNumber, - address, - data, - type, - topics); - } - @Override - public Log get() { - return this; + @JsonDeserialize(using = LogResultDeserialiser.class) + public void setResult(List result) { + super.setResult(result); } - } - - public static class Hash implements LogResult { - private String value; - public Hash() {} - - public Hash(String value) { - this.value = value; + public List getLogs() { + return getResult(); } - @Override - public String get() { - return value; + public interface LogResult { + T get(); } - public void setValue(String value) { - this.value = value; + public static class LogObject extends Log implements LogResult { + + public LogObject() {} + + public LogObject( + boolean removed, + String logIndex, + String transactionIndex, + String transactionHash, + String blockHash, + String blockNumber, + String address, + String data, + String type, + List topics) { + super( + removed, + logIndex, + transactionIndex, + transactionHash, + blockHash, + blockNumber, + address, + data, + type, + topics); + } + + @Override + public Log get() { + return this; + } } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Hash)) { - return false; - } + public static class Hash implements LogResult { + private String value; - Hash hash = (Hash) o; + public Hash() {} - return value != null ? value.equals(hash.value) : hash.value == null; - } + public Hash(String value) { + this.value = value; + } - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } + @Override + public String get() { + return value; + } - public static class LogResultDeserialiser extends JsonDeserializer> { + public void setValue(String value) { + this.value = value; + } - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Hash)) { + return false; + } - @Override - public List deserialize( - JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + Hash hash = (Hash) o; - List logResults = new ArrayList<>(); - JsonToken nextToken = jsonParser.nextToken(); + return value != null ? value.equals(hash.value) : hash.value == null; + } - if (nextToken == JsonToken.START_OBJECT) { - Iterator logObjectIterator = - objectReader.readValues(jsonParser, LogObject.class); - while (logObjectIterator.hasNext()) { - logResults.add(logObjectIterator.next()); + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; } - } else if (nextToken == JsonToken.VALUE_STRING) { - jsonParser.getValueAsString(); + } - Iterator transactionHashIterator = objectReader.readValues(jsonParser, Hash.class); - while (transactionHashIterator.hasNext()) { - logResults.add(transactionHashIterator.next()); + public static class LogResultDeserialiser extends JsonDeserializer> { + + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + + @Override + public List deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + + List logResults = new ArrayList<>(); + JsonToken nextToken = jsonParser.nextToken(); + + if (nextToken == JsonToken.START_OBJECT) { + Iterator logObjectIterator = + objectReader.readValues(jsonParser, LogObject.class); + while (logObjectIterator.hasNext()) { + logResults.add(logObjectIterator.next()); + } + } else if (nextToken == JsonToken.VALUE_STRING) { + jsonParser.getValueAsString(); + + Iterator transactionHashIterator = + objectReader.readValues(jsonParser, Hash.class); + while (transactionHashIterator.hasNext()) { + logResults.add(transactionHashIterator.next()); + } + } + return logResults; } - } - return logResults; } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosSubscribe.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosSubscribe.java index bfd449d4f..7d732a49b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosSubscribe.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosSubscribe.java @@ -3,7 +3,7 @@ import org.fisco.bcos.web3j.protocol.core.Response; public class BcosSubscribe extends Response { - public String getSubscriptionId() { - return getResult(); - } + public String getSubscriptionId() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransaction.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransaction.java index bdfcb94e0..8739d6113 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransaction.java @@ -26,22 +26,23 @@ */ public class BcosTransaction extends Response { - public Optional getTransaction() { - return Optional.ofNullable(getResult()); - } + public Optional getTransaction() { + return Optional.ofNullable(getResult()); + } - public static class ResponseDeserialiser extends JsonDeserializer { + public static class ResponseDeserialiser extends JsonDeserializer { - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); - @Override - public Transaction deserialize( - JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { - if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { - return objectReader.readValue(jsonParser, Transaction.class); - } else { - return null; // null is wrapped by Optional in above getter - } + @Override + public Transaction deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { + return objectReader.readValue(jsonParser, Transaction.class); + } else { + return null; // null is wrapped by Optional in above getter + } + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransactionReceipt.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransactionReceipt.java index a30f2dc6d..f39e00ba1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransactionReceipt.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BcosTransactionReceipt.java @@ -13,22 +13,23 @@ /** getTransactionReceipt. */ public class BcosTransactionReceipt extends Response { - public Optional getTransactionReceipt() { - return Optional.ofNullable(getResult()); - } + public Optional getTransactionReceipt() { + return Optional.ofNullable(getResult()); + } - public static class ResponseDeserialiser extends JsonDeserializer { + public static class ResponseDeserialiser extends JsonDeserializer { - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); - @Override - public TransactionReceipt deserialize( - JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { - if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { - return objectReader.readValue(jsonParser, TransactionReceipt.class); - } else { - return null; // null is wrapped by Optional in above getter - } + @Override + public TransactionReceipt deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + if (jsonParser.getCurrentToken() != JsonToken.VALUE_NULL) { + return objectReader.readValue(jsonParser, TransactionReceipt.class); + } else { + return null; // null is wrapped by Optional in above getter + } + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockHash.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockHash.java index c0c7d9de7..f9da9d142 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockHash.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockHash.java @@ -4,7 +4,7 @@ /** getBlockHashByNumber */ public class BlockHash extends Response { - public String getBlockHashByNumber() { - return getResult(); - } + public String getBlockHashByNumber() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockNumber.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockNumber.java index 2d87aa9e4..d154ffa64 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockNumber.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/BlockNumber.java @@ -6,7 +6,7 @@ /** getblockNumber. */ public class BlockNumber extends Response { - public BigInteger getBlockNumber() { - return Numeric.decodeQuantity(getResult()); - } + public BigInteger getBlockNumber() { + return Numeric.decodeQuantity(getResult()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Call.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Call.java index ddc8f229e..4aeaa4a16 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Call.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Call.java @@ -5,32 +5,41 @@ /** call. */ public class Call extends Response { - public static class CallOutput { - private String currentBlockNumber; - private String output; - - public String getCurrentBlockNumber() { - return currentBlockNumber; - } - - public void setCurrentBlockNumber(String number) { - this.currentBlockNumber = number; + public static class CallOutput { + private String currentBlockNumber; + private String output; + private String status; + + public String getCurrentBlockNumber() { + return currentBlockNumber; + } + + public void setCurrentBlockNumber(String number) { + this.currentBlockNumber = number; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } } - public String getOutput() { - return output; + public CallOutput getValue() { + return getResult(); } - public void setOutput(String output) { - this.output = output; + public void setResult(CallOutput result) { + super.setResult(result); } - } - - public CallOutput getValue() { - return getResult(); - } - - public void setResult(CallOutput result) { - super.setResult(result); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Code.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Code.java index b252f7131..3c5aea1cc 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Code.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Code.java @@ -4,7 +4,7 @@ /** getCode. */ public class Code extends Response { - public String getCode() { - return getResult(); - } + public String getCode() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ConsensusStatus.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ConsensusStatus.java index 184a32c51..c8fe94b8e 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ConsensusStatus.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ConsensusStatus.java @@ -4,7 +4,7 @@ /** getConsensusStatus */ public class ConsensusStatus extends Response { - public String getConsensusStatus() { - return getResult(); - } + public String getConsensusStatus() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupList.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupList.java index c7b071eb2..11dfaefe6 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupList.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupList.java @@ -6,7 +6,7 @@ /** getGroupList */ public class GroupList extends Response> { - public List getGroupList() { - return getResult(); - } + public List getGroupList() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupPeers.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupPeers.java index d6f8d424e..dcac0fbcd 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupPeers.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/GroupPeers.java @@ -5,7 +5,7 @@ /** getGroupPeers */ public class GroupPeers extends Response> { - public List getGroupPeers() { - return getResult(); - } + public List getGroupPeers() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Log.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Log.java index edaa7e0d9..9c732520b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Log.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Log.java @@ -13,206 +13,211 @@ * eth_newPendingTransactionFilter. */ public class Log { - private boolean removed; - private String logIndex; - private String transactionIndex; - private String transactionHash; - private String blockHash; - private String blockNumber; - private String address; - private String data; - private String type; - private List topics; - - public Log() {} - - public Log( - boolean removed, - String logIndex, - String transactionIndex, - String transactionHash, - String blockHash, - String blockNumber, - String address, - String data, - String type, - List topics) { - this.removed = removed; - this.logIndex = logIndex; - this.transactionIndex = transactionIndex; - this.transactionHash = transactionHash; - this.blockHash = blockHash; - this.blockNumber = blockNumber; - this.address = address; - this.data = data; - this.type = type; - this.topics = topics; - } - - public boolean isRemoved() { - return removed; - } - - public void setRemoved(boolean removed) { - this.removed = removed; - } - - public BigInteger getLogIndex() { - return convert(logIndex); - } - - public String getLogIndexRaw() { - return logIndex; - } - - public void setLogIndex(String logIndex) { - this.logIndex = logIndex; - } - - public BigInteger getTransactionIndex() { - return convert(transactionIndex); - } - - public String getTransactionIndexRaw() { - return transactionIndex; - } - - public void setTransactionIndex(String transactionIndex) { - this.transactionIndex = transactionIndex; - } - - public String getTransactionHash() { - return transactionHash; - } - - public void setTransactionHash(String transactionHash) { - this.transactionHash = transactionHash; - } - - public String getBlockHash() { - return blockHash; - } - - public void setBlockHash(String blockHash) { - this.blockHash = blockHash; - } - - public BigInteger getBlockNumber() { - return convert(blockNumber); - } - - public String getBlockNumberRaw() { - return blockNumber; - } - - public void setBlockNumber(String blockNumber) { - this.blockNumber = blockNumber; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getTopics() { - return topics; - } - - public void setTopics(List topics) { - this.topics = topics; - } - - private BigInteger convert(String value) { - if (value != null) { - return Numeric.decodeQuantity(value); - } else { - return null; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Log)) { - return false; - } - - Log log = (Log) o; - - if (isRemoved() != log.isRemoved()) { - return false; - } - if (getLogIndexRaw() != null - ? !getLogIndexRaw().equals(log.getLogIndexRaw()) - : log.getLogIndexRaw() != null) { - return false; - } - if (getTransactionIndexRaw() != null - ? !getTransactionIndexRaw().equals(log.getTransactionIndexRaw()) - : log.getTransactionIndexRaw() != null) { - return false; - } - if (getTransactionHash() != null - ? !getTransactionHash().equals(log.getTransactionHash()) - : log.getTransactionHash() != null) { - return false; - } - if (getBlockHash() != null - ? !getBlockHash().equals(log.getBlockHash()) - : log.getBlockHash() != null) { - return false; - } - if (getBlockNumberRaw() != null - ? !getBlockNumberRaw().equals(log.getBlockNumberRaw()) - : log.getBlockNumberRaw() != null) { - return false; - } - if (getAddress() != null ? !getAddress().equals(log.getAddress()) : log.getAddress() != null) { - return false; - } - if (getData() != null ? !getData().equals(log.getData()) : log.getData() != null) { - return false; - } - if (getType() != null ? !getType().equals(log.getType()) : log.getType() != null) { - return false; - } - return getTopics() != null ? getTopics().equals(log.getTopics()) : log.getTopics() == null; - } - - @Override - public int hashCode() { - int result = (isRemoved() ? 1 : 0); - result = 31 * result + (getLogIndexRaw() != null ? getLogIndexRaw().hashCode() : 0); - result = - 31 * result + (getTransactionIndexRaw() != null ? getTransactionIndexRaw().hashCode() : 0); - result = 31 * result + (getTransactionHash() != null ? getTransactionHash().hashCode() : 0); - result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); - result = 31 * result + (getBlockNumberRaw() != null ? getBlockNumberRaw().hashCode() : 0); - result = 31 * result + (getAddress() != null ? getAddress().hashCode() : 0); - result = 31 * result + (getData() != null ? getData().hashCode() : 0); - result = 31 * result + (getType() != null ? getType().hashCode() : 0); - result = 31 * result + (getTopics() != null ? getTopics().hashCode() : 0); - return result; - } + private boolean removed; + private String logIndex; + private String transactionIndex; + private String transactionHash; + private String blockHash; + private String blockNumber; + private String address; + private String data; + private String type; + private List topics; + + public Log() {} + + public Log( + boolean removed, + String logIndex, + String transactionIndex, + String transactionHash, + String blockHash, + String blockNumber, + String address, + String data, + String type, + List topics) { + this.removed = removed; + this.logIndex = logIndex; + this.transactionIndex = transactionIndex; + this.transactionHash = transactionHash; + this.blockHash = blockHash; + this.blockNumber = blockNumber; + this.address = address; + this.data = data; + this.type = type; + this.topics = topics; + } + + public boolean isRemoved() { + return removed; + } + + public void setRemoved(boolean removed) { + this.removed = removed; + } + + public BigInteger getLogIndex() { + return convert(logIndex); + } + + public String getLogIndexRaw() { + return logIndex; + } + + public void setLogIndex(String logIndex) { + this.logIndex = logIndex; + } + + public BigInteger getTransactionIndex() { + return convert(transactionIndex); + } + + public String getTransactionIndexRaw() { + return transactionIndex; + } + + public void setTransactionIndex(String transactionIndex) { + this.transactionIndex = transactionIndex; + } + + public String getTransactionHash() { + return transactionHash; + } + + public void setTransactionHash(String transactionHash) { + this.transactionHash = transactionHash; + } + + public String getBlockHash() { + return blockHash; + } + + public void setBlockHash(String blockHash) { + this.blockHash = blockHash; + } + + public BigInteger getBlockNumber() { + return convert(blockNumber); + } + + public String getBlockNumberRaw() { + return blockNumber; + } + + public void setBlockNumber(String blockNumber) { + this.blockNumber = blockNumber; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + private BigInteger convert(String value) { + if (value != null) { + return Numeric.decodeQuantity(value); + } else { + return null; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Log)) { + return false; + } + + Log log = (Log) o; + + if (isRemoved() != log.isRemoved()) { + return false; + } + if (getLogIndexRaw() != null + ? !getLogIndexRaw().equals(log.getLogIndexRaw()) + : log.getLogIndexRaw() != null) { + return false; + } + if (getTransactionIndexRaw() != null + ? !getTransactionIndexRaw().equals(log.getTransactionIndexRaw()) + : log.getTransactionIndexRaw() != null) { + return false; + } + if (getTransactionHash() != null + ? !getTransactionHash().equals(log.getTransactionHash()) + : log.getTransactionHash() != null) { + return false; + } + if (getBlockHash() != null + ? !getBlockHash().equals(log.getBlockHash()) + : log.getBlockHash() != null) { + return false; + } + if (getBlockNumberRaw() != null + ? !getBlockNumberRaw().equals(log.getBlockNumberRaw()) + : log.getBlockNumberRaw() != null) { + return false; + } + if (getAddress() != null + ? !getAddress().equals(log.getAddress()) + : log.getAddress() != null) { + return false; + } + if (getData() != null ? !getData().equals(log.getData()) : log.getData() != null) { + return false; + } + if (getType() != null ? !getType().equals(log.getType()) : log.getType() != null) { + return false; + } + return getTopics() != null ? getTopics().equals(log.getTopics()) : log.getTopics() == null; + } + + @Override + public int hashCode() { + int result = (isRemoved() ? 1 : 0); + result = 31 * result + (getLogIndexRaw() != null ? getLogIndexRaw().hashCode() : 0); + result = + 31 * result + + (getTransactionIndexRaw() != null + ? getTransactionIndexRaw().hashCode() + : 0); + result = 31 * result + (getTransactionHash() != null ? getTransactionHash().hashCode() : 0); + result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); + result = 31 * result + (getBlockNumberRaw() != null ? getBlockNumberRaw().hashCode() : 0); + result = 31 * result + (getAddress() != null ? getAddress().hashCode() : 0); + result = 31 * result + (getData() != null ? getData().hashCode() : 0); + result = 31 * result + (getType() != null ? getType().hashCode() : 0); + result = 31 * result + (getTopics() != null ? getTopics().hashCode() : 0); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeIDList.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeIDList.java index b0e2ed085..01a7ffff1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeIDList.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeIDList.java @@ -5,7 +5,7 @@ /** getNodeIDList */ public class NodeIDList extends Response> { - public List getNodeIDList() { - return getResult(); - } + public List getNodeIDList() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeVersion.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeVersion.java index 1ff55957f..dd18792dd 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeVersion.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/NodeVersion.java @@ -1,11 +1,113 @@ package org.fisco.bcos.web3j.protocol.core.methods.response; +import com.fasterxml.jackson.annotation.JsonProperty; import org.fisco.bcos.web3j.protocol.core.Response; /** getNodeVersion. */ -public class NodeVersion extends Response { +public class NodeVersion extends Response { - public String getWeb3ClientVersion() { - return getResult(); - } + public Version getNodeVersion() { + return getResult(); + } + + public static class Version { + @JsonProperty("Build Time") + private String buildTime; + + @JsonProperty("Build Type") + private String buildType; + + @JsonProperty("Chain Id") + private String chainID; + + @JsonProperty("FISCO-BCOS Version") + private String version; + + @JsonProperty("Git Branch") + private String gitBranch; + + @JsonProperty("Git Commit Hash") + private String gitCommit; + + @JsonProperty("Supported Version") + private String supportedVersion; + + public Version() { + super(); + } + + public Version( + String buildTime, + String buildType, + String chainID, + String version, + String gitBranch, + String gitCommit, + String supportedVersion) { + super(); + this.buildTime = buildTime; + this.buildType = buildType; + this.chainID = chainID; + this.version = version; + this.gitBranch = gitBranch; + this.gitCommit = gitCommit; + this.supportedVersion = supportedVersion; + } + + public String getBuildTime() { + return buildTime; + } + + public void setBuildTime(String buildTime) { + this.buildTime = buildTime; + } + + public String getChainID() { + return chainID; + } + + public String getSupportedVersion() { + return supportedVersion; + } + + public void setChainID(String chainID) { + this.chainID = chainID; + } + + public void setSupportedVersion(String supportedVersion) { + this.supportedVersion = supportedVersion; + } + + public String getBuildType() { + return buildType; + } + + public void setBuildType(String buildType) { + this.buildType = buildType; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getGitBranch() { + return gitBranch; + } + + public void setGitBranch(String gitBranch) { + this.gitBranch = gitBranch; + } + + public String getGitCommit() { + return gitCommit; + } + + public void setGitCommit(String gitCommit) { + this.gitCommit = gitCommit; + } + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ObserverList.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ObserverList.java index fd9aa5f93..558f7106d 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ObserverList.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/ObserverList.java @@ -3,10 +3,9 @@ import java.util.List; import org.fisco.bcos.web3j.protocol.core.Response; -/** getGroupList */ public class ObserverList extends Response> { - public List getGroupList() { - return getResult(); - } + public List getObserverList() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PbftView.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PbftView.java index 73fc75298..5a6ae0879 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PbftView.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PbftView.java @@ -7,7 +7,7 @@ /** getPbftView */ public class PbftView extends Response { - public BigInteger getPbftView() { - return Numeric.decodeQuantity(getResult()); - } + public BigInteger getPbftView() { + return Numeric.decodeQuantity(getResult()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Peers.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Peers.java index 3da5f318b..3c0aad31d 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Peers.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Peers.java @@ -7,54 +7,50 @@ /** getPeers */ public class Peers extends Response> { - public List getValue() { - return getResult(); - } - - public void setResult(List result) { - super.setResult(result); - } + public List getPeers() { + return getResult(); + } - public static class Peer { - @JsonProperty("IPAndPort") - private String IPAndPort; + public static class Peer { + @JsonProperty("IPAndPort") + private String IPAndPort; - @JsonProperty("NodeID") - private String nodeID; + @JsonProperty("NodeID") + private String nodeID; - @JsonProperty("Topic") - private List topic; + @JsonProperty("Topic") + private List topic; - public Peer() {} + public Peer() {} - public Peer(String IPAndPort, String nodeID, List topic) { - this.IPAndPort = IPAndPort; - this.nodeID = nodeID; - this.topic = topic; - } + public Peer(String IPAndPort, String nodeID, List topic) { + this.IPAndPort = IPAndPort; + this.nodeID = nodeID; + this.topic = topic; + } - public String getIPAndPort() { - return IPAndPort; - } + public String getIPAndPort() { + return IPAndPort; + } - public void setIPAndPort(String IPAndPort) { - this.IPAndPort = IPAndPort; - } + public void setIPAndPort(String IPAndPort) { + this.IPAndPort = IPAndPort; + } - public String getNodeID() { - return nodeID; - } + public String getNodeID() { + return nodeID; + } - public void setNodeID(String nodeID) { - this.nodeID = nodeID; - } + public void setNodeID(String nodeID) { + this.nodeID = nodeID; + } - public List getTopic() { - return topic; - } + public List getTopic() { + return topic; + } - public void setTopic(List topic) { - this.topic = topic; + public void setTopic(List topic) { + this.topic = topic; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTransactions.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTransactions.java index b774f06b7..f407dba05 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTransactions.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTransactions.java @@ -5,7 +5,7 @@ /** getPendingTransactions */ public class PendingTransactions extends Response> { - public List getPendingTransactions() { - return getResult(); - } + public List getPendingTransactions() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTxSize.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTxSize.java index 9a0a1b41c..42791880f 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTxSize.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/PendingTxSize.java @@ -6,7 +6,7 @@ /** getPendingTxSize */ public class PendingTxSize extends Response { - public BigInteger getPendingTxSize() { - return Numeric.decodeQuantity(getResult()); - } + public BigInteger getPendingTxSize() { + return Numeric.decodeQuantity(getResult()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SealerList.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SealerList.java index 6603d0bb8..a8c6e4ccc 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SealerList.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SealerList.java @@ -3,10 +3,9 @@ import java.util.List; import org.fisco.bcos.web3j.protocol.core.Response; -/** getGroupList */ public class SealerList extends Response> { - public List getGroupList() { - return getResult(); - } + public List getSealerList() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendRawTransaction.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendRawTransaction.java index e957ae1b7..f0733a4a3 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendRawTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendRawTransaction.java @@ -4,7 +4,7 @@ /** sendRawTransaction. */ public class SendRawTransaction extends Response { - public String getTransactionHash() { - return getResult(); - } + public String getTransactionHash() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendTransaction.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendTransaction.java index 90a50bf31..85b51ccc8 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SendTransaction.java @@ -4,7 +4,7 @@ /** sendTransaction. */ public class SendTransaction extends Response { - public String getTransactionHash() { - return getResult(); - } + public String getTransactionHash() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SyncStatus.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SyncStatus.java index 77d427c35..5a4d51a3e 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SyncStatus.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SyncStatus.java @@ -18,145 +18,146 @@ */ public class SyncStatus extends Response { - @Override - @JsonDeserialize(using = SyncStatus.ResponseDeserialiser.class) - public void setResult(SyncStatus.Result result) { - super.setResult(result); - } - - public boolean isSyncing() { - return getResult().isSyncing(); - } - - public static class Result { - private boolean isSyncing = true; - - public Result() {} - - public boolean isSyncing() { - return isSyncing; - } - - public void setSyncing(boolean syncing) { - isSyncing = syncing; - } - } - - @JsonIgnoreProperties({"knownStates", "pulledStates"}) - // these fields although not present in the RPC specification are returned by Geth 1.4.10 - public static class Syncing extends Result { - - private String startingBlock; - private String currentBlock; - private String highestBlock; - private String knownStates; - private String pulledStates; - - public Syncing() {} - - public Syncing( - String startingBlock, - String currentBlock, - String highestBlock, - String knownStates, - String pulledStates) { - this.startingBlock = startingBlock; - this.currentBlock = currentBlock; - this.highestBlock = highestBlock; - this.knownStates = knownStates; - this.pulledStates = pulledStates; - } - - public String getStartingBlock() { - return startingBlock; - } - - public void setStartingBlock(String startingBlock) { - this.startingBlock = startingBlock; + @Override + @JsonDeserialize(using = SyncStatus.ResponseDeserialiser.class) + public void setResult(SyncStatus.Result result) { + super.setResult(result); } - public String getCurrentBlock() { - return currentBlock; + public boolean isSyncing() { + return getResult().isSyncing(); } - public void setCurrentBlock(String currentBlock) { - this.currentBlock = currentBlock; - } + public static class Result { + private boolean isSyncing = true; - public String getHighestBlock() { - return highestBlock; - } + public Result() {} - public void setHighestBlock(String highestBlock) { - this.highestBlock = highestBlock; - } + public boolean isSyncing() { + return isSyncing; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Syncing)) { - return false; - } - - Syncing syncing = (Syncing) o; - - if (isSyncing() != syncing.isSyncing()) { - return false; - } - if (getStartingBlock() != null - ? !getStartingBlock().equals(syncing.getStartingBlock()) - : syncing.getStartingBlock() != null) { - return false; - } - if (getCurrentBlock() != null - ? !getCurrentBlock().equals(syncing.getCurrentBlock()) - : syncing.getCurrentBlock() != null) { - return false; - } - if (getHighestBlock() != null - ? !getHighestBlock().equals(syncing.getHighestBlock()) - : syncing.getHighestBlock() != null) { - return false; - } - if (knownStates != null - ? !knownStates.equals(syncing.knownStates) - : syncing.knownStates != null) { - return false; - } - return pulledStates != null - ? pulledStates.equals(syncing.pulledStates) - : syncing.pulledStates == null; + public void setSyncing(boolean syncing) { + isSyncing = syncing; + } } - @Override - public int hashCode() { - int result = getStartingBlock() != null ? getStartingBlock().hashCode() : 0; - result = 31 * result + Boolean.hashCode(isSyncing()); - result = 31 * result + (getCurrentBlock() != null ? getCurrentBlock().hashCode() : 0); - result = 31 * result + (getHighestBlock() != null ? getHighestBlock().hashCode() : 0); - result = 31 * result + (knownStates != null ? knownStates.hashCode() : 0); - result = 31 * result + (pulledStates != null ? pulledStates.hashCode() : 0); - return result; + @JsonIgnoreProperties({"knownStates", "pulledStates"}) + // these fields although not present in the RPC specification are returned by Geth 1.4.10 + public static class Syncing extends Result { + + private String startingBlock; + private String currentBlock; + private String highestBlock; + private String knownStates; + private String pulledStates; + + public Syncing() {} + + public Syncing( + String startingBlock, + String currentBlock, + String highestBlock, + String knownStates, + String pulledStates) { + this.startingBlock = startingBlock; + this.currentBlock = currentBlock; + this.highestBlock = highestBlock; + this.knownStates = knownStates; + this.pulledStates = pulledStates; + } + + public String getStartingBlock() { + return startingBlock; + } + + public void setStartingBlock(String startingBlock) { + this.startingBlock = startingBlock; + } + + public String getCurrentBlock() { + return currentBlock; + } + + public void setCurrentBlock(String currentBlock) { + this.currentBlock = currentBlock; + } + + public String getHighestBlock() { + return highestBlock; + } + + public void setHighestBlock(String highestBlock) { + this.highestBlock = highestBlock; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Syncing)) { + return false; + } + + Syncing syncing = (Syncing) o; + + if (isSyncing() != syncing.isSyncing()) { + return false; + } + if (getStartingBlock() != null + ? !getStartingBlock().equals(syncing.getStartingBlock()) + : syncing.getStartingBlock() != null) { + return false; + } + if (getCurrentBlock() != null + ? !getCurrentBlock().equals(syncing.getCurrentBlock()) + : syncing.getCurrentBlock() != null) { + return false; + } + if (getHighestBlock() != null + ? !getHighestBlock().equals(syncing.getHighestBlock()) + : syncing.getHighestBlock() != null) { + return false; + } + if (knownStates != null + ? !knownStates.equals(syncing.knownStates) + : syncing.knownStates != null) { + return false; + } + return pulledStates != null + ? pulledStates.equals(syncing.pulledStates) + : syncing.pulledStates == null; + } + + @Override + public int hashCode() { + int result = getStartingBlock() != null ? getStartingBlock().hashCode() : 0; + result = 31 * result + Boolean.hashCode(isSyncing()); + result = 31 * result + (getCurrentBlock() != null ? getCurrentBlock().hashCode() : 0); + result = 31 * result + (getHighestBlock() != null ? getHighestBlock().hashCode() : 0); + result = 31 * result + (knownStates != null ? knownStates.hashCode() : 0); + result = 31 * result + (pulledStates != null ? pulledStates.hashCode() : 0); + return result; + } } - } - - public static class ResponseDeserialiser extends JsonDeserializer { - private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); - - @Override - public Result deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - Result result; - if (jsonParser.getCurrentToken() == JsonToken.VALUE_FALSE) { - result = new Result(); - result.setSyncing(jsonParser.getBooleanValue()); - } else { - result = objectReader.readValue(jsonParser, Syncing.class); - } - return result; + public static class ResponseDeserialiser extends JsonDeserializer { + + private ObjectReader objectReader = ObjectMapperFactory.getObjectReader(); + + @Override + public Result deserialize( + JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + Result result; + if (jsonParser.getCurrentToken() == JsonToken.VALUE_FALSE) { + result = new Result(); + result.setSyncing(jsonParser.getBooleanValue()); + } else { + result = objectReader.readValue(jsonParser, Syncing.class); + } + return result; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SystemConfig.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SystemConfig.java index bb7787d78..d7e9d1236 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SystemConfig.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/SystemConfig.java @@ -4,7 +4,7 @@ /** getSystemConfigByKey */ public class SystemConfig extends Response { - public String getSystemConfigByKey() { - return getResult(); - } + public String getSystemConfigByKey() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TotalTransactionCount.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TotalTransactionCount.java index d1ec0ab56..fbba8334b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TotalTransactionCount.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TotalTransactionCount.java @@ -6,43 +6,43 @@ /** getTotalTransactionCount */ public class TotalTransactionCount extends Response { - public TransactionCount getTotalTransactionCount() { - return getResult(); - } + public TransactionCount getTotalTransactionCount() { + return getResult(); + } - public class TransactionCount { - private String txSum; - private String blockNumber; + public class TransactionCount { + private String txSum; + private String blockNumber; - public TransactionCount() {} + public TransactionCount() {} - public TransactionCount(String txSum, String blockNumber) { - this.txSum = txSum; - this.blockNumber = blockNumber; - } + public TransactionCount(String txSum, String blockNumber) { + this.txSum = txSum; + this.blockNumber = blockNumber; + } - public BigInteger getTxSum() { - return Numeric.decodeQuantity(txSum); - } + public BigInteger getTxSum() { + return Numeric.decodeQuantity(txSum); + } - public String getTxSumRaw() { - return txSum; - } + public String getTxSumRaw() { + return txSum; + } - public void setTxSum(String txSum) { - this.txSum = txSum; - } + public void setTxSum(String txSum) { + this.txSum = txSum; + } - public BigInteger getBlockNumber() { - return Numeric.decodeQuantity(blockNumber); - } + public BigInteger getBlockNumber() { + return Numeric.decodeQuantity(blockNumber); + } - public String getBlockNumberRaw() { - return blockNumber; - } + public String getBlockNumberRaw() { + return blockNumber; + } - public void setBlockNumber(String blockNumber) { - this.blockNumber = blockNumber; + public void setBlockNumber(String blockNumber) { + this.blockNumber = blockNumber; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Transaction.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Transaction.java index 849a2478a..bca051f76 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Transaction.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/Transaction.java @@ -5,332 +5,337 @@ /** Transaction object used by both {@link BcosTransaction} and {@link BcosBlock}. */ public class Transaction { - private String hash; - private String nonce; - private String blockHash; - private String blockNumber; - private String transactionIndex; - private String from; - private String to; - private String value; - private String gasPrice; - private String gas; - private String input; - private String creates; - private String publicKey; - private String raw; - private String r; - private String s; - private int v; // see https://github.com/web3j/web3j/issues/44 - - public Transaction() {} - - public Transaction( - String hash, - String nonce, - String blockHash, - String blockNumber, - String transactionIndex, - String from, - String to, - String value, - String gas, - String gasPrice, - String input, - String creates, - String publicKey, - String raw, - String r, - String s, - int v) { - this.hash = hash; - this.nonce = nonce; - this.blockHash = blockHash; - this.blockNumber = blockNumber; - this.transactionIndex = transactionIndex; - this.from = from; - this.to = to; - this.value = value; - this.gasPrice = gasPrice; - this.gas = gas; - this.input = input; - this.creates = creates; - this.publicKey = publicKey; - this.raw = raw; - this.r = r; - this.s = s; - this.v = v; - } - - public String getHash() { - return hash; - } - - public void setHash(String hash) { - this.hash = hash; - } - - public BigInteger getNonce() { - return Numeric.decodeQuantity(nonce); - } - - public String getNonceRaw() { - return nonce; - } - - public void setNonce(String nonce) { - this.nonce = nonce; - } - - public String getBlockHash() { - return blockHash; - } - - public void setBlockHash(String blockHash) { - this.blockHash = blockHash; - } - - public BigInteger getBlockNumber() { - return Numeric.decodeQuantity(blockNumber); - } - - public String getBlockNumberRaw() { - return blockNumber; - } - - public void setBlockNumber(String blockNumber) { - this.blockNumber = blockNumber; - } - - public BigInteger getTransactionIndex() { - return Numeric.decodeQuantity(transactionIndex); - } - - public String getTransactionIndexRaw() { - return transactionIndex; - } - - public void setTransactionIndex(String transactionIndex) { - this.transactionIndex = transactionIndex; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public BigInteger getValue() { - return Numeric.decodeQuantity(value); - } - - public String getValueRaw() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public BigInteger getGasPrice() { - return Numeric.decodeQuantity(gasPrice); - } - - public String getGasPriceRaw() { - return gasPrice; - } - - public void setGasPrice(String gasPrice) { - this.gasPrice = gasPrice; - } - - public BigInteger getGas() { - return Numeric.decodeQuantity(gas); - } + private String hash; + private String nonce; + private String blockHash; + private String blockNumber; + private String transactionIndex; + private String from; + private String to; + private String value; + private String gasPrice; + private String gas; + private String input; + private String creates; + private String publicKey; + private String raw; + private String r; + private String s; + private int v; // see https://github.com/web3j/web3j/issues/44 + + public Transaction() {} + + public Transaction( + String hash, + String nonce, + String blockHash, + String blockNumber, + String transactionIndex, + String from, + String to, + String value, + String gas, + String gasPrice, + String input, + String creates, + String publicKey, + String raw, + String r, + String s, + int v) { + this.hash = hash; + this.nonce = nonce; + this.blockHash = blockHash; + this.blockNumber = blockNumber; + this.transactionIndex = transactionIndex; + this.from = from; + this.to = to; + this.value = value; + this.gasPrice = gasPrice; + this.gas = gas; + this.input = input; + this.creates = creates; + this.publicKey = publicKey; + this.raw = raw; + this.r = r; + this.s = s; + this.v = v; + } - public String getGasRaw() { - return gas; - } + public String getHash() { + return hash; + } - public void setGas(String gas) { - this.gas = gas; - } + public void setHash(String hash) { + this.hash = hash; + } - public String getInput() { - return input; - } + public BigInteger getNonce() { + return Numeric.decodeQuantity(nonce); + } - public void setInput(String input) { - this.input = input; - } + public String getNonceRaw() { + return nonce; + } - public String getCreates() { - return creates; - } + public void setNonce(String nonce) { + this.nonce = nonce; + } + + public String getBlockHash() { + return blockHash; + } - public void setCreates(String creates) { - this.creates = creates; - } + public void setBlockHash(String blockHash) { + this.blockHash = blockHash; + } - public String getPublicKey() { - return publicKey; - } + public BigInteger getBlockNumber() { + return Numeric.decodeQuantity(blockNumber); + } - public void setPublicKey(String publicKey) { - this.publicKey = publicKey; - } + public String getBlockNumberRaw() { + return blockNumber; + } - public String getRaw() { - return raw; - } + public void setBlockNumber(String blockNumber) { + this.blockNumber = blockNumber; + } - public void setRaw(String raw) { - this.raw = raw; - } + public BigInteger getTransactionIndex() { + return Numeric.decodeQuantity(transactionIndex); + } - public String getR() { - return r; - } + public String getTransactionIndexRaw() { + return transactionIndex; + } - public void setR(String r) { - this.r = r; - } + public void setTransactionIndex(String transactionIndex) { + this.transactionIndex = transactionIndex; + } - public String getS() { - return s; - } + public String getFrom() { + return from; + } - public void setS(String s) { - this.s = s; - } + public void setFrom(String from) { + this.from = from; + } - public int getV() { - return v; - } + public String getTo() { + return to; + } - // public void setV(byte v) { - // this.v = v; - // } - - // Workaround until Geth & Parity return consistent values. At present - // Parity returns a byte value, Geth returns a hex-encoded string - // https://github.com/ethereum/go-ethereum/issues/3339 - public void setV(Object v) { - if (v instanceof String) { - this.v = Numeric.toBigInt((String) v).intValueExact(); - } else { - this.v = ((Integer) v); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Transaction)) { - return false; - } - - Transaction that = (Transaction) o; - - if (getV() != that.getV()) { - return false; - } - if (getHash() != null ? !getHash().equals(that.getHash()) : that.getHash() != null) { - return false; - } - if (getNonceRaw() != null - ? !getNonceRaw().equals(that.getNonceRaw()) - : that.getNonceRaw() != null) { - return false; - } - if (getBlockHash() != null - ? !getBlockHash().equals(that.getBlockHash()) - : that.getBlockHash() != null) { - return false; - } - if (getBlockNumberRaw() != null - ? !getBlockNumberRaw().equals(that.getBlockNumberRaw()) - : that.getBlockNumberRaw() != null) { - return false; - } - if (getTransactionIndexRaw() != null - ? !getTransactionIndexRaw().equals(that.getTransactionIndexRaw()) - : that.getTransactionIndexRaw() != null) { - return false; - } - if (getFrom() != null ? !getFrom().equals(that.getFrom()) : that.getFrom() != null) { - return false; - } - if (getTo() != null ? !getTo().equals(that.getTo()) : that.getTo() != null) { - return false; - } - if (getValueRaw() != null - ? !getValueRaw().equals(that.getValueRaw()) - : that.getValueRaw() != null) { - return false; - } - if (getGasPriceRaw() != null - ? !getGasPriceRaw().equals(that.getGasPriceRaw()) - : that.getGasPriceRaw() != null) { - return false; - } - if (getGasRaw() != null ? !getGasRaw().equals(that.getGasRaw()) : that.getGasRaw() != null) { - return false; - } - if (getInput() != null ? !getInput().equals(that.getInput()) : that.getInput() != null) { - return false; - } - if (getCreates() != null - ? !getCreates().equals(that.getCreates()) - : that.getCreates() != null) { - return false; - } - if (getPublicKey() != null - ? !getPublicKey().equals(that.getPublicKey()) - : that.getPublicKey() != null) { - return false; - } - if (getRaw() != null ? !getRaw().equals(that.getRaw()) : that.getRaw() != null) { - return false; - } - if (getR() != null ? !getR().equals(that.getR()) : that.getR() != null) { - return false; - } - return getS() != null ? getS().equals(that.getS()) : that.getS() == null; - } - - @Override - public int hashCode() { - int result = getHash() != null ? getHash().hashCode() : 0; - result = 31 * result + (getNonceRaw() != null ? getNonceRaw().hashCode() : 0); - result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); - result = 31 * result + (getBlockNumberRaw() != null ? getBlockNumberRaw().hashCode() : 0); - result = - 31 * result + (getTransactionIndexRaw() != null ? getTransactionIndexRaw().hashCode() : 0); - result = 31 * result + (getFrom() != null ? getFrom().hashCode() : 0); - result = 31 * result + (getTo() != null ? getTo().hashCode() : 0); - result = 31 * result + (getValueRaw() != null ? getValueRaw().hashCode() : 0); - result = 31 * result + (getGasPriceRaw() != null ? getGasPriceRaw().hashCode() : 0); - result = 31 * result + (getGasRaw() != null ? getGasRaw().hashCode() : 0); - result = 31 * result + (getInput() != null ? getInput().hashCode() : 0); - result = 31 * result + (getCreates() != null ? getCreates().hashCode() : 0); - result = 31 * result + (getPublicKey() != null ? getPublicKey().hashCode() : 0); - result = 31 * result + (getRaw() != null ? getRaw().hashCode() : 0); - result = 31 * result + (getR() != null ? getR().hashCode() : 0); - result = 31 * result + (getS() != null ? getS().hashCode() : 0); - result = 31 * result + getV(); - return result; - } + public void setTo(String to) { + this.to = to; + } + + public BigInteger getValue() { + return Numeric.decodeQuantity(value); + } + + public String getValueRaw() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public BigInteger getGasPrice() { + return Numeric.decodeQuantity(gasPrice); + } + + public String getGasPriceRaw() { + return gasPrice; + } + + public void setGasPrice(String gasPrice) { + this.gasPrice = gasPrice; + } + + public BigInteger getGas() { + return Numeric.decodeQuantity(gas); + } + + public String getGasRaw() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getInput() { + return input; + } + + public void setInput(String input) { + this.input = input; + } + + public String getCreates() { + return creates; + } + + public void setCreates(String creates) { + this.creates = creates; + } + + public String getPublicKey() { + return publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public String getRaw() { + return raw; + } + + public void setRaw(String raw) { + this.raw = raw; + } + + public String getR() { + return r; + } + + public void setR(String r) { + this.r = r; + } + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } + + public int getV() { + return v; + } + + // public void setV(byte v) { + // this.v = v; + // } + + // Workaround until Geth & Parity return consistent values. At present + // Parity returns a byte value, Geth returns a hex-encoded string + // https://github.com/ethereum/go-ethereum/issues/3339 + public void setV(Object v) { + if (v instanceof String) { + this.v = Numeric.toBigInt((String) v).intValueExact(); + } else { + this.v = ((Integer) v); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Transaction)) { + return false; + } + + Transaction that = (Transaction) o; + + if (getV() != that.getV()) { + return false; + } + if (getHash() != null ? !getHash().equals(that.getHash()) : that.getHash() != null) { + return false; + } + if (getNonceRaw() != null + ? !getNonceRaw().equals(that.getNonceRaw()) + : that.getNonceRaw() != null) { + return false; + } + if (getBlockHash() != null + ? !getBlockHash().equals(that.getBlockHash()) + : that.getBlockHash() != null) { + return false; + } + if (getBlockNumberRaw() != null + ? !getBlockNumberRaw().equals(that.getBlockNumberRaw()) + : that.getBlockNumberRaw() != null) { + return false; + } + if (getTransactionIndexRaw() != null + ? !getTransactionIndexRaw().equals(that.getTransactionIndexRaw()) + : that.getTransactionIndexRaw() != null) { + return false; + } + if (getFrom() != null ? !getFrom().equals(that.getFrom()) : that.getFrom() != null) { + return false; + } + if (getTo() != null ? !getTo().equals(that.getTo()) : that.getTo() != null) { + return false; + } + if (getValueRaw() != null + ? !getValueRaw().equals(that.getValueRaw()) + : that.getValueRaw() != null) { + return false; + } + if (getGasPriceRaw() != null + ? !getGasPriceRaw().equals(that.getGasPriceRaw()) + : that.getGasPriceRaw() != null) { + return false; + } + if (getGasRaw() != null + ? !getGasRaw().equals(that.getGasRaw()) + : that.getGasRaw() != null) { + return false; + } + if (getInput() != null ? !getInput().equals(that.getInput()) : that.getInput() != null) { + return false; + } + if (getCreates() != null + ? !getCreates().equals(that.getCreates()) + : that.getCreates() != null) { + return false; + } + if (getPublicKey() != null + ? !getPublicKey().equals(that.getPublicKey()) + : that.getPublicKey() != null) { + return false; + } + if (getRaw() != null ? !getRaw().equals(that.getRaw()) : that.getRaw() != null) { + return false; + } + if (getR() != null ? !getR().equals(that.getR()) : that.getR() != null) { + return false; + } + return getS() != null ? getS().equals(that.getS()) : that.getS() == null; + } + + @Override + public int hashCode() { + int result = getHash() != null ? getHash().hashCode() : 0; + result = 31 * result + (getNonceRaw() != null ? getNonceRaw().hashCode() : 0); + result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); + result = 31 * result + (getBlockNumberRaw() != null ? getBlockNumberRaw().hashCode() : 0); + result = + 31 * result + + (getTransactionIndexRaw() != null + ? getTransactionIndexRaw().hashCode() + : 0); + result = 31 * result + (getFrom() != null ? getFrom().hashCode() : 0); + result = 31 * result + (getTo() != null ? getTo().hashCode() : 0); + result = 31 * result + (getValueRaw() != null ? getValueRaw().hashCode() : 0); + result = 31 * result + (getGasPriceRaw() != null ? getGasPriceRaw().hashCode() : 0); + result = 31 * result + (getGasRaw() != null ? getGasRaw().hashCode() : 0); + result = 31 * result + (getInput() != null ? getInput().hashCode() : 0); + result = 31 * result + (getCreates() != null ? getCreates().hashCode() : 0); + result = 31 * result + (getPublicKey() != null ? getPublicKey().hashCode() : 0); + result = 31 * result + (getRaw() != null ? getRaw().hashCode() : 0); + result = 31 * result + (getR() != null ? getR().hashCode() : 0); + result = 31 * result + (getS() != null ? getS().hashCode() : 0); + result = 31 * result + getV(); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TransactionReceipt.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TransactionReceipt.java index d6746cb7f..3dadc75a7 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TransactionReceipt.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/TransactionReceipt.java @@ -6,320 +6,302 @@ /** TransactionReceipt object used by {@link BcosTransactionReceipt}. */ public class TransactionReceipt { - private String transactionHash; - private String transactionIndex; - private String blockHash; - private String blockNumber; - private String cumulativeGasUsed; - private String gasUsed; - private String contractAddress; - private String root; - // status is only present on Byzantium transactions onwards - // see EIP 658 https://github.com/ethereum/EIPs/pull/658 - private String status; - private String from; - private String to; - private String output; - private List logs; - private String logsBloom; - - public TransactionReceipt() {} - - public TransactionReceipt( - String transactionHash, - String transactionIndex, - String blockHash, - String blockNumber, - String cumulativeGasUsed, - String gasUsed, - String contractAddress, - String root, - String status, - String from, - String to, - String output, - List logs, - String logsBloom) { - this.transactionHash = transactionHash; - this.transactionIndex = transactionIndex; - this.blockHash = blockHash; - this.blockNumber = blockNumber; - this.cumulativeGasUsed = cumulativeGasUsed; - this.gasUsed = gasUsed; - this.contractAddress = contractAddress; - this.root = root; - this.status = status; - this.from = from; - this.to = to; - this.output = output; - this.logs = logs; - this.logsBloom = logsBloom; - } - - public String getTransactionHash() { - return transactionHash; - } - - public void setTransactionHash(String transactionHash) { - this.transactionHash = transactionHash; - } - - public BigInteger getTransactionIndex() { - return Numeric.decodeQuantity(transactionIndex); - } - - public String getTransactionIndexRaw() { - return transactionIndex; - } - - public void setTransactionIndex(String transactionIndex) { - this.transactionIndex = transactionIndex; - } - - public String getBlockHash() { - return blockHash; - } - - public void setBlockHash(String blockHash) { - this.blockHash = blockHash; - } - - public BigInteger getBlockNumber() { - return Numeric.decodeQuantity(blockNumber); - } - - public String getBlockNumberRaw() { - return blockNumber; - } - - public String getOutput() { - return output; - } - - public void setOutput(String output) { - this.output = output; - } - - public void setBlockNumber(String blockNumber) { - this.blockNumber = blockNumber; - } - - public BigInteger getCumulativeGasUsed() { - return Numeric.decodeQuantity(cumulativeGasUsed); - } - - public String getCumulativeGasUsedRaw() { - return cumulativeGasUsed; - } - - public void setCumulativeGasUsed(String cumulativeGasUsed) { - this.cumulativeGasUsed = cumulativeGasUsed; - } - - public BigInteger getGasUsed() { - return Numeric.decodeQuantity(gasUsed); - } - - public String getGasUsedRaw() { - return gasUsed; - } - - public void setGasUsed(String gasUsed) { - this.gasUsed = gasUsed; - } - - public String getContractAddress() { - return contractAddress; - } - - public void setContractAddress(String contractAddress) { - this.contractAddress = contractAddress; - } - - public String getRoot() { - return root; - } - - public void setRoot(String root) { - this.root = root; - } - - public String getStatus() { - return status; - } + private String transactionHash; + private String transactionIndex; + private String blockHash; + private String blockNumber; + private String gasUsed; + private String contractAddress; + private String root; + // status is only present on Byzantium transactions onwards + // see EIP 658 https://github.com/ethereum/EIPs/pull/658 + private String status; + private String from; + private String to; + private String output; + private List logs; + private String logsBloom; + + public TransactionReceipt() {} + + public TransactionReceipt( + String transactionHash, + String transactionIndex, + String blockHash, + String blockNumber, + String gasUsed, + String contractAddress, + String root, + String status, + String from, + String to, + String output, + List logs, + String logsBloom) { + this.transactionHash = transactionHash; + this.transactionIndex = transactionIndex; + this.blockHash = blockHash; + this.blockNumber = blockNumber; + this.gasUsed = gasUsed; + this.contractAddress = contractAddress; + this.root = root; + this.status = status; + this.from = from; + this.to = to; + this.output = output; + this.logs = logs; + this.logsBloom = logsBloom; + } + + public String getTransactionHash() { + return transactionHash; + } + + public void setTransactionHash(String transactionHash) { + this.transactionHash = transactionHash; + } + + public BigInteger getTransactionIndex() { + return Numeric.decodeQuantity(transactionIndex); + } + + public String getTransactionIndexRaw() { + return transactionIndex; + } + + public void setTransactionIndex(String transactionIndex) { + this.transactionIndex = transactionIndex; + } + + public String getBlockHash() { + return blockHash; + } - public void setStatus(String status) { - this.status = status; - } + public void setBlockHash(String blockHash) { + this.blockHash = blockHash; + } - public boolean isStatusOK() { - if (null == status) { - return true; + public BigInteger getBlockNumber() { + return Numeric.decodeQuantity(blockNumber); } - BigInteger statusQuantity = Numeric.decodeQuantity(status); - return BigInteger.ZERO.equals(statusQuantity); - } - public String getFrom() { - return from; - } + public String getBlockNumberRaw() { + return blockNumber; + } - public void setFrom(String from) { - this.from = from; - } + public String getOutput() { + return output; + } - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public List getLogs() { - return logs; - } - - public void setLogs(List logs) { - this.logs = logs; - } - - public String getLogsBloom() { - return logsBloom; - } - - public void setLogsBloom(String logsBloom) { - this.logsBloom = logsBloom; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof TransactionReceipt)) { - return false; - } - - TransactionReceipt that = (TransactionReceipt) o; - - if (getTransactionHash() != null - ? !getTransactionHash().equals(that.getTransactionHash()) - : that.getTransactionHash() != null) { - return false; - } - if (transactionIndex != null - ? !transactionIndex.equals(that.transactionIndex) - : that.transactionIndex != null) { - return false; - } - if (getBlockHash() != null - ? !getBlockHash().equals(that.getBlockHash()) - : that.getBlockHash() != null) { - return false; - } - if (blockNumber != null ? !blockNumber.equals(that.blockNumber) : that.blockNumber != null) { - return false; - } - if (cumulativeGasUsed != null - ? !cumulativeGasUsed.equals(that.cumulativeGasUsed) - : that.cumulativeGasUsed != null) { - return false; - } - if (gasUsed != null ? !gasUsed.equals(that.gasUsed) : that.gasUsed != null) { - return false; - } - if (getContractAddress() != null - ? !getContractAddress().equals(that.getContractAddress()) - : that.getContractAddress() != null) { - return false; - } - if (getRoot() != null ? !getRoot().equals(that.getRoot()) : that.getRoot() != null) { - return false; - } - if (getStatus() != null ? !getStatus().equals(that.getStatus()) : that.getStatus() != null) { - return false; - } - if (getFrom() != null ? !getFrom().equals(that.getFrom()) : that.getFrom() != null) { - return false; - } - if (getTo() != null ? !getTo().equals(that.getTo()) : that.getTo() != null) { - return false; - } - if (getLogs() != null ? !getLogs().equals(that.getLogs()) : that.getLogs() != null) { - return false; - } - if (getOutput() != null ? !getOutput().equals(that.getOutput()) : that.getOutput() != null) { - return false; - } - return getLogsBloom() != null - ? getLogsBloom().equals(that.getLogsBloom()) - : that.getLogsBloom() == null; - } - - @Override - public int hashCode() { - int result = getTransactionHash() != null ? getTransactionHash().hashCode() : 0; - result = 31 * result + (transactionIndex != null ? transactionIndex.hashCode() : 0); - result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); - result = 31 * result + (blockNumber != null ? blockNumber.hashCode() : 0); - result = 31 * result + (cumulativeGasUsed != null ? cumulativeGasUsed.hashCode() : 0); - result = 31 * result + (gasUsed != null ? gasUsed.hashCode() : 0); - result = 31 * result + (getContractAddress() != null ? getContractAddress().hashCode() : 0); - result = 31 * result + (getRoot() != null ? getRoot().hashCode() : 0); - result = 31 * result + (getStatus() != null ? getStatus().hashCode() : 0); - result = 31 * result + (getFrom() != null ? getFrom().hashCode() : 0); - result = 31 * result + (getTo() != null ? getTo().hashCode() : 0); - result = 31 * result + (getOutput() != null ? getOutput().hashCode() : 0); - result = 31 * result + (getLogs() != null ? getLogs().hashCode() : 0); - result = 31 * result + (getLogsBloom() != null ? getLogsBloom().hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "TransactionReceipt{" - + "transactionHash='" - + transactionHash - + '\'' - + ", transactionIndex='" - + transactionIndex - + '\'' - + ", blockHash='" - + blockHash - + '\'' - + ", blockNumber='" - + blockNumber - + '\'' - + ", cumulativeGasUsed='" - + cumulativeGasUsed - + '\'' - + ", gasUsed='" - + gasUsed - + '\'' - + ", contractAddress='" - + contractAddress - + '\'' - + ", root='" - + root - + '\'' - + ", status='" - + status - + '\'' - + ", from='" - + from - + '\'' - + ", to='" - + to - + '\'' - + ", output='" - + output - + '\'' - + ", logs=" - + logs - + ", logsBloom='" - + logsBloom - + '\'' - + '}'; - } + public void setOutput(String output) { + this.output = output; + } + + public void setBlockNumber(String blockNumber) { + this.blockNumber = blockNumber; + } + + public BigInteger getGasUsed() { + return Numeric.decodeQuantity(gasUsed); + } + + public String getGasUsedRaw() { + return gasUsed; + } + + public void setGasUsed(String gasUsed) { + this.gasUsed = gasUsed; + } + + public String getContractAddress() { + return contractAddress; + } + + public void setContractAddress(String contractAddress) { + this.contractAddress = contractAddress; + } + + public String getRoot() { + return root; + } + + public void setRoot(String root) { + this.root = root; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public boolean isStatusOK() { + if (null == status) { + return true; + } + BigInteger statusQuantity = Numeric.decodeQuantity(status); + return BigInteger.ZERO.equals(statusQuantity); + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + public List getLogs() { + return logs; + } + + public void setLogs(List logs) { + this.logs = logs; + } + + public String getLogsBloom() { + return logsBloom; + } + + public void setLogsBloom(String logsBloom) { + this.logsBloom = logsBloom; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TransactionReceipt)) { + return false; + } + + TransactionReceipt that = (TransactionReceipt) o; + + if (getTransactionHash() != null + ? !getTransactionHash().equals(that.getTransactionHash()) + : that.getTransactionHash() != null) { + return false; + } + if (transactionIndex != null + ? !transactionIndex.equals(that.transactionIndex) + : that.transactionIndex != null) { + return false; + } + if (getBlockHash() != null + ? !getBlockHash().equals(that.getBlockHash()) + : that.getBlockHash() != null) { + return false; + } + if (blockNumber != null + ? !blockNumber.equals(that.blockNumber) + : that.blockNumber != null) { + return false; + } + if (gasUsed != null ? !gasUsed.equals(that.gasUsed) : that.gasUsed != null) { + return false; + } + if (getContractAddress() != null + ? !getContractAddress().equals(that.getContractAddress()) + : that.getContractAddress() != null) { + return false; + } + if (getRoot() != null ? !getRoot().equals(that.getRoot()) : that.getRoot() != null) { + return false; + } + if (getStatus() != null + ? !getStatus().equals(that.getStatus()) + : that.getStatus() != null) { + return false; + } + if (getFrom() != null ? !getFrom().equals(that.getFrom()) : that.getFrom() != null) { + return false; + } + if (getTo() != null ? !getTo().equals(that.getTo()) : that.getTo() != null) { + return false; + } + if (getLogs() != null ? !getLogs().equals(that.getLogs()) : that.getLogs() != null) { + return false; + } + if (getOutput() != null + ? !getOutput().equals(that.getOutput()) + : that.getOutput() != null) { + return false; + } + return getLogsBloom() != null + ? getLogsBloom().equals(that.getLogsBloom()) + : that.getLogsBloom() == null; + } + + @Override + public int hashCode() { + int result = getTransactionHash() != null ? getTransactionHash().hashCode() : 0; + result = 31 * result + (transactionIndex != null ? transactionIndex.hashCode() : 0); + result = 31 * result + (getBlockHash() != null ? getBlockHash().hashCode() : 0); + result = 31 * result + (blockNumber != null ? blockNumber.hashCode() : 0); + result = 31 * result + (gasUsed != null ? gasUsed.hashCode() : 0); + result = 31 * result + (getContractAddress() != null ? getContractAddress().hashCode() : 0); + result = 31 * result + (getRoot() != null ? getRoot().hashCode() : 0); + result = 31 * result + (getStatus() != null ? getStatus().hashCode() : 0); + result = 31 * result + (getFrom() != null ? getFrom().hashCode() : 0); + result = 31 * result + (getTo() != null ? getTo().hashCode() : 0); + result = 31 * result + (getOutput() != null ? getOutput().hashCode() : 0); + result = 31 * result + (getLogs() != null ? getLogs().hashCode() : 0); + result = 31 * result + (getLogsBloom() != null ? getLogsBloom().hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "TransactionReceipt{" + + "transactionHash='" + + transactionHash + + '\'' + + ", transactionIndex='" + + transactionIndex + + '\'' + + ", blockHash='" + + blockHash + + '\'' + + ", blockNumber='" + + blockNumber + + '\'' + + ", gasUsed='" + + gasUsed + + '\'' + + ", contractAddress='" + + contractAddress + + '\'' + + ", root='" + + root + + '\'' + + ", status='" + + status + + '\'' + + ", from='" + + from + + '\'' + + ", to='" + + to + + '\'' + + ", output='" + + output + + '\'' + + ", logs=" + + logs + + ", logsBloom='" + + logsBloom + + '\'' + + '}'; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/UninstallFilter.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/UninstallFilter.java index f0b3a2e6c..ca71e5729 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/UninstallFilter.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/UninstallFilter.java @@ -4,7 +4,7 @@ /** getUninstallFilter */ public class UninstallFilter extends Response { - public boolean isUninstalled() { - return getResult(); - } + public boolean isUninstalled() { + return getResult(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/VoidResponse.java b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/VoidResponse.java index fc289299e..38a870836 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/VoidResponse.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/core/methods/response/VoidResponse.java @@ -11,7 +11,7 @@ * */ public class VoidResponse extends Response { - public boolean isValid() { - return !hasError(); - } + public boolean isValid() { + return !hasError(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/KeepAsJsonDeserialzier.java b/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/KeepAsJsonDeserialzier.java index 7b97fb247..815961af3 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/KeepAsJsonDeserialzier.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/KeepAsJsonDeserialzier.java @@ -9,11 +9,11 @@ public class KeepAsJsonDeserialzier extends JsonDeserializer { - @Override - public String deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException { + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { - TreeNode tree = jp.getCodec().readTree(jp); - return tree.toString(); - } + TreeNode tree = jp.getCodec().readTree(jp); + return tree.toString(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/RawResponseDeserializer.java b/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/RawResponseDeserializer.java index 231ccb473..7085274aa 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/RawResponseDeserializer.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/deserializer/RawResponseDeserializer.java @@ -14,43 +14,43 @@ /** A jackson deserializer that sets the rawResponse variable of Response objects. */ public class RawResponseDeserializer extends StdDeserializer - implements ResolvableDeserializer { + implements ResolvableDeserializer { - private final JsonDeserializer defaultDeserializer; + private final JsonDeserializer defaultDeserializer; - public RawResponseDeserializer(JsonDeserializer defaultDeserializer) { - super(Response.class); - this.defaultDeserializer = defaultDeserializer; - } + public RawResponseDeserializer(JsonDeserializer defaultDeserializer) { + super(Response.class); + this.defaultDeserializer = defaultDeserializer; + } - @Override - public Response deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - Response deserializedResponse = (Response) defaultDeserializer.deserialize(jp, ctxt); + @Override + public Response deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + Response deserializedResponse = (Response) defaultDeserializer.deserialize(jp, ctxt); - deserializedResponse.setRawResponse(getRawResponse(jp)); - return deserializedResponse; - } + deserializedResponse.setRawResponse(getRawResponse(jp)); + return deserializedResponse; + } - // Must implement ResolvableDeserializer when modifying BeanDeserializer - // otherwise deserializing throws JsonMappingException - @Override - public void resolve(DeserializationContext ctxt) throws JsonMappingException { - ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt); - } + // Must implement ResolvableDeserializer when modifying BeanDeserializer + // otherwise deserializing throws JsonMappingException + @Override + public void resolve(DeserializationContext ctxt) throws JsonMappingException { + ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt); + } - private String getRawResponse(JsonParser jp) throws IOException { - final InputStream inputSource = (InputStream) jp.getInputSource(); + private String getRawResponse(JsonParser jp) throws IOException { + final InputStream inputSource = (InputStream) jp.getInputSource(); - if (inputSource == null) { - return ""; - } + if (inputSource == null) { + return ""; + } - inputSource.reset(); + inputSource.reset(); - return streamToString(inputSource); - } + return streamToString(inputSource); + } - private String streamToString(InputStream input) throws IOException { - return new Scanner(input, StandardCharsets.UTF_8.name()).useDelimiter("\\Z").next(); - } + private String streamToString(InputStream input) throws IOException { + return new Scanner(input, StandardCharsets.UTF_8.name()).useDelimiter("\\Z").next(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageDecodingException.java b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageDecodingException.java index 1b0992fc0..c87328470 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageDecodingException.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageDecodingException.java @@ -2,11 +2,11 @@ /** Encoding exception. */ public class MessageDecodingException extends RuntimeException { - public MessageDecodingException(String message) { - super(message); - } + public MessageDecodingException(String message) { + super(message); + } - public MessageDecodingException(String message, Throwable cause) { - super(message, cause); - } + public MessageDecodingException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageEncodingException.java b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageEncodingException.java index bb690e40a..9affcaa6d 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageEncodingException.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/MessageEncodingException.java @@ -2,11 +2,11 @@ /** Encoding exception. */ public class MessageEncodingException extends RuntimeException { - public MessageEncodingException(String message) { - super(message); - } + public MessageEncodingException(String message) { + super(message); + } - public MessageEncodingException(String message, Throwable cause) { - super(message, cause); - } + public MessageEncodingException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionException.java b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionException.java index c5402b40b..98ae74429 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionException.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionException.java @@ -4,57 +4,57 @@ import java.util.Optional; public class TransactionException extends Exception { - private Optional transactionHash = Optional.empty(); - private String status; - private BigInteger gasUsed; - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public BigInteger getGasUsed() { - return gasUsed; - } - - public void setGasUsed(BigInteger gasUsed) { - this.gasUsed = gasUsed; - } - - public void setTransactionHash(Optional transactionHash) { - this.transactionHash = transactionHash; - } - - public TransactionException(String message) { - super(message); - } - - public TransactionException(String message, String transactionHash) { - super(message); - this.transactionHash = Optional.ofNullable(transactionHash); - } - - public TransactionException( - String message, String status, BigInteger gasUsed, String transactionHash) { - super(message); - this.status = status; - this.gasUsed = gasUsed; - this.transactionHash = Optional.ofNullable(transactionHash); - } - - public TransactionException(Throwable cause) { - super(cause); - } - - /** - * Obtain the transaction hash . - * - * @return optional transaction hash . - */ - public Optional getTransactionHash() { - return transactionHash; - } + private Optional transactionHash = Optional.empty(); + private String status; + private BigInteger gasUsed; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public BigInteger getGasUsed() { + return gasUsed; + } + + public void setGasUsed(BigInteger gasUsed) { + this.gasUsed = gasUsed; + } + + public void setTransactionHash(Optional transactionHash) { + this.transactionHash = transactionHash; + } + + public TransactionException(String message) { + super(message); + } + + public TransactionException(String message, String transactionHash) { + super(message); + this.transactionHash = Optional.ofNullable(transactionHash); + } + + public TransactionException( + String message, String status, BigInteger gasUsed, String transactionHash) { + super(message); + this.status = status; + this.gasUsed = gasUsed; + this.transactionHash = Optional.ofNullable(transactionHash); + } + + public TransactionException(Throwable cause) { + super(cause); + } + + /** + * Obtain the transaction hash . + * + * @return optional transaction hash . + */ + public Optional getTransactionHash() { + return transactionHash; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionTimeoutException.java b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionTimeoutException.java index 55adf96a2..7fa2285ee 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionTimeoutException.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/exceptions/TransactionTimeoutException.java @@ -5,11 +5,11 @@ * transaction to execute. */ public class TransactionTimeoutException extends Exception { - public TransactionTimeoutException(String message) { - super(message); - } + public TransactionTimeoutException(String message) { + super(message); + } - public TransactionTimeoutException(String message, Throwable cause) { - super(message, cause); - } + public TransactionTimeoutException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/http/HttpService.java b/src/main/java/org/fisco/bcos/web3j/protocol/http/HttpService.java index 49e4e8b43..5df4944ad 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/http/HttpService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/http/HttpService.java @@ -19,78 +19,81 @@ /** HTTP implementation of our services API. */ public class HttpService extends Service { - public static final String DEFAULT_URL = "http://localhost:8545/"; + public static final String DEFAULT_URL = "http://localhost:8545/"; - private CloseableHttpClient httpClient; + private CloseableHttpClient httpClient; - private final String url; + private final String url; - public HttpService(String url, CloseableHttpClient httpClient, boolean includeRawResponses) { - super(includeRawResponses); - this.url = url; - this.httpClient = httpClient; - } + public HttpService(String url, CloseableHttpClient httpClient, boolean includeRawResponses) { + super(includeRawResponses); + this.url = url; + this.httpClient = httpClient; + } - public HttpService(String url, CloseableHttpClient httpClient) { - this(url, httpClient, false); - } + public HttpService(String url, CloseableHttpClient httpClient) { + this(url, httpClient, false); + } - public HttpService(String url) { - this(url, HttpClients.custom().setConnectionManagerShared(true).build()); - } + public HttpService(String url) { + this(url, HttpClients.custom().setConnectionManagerShared(true).build()); + } - public HttpService() { - this(DEFAULT_URL); - } + public HttpService() { + this(DEFAULT_URL); + } - protected void setHttpClient(CloseableHttpClient httpClient) { - this.httpClient = httpClient; - } + protected void setHttpClient(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + } - @Override - public T send(Request request, Class responseType) throws IOException { + @Override + public T send(Request request, Class responseType) throws IOException { - byte[] payload = objectMapper.writeValueAsBytes(request); + byte[] payload = objectMapper.writeValueAsBytes(request); - HttpPost httpPost = new HttpPost(this.url); - httpPost.setEntity(new ByteArrayEntity(payload)); - Header[] headers = buildHeaders(); - httpPost.setHeaders(headers); + HttpPost httpPost = new HttpPost(this.url); + httpPost.setEntity(new ByteArrayEntity(payload)); + Header[] headers = buildHeaders(); + httpPost.setHeaders(headers); - ResponseHandler responseHandler = getResponseHandler(responseType); - try { - return httpClient.execute(httpPost, responseHandler); - } finally { - httpClient.close(); - } - } - - private Header[] buildHeaders() { - List

headers = new ArrayList<>(); - headers.add(new BasicHeader("Content-Type", "application/json; charset=UTF-8")); - addHeaders(headers); - return headers.toArray(new Header[0]); - } - - protected void addHeaders(List
headers) {} - - public ResponseHandler getResponseHandler(Class type) { - return response -> { - int status = response.getStatusLine().getStatusCode(); - if (status >= 200 && status < 300) { - HttpEntity entity = response.getEntity(); - - if (entity != null) { - return objectMapper.readValue(response.getEntity().getContent(), type); - } else { - return null; + ResponseHandler responseHandler = getResponseHandler(responseType); + try { + return httpClient.execute(httpPost, responseHandler); + } finally { + httpClient.close(); } - } else { - throw new ClientProtocolException("Unexpected response status: " + status); - } - }; - } - - @Override - public void close() throws IOException {} + } + + @Override + public void sendOnly(Request request) throws IOException {} + + private Header[] buildHeaders() { + List
headers = new ArrayList<>(); + headers.add(new BasicHeader("Content-Type", "application/json; charset=UTF-8")); + addHeaders(headers); + return headers.toArray(new Header[0]); + } + + protected void addHeaders(List
headers) {} + + public ResponseHandler getResponseHandler(Class type) { + return response -> { + int status = response.getStatusLine().getStatusCode(); + if (status >= 200 && status < 300) { + HttpEntity entity = response.getEntity(); + + if (entity != null) { + return objectMapper.readValue(response.getEntity().getContent(), type); + } else { + return null; + } + } else { + throw new ClientProtocolException("Unexpected response status: " + status); + } + }; + } + + @Override + public void close() throws IOException {} } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IOFacade.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IOFacade.java index 50292ed0d..622045ab1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IOFacade.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IOFacade.java @@ -4,7 +4,7 @@ /** Simple IO facade for the *nix and Windows IPC implementations. */ public interface IOFacade { - void write(String payload) throws IOException; + void write(String payload) throws IOException; - String read() throws IOException; + String read() throws IOException; } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IpcService.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IpcService.java index cdea400d1..ba32367ae 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IpcService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/IpcService.java @@ -10,32 +10,32 @@ /** Ipc service implementation. */ public class IpcService extends Service { - private static final Log log = LogFactory.getLog(IpcService.class); + private static final Log log = LogFactory.getLog(IpcService.class); - private final IOFacade ioFacade; + private final IOFacade ioFacade; - public IpcService(IOFacade ioFacade, boolean includeRawResponses) { - super(includeRawResponses); - this.ioFacade = ioFacade; - } + public IpcService(IOFacade ioFacade, boolean includeRawResponses) { + super(includeRawResponses); + this.ioFacade = ioFacade; + } - public IpcService(IOFacade ioFacade) { - this(ioFacade, false); - } + public IpcService(IOFacade ioFacade) { + this(ioFacade, false); + } - @Override - public T send(Request request, Class responseType) throws IOException { - String payload = objectMapper.writeValueAsString(request); + @Override + public T send(Request request, Class responseType) throws IOException { + String payload = objectMapper.writeValueAsString(request); - ioFacade.write(payload); - log.debug(">> " + payload); + ioFacade.write(payload); + log.debug(">> " + payload); - String result = ioFacade.read(); - log.debug("<< " + result); + String result = ioFacade.read(); + log.debug("<< " + result); - return objectMapper.readValue(result, responseType); - } + return objectMapper.readValue(result, responseType); + } - @Override - public void close() throws IOException {} + @Override + public void close() throws IOException {} } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixDomainSocket.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixDomainSocket.java index cb6bc6aac..d3cd7ebd1 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixDomainSocket.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixDomainSocket.java @@ -11,55 +11,57 @@ /** Unix domain socket IO implementation for IPC. */ public class UnixDomainSocket implements IOFacade { - private static final int DEFAULT_BUFFER_SIZE = 1024; + private static final int DEFAULT_BUFFER_SIZE = 1024; - private final int bufferSize; + private final int bufferSize; - private final InputStreamReader reader; - private final PrintWriter writer; + private final InputStreamReader reader; + private final PrintWriter writer; - public UnixDomainSocket(String ipcSocketPath) { - this(ipcSocketPath, DEFAULT_BUFFER_SIZE); - } + public UnixDomainSocket(String ipcSocketPath) { + this(ipcSocketPath, DEFAULT_BUFFER_SIZE); + } - public UnixDomainSocket(String ipcSocketPath, int bufferSize) { - this.bufferSize = bufferSize; + public UnixDomainSocket(String ipcSocketPath, int bufferSize) { + this.bufferSize = bufferSize; - try { - UnixSocketAddress address = new UnixSocketAddress(ipcSocketPath); - UnixSocketChannel channel = UnixSocketChannel.open(address); + try { + UnixSocketAddress address = new UnixSocketAddress(ipcSocketPath); + UnixSocketChannel channel = UnixSocketChannel.open(address); - reader = new InputStreamReader(Channels.newInputStream(channel)); - writer = new PrintWriter(Channels.newOutputStream(channel)); + reader = new InputStreamReader(Channels.newInputStream(channel)); + writer = new PrintWriter(Channels.newOutputStream(channel)); - } catch (IOException e) { - throw new RuntimeException("Provided file socket cannot be opened: " + ipcSocketPath, e); + } catch (IOException e) { + throw new RuntimeException( + "Provided file socket cannot be opened: " + ipcSocketPath, e); + } } - } - UnixDomainSocket(InputStreamReader reader, PrintWriter writer, int bufferSize) { - this.bufferSize = bufferSize; - this.writer = writer; - this.reader = reader; - } + UnixDomainSocket(InputStreamReader reader, PrintWriter writer, int bufferSize) { + this.bufferSize = bufferSize; + this.writer = writer; + this.reader = reader; + } - @Override - public void write(String payload) throws IOException { - writer.write(payload); - writer.flush(); - } + @Override + public void write(String payload) throws IOException { + writer.write(payload); + writer.flush(); + } - @Override - public String read() throws IOException { - CharBuffer response = CharBuffer.allocate(bufferSize); - String result = ""; + @Override + public String read() throws IOException { + CharBuffer response = CharBuffer.allocate(bufferSize); + String result = ""; - do { - response.clear(); - reader.read(response); - result += new String(response.array(), response.arrayOffset(), response.position()); - } while (response.position() == response.limit() && response.get(response.limit() - 1) != '\n'); + do { + response.clear(); + reader.read(response); + result += new String(response.array(), response.arrayOffset(), response.position()); + } while (response.position() == response.limit() + && response.get(response.limit() - 1) != '\n'); - return result; - } + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixIpcService.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixIpcService.java index 2bcb02b2b..cd4ec6d47 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixIpcService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/UnixIpcService.java @@ -3,7 +3,7 @@ /** Unix domain socket implementation of our services API. */ public class UnixIpcService extends IpcService { - public UnixIpcService(String ipcSocketPath) { - super(new UnixDomainSocket(ipcSocketPath)); - } + public UnixIpcService(String ipcSocketPath) { + super(new UnixDomainSocket(ipcSocketPath)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsIpcService.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsIpcService.java index 160e45047..5958fc379 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsIpcService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsIpcService.java @@ -7,7 +7,7 @@ */ public class WindowsIpcService extends IpcService { - public WindowsIpcService(String ipcSocketPath) { - super(new WindowsNamedPipe(ipcSocketPath)); - } + public WindowsIpcService(String ipcSocketPath) { + super(new WindowsNamedPipe(ipcSocketPath)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsNamedPipe.java b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsNamedPipe.java index 46036fc70..3d45c65bb 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsNamedPipe.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/ipc/WindowsNamedPipe.java @@ -6,23 +6,23 @@ /** Windows named pipe IO implementation for IPC. */ public class WindowsNamedPipe implements IOFacade { - private final RandomAccessFile pipe; + private final RandomAccessFile pipe; - public WindowsNamedPipe(String ipcSocketPath) { - try { - pipe = new RandomAccessFile(ipcSocketPath, "rw"); - } catch (IOException e) { - throw new RuntimeException("Provided file pipe cannot be opened: " + ipcSocketPath, e); + public WindowsNamedPipe(String ipcSocketPath) { + try { + pipe = new RandomAccessFile(ipcSocketPath, "rw"); + } catch (IOException e) { + throw new RuntimeException("Provided file pipe cannot be opened: " + ipcSocketPath, e); + } } - } - @Override - public void write(String payload) throws IOException { - pipe.write(payload.getBytes()); - } + @Override + public void write(String payload) throws IOException { + pipe.write(payload.getBytes()); + } - @Override - public String read() throws IOException { - return pipe.readLine(); - } + @Override + public String read() throws IOException { + return pipe.readLine(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/rx/JsonRpc2_0Rx.java b/src/main/java/org/fisco/bcos/web3j/protocol/rx/JsonRpc2_0Rx.java index 301e4cd30..1772e97fd 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/rx/JsonRpc2_0Rx.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/rx/JsonRpc2_0Rx.java @@ -27,217 +27,226 @@ /** web3j reactive API implementation. */ public class JsonRpc2_0Rx { - private final Web3j web3j; - private final ScheduledExecutorService scheduledExecutorService; - private final Scheduler scheduler; - - public JsonRpc2_0Rx(Web3j web3j, ScheduledExecutorService scheduledExecutorService) { - this.web3j = web3j; - this.scheduledExecutorService = scheduledExecutorService; - this.scheduler = Schedulers.from(scheduledExecutorService); - } - - public Flowable blockHashFlowable(long pollingInterval) { - return Flowable.create( - subscriber -> { - BlockFilter blockFilter = new BlockFilter(web3j, subscriber::onNext); - run(blockFilter, subscriber, pollingInterval); - }, - BackpressureStrategy.BUFFER); - } - - public Flowable pendingTransactionHashFlowable(long pollingInterval) { - return Flowable.create( - subscriber -> { - PendingTransactionFilter pendingTransactionFilter = - new PendingTransactionFilter(web3j, subscriber::onNext); - - run(pendingTransactionFilter, subscriber, pollingInterval); - }, - BackpressureStrategy.BUFFER); - } - - public Flowable logFlowable(BcosFilter ethFilter, long pollingInterval) { - return Flowable.create( - subscriber -> { - LogFilter logFilter = new LogFilter(web3j, subscriber::onNext, ethFilter); - - run(logFilter, subscriber, pollingInterval); - }, - BackpressureStrategy.BUFFER); - } - - private void run(Filter filter, FlowableEmitter emitter, long pollingInterval) { - - filter.run(scheduledExecutorService, pollingInterval); - emitter.setCancellable(filter::cancel); - } - - public Flowable transactionFlowable(long pollingInterval) { - return blockFlowable(true, pollingInterval).flatMapIterable(JsonRpc2_0Rx::toTransactions); - } - - public Flowable pendingTransactionFlowable(long pollingInterval) { - return pendingTransactionHashFlowable(pollingInterval) - .flatMap(transactionHash -> web3j.getTransactionByHash(transactionHash).flowable()) - .filter(ethTransaction -> ethTransaction.getTransaction().isPresent()) - .map(ethTransaction -> ethTransaction.getTransaction().get()); - } - - public Flowable blockFlowable(boolean fullTransactionObjects, long pollingInterval) { - return blockHashFlowable(pollingInterval) - .flatMap(blockHash -> web3j.getBlockByHash(blockHash, fullTransactionObjects).flowable()); - } - - public Flowable replayBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects) { - return replayBlocksFlowable(startBlock, endBlock, fullTransactionObjects, true); - } - - public Flowable replayBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects, - boolean ascending) { - // We use a scheduler to ensure this Flowable runs asynchronously for users to be - // consistent with the other Flowables - return replayBlocksFlowableSync(startBlock, endBlock, fullTransactionObjects, ascending) - .subscribeOn(scheduler); - } - - private Flowable replayBlocksFlowableSync( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects) { - return replayBlocksFlowableSync(startBlock, endBlock, fullTransactionObjects, true); - } - - private Flowable replayBlocksFlowableSync( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects, - boolean ascending) { - - BigInteger startBlockNumber = null; - BigInteger endBlockNumber = null; - try { - startBlockNumber = getBlockNumber(startBlock); - endBlockNumber = getBlockNumber(endBlock); - } catch (IOException e) { - Flowable.error(e); - } - - if (ascending) { - return Flowables.range(startBlockNumber, endBlockNumber) - .flatMap( - i -> - web3j - .getBlockByNumber(new DefaultBlockParameterNumber(i), fullTransactionObjects) - .flowable()); - } else { - return Flowables.range(startBlockNumber, endBlockNumber, false) - .flatMap( - i -> - web3j - .getBlockByNumber(new DefaultBlockParameterNumber(i), fullTransactionObjects) - .flowable()); - } - } - - public Flowable replayTransactionsFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - return replayBlocksFlowable(startBlock, endBlock, true) - .flatMapIterable(JsonRpc2_0Rx::toTransactions); - } - - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - boolean fullTransactionObjects, - Flowable onCompleteFlowable) { - // We use a scheduler to ensure this Flowable runs asynchronously for users to be - // consistent with the other Flowables - return replayPastBlocksFlowableSync(startBlock, fullTransactionObjects, onCompleteFlowable) - .subscribeOn(scheduler); - } - - public Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects) { - return replayPastBlocksFlowable(startBlock, fullTransactionObjects, Flowable.empty()); - } - - private Flowable replayPastBlocksFlowableSync( - DefaultBlockParameter startBlock, - boolean fullTransactionObjects, - Flowable onCompleteFlowable) { - - BigInteger startBlockNumber; - BigInteger latestBlockNumber; - try { - startBlockNumber = getBlockNumber(startBlock); - latestBlockNumber = getLatestBlockNumber(); - } catch (IOException e) { - return Flowable.error(e); - } - - if (startBlockNumber.compareTo(latestBlockNumber) > -1) { - return onCompleteFlowable; - } else { - return Flowable.concat( - replayBlocksFlowableSync( - new DefaultBlockParameterNumber(startBlockNumber), - new DefaultBlockParameterNumber(latestBlockNumber), - fullTransactionObjects), - Flowable.defer( - () -> - replayPastBlocksFlowableSync( - new DefaultBlockParameterNumber(latestBlockNumber.add(BigInteger.ONE)), - fullTransactionObjects, - onCompleteFlowable))); - } - } - - public Flowable replayPastTransactionsFlowable(DefaultBlockParameter startBlock) { - return replayPastBlocksFlowable(startBlock, true, Flowable.empty()) - .flatMapIterable(JsonRpc2_0Rx::toTransactions); - } - - public Flowable replayPastAndFutureBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects, long pollingInterval) { - - return replayPastBlocksFlowable( - startBlock, fullTransactionObjects, blockFlowable(fullTransactionObjects, pollingInterval)); - } - - public Flowable replayPastAndFutureTransactionsFlowable( - DefaultBlockParameter startBlock, long pollingInterval) { - return replayPastAndFutureBlocksFlowable(startBlock, true, pollingInterval) - .flatMapIterable(JsonRpc2_0Rx::toTransactions); - } - - private BigInteger getLatestBlockNumber() throws IOException { - return getBlockNumber(DefaultBlockParameterName.LATEST); - } - - private BigInteger getBlockNumber(DefaultBlockParameter defaultBlockParameter) - throws IOException { - if (defaultBlockParameter instanceof DefaultBlockParameterNumber) { - return ((DefaultBlockParameterNumber) defaultBlockParameter).getBlockNumber(); - } else { - BcosBlock latestEthBlock = web3j.getBlockByNumber(defaultBlockParameter, false).send(); - return latestEthBlock.getBlock().getNumber(); - } - } - - private static List toTransactions(BcosBlock ethBlock) { - // If you ever see an exception thrown here, it's probably due to an incomplete chain in - // Geth/Parity. You should resync to solve. - return ethBlock - .getBlock() - .getTransactions() - .stream() - .map(transactionResult -> (Transaction) transactionResult.get()) - .collect(Collectors.toList()); - } + private final Web3j web3j; + private final ScheduledExecutorService scheduledExecutorService; + private final Scheduler scheduler; + + public JsonRpc2_0Rx(Web3j web3j, ScheduledExecutorService scheduledExecutorService) { + this.web3j = web3j; + this.scheduledExecutorService = scheduledExecutorService; + this.scheduler = Schedulers.from(scheduledExecutorService); + } + + public Flowable blockHashFlowable(long pollingInterval) { + return Flowable.create( + subscriber -> { + BlockFilter blockFilter = new BlockFilter(web3j, subscriber::onNext); + run(blockFilter, subscriber, pollingInterval); + }, + BackpressureStrategy.BUFFER); + } + + public Flowable pendingTransactionHashFlowable(long pollingInterval) { + return Flowable.create( + subscriber -> { + PendingTransactionFilter pendingTransactionFilter = + new PendingTransactionFilter(web3j, subscriber::onNext); + + run(pendingTransactionFilter, subscriber, pollingInterval); + }, + BackpressureStrategy.BUFFER); + } + + public Flowable logFlowable(BcosFilter ethFilter, long pollingInterval) { + return Flowable.create( + subscriber -> { + LogFilter logFilter = new LogFilter(web3j, subscriber::onNext, ethFilter); + + run(logFilter, subscriber, pollingInterval); + }, + BackpressureStrategy.BUFFER); + } + + private void run( + Filter filter, FlowableEmitter emitter, long pollingInterval) { + + filter.run(scheduledExecutorService, pollingInterval); + emitter.setCancellable(filter::cancel); + } + + public Flowable transactionFlowable(long pollingInterval) { + return blockFlowable(true, pollingInterval).flatMapIterable(JsonRpc2_0Rx::toTransactions); + } + + public Flowable pendingTransactionFlowable(long pollingInterval) { + return pendingTransactionHashFlowable(pollingInterval) + .flatMap(transactionHash -> web3j.getTransactionByHash(transactionHash).flowable()) + .filter(ethTransaction -> ethTransaction.getTransaction().isPresent()) + .map(ethTransaction -> ethTransaction.getTransaction().get()); + } + + public Flowable blockFlowable(boolean fullTransactionObjects, long pollingInterval) { + return blockHashFlowable(pollingInterval) + .flatMap( + blockHash -> + web3j.getBlockByHash(blockHash, fullTransactionObjects).flowable()); + } + + public Flowable replayBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects) { + return replayBlocksFlowable(startBlock, endBlock, fullTransactionObjects, true); + } + + public Flowable replayBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects, + boolean ascending) { + // We use a scheduler to ensure this Flowable runs asynchronously for users to be + // consistent with the other Flowables + return replayBlocksFlowableSync(startBlock, endBlock, fullTransactionObjects, ascending) + .subscribeOn(scheduler); + } + + private Flowable replayBlocksFlowableSync( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects) { + return replayBlocksFlowableSync(startBlock, endBlock, fullTransactionObjects, true); + } + + private Flowable replayBlocksFlowableSync( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects, + boolean ascending) { + + BigInteger startBlockNumber = null; + BigInteger endBlockNumber = null; + try { + startBlockNumber = getBlockNumber(startBlock); + endBlockNumber = getBlockNumber(endBlock); + } catch (IOException e) { + Flowable.error(e); + } + + if (ascending) { + return Flowables.range(startBlockNumber, endBlockNumber) + .flatMap( + i -> + web3j.getBlockByNumber( + new DefaultBlockParameterNumber(i), + fullTransactionObjects) + .flowable()); + } else { + return Flowables.range(startBlockNumber, endBlockNumber, false) + .flatMap( + i -> + web3j.getBlockByNumber( + new DefaultBlockParameterNumber(i), + fullTransactionObjects) + .flowable()); + } + } + + public Flowable replayTransactionsFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return replayBlocksFlowable(startBlock, endBlock, true) + .flatMapIterable(JsonRpc2_0Rx::toTransactions); + } + + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + boolean fullTransactionObjects, + Flowable onCompleteFlowable) { + // We use a scheduler to ensure this Flowable runs asynchronously for users to be + // consistent with the other Flowables + return replayPastBlocksFlowableSync(startBlock, fullTransactionObjects, onCompleteFlowable) + .subscribeOn(scheduler); + } + + public Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, boolean fullTransactionObjects) { + return replayPastBlocksFlowable(startBlock, fullTransactionObjects, Flowable.empty()); + } + + private Flowable replayPastBlocksFlowableSync( + DefaultBlockParameter startBlock, + boolean fullTransactionObjects, + Flowable onCompleteFlowable) { + + BigInteger startBlockNumber; + BigInteger latestBlockNumber; + try { + startBlockNumber = getBlockNumber(startBlock); + latestBlockNumber = getLatestBlockNumber(); + } catch (IOException e) { + return Flowable.error(e); + } + + if (startBlockNumber.compareTo(latestBlockNumber) > -1) { + return onCompleteFlowable; + } else { + return Flowable.concat( + replayBlocksFlowableSync( + new DefaultBlockParameterNumber(startBlockNumber), + new DefaultBlockParameterNumber(latestBlockNumber), + fullTransactionObjects), + Flowable.defer( + () -> + replayPastBlocksFlowableSync( + new DefaultBlockParameterNumber( + latestBlockNumber.add(BigInteger.ONE)), + fullTransactionObjects, + onCompleteFlowable))); + } + } + + public Flowable replayPastTransactionsFlowable(DefaultBlockParameter startBlock) { + return replayPastBlocksFlowable(startBlock, true, Flowable.empty()) + .flatMapIterable(JsonRpc2_0Rx::toTransactions); + } + + public Flowable replayPastAndFutureBlocksFlowable( + DefaultBlockParameter startBlock, + boolean fullTransactionObjects, + long pollingInterval) { + + return replayPastBlocksFlowable( + startBlock, + fullTransactionObjects, + blockFlowable(fullTransactionObjects, pollingInterval)); + } + + public Flowable replayPastAndFutureTransactionsFlowable( + DefaultBlockParameter startBlock, long pollingInterval) { + return replayPastAndFutureBlocksFlowable(startBlock, true, pollingInterval) + .flatMapIterable(JsonRpc2_0Rx::toTransactions); + } + + private BigInteger getLatestBlockNumber() throws IOException { + return getBlockNumber(DefaultBlockParameterName.LATEST); + } + + private BigInteger getBlockNumber(DefaultBlockParameter defaultBlockParameter) + throws IOException { + if (defaultBlockParameter instanceof DefaultBlockParameterNumber) { + return ((DefaultBlockParameterNumber) defaultBlockParameter).getBlockNumber(); + } else { + BcosBlock latestEthBlock = web3j.getBlockByNumber(defaultBlockParameter, false).send(); + return latestEthBlock.getBlock().getNumber(); + } + } + + private static List toTransactions(BcosBlock ethBlock) { + // If you ever see an exception thrown here, it's probably due to an incomplete chain in + // Geth/Parity. You should resync to solve. + return ethBlock.getBlock() + .getTransactions() + .stream() + .map(transactionResult -> (Transaction) transactionResult.get()) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/rx/Web3jRx.java b/src/main/java/org/fisco/bcos/web3j/protocol/rx/Web3jRx.java index 4950a86dd..c62cbdce3 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/rx/Web3jRx.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/rx/Web3jRx.java @@ -13,182 +13,182 @@ /** The Observables JSON-RPC client event API. */ public interface Web3jRx { - /** - * Create an flowable to filter for specific log events on the blockchain. - * - * @param filter filter criteria - * @return a {@link Flowable} instance that emits all Log events matching the filter - */ - Flowable logFlowable(BcosFilter filter); - - /** - * Create an Flowable to emit block hashes. - * - * @return a {@link Flowable} instance that emits all new block hashes as new blocks are created - * on the blockchain - */ - Flowable blockHashFlowable(); - - /** - * Create an Flowable to emit pending transactions, i.e. those transactions that have been - * submitted by a node, but don't yet form part of a block (haven't been mined yet). - * - * @return a {@link Flowable} instance to emit pending transaction hashes. - */ - Flowable pendingTransactionHashFlowable(); - - /** - * Create an {@link Flowable} instance to emit all new transactions as they are confirmed on the - * blockchain. i.e. they have been mined and are incorporated into a block. - * - * @return a {@link Flowable} instance to emit new transactions on the blockchain - */ - Flowable transactionFlowable(); - - /** - * Create an {@link Flowable} instance to emit all pending transactions that have yet to be placed - * into a block on the blockchain. - * - * @return a {@link Flowable} instance to emit pending transactions - */ - Flowable pendingTransactionFlowable(); - - /** - * Create an {@link Flowable} instance that emits newly created blocks on the blockchain. - * - * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise - * transaction hashes - * @return a {@link Flowable} instance that emits all new blocks as they are added to the - * blockchain - */ - Flowable blockFlowable(boolean fullTransactionObjects); - - /** - * Create an {@link Flowable} instance that emits all blocks from the blockchain contained within - * the requested range. - * - * @param startBlock block number to commence with - * @param endBlock block number to finish with - * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise - * transaction hashes - * @return a {@link Flowable} instance to emit these blocks - */ - Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects); - - /** - * Create an {@link Flowable} instance that emits all blocks from the blockchain contained within - * the requested range. - * - * @param startBlock block number to commence with - * @param endBlock block number to finish with - * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise - * transaction hashes - * @param ascending if true, emits blocks in ascending order between range, otherwise in - * descending order - * @return a {@link Flowable} instance to emit these blocks - */ - Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - DefaultBlockParameter endBlock, - boolean fullTransactionObjects, - boolean ascending); - - /** - * Create a {@link Flowable} instance that emits all transactions from the blockchain starting - * with a provided block number. Once it has replayed up to the most current block, the provided - * Flowable is invoked. - * - *

To automatically subscribe to new blocks, use {@link - * #replayPastAndFutureBlocksFlowable(DefaultBlockParameter, boolean)}. - * - * @param startBlock the block number we wish to request from - * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided in - * the {@link BcosBlock} responses - * @param onCompleteFlowable a subsequent Flowable that we wish to run once we are caught up with - * the latest block - * @return a {@link Flowable} instance to emit all requested blocks - */ - Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, - boolean fullTransactionObjects, - Flowable onCompleteFlowable); - - /** - * Creates a {@link Flowable} instance that emits all blocks from the requested block number to - * the most current. Once it has emitted the most current block, onComplete is called. - * - * @param startBlock the block number we wish to request from - * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided in - * the {@link BcosBlock} responses - * @return a {@link Flowable} instance to emit all requested blocks - */ - Flowable replayPastBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects); - - /** - * Create a {@link Flowable} instance that emits all transactions from the blockchain contained - * within the requested range. - * - * @param startBlock block number to commence with - * @param endBlock block number to finish with - * @return a {@link Flowable} instance to emit these transactions in the order they appear in the - * blocks - */ - Flowable replayPastTransactionsFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock); - - /** - * Creates a {@link Flowable} instance that emits all transactions from the requested block number - * to the most current. Once it has emitted the most current block's transactions, onComplete is - * called. - * - * @param startBlock the block number we wish to request from - * @return a {@link Flowable} instance to emit all requested transactions - */ - Flowable replayPastTransactionsFlowable(DefaultBlockParameter startBlock); - - /** - * Creates a {@link Flowable} instance that emits all blocks from the requested block number to - * the most current. Once it has emitted the most current block, it starts emitting new blocks as - * they are created. - * - * @param startBlock the block number we wish to request from - * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided in - * the {@link BcosBlock} responses - * @return a {@link Flowable} instance to emit all requested blocks and future - */ - Flowable replayPastAndFutureBlocksFlowable( - DefaultBlockParameter startBlock, boolean fullTransactionObjects); - - /** - * As per {@link #replayPastAndFutureBlocksFlowable(DefaultBlockParameter, boolean)}, except that - * all transactions contained within the blocks are emitted. - * - * @param startBlock the block number we wish to request from - * @return a {@link Flowable} instance to emit all requested transactions and future - */ - Flowable replayPastAndFutureTransactionsFlowable(DefaultBlockParameter startBlock); - - /** - * Creates a {@link Flowable} instance that emits a notification when a new header is appended to - * a chain, including chain reorganizations. - * - * @return a {@link Flowable} instance that emits a notification for every new header - */ - Flowable newHeadsNotifications(); - - /** - * Creates aa {@link Flowable} instance that emits notifications for logs included in new imported - * blocks. - * - * @param addresses only return logs from this list of address. Return logs from all addresses if - * the list is empty - * @param topics only return logs that match specified topics. Returns logs for all topics if the - * list is empty - * @return a {@link Flowable} instance that emits logs included in new blocks - */ - Flowable logsNotifications(List addresses, List topics); + /** + * Create an flowable to filter for specific log events on the blockchain. + * + * @param filter filter criteria + * @return a {@link Flowable} instance that emits all Log events matching the filter + */ + Flowable logFlowable(BcosFilter filter); + + /** + * Create an Flowable to emit block hashes. + * + * @return a {@link Flowable} instance that emits all new block hashes as new blocks are created + * on the blockchain + */ + Flowable blockHashFlowable(); + + /** + * Create an Flowable to emit pending transactions, i.e. those transactions that have been + * submitted by a node, but don't yet form part of a block (haven't been mined yet). + * + * @return a {@link Flowable} instance to emit pending transaction hashes. + */ + Flowable pendingTransactionHashFlowable(); + + /** + * Create an {@link Flowable} instance to emit all new transactions as they are confirmed on the + * blockchain. i.e. they have been mined and are incorporated into a block. + * + * @return a {@link Flowable} instance to emit new transactions on the blockchain + */ + Flowable transactionFlowable(); + + /** + * Create an {@link Flowable} instance to emit all pending transactions that have yet to be + * placed into a block on the blockchain. + * + * @return a {@link Flowable} instance to emit pending transactions + */ + Flowable pendingTransactionFlowable(); + + /** + * Create an {@link Flowable} instance that emits newly created blocks on the blockchain. + * + * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise + * transaction hashes + * @return a {@link Flowable} instance that emits all new blocks as they are added to the + * blockchain + */ + Flowable blockFlowable(boolean fullTransactionObjects); + + /** + * Create an {@link Flowable} instance that emits all blocks from the blockchain contained + * within the requested range. + * + * @param startBlock block number to commence with + * @param endBlock block number to finish with + * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise + * transaction hashes + * @return a {@link Flowable} instance to emit these blocks + */ + Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects); + + /** + * Create an {@link Flowable} instance that emits all blocks from the blockchain contained + * within the requested range. + * + * @param startBlock block number to commence with + * @param endBlock block number to finish with + * @param fullTransactionObjects if true, provides transactions embedded in blocks, otherwise + * transaction hashes + * @param ascending if true, emits blocks in ascending order between range, otherwise in + * descending order + * @return a {@link Flowable} instance to emit these blocks + */ + Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock, + boolean fullTransactionObjects, + boolean ascending); + + /** + * Create a {@link Flowable} instance that emits all transactions from the blockchain starting + * with a provided block number. Once it has replayed up to the most current block, the provided + * Flowable is invoked. + * + *

To automatically subscribe to new blocks, use {@link + * #replayPastAndFutureBlocksFlowable(DefaultBlockParameter, boolean)}. + * + * @param startBlock the block number we wish to request from + * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided + * in the {@link BcosBlock} responses + * @param onCompleteFlowable a subsequent Flowable that we wish to run once we are caught up + * with the latest block + * @return a {@link Flowable} instance to emit all requested blocks + */ + Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, + boolean fullTransactionObjects, + Flowable onCompleteFlowable); + + /** + * Creates a {@link Flowable} instance that emits all blocks from the requested block number to + * the most current. Once it has emitted the most current block, onComplete is called. + * + * @param startBlock the block number we wish to request from + * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided + * in the {@link BcosBlock} responses + * @return a {@link Flowable} instance to emit all requested blocks + */ + Flowable replayPastBlocksFlowable( + DefaultBlockParameter startBlock, boolean fullTransactionObjects); + + /** + * Create a {@link Flowable} instance that emits all transactions from the blockchain contained + * within the requested range. + * + * @param startBlock block number to commence with + * @param endBlock block number to finish with + * @return a {@link Flowable} instance to emit these transactions in the order they appear in + * the blocks + */ + Flowable replayPastTransactionsFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock); + + /** + * Creates a {@link Flowable} instance that emits all transactions from the requested block + * number to the most current. Once it has emitted the most current block's transactions, + * onComplete is called. + * + * @param startBlock the block number we wish to request from + * @return a {@link Flowable} instance to emit all requested transactions + */ + Flowable replayPastTransactionsFlowable(DefaultBlockParameter startBlock); + + /** + * Creates a {@link Flowable} instance that emits all blocks from the requested block number to + * the most current. Once it has emitted the most current block, it starts emitting new blocks + * as they are created. + * + * @param startBlock the block number we wish to request from + * @param fullTransactionObjects if we require full {@link Transaction} objects to be provided + * in the {@link BcosBlock} responses + * @return a {@link Flowable} instance to emit all requested blocks and future + */ + Flowable replayPastAndFutureBlocksFlowable( + DefaultBlockParameter startBlock, boolean fullTransactionObjects); + + /** + * As per {@link #replayPastAndFutureBlocksFlowable(DefaultBlockParameter, boolean)}, except + * that all transactions contained within the blocks are emitted. + * + * @param startBlock the block number we wish to request from + * @return a {@link Flowable} instance to emit all requested transactions and future + */ + Flowable replayPastAndFutureTransactionsFlowable(DefaultBlockParameter startBlock); + + /** + * Creates a {@link Flowable} instance that emits a notification when a new header is appended + * to a chain, including chain reorganizations. + * + * @return a {@link Flowable} instance that emits a notification for every new header + */ + Flowable newHeadsNotifications(); + + /** + * Creates aa {@link Flowable} instance that emits notifications for logs included in new + * imported blocks. + * + * @param addresses only return logs from this list of address. Return logs from all addresses + * if the list is empty + * @param topics only return logs that match specified topics. Returns logs for all topics if + * the list is empty + * @return a {@link Flowable} instance that emits logs included in new blocks + */ + Flowable logsNotifications(List addresses, List topics); } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketClient.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketClient.java index 9479343d4..2ad2b9881 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketClient.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketClient.java @@ -12,56 +12,56 @@ */ public class WebSocketClient extends org.java_websocket.client.WebSocketClient { - private static final Logger log = LoggerFactory.getLogger(WebSocketClient.class); + private static final Logger log = LoggerFactory.getLogger(WebSocketClient.class); - private WebSocketListener listener; + private WebSocketListener listener; - public WebSocketClient(URI serverUri) { - super(serverUri); - } + public WebSocketClient(URI serverUri) { + super(serverUri); + } - public WebSocketClient(URI serverUri, Map httpHeaders) { - super(serverUri, httpHeaders); - } + public WebSocketClient(URI serverUri, Map httpHeaders) { + super(serverUri, httpHeaders); + } - @Override - public void onOpen(ServerHandshake serverHandshake) { - log.info("Opened WebSocket connection to {}", uri); - } + @Override + public void onOpen(ServerHandshake serverHandshake) { + log.info("Opened WebSocket connection to {}", uri); + } - @Override - public void onMessage(String s) { - try { - log.debug("Received message {} from server {}", s, uri); - listener.onMessage(s); - } catch (Exception e) { - log.error("Failed to process message '{}' from server {}", s, uri); + @Override + public void onMessage(String s) { + try { + log.debug("Received message {} from server {}", s, uri); + listener.onMessage(s); + } catch (Exception e) { + log.error("Failed to process message '{}' from server {}", s, uri); + } } - } - @Override - public void onClose(int code, String reason, boolean remote) { - log.info( - "Closed WebSocket connection to {}, because of reason: '{}'." - + "Conection closed remotely: {}", - uri, - reason, - remote); - listener.onClose(); - } + @Override + public void onClose(int code, String reason, boolean remote) { + log.info( + "Closed WebSocket connection to {}, because of reason: '{}'." + + "Conection closed remotely: {}", + uri, + reason, + remote); + listener.onClose(); + } - @Override - public void onError(Exception e) { - log.error(String.format("WebSocket connection to {} failed with error", uri), e); - listener.onError(e); - } + @Override + public void onError(Exception e) { + log.error(String.format("WebSocket connection to {} failed with error", uri), e); + listener.onError(e); + } - /** - * Set a listener that will be called when a new message is received by the client. - * - * @param listener WebSocket listener - */ - public void setListener(WebSocketListener listener) { - this.listener = listener; - } + /** + * Set a listener that will be called when a new message is received by the client. + * + * @param listener WebSocket listener + */ + public void setListener(WebSocketListener listener) { + this.listener = listener; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketListener.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketListener.java index 98f882541..2cca1854b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketListener.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketListener.java @@ -5,15 +5,15 @@ /** A listener used to notify about about new WebSocket messages. */ public interface WebSocketListener { - /** - * Called when a new WebSocket message is delivered. - * - * @param message new WebSocket message - * @throws IOException thrown if an observer failed to process the message - */ - void onMessage(String message) throws IOException; + /** + * Called when a new WebSocket message is delivered. + * + * @param message new WebSocket message + * @throws IOException thrown if an observer failed to process the message + */ + void onMessage(String message) throws IOException; - void onError(Exception e); + void onError(Exception e); - void onClose(); + void onClose(); } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketRequest.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketRequest.java index 1170c47d7..3bbdd993b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketRequest.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketRequest.java @@ -8,19 +8,19 @@ * @param type of a data item that should be returned by the sent request */ class WebSocketRequest { - private CompletableFuture onReply; - private Class responseType; + private CompletableFuture onReply; + private Class responseType; - public WebSocketRequest(CompletableFuture onReply, Class responseType) { - this.onReply = onReply; - this.responseType = responseType; - } + public WebSocketRequest(CompletableFuture onReply, Class responseType) { + this.onReply = onReply; + this.responseType = responseType; + } - public CompletableFuture getOnReply() { - return onReply; - } + public CompletableFuture getOnReply() { + return onReply; + } - public Class getResponseType() { - return responseType; - } + public Class getResponseType() { + return responseType; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketService.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketService.java index 921e1c6bc..9df444574 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketService.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketService.java @@ -35,386 +35,406 @@ */ public class WebSocketService implements Web3jService { - private static final Logger log = LoggerFactory.getLogger(WebSocketService.class); - - // Timeout for JSON-RPC requests - static final long REQUEST_TIMEOUT = 60; - - // WebSocket client - private final WebSocketClient webSocketClient; - // Executor to schedule request timeouts - private final ScheduledExecutorService executor; - // Object mapper to map incoming JSON objects - private final ObjectMapper objectMapper; - - // Map of a sent request id to objects necessary to process this request - private Map> requestForId = new ConcurrentHashMap<>(); - // Map of a sent subscription request id to objects necessary to process - // subscription events - private Map> subscriptionRequestForId = new ConcurrentHashMap<>(); - // Map of a subscription id to objects necessary to process incoming events - private Map> subscriptionForId = new ConcurrentHashMap<>(); - - public WebSocketService(String serverUrl, boolean includeRawResponses) { - this(new WebSocketClient(parseURI(serverUrl)), includeRawResponses); - } - - public WebSocketService(WebSocketClient webSocketClient, boolean includeRawResponses) { - this(webSocketClient, Executors.newScheduledThreadPool(1), includeRawResponses); - } - - public WebSocketService( - WebSocketClient webSocketClient, - ScheduledExecutorService executor, - boolean includeRawResponses) { - this.webSocketClient = webSocketClient; - this.executor = executor; - this.objectMapper = ObjectMapperFactory.getObjectMapper(includeRawResponses); - } - - /** - * Connect to a WebSocket server. - * - * @throws ConnectException thrown if failed to connect to the server via WebSocket protocol - */ - public void connect() throws ConnectException { - try { - connectToWebSocket(); - setWebSocketListener(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - log.warn("Interrupted while connecting via WebSocket protocol"); - } - } - - private void connectToWebSocket() throws InterruptedException, ConnectException { - boolean connected = webSocketClient.connectBlocking(); - if (!connected) { - throw new ConnectException("Failed to connect to WebSocket"); - } - } - - private void setWebSocketListener() { - webSocketClient.setListener( - new WebSocketListener() { - @Override - public void onMessage(String message) throws IOException { - onWebSocketMessage(message); - } - - @Override - public void onError(Exception e) { - log.error("Received error from a WebSocket connection", e); - } - - @Override - public void onClose() { - onWebSocketClose(); - } - }); - } - - @Override - public T send(Request request, Class responseType) throws IOException { - try { - return sendAsync(request, responseType).get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IOException("Interrupted WebSocket request", e); - } catch (ExecutionException e) { - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } - - throw new RuntimeException("Unexpected exception", e.getCause()); - } - } - - @Override - public CompletableFuture sendAsync( - Request request, Class responseType) { - - CompletableFuture result = new CompletableFuture<>(); - long requestId = request.getId(); - requestForId.put(requestId, new WebSocketRequest<>(result, responseType)); - try { - sendRequest(request, requestId); - } catch (IOException e) { - closeRequest(requestId, e); - } - - return result; - } - - private void sendRequest(Request request, long requestId) throws JsonProcessingException { - String payload = objectMapper.writeValueAsString(request); - log.debug("Sending request: {}", payload); - webSocketClient.send(payload); - setRequestTimeout(requestId); - } - - private void setRequestTimeout(long requestId) { - executor.schedule( - () -> - closeRequest( - requestId, - new IOException(String.format("Request with id %d timed out", requestId))), - REQUEST_TIMEOUT, - TimeUnit.SECONDS); - } - - void closeRequest(long requestId, Exception e) { - CompletableFuture result = requestForId.get(requestId).getOnReply(); - requestForId.remove(requestId); - result.completeExceptionally(e); - } - - void onWebSocketMessage(String messageStr) throws IOException { - JsonNode replyJson = parseToTree(messageStr); - - if (isReply(replyJson)) { - processRequestReply(messageStr, replyJson); - } else if (isSubscriptionEvent(replyJson)) { - processSubscriptionEvent(messageStr, replyJson); - } else { - throw new IOException("Unknown message type"); - } - } - - private void processRequestReply(String replyStr, JsonNode replyJson) throws IOException { - long replyId = getReplyId(replyJson); - WebSocketRequest request = getAndRemoveRequest(replyId); - try { - Object reply = objectMapper.convertValue(replyJson, request.getResponseType()); - // Instead of sending a reply to a caller asynchronously we need to process it here - // to avoid race conditions we need to modify state of this class. - if (reply instanceof BcosSubscribe) { - processSubscriptionResponse(replyId, (BcosSubscribe) reply); - } - - sendReplyToListener(request, reply); - } catch (IllegalArgumentException e) { - sendExceptionToListener(replyStr, request, e); - } - } - - private void processSubscriptionResponse(long replyId, BcosSubscribe reply) throws IOException { - WebSocketSubscription subscription = subscriptionRequestForId.get(replyId); - processSubscriptionResponse(reply, subscription.getSubject(), subscription.getResponseType()); - } - - private > void processSubscriptionResponse( - BcosSubscribe subscriptionReply, BehaviorSubject subject, Class responseType) - throws IOException { - if (!subscriptionReply.hasError()) { - establishSubscription(subject, responseType, subscriptionReply); - } else { - reportSubscriptionError(subject, subscriptionReply); - } - } - - private > void establishSubscription( - BehaviorSubject subject, Class responseType, BcosSubscribe subscriptionReply) { - log.info("Subscribed to RPC events with id {}", subscriptionReply.getSubscriptionId()); - subscriptionForId.put( - subscriptionReply.getSubscriptionId(), new WebSocketSubscription<>(subject, responseType)); - } - - private > String getSubscriptionId(BehaviorSubject subject) { - return subscriptionForId - .entrySet() - .stream() - .filter(entry -> entry.getValue().getSubject() == subject) - .map(Map.Entry::getKey) - .findFirst() - .orElse(null); - } - - private > void reportSubscriptionError( - BehaviorSubject subject, BcosSubscribe subscriptionReply) { - Response.Error error = subscriptionReply.getError(); - log.error("Subscription request returned error: {}", error.getMessage()); - subject.onError( - new IOException( - String.format("Subscription request failed with error: %s", error.getMessage()))); - } - - private void sendReplyToListener(WebSocketRequest request, Object reply) { - request.getOnReply().complete(reply); - } - - private void sendExceptionToListener( - String replyStr, WebSocketRequest request, IllegalArgumentException e) { - request - .getOnReply() - .completeExceptionally( - new IOException( - String.format( - "Failed to parse '%s' as type %s", replyStr, request.getResponseType()), - e)); - } - - private void processSubscriptionEvent(String replyStr, JsonNode replyJson) { - log.info("Processing event: {}", replyStr); - String subscriptionId = extractSubscriptionId(replyJson); - WebSocketSubscription subscription = subscriptionForId.get(subscriptionId); - - if (subscription != null) { - sendEventToSubscriber(replyJson, subscription); - } else { - log.warn("No subscriber for WebSocket event with subscription id {}", subscriptionId); - } - } - - private String extractSubscriptionId(JsonNode replyJson) { - return replyJson.get("params").get("subscription").asText(); - } - - private void sendEventToSubscriber(JsonNode replyJson, WebSocketSubscription subscription) { - Object event = objectMapper.convertValue(replyJson, subscription.getResponseType()); - subscription.getSubject().onNext(event); - } - - private boolean isReply(JsonNode replyJson) { - return replyJson.has("id"); - } - - private boolean isSubscriptionEvent(JsonNode replyJson) { - return replyJson.has("method"); - } - - private JsonNode parseToTree(String replyStr) throws IOException { - try { - return objectMapper.readTree(replyStr); - } catch (IOException e) { - throw new IOException("Failed to parse incoming WebSocket message", e); - } - } - - private WebSocketRequest getAndRemoveRequest(long id) throws IOException { - if (!requestForId.containsKey(id)) { - throw new IOException(String.format("Received reply for unexpected request id: %d", id)); - } - WebSocketRequest request = requestForId.get(id); - requestForId.remove(id); - return request; - } - - private long getReplyId(JsonNode replyJson) throws IOException { - JsonNode idField = replyJson.get("id"); - if (idField == null) { - throw new IOException("'id' field is missing in the reply"); - } - - if (!idField.isIntegralNumber()) { - throw new IOException( - String.format("'id' expected to be long, but it is: '%s'", idField.asText())); - } - - return idField.longValue(); - } - - private static URI parseURI(String serverUrl) { - try { - return new URI(serverUrl); - } catch (URISyntaxException e) { - throw new RuntimeException(String.format("Failed to parse URL: '%s'", serverUrl), e); - } - } - - @Override - public > Flowable subscribe( - Request request, String unsubscribeMethod, Class responseType) { - // We can't use usual Observer since we can call "onError" - // before first client is subscribed and we need to - // preserve it - BehaviorSubject subject = BehaviorSubject.create(); - - // We need to subscribe synchronously, since if we return - // an Flowable to a client before we got a reply - // a client can unsubscribe before we know a subscription - // id and this can cause a race condition - subscribeToEventsStream(request, subject, responseType); - - return subject - .doOnDispose(() -> closeSubscription(subject, unsubscribeMethod)) - .toFlowable(BackpressureStrategy.BUFFER); - } - - private > void subscribeToEventsStream( - Request request, BehaviorSubject subject, Class responseType) { - - subscriptionRequestForId.put( - request.getId(), new WebSocketSubscription<>(subject, responseType)); - try { - send(request, BcosSubscribe.class); - } catch (IOException e) { - log.error("Failed to subscribe to RPC events with request id {}", request.getId()); - subject.onError(e); - } - } - - private > void closeSubscription( - BehaviorSubject subject, String unsubscribeMethod) { - String subscriptionId = getSubscriptionId(subject); - if (subscriptionId != null) { - subscriptionForId.remove(subscriptionId); - unsubscribeFromEventsStream(subscriptionId, unsubscribeMethod); - } else { - log.warn("Trying to unsubscribe from a non-existing subscription. Race condition?"); - } - } - - private void unsubscribeFromEventsStream(String subscriptionId, String unsubscribeMethod) { - sendAsync(unsubscribeRequest(subscriptionId, unsubscribeMethod), BcosUnsubscribe.class) - .thenAccept( - ethUnsubscribe -> { - log.debug("Successfully unsubscribed from subscription with id {}", subscriptionId); - }) - .exceptionally( - throwable -> { - log.error("Failed to unsubscribe from subscription with id {}", subscriptionId); - return null; - }); - } - - private Request unsubscribeRequest( - String subscriptionId, String unsubscribeMethod) { - return new Request<>( - unsubscribeMethod, Collections.singletonList(subscriptionId), this, BcosUnsubscribe.class); - } - - @Override - public void close() { - webSocketClient.close(); - executor.shutdown(); - } - - void onWebSocketClose() { - closeOutstandingRequests(); - closeOutstandingSubscriptions(); - } - - private void closeOutstandingRequests() { - requestForId - .values() - .forEach( - request -> { - request.getOnReply().completeExceptionally(new IOException("Connection was closed")); - }); - } - - private void closeOutstandingSubscriptions() { - subscriptionForId - .values() - .forEach( - subscription -> { - subscription.getSubject().onError(new IOException("Connection was closed")); - }); - } - - // Method visible for unit-tests - boolean isWaitingForReply(long requestId) { - return requestForId.containsKey(requestId); - } + private static final Logger log = LoggerFactory.getLogger(WebSocketService.class); + + // Timeout for JSON-RPC requests + static final long REQUEST_TIMEOUT = 60; + + // WebSocket client + private final WebSocketClient webSocketClient; + // Executor to schedule request timeouts + private final ScheduledExecutorService executor; + // Object mapper to map incoming JSON objects + private final ObjectMapper objectMapper; + + // Map of a sent request id to objects necessary to process this request + private Map> requestForId = new ConcurrentHashMap<>(); + // Map of a sent subscription request id to objects necessary to process + // subscription events + private Map> subscriptionRequestForId = + new ConcurrentHashMap<>(); + // Map of a subscription id to objects necessary to process incoming events + private Map> subscriptionForId = new ConcurrentHashMap<>(); + + public WebSocketService(String serverUrl, boolean includeRawResponses) { + this(new WebSocketClient(parseURI(serverUrl)), includeRawResponses); + } + + public WebSocketService(WebSocketClient webSocketClient, boolean includeRawResponses) { + this(webSocketClient, Executors.newScheduledThreadPool(1), includeRawResponses); + } + + public WebSocketService( + WebSocketClient webSocketClient, + ScheduledExecutorService executor, + boolean includeRawResponses) { + this.webSocketClient = webSocketClient; + this.executor = executor; + this.objectMapper = ObjectMapperFactory.getObjectMapper(includeRawResponses); + } + + /** + * Connect to a WebSocket server. + * + * @throws ConnectException thrown if failed to connect to the server via WebSocket protocol + */ + public void connect() throws ConnectException { + try { + connectToWebSocket(); + setWebSocketListener(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.warn("Interrupted while connecting via WebSocket protocol"); + } + } + + private void connectToWebSocket() throws InterruptedException, ConnectException { + boolean connected = webSocketClient.connectBlocking(); + if (!connected) { + throw new ConnectException("Failed to connect to WebSocket"); + } + } + + private void setWebSocketListener() { + webSocketClient.setListener( + new WebSocketListener() { + @Override + public void onMessage(String message) throws IOException { + onWebSocketMessage(message); + } + + @Override + public void onError(Exception e) { + log.error("Received error from a WebSocket connection", e); + } + + @Override + public void onClose() { + onWebSocketClose(); + } + }); + } + + @Override + public T send(Request request, Class responseType) throws IOException { + try { + return sendAsync(request, responseType).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException("Interrupted WebSocket request", e); + } catch (ExecutionException e) { + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } + + throw new RuntimeException("Unexpected exception", e.getCause()); + } + } + + @Override + public void sendOnly(Request request) throws IOException {} + + @Override + public CompletableFuture sendAsync( + Request request, Class responseType) { + + CompletableFuture result = new CompletableFuture<>(); + long requestId = request.getId(); + requestForId.put(requestId, new WebSocketRequest<>(result, responseType)); + try { + sendRequest(request, requestId); + } catch (IOException e) { + closeRequest(requestId, e); + } + + return result; + } + + private void sendRequest(Request request, long requestId) throws JsonProcessingException { + String payload = objectMapper.writeValueAsString(request); + log.debug("Sending request: {}", payload); + webSocketClient.send(payload); + setRequestTimeout(requestId); + } + + private void setRequestTimeout(long requestId) { + executor.schedule( + () -> + closeRequest( + requestId, + new IOException( + String.format("Request with id %d timed out", requestId))), + REQUEST_TIMEOUT, + TimeUnit.SECONDS); + } + + void closeRequest(long requestId, Exception e) { + CompletableFuture result = requestForId.get(requestId).getOnReply(); + requestForId.remove(requestId); + result.completeExceptionally(e); + } + + void onWebSocketMessage(String messageStr) throws IOException { + JsonNode replyJson = parseToTree(messageStr); + + if (isReply(replyJson)) { + processRequestReply(messageStr, replyJson); + } else if (isSubscriptionEvent(replyJson)) { + processSubscriptionEvent(messageStr, replyJson); + } else { + throw new IOException("Unknown message type"); + } + } + + private void processRequestReply(String replyStr, JsonNode replyJson) throws IOException { + long replyId = getReplyId(replyJson); + WebSocketRequest request = getAndRemoveRequest(replyId); + try { + Object reply = objectMapper.convertValue(replyJson, request.getResponseType()); + // Instead of sending a reply to a caller asynchronously we need to process it + // here + // to avoid race conditions we need to modify state of this class. + if (reply instanceof BcosSubscribe) { + processSubscriptionResponse(replyId, (BcosSubscribe) reply); + } + + sendReplyToListener(request, reply); + } catch (IllegalArgumentException e) { + sendExceptionToListener(replyStr, request, e); + } + } + + private void processSubscriptionResponse(long replyId, BcosSubscribe reply) throws IOException { + WebSocketSubscription subscription = subscriptionRequestForId.get(replyId); + processSubscriptionResponse( + reply, subscription.getSubject(), subscription.getResponseType()); + } + + private > void processSubscriptionResponse( + BcosSubscribe subscriptionReply, BehaviorSubject subject, Class responseType) + throws IOException { + if (!subscriptionReply.hasError()) { + establishSubscription(subject, responseType, subscriptionReply); + } else { + reportSubscriptionError(subject, subscriptionReply); + } + } + + private > void establishSubscription( + BehaviorSubject subject, Class responseType, BcosSubscribe subscriptionReply) { + log.info("Subscribed to RPC events with id {}", subscriptionReply.getSubscriptionId()); + subscriptionForId.put( + subscriptionReply.getSubscriptionId(), + new WebSocketSubscription<>(subject, responseType)); + } + + private > String getSubscriptionId(BehaviorSubject subject) { + return subscriptionForId + .entrySet() + .stream() + .filter(entry -> entry.getValue().getSubject() == subject) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); + } + + private > void reportSubscriptionError( + BehaviorSubject subject, BcosSubscribe subscriptionReply) { + Response.Error error = subscriptionReply.getError(); + log.error("Subscription request returned error: {}", error.getMessage()); + subject.onError( + new IOException( + String.format( + "Subscription request failed with error: %s", error.getMessage()))); + } + + private void sendReplyToListener(WebSocketRequest request, Object reply) { + request.getOnReply().complete(reply); + } + + private void sendExceptionToListener( + String replyStr, WebSocketRequest request, IllegalArgumentException e) { + request.getOnReply() + .completeExceptionally( + new IOException( + String.format( + "Failed to parse '%s' as type %s", + replyStr, request.getResponseType()), + e)); + } + + private void processSubscriptionEvent(String replyStr, JsonNode replyJson) { + log.info("Processing event: {}", replyStr); + String subscriptionId = extractSubscriptionId(replyJson); + WebSocketSubscription subscription = subscriptionForId.get(subscriptionId); + + if (subscription != null) { + sendEventToSubscriber(replyJson, subscription); + } else { + log.warn("No subscriber for WebSocket event with subscription id {}", subscriptionId); + } + } + + private String extractSubscriptionId(JsonNode replyJson) { + return replyJson.get("params").get("subscription").asText(); + } + + private void sendEventToSubscriber(JsonNode replyJson, WebSocketSubscription subscription) { + Object event = objectMapper.convertValue(replyJson, subscription.getResponseType()); + subscription.getSubject().onNext(event); + } + + private boolean isReply(JsonNode replyJson) { + return replyJson.has("id"); + } + + private boolean isSubscriptionEvent(JsonNode replyJson) { + return replyJson.has("method"); + } + + private JsonNode parseToTree(String replyStr) throws IOException { + try { + return objectMapper.readTree(replyStr); + } catch (IOException e) { + throw new IOException("Failed to parse incoming WebSocket message", e); + } + } + + private WebSocketRequest getAndRemoveRequest(long id) throws IOException { + if (!requestForId.containsKey(id)) { + throw new IOException( + String.format("Received reply for unexpected request id: %d", id)); + } + WebSocketRequest request = requestForId.get(id); + requestForId.remove(id); + return request; + } + + private long getReplyId(JsonNode replyJson) throws IOException { + JsonNode idField = replyJson.get("id"); + if (idField == null) { + throw new IOException("'id' field is missing in the reply"); + } + + if (!idField.isIntegralNumber()) { + throw new IOException( + String.format("'id' expected to be long, but it is: '%s'", idField.asText())); + } + + return idField.longValue(); + } + + private static URI parseURI(String serverUrl) { + try { + return new URI(serverUrl); + } catch (URISyntaxException e) { + throw new RuntimeException(String.format("Failed to parse URL: '%s'", serverUrl), e); + } + } + + @Override + public > Flowable subscribe( + Request request, String unsubscribeMethod, Class responseType) { + // We can't use usual Observer since we can call "onError" + // before first client is subscribed and we need to + // preserve it + BehaviorSubject subject = BehaviorSubject.create(); + + // We need to subscribe synchronously, since if we return + // an Flowable to a client before we got a reply + // a client can unsubscribe before we know a subscription + // id and this can cause a race condition + subscribeToEventsStream(request, subject, responseType); + + return subject.doOnDispose(() -> closeSubscription(subject, unsubscribeMethod)) + .toFlowable(BackpressureStrategy.BUFFER); + } + + private > void subscribeToEventsStream( + Request request, BehaviorSubject subject, Class responseType) { + + subscriptionRequestForId.put( + request.getId(), new WebSocketSubscription<>(subject, responseType)); + try { + send(request, BcosSubscribe.class); + } catch (IOException e) { + log.error("Failed to subscribe to RPC events with request id {}", request.getId()); + subject.onError(e); + } + } + + private > void closeSubscription( + BehaviorSubject subject, String unsubscribeMethod) { + String subscriptionId = getSubscriptionId(subject); + if (subscriptionId != null) { + subscriptionForId.remove(subscriptionId); + unsubscribeFromEventsStream(subscriptionId, unsubscribeMethod); + } else { + log.warn("Trying to unsubscribe from a non-existing subscription. Race condition?"); + } + } + + private void unsubscribeFromEventsStream(String subscriptionId, String unsubscribeMethod) { + sendAsync(unsubscribeRequest(subscriptionId, unsubscribeMethod), BcosUnsubscribe.class) + .thenAccept( + ethUnsubscribe -> { + log.debug( + "Successfully unsubscribed from subscription with id {}", + subscriptionId); + }) + .exceptionally( + throwable -> { + log.error( + "Failed to unsubscribe from subscription with id {}", + subscriptionId); + return null; + }); + } + + private Request unsubscribeRequest( + String subscriptionId, String unsubscribeMethod) { + return new Request<>( + unsubscribeMethod, + Collections.singletonList(subscriptionId), + this, + BcosUnsubscribe.class); + } + + @Override + public void close() { + webSocketClient.close(); + executor.shutdown(); + } + + void onWebSocketClose() { + closeOutstandingRequests(); + closeOutstandingSubscriptions(); + } + + private void closeOutstandingRequests() { + requestForId + .values() + .forEach( + request -> { + request.getOnReply() + .completeExceptionally( + new IOException("Connection was closed")); + }); + } + + private void closeOutstandingSubscriptions() { + subscriptionForId + .values() + .forEach( + subscription -> { + subscription + .getSubject() + .onError(new IOException("Connection was closed")); + }); + } + + // Method visible for unit-tests + boolean isWaitingForReply(long requestId) { + return requestForId.containsKey(requestId); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketSubscription.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketSubscription.java index f0e6cc9f3..0e26e1aed 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketSubscription.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/WebSocketSubscription.java @@ -8,25 +8,25 @@ * @param type of a data item that should be returned by a WebSocket subscription. */ public class WebSocketSubscription { - private BehaviorSubject subject; - private Class responseType; + private BehaviorSubject subject; + private Class responseType; - /** - * Creates WebSocketSubscription. - * - * @param subject used to send new data items to listeners - * @param responseType type of a data item returned by a WebSocket subscription - */ - public WebSocketSubscription(BehaviorSubject subject, Class responseType) { - this.subject = subject; - this.responseType = responseType; - } + /** + * Creates WebSocketSubscription. + * + * @param subject used to send new data items to listeners + * @param responseType type of a data item returned by a WebSocket subscription + */ + public WebSocketSubscription(BehaviorSubject subject, Class responseType) { + this.subject = subject; + this.responseType = responseType; + } - public BehaviorSubject getSubject() { - return subject; - } + public BehaviorSubject getSubject() { + return subject; + } - public Class getResponseType() { - return responseType; - } + public Class getResponseType() { + return responseType; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Log.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Log.java index 6f437a43d..d6160891b 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Log.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Log.java @@ -3,44 +3,44 @@ import java.util.List; public class Log { - private String address; - private String blockHash; - private String blockNumber; - private String data; - private String logIndex; - private List topics; - private String transactionHash; - private String transactionIndex; - - public String getAddress() { - return address; - } - - public String getBlockHash() { - return blockHash; - } - - public String getBlockNumber() { - return blockNumber; - } - - public String getData() { - return data; - } - - public String getLogIndex() { - return logIndex; - } - - public List getTopics() { - return topics; - } - - public String getTransactionHash() { - return transactionHash; - } - - public String getTransactionIndex() { - return transactionIndex; - } + private String address; + private String blockHash; + private String blockNumber; + private String data; + private String logIndex; + private List topics; + private String transactionHash; + private String transactionIndex; + + public String getAddress() { + return address; + } + + public String getBlockHash() { + return blockHash; + } + + public String getBlockNumber() { + return blockNumber; + } + + public String getData() { + return data; + } + + public String getLogIndex() { + return logIndex; + } + + public List getTopics() { + return topics; + } + + public String getTransactionHash() { + return transactionHash; + } + + public String getTransactionIndex() { + return transactionIndex; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NewHead.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NewHead.java index c418ac918..14bea9a6f 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NewHead.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NewHead.java @@ -1,79 +1,79 @@ package org.fisco.bcos.web3j.protocol.websocket.events; public class NewHead { - private String difficulty; - private String extraData; - private String gasLimit; - private String gasUsed; - private String hash; - private String logsBloom; - private String sealer; - private String nonce; - private String number; - private String parentHash; - private String receiptRoot; - private String sha3Uncles; - private String stateRoot; - private String timestamp; - private String transactionRoot; - - public String getDifficulty() { - return difficulty; - } - - public String getExtraData() { - return extraData; - } - - public String getGasLimit() { - return gasLimit; - } - - public String getGasUsed() { - return gasUsed; - } - - public String getHash() { - return hash; - } - - public String getLogsBloom() { - return logsBloom; - } - - public String getSealer() { - return sealer; - } - - public String getNonce() { - return nonce; - } - - public String getNumber() { - return number; - } - - public String getParentHash() { - return parentHash; - } - - public String getReceiptRoot() { - return receiptRoot; - } - - public String getSha3Uncles() { - return sha3Uncles; - } - - public String getStateRoot() { - return stateRoot; - } - - public String getTimestamp() { - return timestamp; - } - - public String getTransactionRoot() { - return transactionRoot; - } + private String difficulty; + private String extraData; + private String gasLimit; + private String gasUsed; + private String hash; + private String logsBloom; + private String sealer; + private String nonce; + private String number; + private String parentHash; + private String receiptRoot; + private String sha3Uncles; + private String stateRoot; + private String timestamp; + private String transactionRoot; + + public String getDifficulty() { + return difficulty; + } + + public String getExtraData() { + return extraData; + } + + public String getGasLimit() { + return gasLimit; + } + + public String getGasUsed() { + return gasUsed; + } + + public String getHash() { + return hash; + } + + public String getLogsBloom() { + return logsBloom; + } + + public String getSealer() { + return sealer; + } + + public String getNonce() { + return nonce; + } + + public String getNumber() { + return number; + } + + public String getParentHash() { + return parentHash; + } + + public String getReceiptRoot() { + return receiptRoot; + } + + public String getSha3Uncles() { + return sha3Uncles; + } + + public String getStateRoot() { + return stateRoot; + } + + public String getTimestamp() { + return timestamp; + } + + public String getTransactionRoot() { + return transactionRoot; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Notification.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Notification.java index 4d5d1c50b..c909b89ed 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Notification.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/Notification.java @@ -9,19 +9,19 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) public class Notification { - private String jsonrpc; - private String method; - private NotificationParams params; + private String jsonrpc; + private String method; + private NotificationParams params; - public String getJsonrpc() { - return jsonrpc; - } + public String getJsonrpc() { + return jsonrpc; + } - public String getMethod() { - return method; - } + public String getMethod() { + return method; + } - public NotificationParams getParams() { - return params; - } + public NotificationParams getParams() { + return params; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NotificationParams.java b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NotificationParams.java index 5e424ca01..45ad0e7ee 100644 --- a/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NotificationParams.java +++ b/src/main/java/org/fisco/bcos/web3j/protocol/websocket/events/NotificationParams.java @@ -9,14 +9,14 @@ */ @JsonIgnoreProperties(ignoreUnknown = true) public class NotificationParams { - private T result; - private String subsciption; + private T result; + private String subsciption; - public T getResult() { - return result; - } + public T getResult() { + return result; + } - public String getSubsciption() { - return subsciption; - } + public String getSubsciption() { + return subsciption; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/rlp/RlpDecoder.java b/src/main/java/org/fisco/bcos/web3j/rlp/RlpDecoder.java index ac8dfbfc9..375a4aba9 100644 --- a/src/main/java/org/fisco/bcos/web3j/rlp/RlpDecoder.java +++ b/src/main/java/org/fisco/bcos/web3j/rlp/RlpDecoder.java @@ -10,159 +10,160 @@ */ public class RlpDecoder { - /** - * [0x80] If a string is 0-55 bytes long, the RLP encoding consists of a single byte with value - * 0x80 plus the length of the string followed by the string. The range of the first byte is thus - * [0x80, 0xb7]. - */ - public static int OFFSET_SHORT_STRING = 0x80; - - /** - * [0xb7] If a string is more than 55 bytes long, the RLP encoding consists of a single byte with - * value 0xb7 plus the length of the length of the string in binary form, followed by the length - * of the string, followed by the string. For example, a length-1024 string would be encoded as - * \xb9\x04\x00 followed by the string. The range of the first byte is thus [0xb8, 0xbf]. - */ - public static int OFFSET_LONG_STRING = 0xb7; - - /** - * [0xc0] If the total payload of a list (i.e. the combined length of all its items) is 0-55 bytes - * long, the RLP encoding consists of a single byte with value 0xc0 plus the length of the list - * followed by the concatenation of the RLP encodings of the items. The range of the first byte is - * thus [0xc0, 0xf7]. - */ - public static int OFFSET_SHORT_LIST = 0xc0; + /** + * [0x80] If a string is 0-55 bytes long, the RLP encoding consists of a single byte with value + * 0x80 plus the length of the string followed by the string. The range of the first byte is + * thus [0x80, 0xb7]. + */ + public static int OFFSET_SHORT_STRING = 0x80; + + /** + * [0xb7] If a string is more than 55 bytes long, the RLP encoding consists of a single byte + * with value 0xb7 plus the length of the length of the string in binary form, followed by the + * length of the string, followed by the string. For example, a length-1024 string would be + * encoded as \xb9\x04\x00 followed by the string. The range of the first byte is thus [0xb8, + * 0xbf]. + */ + public static int OFFSET_LONG_STRING = 0xb7; + + /** + * [0xc0] If the total payload of a list (i.e. the combined length of all its items) is 0-55 + * bytes long, the RLP encoding consists of a single byte with value 0xc0 plus the length of the + * list followed by the concatenation of the RLP encodings of the items. The range of the first + * byte is thus [0xc0, 0xf7]. + */ + public static int OFFSET_SHORT_LIST = 0xc0; + + /** + * [0xf7] If the total payload of a list is more than 55 bytes long, the RLP encoding consists + * of a single byte with value 0xf7 plus the length of the length of the list in binary form, + * followed by the length of the list, followed by the concatenation of the RLP encodings of the + * items. The range of the first byte is thus [0xf8, 0xff]. + */ + public static int OFFSET_LONG_LIST = 0xf7; + + /** + * Parse wire byte[] message into RLP elements. + * + * @param rlpEncoded - RLP encoded byte-array + * @return recursive RLP structure + */ + public static RlpList decode(byte[] rlpEncoded) { + RlpList rlpList = new RlpList(new ArrayList<>()); + traverse(rlpEncoded, 0, rlpEncoded.length, rlpList); + return rlpList; + } + + private static void traverse(byte[] data, int startPos, int endPos, RlpList rlpList) { + + try { + if (data == null || data.length == 0) { + return; + } + + while (startPos < endPos) { + + int prefix = data[startPos] & 0xff; + + if (prefix < OFFSET_SHORT_STRING) { + + // 1. the data is a string if the range of the + // first byte(i.e. prefix) is [0x00, 0x7f], + // and the string is the first byte itself exactly; + + byte[] rlpData = {(byte) prefix}; + rlpList.getValues().add(RlpString.create(rlpData)); + startPos += 1; + + } else if (prefix == OFFSET_SHORT_STRING) { + + // null + rlpList.getValues().add(RlpString.create(new byte[0])); + startPos += 1; + + } else if (prefix > OFFSET_SHORT_STRING && prefix <= OFFSET_LONG_STRING) { - /** - * [0xf7] If the total payload of a list is more than 55 bytes long, the RLP encoding consists of - * a single byte with value 0xf7 plus the length of the length of the list in binary form, - * followed by the length of the list, followed by the concatenation of the RLP encodings of the - * items. The range of the first byte is thus [0xf8, 0xff]. - */ - public static int OFFSET_LONG_LIST = 0xf7; + // 2. the data is a string if the range of the + // first byte is [0x80, 0xb7], and the string + // which length is equal to the first byte minus 0x80 + // follows the first byte; - /** - * Parse wire byte[] message into RLP elements. - * - * @param rlpEncoded - RLP encoded byte-array - * @return recursive RLP structure - */ - public static RlpList decode(byte[] rlpEncoded) { - RlpList rlpList = new RlpList(new ArrayList<>()); - traverse(rlpEncoded, 0, rlpEncoded.length, rlpList); - return rlpList; - } - - private static void traverse(byte[] data, int startPos, int endPos, RlpList rlpList) { - - try { - if (data == null || data.length == 0) { - return; - } - - while (startPos < endPos) { - - int prefix = data[startPos] & 0xff; - - if (prefix < OFFSET_SHORT_STRING) { - - // 1. the data is a string if the range of the - // first byte(i.e. prefix) is [0x00, 0x7f], - // and the string is the first byte itself exactly; - - byte[] rlpData = {(byte) prefix}; - rlpList.getValues().add(RlpString.create(rlpData)); - startPos += 1; - - } else if (prefix == OFFSET_SHORT_STRING) { - - // null - rlpList.getValues().add(RlpString.create(new byte[0])); - startPos += 1; - - } else if (prefix > OFFSET_SHORT_STRING && prefix <= OFFSET_LONG_STRING) { - - // 2. the data is a string if the range of the - // first byte is [0x80, 0xb7], and the string - // which length is equal to the first byte minus 0x80 - // follows the first byte; - - byte strLen = (byte) (prefix - OFFSET_SHORT_STRING); - - byte[] rlpData = new byte[strLen]; - System.arraycopy(data, startPos + 1, rlpData, 0, strLen); - - rlpList.getValues().add(RlpString.create(rlpData)); - startPos += 1 + strLen; - - } else if (prefix > OFFSET_LONG_STRING && prefix < OFFSET_SHORT_LIST) { - - // 3. the data is a string if the range of the - // first byte is [0xb8, 0xbf], and the length of the - // string which length in bytes is equal to the - // first byte minus 0xb7 follows the first byte, - // and the string follows the length of the string; - - byte lenOfStrLen = (byte) (prefix - OFFSET_LONG_STRING); - int strLen = calcLength(lenOfStrLen, data, startPos); - - // now we can parse an item for data[1]..data[length] - byte[] rlpData = new byte[strLen]; - System.arraycopy(data, startPos + lenOfStrLen + 1, rlpData, 0, strLen); - - rlpList.getValues().add(RlpString.create(rlpData)); - startPos += lenOfStrLen + strLen + 1; - - } else if (prefix >= OFFSET_SHORT_LIST && prefix <= OFFSET_LONG_LIST) { + byte strLen = (byte) (prefix - OFFSET_SHORT_STRING); - // 4. the data is a list if the range of the - // first byte is [0xc0, 0xf7], and the concatenation of - // the RLP encodings of all items of the list which the - // total payload is equal to the first byte minus 0xc0 follows the first byte; + byte[] rlpData = new byte[strLen]; + System.arraycopy(data, startPos + 1, rlpData, 0, strLen); - byte listLen = (byte) (prefix - OFFSET_SHORT_LIST); + rlpList.getValues().add(RlpString.create(rlpData)); + startPos += 1 + strLen; - RlpList newLevelList = new RlpList(new ArrayList<>()); - traverse(data, startPos + 1, startPos + listLen + 1, newLevelList); - rlpList.getValues().add(newLevelList); + } else if (prefix > OFFSET_LONG_STRING && prefix < OFFSET_SHORT_LIST) { - startPos += 1 + listLen; + // 3. the data is a string if the range of the + // first byte is [0xb8, 0xbf], and the length of the + // string which length in bytes is equal to the + // first byte minus 0xb7 follows the first byte, + // and the string follows the length of the string; - } else if (prefix > OFFSET_LONG_LIST) { + byte lenOfStrLen = (byte) (prefix - OFFSET_LONG_STRING); + int strLen = calcLength(lenOfStrLen, data, startPos); - // 5. the data is a list if the range of the - // first byte is [0xf8, 0xff], and the total payload of the - // list which length is equal to the - // first byte minus 0xf7 follows the first byte, - // and the concatenation of the RLP encodings of all items of - // the list follows the total payload of the list; + // now we can parse an item for data[1]..data[length] + byte[] rlpData = new byte[strLen]; + System.arraycopy(data, startPos + lenOfStrLen + 1, rlpData, 0, strLen); - byte lenOfListLen = (byte) (prefix - OFFSET_LONG_LIST); - int listLen = calcLength(lenOfListLen, data, startPos); + rlpList.getValues().add(RlpString.create(rlpData)); + startPos += lenOfStrLen + strLen + 1; - RlpList newLevelList = new RlpList(new ArrayList<>()); - traverse( - data, - startPos + lenOfListLen + 1, - startPos + lenOfListLen + listLen + 1, - newLevelList); - rlpList.getValues().add(newLevelList); + } else if (prefix >= OFFSET_SHORT_LIST && prefix <= OFFSET_LONG_LIST) { - startPos += lenOfListLen + listLen + 1; + // 4. the data is a list if the range of the + // first byte is [0xc0, 0xf7], and the concatenation of + // the RLP encodings of all items of the list which the + // total payload is equal to the first byte minus 0xc0 follows the first byte; + + byte listLen = (byte) (prefix - OFFSET_SHORT_LIST); + + RlpList newLevelList = new RlpList(new ArrayList<>()); + traverse(data, startPos + 1, startPos + listLen + 1, newLevelList); + rlpList.getValues().add(newLevelList); + + startPos += 1 + listLen; + + } else if (prefix > OFFSET_LONG_LIST) { + + // 5. the data is a list if the range of the + // first byte is [0xf8, 0xff], and the total payload of the + // list which length is equal to the + // first byte minus 0xf7 follows the first byte, + // and the concatenation of the RLP encodings of all items of + // the list follows the total payload of the list; + + byte lenOfListLen = (byte) (prefix - OFFSET_LONG_LIST); + int listLen = calcLength(lenOfListLen, data, startPos); + + RlpList newLevelList = new RlpList(new ArrayList<>()); + traverse( + data, + startPos + lenOfListLen + 1, + startPos + lenOfListLen + listLen + 1, + newLevelList); + rlpList.getValues().add(newLevelList); + + startPos += lenOfListLen + listLen + 1; + } + } + } catch (Exception e) { + throw new RuntimeException("RLP wrong encoding", e); } - } - } catch (Exception e) { - throw new RuntimeException("RLP wrong encoding", e); } - } - - private static int calcLength(int lengthOfLength, byte[] data, int pos) { - byte pow = (byte) (lengthOfLength - 1); - int length = 0; - for (int i = 1; i <= lengthOfLength; ++i) { - length += (data[pos + i] & 0xff) << (8 * pow); - pow--; + + private static int calcLength(int lengthOfLength, byte[] data, int pos) { + byte pow = (byte) (lengthOfLength - 1); + int length = 0; + for (int i = 1; i <= lengthOfLength; ++i) { + length += (data[pos + i] & 0xff) << (8 * pow); + pow--; + } + return length; } - return length; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/rlp/RlpEncoder.java b/src/main/java/org/fisco/bcos/web3j/rlp/RlpEncoder.java index c82f00e1d..8dcf1d186 100644 --- a/src/main/java/org/fisco/bcos/web3j/rlp/RlpEncoder.java +++ b/src/main/java/org/fisco/bcos/web3j/rlp/RlpEncoder.java @@ -14,77 +14,78 @@ */ public class RlpEncoder { - public static byte[] encode(RlpType value) { - if (value instanceof RlpString) { - return encodeString((RlpString) value); - } else { - return encodeList((RlpList) value); + public static byte[] encode(RlpType value) { + if (value instanceof RlpString) { + return encodeString((RlpString) value); + } else { + return encodeList((RlpList) value); + } } - } - private static byte[] encode(byte[] bytesValue, int offset) { - if (bytesValue.length == 1 - && offset == OFFSET_SHORT_STRING - && bytesValue[0] >= (byte) 0x00 - && bytesValue[0] <= (byte) 0x7f) { - return bytesValue; - } else if (bytesValue.length <= 55) { - byte[] result = new byte[bytesValue.length + 1]; - result[0] = (byte) (offset + bytesValue.length); - System.arraycopy(bytesValue, 0, result, 1, bytesValue.length); - return result; - } else { - byte[] encodedStringLength = toMinimalByteArray(bytesValue.length); - byte[] result = new byte[bytesValue.length + encodedStringLength.length + 1]; + private static byte[] encode(byte[] bytesValue, int offset) { + if (bytesValue.length == 1 + && offset == OFFSET_SHORT_STRING + && bytesValue[0] >= (byte) 0x00 + && bytesValue[0] <= (byte) 0x7f) { + return bytesValue; + } else if (bytesValue.length <= 55) { + byte[] result = new byte[bytesValue.length + 1]; + result[0] = (byte) (offset + bytesValue.length); + System.arraycopy(bytesValue, 0, result, 1, bytesValue.length); + return result; + } else { + byte[] encodedStringLength = toMinimalByteArray(bytesValue.length); + byte[] result = new byte[bytesValue.length + encodedStringLength.length + 1]; - result[0] = (byte) ((offset + 0x37) + encodedStringLength.length); - System.arraycopy(encodedStringLength, 0, result, 1, encodedStringLength.length); - System.arraycopy(bytesValue, 0, result, encodedStringLength.length + 1, bytesValue.length); - return result; + result[0] = (byte) ((offset + 0x37) + encodedStringLength.length); + System.arraycopy(encodedStringLength, 0, result, 1, encodedStringLength.length); + System.arraycopy( + bytesValue, 0, result, encodedStringLength.length + 1, bytesValue.length); + return result; + } } - } - static byte[] encodeString(RlpString value) { - return encode(value.getBytes(), OFFSET_SHORT_STRING); - } + static byte[] encodeString(RlpString value) { + return encode(value.getBytes(), OFFSET_SHORT_STRING); + } - private static byte[] toMinimalByteArray(int value) { - byte[] encoded = toByteArray(value); + private static byte[] toMinimalByteArray(int value) { + byte[] encoded = toByteArray(value); - for (int i = 0; i < encoded.length; i++) { - if (encoded[i] != 0) { - return Arrays.copyOfRange(encoded, i, encoded.length); - } - } + for (int i = 0; i < encoded.length; i++) { + if (encoded[i] != 0) { + return Arrays.copyOfRange(encoded, i, encoded.length); + } + } - return new byte[] {}; - } + return new byte[] {}; + } - private static byte[] toByteArray(int value) { - return new byte[] { - (byte) ((value >> 24) & 0xff), - (byte) ((value >> 16) & 0xff), - (byte) ((value >> 8) & 0xff), - (byte) (value & 0xff) - }; - } + private static byte[] toByteArray(int value) { + return new byte[] { + (byte) ((value >> 24) & 0xff), + (byte) ((value >> 16) & 0xff), + (byte) ((value >> 8) & 0xff), + (byte) (value & 0xff) + }; + } - static byte[] encodeList(RlpList value) { - List values = value.getValues(); - if (values.isEmpty()) { - return encode(new byte[] {}, OFFSET_SHORT_LIST); - } else { - byte[] result = new byte[0]; - for (RlpType entry : values) { - result = concat(result, encode(entry)); - } - return encode(result, OFFSET_SHORT_LIST); + static byte[] encodeList(RlpList value) { + List values = value.getValues(); + if (values.isEmpty()) { + return encode(new byte[] {}, OFFSET_SHORT_LIST); + } else { + byte[] result = new byte[0]; + for (RlpType entry : values) { + result = concat(result, encode(entry)); + } + return encode(result, OFFSET_SHORT_LIST); + } } - } - private static byte[] concat(byte[] b1, byte[] b2) { - byte[] result = Arrays.copyOf(b1, b1.length + b2.length); - System.arraycopy(b2, 0, result, b1.length, b2.length); - return result; - } + private static byte[] concat(byte[] b1, byte[] b2) { + byte[] result = Arrays.copyOf(b1, b1.length + b2.length); + System.arraycopy(b2, 0, result, b1.length, b2.length); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/rlp/RlpList.java b/src/main/java/org/fisco/bcos/web3j/rlp/RlpList.java index 2762da62e..3a0306e0c 100644 --- a/src/main/java/org/fisco/bcos/web3j/rlp/RlpList.java +++ b/src/main/java/org/fisco/bcos/web3j/rlp/RlpList.java @@ -5,17 +5,17 @@ /** RLP list type. */ public class RlpList implements RlpType { - private final List values; + private final List values; - public RlpList(RlpType... values) { - this.values = Arrays.asList(values); - } + public RlpList(RlpType... values) { + this.values = Arrays.asList(values); + } - public RlpList(List values) { - this.values = values; - } + public RlpList(List values) { + this.values = values; + } - public List getValues() { - return values; - } + public List getValues() { + return values; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/rlp/RlpString.java b/src/main/java/org/fisco/bcos/web3j/rlp/RlpString.java index c4d610237..1ea4b71a4 100644 --- a/src/main/java/org/fisco/bcos/web3j/rlp/RlpString.java +++ b/src/main/java/org/fisco/bcos/web3j/rlp/RlpString.java @@ -6,75 +6,75 @@ /** RLP string type. */ public class RlpString implements RlpType { - private static final byte[] EMPTY = new byte[] {}; + private static final byte[] EMPTY = new byte[] {}; - private final byte[] value; + private final byte[] value; - private RlpString(byte[] value) { - this.value = value; - } + private RlpString(byte[] value) { + this.value = value; + } - public byte[] getBytes() { - return value; - } + public byte[] getBytes() { + return value; + } - public BigInteger asPositiveBigInteger() { - if (value.length == 0) { - return BigInteger.ZERO; + public BigInteger asPositiveBigInteger() { + if (value.length == 0) { + return BigInteger.ZERO; + } + return new BigInteger(1, value); } - return new BigInteger(1, value); - } - - public String asString() { - return Numeric.toHexString(value); - } - - public static RlpString create(byte[] value) { - return new RlpString(value); - } - - public static RlpString create(byte value) { - return new RlpString(new byte[] {value}); - } - - public static RlpString create(BigInteger value) { - // RLP encoding only supports positive integer values - if (value.signum() < 1) { - return new RlpString(EMPTY); - } else { - byte[] bytes = value.toByteArray(); - if (bytes[0] == 0) { // remove leading zero - return new RlpString(Arrays.copyOfRange(bytes, 1, bytes.length)); - } else { - return new RlpString(bytes); - } + + public String asString() { + return Numeric.toHexString(value); } - } - public static RlpString create(long value) { - return create(BigInteger.valueOf(value)); - } + public static RlpString create(byte[] value) { + return new RlpString(value); + } - public static RlpString create(String value) { - return new RlpString(value.getBytes()); - } + public static RlpString create(byte value) { + return new RlpString(new byte[] {value}); + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public static RlpString create(BigInteger value) { + // RLP encoding only supports positive integer values + if (value.signum() < 1) { + return new RlpString(EMPTY); + } else { + byte[] bytes = value.toByteArray(); + if (bytes[0] == 0) { // remove leading zero + return new RlpString(Arrays.copyOfRange(bytes, 1, bytes.length)); + } else { + return new RlpString(bytes); + } + } } - if (o == null || getClass() != o.getClass()) { - return false; + + public static RlpString create(long value) { + return create(BigInteger.valueOf(value)); } - RlpString rlpString = (RlpString) o; + public static RlpString create(String value) { + return new RlpString(value.getBytes()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - return Arrays.equals(value, rlpString.value); - } + RlpString rlpString = (RlpString) o; - @Override - public int hashCode() { - return Arrays.hashCode(value); - } + return Arrays.equals(value, rlpString.value); + } + + @Override + public int hashCode() { + return Arrays.hashCode(value); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/Abi.java b/src/main/java/org/fisco/bcos/web3j/solidity/Abi.java index ba9e396f4..cc651b527 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/Abi.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/Abi.java @@ -41,296 +41,304 @@ import org.fisco.bcos.web3j.utils.ByteUtil; public class Abi extends ArrayList { - private static final ObjectMapper DEFAULT_MAPPER = - new ObjectMapper() - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); - - public static Abi fromJson(String json) { - try { - return DEFAULT_MAPPER.readValue(json, Abi.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public String toJson() { - try { - return new ObjectMapper().writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - private T find( - Class resultClass, final Entry.Type type, final Predicate searchPredicate) { - return (T) - CollectionUtils.find( - this, entry -> entry.type == type && searchPredicate.evaluate((T) entry)); - } - - public Function findFunction(Predicate searchPredicate) { - return find(Function.class, Entry.Type.function, searchPredicate); - } - - public Event findEvent(Predicate searchPredicate) { - return find(Event.class, Entry.Type.event, searchPredicate); - } - - public Constructor findConstructor() { - return find(Constructor.class, Entry.Type.constructor, object -> true); - } - - @Override - public String toString() { - return toJson(); - } - - @JsonInclude(Include.NON_NULL) - public abstract static class Entry { - - public enum Type { - constructor, - function, - event, - fallback + private static final ObjectMapper DEFAULT_MAPPER = + new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); + + public static Abi fromJson(String json) { + try { + return DEFAULT_MAPPER.readValue(json, Abi.class); + } catch (IOException e) { + throw new RuntimeException(e); + } } - @JsonInclude(Include.NON_NULL) - public static class Param { - public Boolean indexed; - public String name; - public SolidityType type; - - public static List decodeList(List params, byte[] encoded) { - List result = new ArrayList<>(params.size()); - - int offset = 0; - for (Param param : params) { - Object decoded = - param.type.isDynamicType() - ? param.type.decode(encoded, decodeInt(encoded, offset).intValue()) - : param.type.decode(encoded, offset); - result.add(decoded); - - offset += param.type.getFixedSize(); + public String toJson() { + try { + return new ObjectMapper().writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); } - - return result; - } - - @Override - public String toString() { - return format( - "%s%s%s", - type.getCanonicalName(), (indexed != null && indexed) ? " indexed " : " ", name); - } } - public final Boolean anonymous; - public final Boolean constant; - public final String name; - public final List inputs; - public final List outputs; - public final Type type; - public final Boolean payable; - - public Entry( - Boolean anonymous, - Boolean constant, - String name, - List inputs, - List outputs, - Type type, - Boolean payable) { - this.anonymous = anonymous; - this.constant = constant; - this.name = name; - this.inputs = inputs; - this.outputs = outputs; - this.type = type; - this.payable = payable; + private T find( + Class resultClass, final Entry.Type type, final Predicate searchPredicate) { + return (T) + CollectionUtils.find( + this, entry -> entry.type == type && searchPredicate.evaluate((T) entry)); } - public String formatSignature() { - StringBuilder paramsTypes = new StringBuilder(); - for (Entry.Param param : inputs) { - paramsTypes.append(param.type.getCanonicalName()).append(","); - } - - return format("%s(%s)", name, stripEnd(paramsTypes.toString(), ",")); + public Function findFunction(Predicate searchPredicate) { + return find(Function.class, Entry.Type.function, searchPredicate); } - public byte[] fingerprintSignature() { - return sha3(formatSignature().getBytes()); + public Event findEvent(Predicate searchPredicate) { + return find(Event.class, Entry.Type.event, searchPredicate); } - public byte[] encodeSignature() { - return fingerprintSignature(); + public Constructor findConstructor() { + return find(Constructor.class, Entry.Type.constructor, object -> true); } - @JsonCreator - public static Entry create( - @JsonProperty("anonymous") boolean anonymous, - @JsonProperty("constant") boolean constant, - @JsonProperty("name") String name, - @JsonProperty("inputs") List inputs, - @JsonProperty("outputs") List outputs, - @JsonProperty("type") Type type, - @JsonProperty(value = "payable", required = false, defaultValue = "false") - Boolean payable) { - Entry result = null; - switch (type) { - case constructor: - result = new Constructor(inputs, outputs); - break; - case function: - case fallback: - result = new Function(constant, name, inputs, outputs, payable); - break; - case event: - result = new Event(anonymous, name, inputs, outputs); - break; - } - - return result; + @Override + public String toString() { + return toJson(); } - } - public static class Constructor extends Entry { + @JsonInclude(Include.NON_NULL) + public abstract static class Entry { - public Constructor(List inputs, List outputs) { - super(null, null, "", inputs, outputs, Type.constructor, false); - } + public enum Type { + constructor, + function, + event, + fallback + } - public List decode(byte[] encoded) { - return Param.decodeList(inputs, encoded); - } + @JsonInclude(Include.NON_NULL) + public static class Param { + public Boolean indexed; + public String name; + public SolidityType type; + + public static List decodeList(List params, byte[] encoded) { + List result = new ArrayList<>(params.size()); + + int offset = 0; + for (Param param : params) { + Object decoded = + param.type.isDynamicType() + ? param.type.decode( + encoded, decodeInt(encoded, offset).intValue()) + : param.type.decode(encoded, offset); + result.add(decoded); + + offset += param.type.getFixedSize(); + } + + return result; + } + + @Override + public String toString() { + return format( + "%s%s%s", + type.getCanonicalName(), + (indexed != null && indexed) ? " indexed " : " ", + name); + } + } - public String formatSignature(String contractName) { - return format("function %s(%s)", contractName, join(inputs, ", ")); - } - } + public final Boolean anonymous; + public final Boolean constant; + public final String name; + public final List inputs; + public final List outputs; + public final Type type; + public final Boolean payable; + + public Entry( + Boolean anonymous, + Boolean constant, + String name, + List inputs, + List outputs, + Type type, + Boolean payable) { + this.anonymous = anonymous; + this.constant = constant; + this.name = name; + this.inputs = inputs; + this.outputs = outputs; + this.type = type; + this.payable = payable; + } - public static class Function extends Entry { + public String formatSignature() { + StringBuilder paramsTypes = new StringBuilder(); + for (Entry.Param param : inputs) { + paramsTypes.append(param.type.getCanonicalName()).append(","); + } - private static final int ENCODED_SIGN_LENGTH = 4; + return format("%s(%s)", name, stripEnd(paramsTypes.toString(), ",")); + } - public Function( - boolean constant, String name, List inputs, List outputs, Boolean payable) { - super(null, constant, name, inputs, outputs, Type.function, payable); - } + public byte[] fingerprintSignature() { + return sha3(formatSignature().getBytes()); + } - public byte[] encode(Object... args) { - return ByteUtil.merge(encodeSignature(), encodeArguments(args)); - } + public byte[] encodeSignature() { + return fingerprintSignature(); + } - private byte[] encodeArguments(Object... args) { - if (args.length > inputs.size()) - throw new RuntimeException("Too many arguments: " + args.length + " > " + inputs.size()); - - int staticSize = 0; - int dynamicCnt = 0; - // calculating static size and number of dynamic params - for (int i = 0; i < args.length; i++) { - SolidityType type = inputs.get(i).type; - if (type.isDynamicType()) { - dynamicCnt++; + @JsonCreator + public static Entry create( + @JsonProperty("anonymous") boolean anonymous, + @JsonProperty("constant") boolean constant, + @JsonProperty("name") String name, + @JsonProperty("inputs") List inputs, + @JsonProperty("outputs") List outputs, + @JsonProperty("type") Type type, + @JsonProperty(value = "payable", required = false, defaultValue = "false") + Boolean payable) { + Entry result = null; + switch (type) { + case constructor: + result = new Constructor(inputs, outputs); + break; + case function: + case fallback: + result = new Function(constant, name, inputs, outputs, payable); + break; + case event: + result = new Event(anonymous, name, inputs, outputs); + break; + } + + return result; } - staticSize += type.getFixedSize(); - } - - byte[][] bb = new byte[args.length + dynamicCnt][]; - for (int curDynamicPtr = staticSize, curDynamicCnt = 0, i = 0; i < args.length; i++) { - SolidityType type = inputs.get(i).type; - if (type.isDynamicType()) { - byte[] dynBB = type.encode(args[i]); - bb[i] = encodeInt(curDynamicPtr); - bb[args.length + curDynamicCnt] = dynBB; - curDynamicCnt++; - curDynamicPtr += dynBB.length; - } else { - bb[i] = type.encode(args[i]); + } + + public static class Constructor extends Entry { + + public Constructor(List inputs, List outputs) { + super(null, null, "", inputs, outputs, Type.constructor, false); } - } - return ByteUtil.merge(bb); - } + public List decode(byte[] encoded) { + return Param.decodeList(inputs, encoded); + } - public List decode(byte[] encoded) { - return Param.decodeList(inputs, subarray(encoded, ENCODED_SIGN_LENGTH, encoded.length)); + public String formatSignature(String contractName) { + return format("function %s(%s)", contractName, join(inputs, ", ")); + } } - public List decodeResult(byte[] encoded) { - return Param.decodeList(outputs, encoded); - } + public static class Function extends Entry { - @Override - public byte[] encodeSignature() { - return extractSignature(super.encodeSignature()); - } + private static final int ENCODED_SIGN_LENGTH = 4; - public static byte[] extractSignature(byte[] data) { - return subarray(data, 0, ENCODED_SIGN_LENGTH); - } + public Function( + boolean constant, + String name, + List inputs, + List outputs, + Boolean payable) { + super(null, constant, name, inputs, outputs, Type.function, payable); + } - @Override - public String toString() { - String returnTail = ""; - if (constant) { - returnTail += " constant"; - } - if (!outputs.isEmpty()) { - List types = new ArrayList<>(); - for (Param output : outputs) { - types.add(output.type.getCanonicalName()); + public byte[] encode(Object... args) { + return ByteUtil.merge(encodeSignature(), encodeArguments(args)); } - returnTail += format(" returns(%s)", join(types, ", ")); - } - return format("function %s(%s)%s;", name, join(inputs, ", "), returnTail); - } - } + private byte[] encodeArguments(Object... args) { + if (args.length > inputs.size()) + throw new RuntimeException( + "Too many arguments: " + args.length + " > " + inputs.size()); + + int staticSize = 0; + int dynamicCnt = 0; + // calculating static size and number of dynamic params + for (int i = 0; i < args.length; i++) { + SolidityType type = inputs.get(i).type; + if (type.isDynamicType()) { + dynamicCnt++; + } + staticSize += type.getFixedSize(); + } + + byte[][] bb = new byte[args.length + dynamicCnt][]; + for (int curDynamicPtr = staticSize, curDynamicCnt = 0, i = 0; i < args.length; i++) { + SolidityType type = inputs.get(i).type; + if (type.isDynamicType()) { + byte[] dynBB = type.encode(args[i]); + bb[i] = encodeInt(curDynamicPtr); + bb[args.length + curDynamicCnt] = dynBB; + curDynamicCnt++; + curDynamicPtr += dynBB.length; + } else { + bb[i] = type.encode(args[i]); + } + } + + return ByteUtil.merge(bb); + } - public static class Event extends Entry { + public List decode(byte[] encoded) { + return Param.decodeList(inputs, subarray(encoded, ENCODED_SIGN_LENGTH, encoded.length)); + } - public Event(boolean anonymous, String name, List inputs, List outputs) { - super(anonymous, null, name, inputs, outputs, Type.event, false); - } + public List decodeResult(byte[] encoded) { + return Param.decodeList(outputs, encoded); + } - public List decode(byte[] data, byte[][] topics) { - List result = new ArrayList<>(inputs.size()); - - byte[][] argTopics = anonymous ? topics : subarray(topics, 1, topics.length); - List indexedParams = filteredInputs(true); - List indexed = new ArrayList<>(); - for (int i = 0; i < indexedParams.size(); i++) { - Object decodedTopic; - if (indexedParams.get(i).type.isDynamicType()) { - // If arrays (including string and bytes) are used as indexed arguments, - // the Keccak-256 hash of it is stored as topic instead. - decodedTopic = SolidityType.Bytes32Type.decodeBytes32(argTopics[i], 0); - } else { - decodedTopic = indexedParams.get(i).type.decode(argTopics[i]); + @Override + public byte[] encodeSignature() { + return extractSignature(super.encodeSignature()); } - indexed.add(decodedTopic); - } - List notIndexed = Param.decodeList(filteredInputs(false), data); - for (Param input : inputs) { - result.add(input.indexed ? indexed.remove(0) : notIndexed.remove(0)); - } + public static byte[] extractSignature(byte[] data) { + return subarray(data, 0, ENCODED_SIGN_LENGTH); + } - return result; + @Override + public String toString() { + String returnTail = ""; + if (constant) { + returnTail += " constant"; + } + if (!outputs.isEmpty()) { + List types = new ArrayList<>(); + for (Param output : outputs) { + types.add(output.type.getCanonicalName()); + } + returnTail += format(" returns(%s)", join(types, ", ")); + } + + return format("function %s(%s)%s;", name, join(inputs, ", "), returnTail); + } } - private List filteredInputs(final boolean indexed) { - return select(inputs, param -> param.indexed == indexed); - } + public static class Event extends Entry { - @Override - public String toString() { - return format("event %s(%s);", name, join(inputs, ", ")); + public Event(boolean anonymous, String name, List inputs, List outputs) { + super(anonymous, null, name, inputs, outputs, Type.event, false); + } + + public List decode(byte[] data, byte[][] topics) { + List result = new ArrayList<>(inputs.size()); + + byte[][] argTopics = anonymous ? topics : subarray(topics, 1, topics.length); + List indexedParams = filteredInputs(true); + List indexed = new ArrayList<>(); + for (int i = 0; i < indexedParams.size(); i++) { + Object decodedTopic; + if (indexedParams.get(i).type.isDynamicType()) { + // If arrays (including string and bytes) are used as indexed arguments, + // the Keccak-256 hash of it is stored as topic instead. + decodedTopic = SolidityType.Bytes32Type.decodeBytes32(argTopics[i], 0); + } else { + decodedTopic = indexedParams.get(i).type.decode(argTopics[i]); + } + indexed.add(decodedTopic); + } + List notIndexed = Param.decodeList(filteredInputs(false), data); + + for (Param input : inputs) { + result.add(input.indexed ? indexed.remove(0) : notIndexed.remove(0)); + } + + return result; + } + + private List filteredInputs(final boolean indexed) { + return select(inputs, param -> param.indexed == indexed); + } + + @Override + public String toString() { + return format("event %s(%s);", name, join(inputs, ", ")); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/SolidityType.java b/src/main/java/org/fisco/bcos/web3j/solidity/SolidityType.java index dd0c2d4a3..fc2718622 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/SolidityType.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/SolidityType.java @@ -30,520 +30,528 @@ import org.fisco.bcos.web3j.utils.ByteUtil; public abstract class SolidityType { - protected String name; - - public SolidityType(String name) { - this.name = name; - } - - /** The type name as it was specified in the interface description */ - public String getName() { - return name; - } - - /** - * The canonical type name (used for the method signature creation) E.g. 'int' - canonical - * 'int256' - */ - @JsonValue - public String getCanonicalName() { - return getName(); - } - - @JsonCreator - public static SolidityType getType(String typeName) { - if (typeName.contains("[")) return ArrayType.getType(typeName); - if ("bool".equals(typeName)) return new BoolType(); - if (typeName.startsWith("int")) return new IntType(typeName); - if (typeName.startsWith("uint")) return new UnsignedIntType(typeName); - if ("address".equals(typeName)) return new AddressType(); - if ("string".equals(typeName)) return new StringType(); - if ("bytes".equals(typeName)) return new BytesType(); - if ("function".equals(typeName)) return new FunctionType(); - if (typeName.startsWith("bytes")) return new Bytes32Type(typeName); - throw new RuntimeException("Unknown type: " + typeName); - } - - /** - * Encodes the value according to specific type rules - * - * @param value - */ - public abstract byte[] encode(Object value); - - public abstract Object decode(byte[] encoded, int offset); - - public Object decode(byte[] encoded) { - return decode(encoded, 0); - } - - /** - * @return fixed size in bytes. For the dynamic types returns IntType.getFixedSize() which is - * effectively the int offset to dynamic data - */ - public int getFixedSize() { - return 32; - } - - public boolean isDynamicType() { - return false; - } - - @Override - public String toString() { - return getName(); - } - - public abstract static class ArrayType extends SolidityType { - public static ArrayType getType(String typeName) { - int idx1 = typeName.indexOf("["); - int idx2 = typeName.indexOf("]", idx1); - if (idx1 + 1 == idx2) { - return new DynamicArrayType(typeName); - } else { - return new StaticArrayType(typeName); - } - } - - SolidityType elementType; + protected String name; - public ArrayType(String name) { - super(name); - int idx = name.indexOf("["); - String st = name.substring(0, idx); - int idx2 = name.indexOf("]", idx); - String subDim = idx2 + 1 == name.length() ? "" : name.substring(idx2 + 1); - elementType = SolidityType.getType(st + subDim); + public SolidityType(String name) { + this.name = name; } - @Override - public byte[] encode(Object value) { - if (value.getClass().isArray()) { - List elems = new ArrayList<>(); - for (int i = 0; i < Array.getLength(value); i++) { - elems.add(Array.get(value, i)); - } - return encodeList(elems); - } else if (value instanceof List) { - return encodeList((List) value); - } else { - throw new RuntimeException("List value expected for type " + getName()); - } + /** The type name as it was specified in the interface description */ + public String getName() { + return name; } - @Override + /** + * The canonical type name (used for the method signature creation) E.g. 'int' - canonical + * 'int256' + */ + @JsonValue public String getCanonicalName() { - return getArrayCanonicalName(""); + return getName(); } - String getArrayCanonicalName(String parentDimStr) { - String myDimStr = parentDimStr + getCanonicalDimension(); - if (getElementType() instanceof ArrayType) { - return ((ArrayType) getElementType()).getArrayCanonicalName(myDimStr); - } else { - return getElementType().getCanonicalName() + myDimStr; - } + @JsonCreator + public static SolidityType getType(String typeName) { + if (typeName.contains("[")) return ArrayType.getType(typeName); + if ("bool".equals(typeName)) return new BoolType(); + if (typeName.startsWith("int")) return new IntType(typeName); + if (typeName.startsWith("uint")) return new UnsignedIntType(typeName); + if ("address".equals(typeName)) return new AddressType(); + if ("string".equals(typeName)) return new StringType(); + if ("bytes".equals(typeName)) return new BytesType(); + if ("function".equals(typeName)) return new FunctionType(); + if (typeName.startsWith("bytes")) return new Bytes32Type(typeName); + throw new RuntimeException("Unknown type: " + typeName); } - protected abstract String getCanonicalDimension(); + /** + * Encodes the value according to specific type rules + * + * @param value + */ + public abstract byte[] encode(Object value); - public SolidityType getElementType() { - return elementType; - } + public abstract Object decode(byte[] encoded, int offset); - public abstract byte[] encodeList(List l); - } - - public static class StaticArrayType extends ArrayType { - int size; - - public StaticArrayType(String name) { - super(name); - int idx1 = name.indexOf("["); - int idx2 = name.indexOf("]", idx1); - String dim = name.substring(idx1 + 1, idx2); - size = Integer.parseInt(dim); + public Object decode(byte[] encoded) { + return decode(encoded, 0); } - @Override - public String getCanonicalName() { - if (elementType instanceof ArrayType) { - String elementTypeName = elementType.getCanonicalName(); - int idx1 = elementTypeName.indexOf("["); - return elementTypeName.substring(0, idx1) - + "[" - + size - + "]" - + elementTypeName.substring(idx1); - } else { - return elementType.getCanonicalName() + "[" + size + "]"; - } + /** + * @return fixed size in bytes. For the dynamic types returns IntType.getFixedSize() which is + * effectively the int offset to dynamic data + */ + public int getFixedSize() { + return 32; } - @Override - protected String getCanonicalDimension() { - return "[" + size + "]"; + public boolean isDynamicType() { + return false; } @Override - public byte[] encodeList(List l) { - if (l.size() != size) - throw new RuntimeException( - "List size (" + l.size() + ") != " + size + " for type " + getName()); - byte[][] elems = new byte[size][]; - for (int i = 0; i < l.size(); i++) { - elems[i] = elementType.encode(l.get(i)); - } - return ByteUtil.merge(elems); - } + public String toString() { + return getName(); + } + + public abstract static class ArrayType extends SolidityType { + public static ArrayType getType(String typeName) { + int idx1 = typeName.indexOf("["); + int idx2 = typeName.indexOf("]", idx1); + if (idx1 + 1 == idx2) { + return new DynamicArrayType(typeName); + } else { + return new StaticArrayType(typeName); + } + } - @Override - public Object[] decode(byte[] encoded, int offset) { - Object[] result = new Object[size]; - for (int i = 0; i < size; i++) { - result[i] = elementType.decode(encoded, offset + i * elementType.getFixedSize()); - } + SolidityType elementType; - return result; - } + public ArrayType(String name) { + super(name); + int idx = name.indexOf("["); + String st = name.substring(0, idx); + int idx2 = name.indexOf("]", idx); + String subDim = idx2 + 1 == name.length() ? "" : name.substring(idx2 + 1); + elementType = SolidityType.getType(st + subDim); + } - @Override - public int getFixedSize() { - // return negative if elementType is dynamic - return elementType.getFixedSize() * size; - } - } + @Override + public byte[] encode(Object value) { + if (value.getClass().isArray()) { + List elems = new ArrayList<>(); + for (int i = 0; i < Array.getLength(value); i++) { + elems.add(Array.get(value, i)); + } + return encodeList(elems); + } else if (value instanceof List) { + return encodeList((List) value); + } else { + throw new RuntimeException("List value expected for type " + getName()); + } + } - public static class DynamicArrayType extends ArrayType { - public DynamicArrayType(String name) { - super(name); - } + @Override + public String getCanonicalName() { + return getArrayCanonicalName(""); + } - @Override - public String getCanonicalName() { - if (elementType instanceof ArrayType) { - String elementTypeName = elementType.getCanonicalName(); - int idx1 = elementTypeName.indexOf("["); - return elementTypeName.substring(0, idx1) + "[]" + elementTypeName.substring(idx1); - } else { - return elementType.getCanonicalName() + "[]"; - } - } + String getArrayCanonicalName(String parentDimStr) { + String myDimStr = parentDimStr + getCanonicalDimension(); + if (getElementType() instanceof ArrayType) { + return ((ArrayType) getElementType()).getArrayCanonicalName(myDimStr); + } else { + return getElementType().getCanonicalName() + myDimStr; + } + } - @Override - protected String getCanonicalDimension() { - return "[]"; - } + protected abstract String getCanonicalDimension(); - @Override - public byte[] encodeList(List l) { - byte[][] elems; - if (elementType.isDynamicType()) { - elems = new byte[l.size() * 2 + 1][]; - elems[0] = IntType.encodeInt(l.size()); - int offset = l.size() * 32; - for (int i = 0; i < l.size(); i++) { - elems[i + 1] = IntType.encodeInt(offset); - byte[] encoded = elementType.encode(l.get(i)); - elems[l.size() + i + 1] = encoded; - offset += 32 * ((encoded.length - 1) / 32 + 1); - } - } else { - elems = new byte[l.size() + 1][]; - elems[0] = IntType.encodeInt(l.size()); - - for (int i = 0; i < l.size(); i++) { - elems[i + 1] = elementType.encode(l.get(i)); - } - } - return ByteUtil.merge(elems); - } + public SolidityType getElementType() { + return elementType; + } - @Override - public Object decode(byte[] encoded, int origOffset) { - int len = IntType.decodeInt(encoded, origOffset).intValue(); - origOffset += 32; - int offset = origOffset; - Object[] ret = new Object[len]; - - for (int i = 0; i < len; i++) { - if (elementType.isDynamicType()) { - ret[i] = - elementType.decode( - encoded, origOffset + IntType.decodeInt(encoded, offset).intValue()); - } else { - ret[i] = elementType.decode(encoded, offset); - } - offset += elementType.getFixedSize(); - } - return ret; + public abstract byte[] encodeList(List l); } - @Override - public boolean isDynamicType() { - return true; - } - } + public static class StaticArrayType extends ArrayType { + int size; - public static class BytesType extends SolidityType { - protected BytesType(String name) { - super(name); - } + public StaticArrayType(String name) { + super(name); + int idx1 = name.indexOf("["); + int idx2 = name.indexOf("]", idx1); + String dim = name.substring(idx1 + 1, idx2); + size = Integer.parseInt(dim); + } - public BytesType() { - super("bytes"); - } + @Override + public String getCanonicalName() { + if (elementType instanceof ArrayType) { + String elementTypeName = elementType.getCanonicalName(); + int idx1 = elementTypeName.indexOf("["); + return elementTypeName.substring(0, idx1) + + "[" + + size + + "]" + + elementTypeName.substring(idx1); + } else { + return elementType.getCanonicalName() + "[" + size + "]"; + } + } - @Override - public byte[] encode(Object value) { - byte[] bb; - if (value instanceof byte[]) { - bb = (byte[]) value; - } else if (value instanceof String) { - bb = ((String) value).getBytes(); - } else { - throw new RuntimeException("byte[] or String value is expected for type 'bytes'"); - } - byte[] ret = new byte[((bb.length - 1) / 32 + 1) * 32]; // padding 32 bytes - System.arraycopy(bb, 0, ret, 0, bb.length); - - return ByteUtil.merge(IntType.encodeInt(bb.length), ret); - } + @Override + protected String getCanonicalDimension() { + return "[" + size + "]"; + } - @Override - public Object decode(byte[] encoded, int offset) { - int len = IntType.decodeInt(encoded, offset).intValue(); - if (len == 0) return new byte[0]; - offset += 32; - return Arrays.copyOfRange(encoded, offset, offset + len); - } + @Override + public byte[] encodeList(List l) { + if (l.size() != size) + throw new RuntimeException( + "List size (" + l.size() + ") != " + size + " for type " + getName()); + byte[][] elems = new byte[size][]; + for (int i = 0; i < l.size(); i++) { + elems[i] = elementType.encode(l.get(i)); + } + return ByteUtil.merge(elems); + } - @Override - public boolean isDynamicType() { - return true; - } - } + @Override + public Object[] decode(byte[] encoded, int offset) { + Object[] result = new Object[size]; + for (int i = 0; i < size; i++) { + result[i] = elementType.decode(encoded, offset + i * elementType.getFixedSize()); + } - public static class StringType extends BytesType { - public StringType() { - super("string"); - } + return result; + } - @Override - public byte[] encode(Object value) { - if (!(value instanceof String)) - throw new RuntimeException("String value expected for type 'string'"); - return super.encode(((String) value).getBytes(StandardCharsets.UTF_8)); + @Override + public int getFixedSize() { + // return negative if elementType is dynamic + return elementType.getFixedSize() * size; + } } - @Override - public Object decode(byte[] encoded, int offset) { - return new String((byte[]) super.decode(encoded, offset), StandardCharsets.UTF_8); - } - } + public static class DynamicArrayType extends ArrayType { + public DynamicArrayType(String name) { + super(name); + } - public static class Bytes32Type extends SolidityType { - public Bytes32Type(String s) { - super(s); - } + @Override + public String getCanonicalName() { + if (elementType instanceof ArrayType) { + String elementTypeName = elementType.getCanonicalName(); + int idx1 = elementTypeName.indexOf("["); + return elementTypeName.substring(0, idx1) + "[]" + elementTypeName.substring(idx1); + } else { + return elementType.getCanonicalName() + "[]"; + } + } - @Override - public byte[] encode(Object value) { - if (value instanceof Number) { - BigInteger bigInt = new BigInteger(value.toString()); - return IntType.encodeInt(bigInt); - } else if (value instanceof String) { - byte[] ret = new byte[32]; - byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8); - System.arraycopy(bytes, 0, ret, 0, bytes.length); - return ret; - } else if (value instanceof byte[]) { - byte[] bytes = (byte[]) value; - byte[] ret = new byte[32]; - System.arraycopy(bytes, 0, ret, 32 - bytes.length, bytes.length); - return ret; - } - - throw new RuntimeException("Can't encode java type " + value.getClass() + " to bytes32"); - } + @Override + protected String getCanonicalDimension() { + return "[]"; + } - @Override - public Object decode(byte[] encoded, int offset) { - return decodeBytes32(encoded, offset); - } + @Override + public byte[] encodeList(List l) { + byte[][] elems; + if (elementType.isDynamicType()) { + elems = new byte[l.size() * 2 + 1][]; + elems[0] = IntType.encodeInt(l.size()); + int offset = l.size() * 32; + for (int i = 0; i < l.size(); i++) { + elems[i + 1] = IntType.encodeInt(offset); + byte[] encoded = elementType.encode(l.get(i)); + elems[l.size() + i + 1] = encoded; + offset += 32 * ((encoded.length - 1) / 32 + 1); + } + } else { + elems = new byte[l.size() + 1][]; + elems[0] = IntType.encodeInt(l.size()); + + for (int i = 0; i < l.size(); i++) { + elems[i + 1] = elementType.encode(l.get(i)); + } + } + return ByteUtil.merge(elems); + } - public static byte[] decodeBytes32(byte[] encoded, int offset) { - return Arrays.copyOfRange(encoded, offset, offset + 32); - } - } + @Override + public Object decode(byte[] encoded, int origOffset) { + int len = IntType.decodeInt(encoded, origOffset).intValue(); + origOffset += 32; + int offset = origOffset; + Object[] ret = new Object[len]; + + for (int i = 0; i < len; i++) { + if (elementType.isDynamicType()) { + ret[i] = + elementType.decode( + encoded, + origOffset + IntType.decodeInt(encoded, offset).intValue()); + } else { + ret[i] = elementType.decode(encoded, offset); + } + offset += elementType.getFixedSize(); + } + return ret; + } - public static class AddressType extends IntType { - public AddressType() { - super("address"); + @Override + public boolean isDynamicType() { + return true; + } } - @Override - public byte[] encode(Object value) { - if (value instanceof String && !((String) value).startsWith("0x")) { - // address is supposed to be always in hex - value = "0x" + value; - } - byte[] addr = super.encode(value); - for (int i = 0; i < 12; i++) { - if (addr[i] != 0) { - throw new RuntimeException( - "Invalid address (should be 20 bytes length): " + toHexString(addr)); - } - } - return addr; - } + public static class BytesType extends SolidityType { + protected BytesType(String name) { + super(name); + } - @Override - public Object decode(byte[] encoded, int offset) { - BigInteger bi = (BigInteger) super.decode(encoded, offset); - return ByteUtil.bigIntegerToBytes(bi, 20); - } - } + public BytesType() { + super("bytes"); + } - public abstract static class NumericType extends SolidityType { - public NumericType(String name) { - super(name); - } + @Override + public byte[] encode(Object value) { + byte[] bb; + if (value instanceof byte[]) { + bb = (byte[]) value; + } else if (value instanceof String) { + bb = ((String) value).getBytes(); + } else { + throw new RuntimeException("byte[] or String value is expected for type 'bytes'"); + } + byte[] ret = new byte[((bb.length - 1) / 32 + 1) * 32]; // padding 32 bytes + System.arraycopy(bb, 0, ret, 0, bb.length); + + return ByteUtil.merge(IntType.encodeInt(bb.length), ret); + } - BigInteger encodeInternal(Object value) { - BigInteger bigInt; - if (value instanceof String) { - String s = ((String) value).toLowerCase().trim(); - int radix = 10; - if (s.startsWith("0x")) { - s = s.substring(2); - radix = 16; - } else if (s.contains("a") - || s.contains("b") - || s.contains("c") - || s.contains("d") - || s.contains("e") - || s.contains("f")) { - radix = 16; - } - bigInt = new BigInteger(s, radix); - } else if (value instanceof BigInteger) { - bigInt = (BigInteger) value; - } else if (value instanceof Number) { - bigInt = new BigInteger(value.toString()); - } else if (value instanceof byte[]) { - bigInt = ByteUtil.bytesToBigInteger((byte[]) value); - } else { - throw new RuntimeException( - "Invalid value for type '" + this + "': " + value + " (" + value.getClass() + ")"); - } - return bigInt; - } - } + @Override + public Object decode(byte[] encoded, int offset) { + int len = IntType.decodeInt(encoded, offset).intValue(); + if (len == 0) return new byte[0]; + offset += 32; + return Arrays.copyOfRange(encoded, offset, offset + len); + } - public static class IntType extends NumericType { - public IntType(String name) { - super(name); + @Override + public boolean isDynamicType() { + return true; + } } - @Override - public String getCanonicalName() { - if (getName().equals("int")) return "int256"; - return super.getCanonicalName(); - } + public static class StringType extends BytesType { + public StringType() { + super("string"); + } - public static BigInteger decodeInt(byte[] encoded, int offset) { - return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + 32)); - } + @Override + public byte[] encode(Object value) { + if (!(value instanceof String)) + throw new RuntimeException("String value expected for type 'string'"); + return super.encode(((String) value).getBytes(StandardCharsets.UTF_8)); + } - public static byte[] encodeInt(int i) { - return encodeInt(new BigInteger("" + i)); + @Override + public Object decode(byte[] encoded, int offset) { + return new String((byte[]) super.decode(encoded, offset), StandardCharsets.UTF_8); + } } - public static byte[] encodeInt(BigInteger bigInt) { - return ByteUtil.bigIntegerToBytesSigned(bigInt, 32); - } + public static class Bytes32Type extends SolidityType { + public Bytes32Type(String s) { + super(s); + } - @Override - public Object decode(byte[] encoded, int offset) { - return decodeInt(encoded, offset); - } + @Override + public byte[] encode(Object value) { + if (value instanceof Number) { + BigInteger bigInt = new BigInteger(value.toString()); + return IntType.encodeInt(bigInt); + } else if (value instanceof String) { + byte[] ret = new byte[32]; + byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8); + System.arraycopy(bytes, 0, ret, 0, bytes.length); + return ret; + } else if (value instanceof byte[]) { + byte[] bytes = (byte[]) value; + byte[] ret = new byte[32]; + System.arraycopy(bytes, 0, ret, 32 - bytes.length, bytes.length); + return ret; + } + + throw new RuntimeException( + "Can't encode java type " + value.getClass() + " to bytes32"); + } - @Override - public byte[] encode(Object value) { - BigInteger bigInt = encodeInternal(value); - return encodeInt(bigInt); - } - } + @Override + public Object decode(byte[] encoded, int offset) { + return decodeBytes32(encoded, offset); + } - public static class UnsignedIntType extends NumericType { - public UnsignedIntType(String name) { - super(name); + public static byte[] decodeBytes32(byte[] encoded, int offset) { + return Arrays.copyOfRange(encoded, offset, offset + 32); + } } - @Override - public String getCanonicalName() { - if (getName().equals("uint")) return "uint256"; - return super.getCanonicalName(); - } + public static class AddressType extends IntType { + public AddressType() { + super("address"); + } - public static BigInteger decodeInt(byte[] encoded, int offset) { - return new BigInteger(1, Arrays.copyOfRange(encoded, offset, offset + 32)); - } + @Override + public byte[] encode(Object value) { + if (value instanceof String && !((String) value).startsWith("0x")) { + // address is supposed to be always in hex + value = "0x" + value; + } + byte[] addr = super.encode(value); + for (int i = 0; i < 12; i++) { + if (addr[i] != 0) { + throw new RuntimeException( + "Invalid address (should be 20 bytes length): " + toHexString(addr)); + } + } + return addr; + } - public static byte[] encodeInt(int i) { - return encodeInt(new BigInteger("" + i)); + @Override + public Object decode(byte[] encoded, int offset) { + BigInteger bi = (BigInteger) super.decode(encoded, offset); + return ByteUtil.bigIntegerToBytes(bi, 20); + } } - public static byte[] encodeInt(BigInteger bigInt) { - if (bigInt.signum() == -1) { - throw new RuntimeException("Wrong value for uint type: " + bigInt); - } - return ByteUtil.bigIntegerToBytes(bigInt, 32); - } + public abstract static class NumericType extends SolidityType { + public NumericType(String name) { + super(name); + } - @Override - public byte[] encode(Object value) { - BigInteger bigInt = encodeInternal(value); - return encodeInt(bigInt); + BigInteger encodeInternal(Object value) { + BigInteger bigInt; + if (value instanceof String) { + String s = ((String) value).toLowerCase().trim(); + int radix = 10; + if (s.startsWith("0x")) { + s = s.substring(2); + radix = 16; + } else if (s.contains("a") + || s.contains("b") + || s.contains("c") + || s.contains("d") + || s.contains("e") + || s.contains("f")) { + radix = 16; + } + bigInt = new BigInteger(s, radix); + } else if (value instanceof BigInteger) { + bigInt = (BigInteger) value; + } else if (value instanceof Number) { + bigInt = new BigInteger(value.toString()); + } else if (value instanceof byte[]) { + bigInt = ByteUtil.bytesToBigInteger((byte[]) value); + } else { + throw new RuntimeException( + "Invalid value for type '" + + this + + "': " + + value + + " (" + + value.getClass() + + ")"); + } + return bigInt; + } } - @Override - public Object decode(byte[] encoded, int offset) { - return decodeInt(encoded, offset); - } - } + public static class IntType extends NumericType { + public IntType(String name) { + super(name); + } - public static class BoolType extends IntType { - public BoolType() { - super("bool"); - } + @Override + public String getCanonicalName() { + if (getName().equals("int")) return "int256"; + return super.getCanonicalName(); + } - @Override - public byte[] encode(Object value) { - if (!(value instanceof Boolean)) - throw new RuntimeException("Wrong value for bool type: " + value); - return super.encode(value == Boolean.TRUE ? 1 : 0); + public static BigInteger decodeInt(byte[] encoded, int offset) { + return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + 32)); + } + + public static byte[] encodeInt(int i) { + return encodeInt(new BigInteger("" + i)); + } + + public static byte[] encodeInt(BigInteger bigInt) { + return ByteUtil.bigIntegerToBytesSigned(bigInt, 32); + } + + @Override + public Object decode(byte[] encoded, int offset) { + return decodeInt(encoded, offset); + } + + @Override + public byte[] encode(Object value) { + BigInteger bigInt = encodeInternal(value); + return encodeInt(bigInt); + } } - @Override - public Object decode(byte[] encoded, int offset) { - return Boolean.valueOf(((Number) super.decode(encoded, offset)).intValue() != 0); + public static class UnsignedIntType extends NumericType { + public UnsignedIntType(String name) { + super(name); + } + + @Override + public String getCanonicalName() { + if (getName().equals("uint")) return "uint256"; + return super.getCanonicalName(); + } + + public static BigInteger decodeInt(byte[] encoded, int offset) { + return new BigInteger(1, Arrays.copyOfRange(encoded, offset, offset + 32)); + } + + public static byte[] encodeInt(int i) { + return encodeInt(new BigInteger("" + i)); + } + + public static byte[] encodeInt(BigInteger bigInt) { + if (bigInt.signum() == -1) { + throw new RuntimeException("Wrong value for uint type: " + bigInt); + } + return ByteUtil.bigIntegerToBytes(bigInt, 32); + } + + @Override + public byte[] encode(Object value) { + BigInteger bigInt = encodeInternal(value); + return encodeInt(bigInt); + } + + @Override + public Object decode(byte[] encoded, int offset) { + return decodeInt(encoded, offset); + } } - } - public static class FunctionType extends Bytes32Type { - public FunctionType() { - super("function"); + public static class BoolType extends IntType { + public BoolType() { + super("bool"); + } + + @Override + public byte[] encode(Object value) { + if (!(value instanceof Boolean)) + throw new RuntimeException("Wrong value for bool type: " + value); + return super.encode(value == Boolean.TRUE ? 1 : 0); + } + + @Override + public Object decode(byte[] encoded, int offset) { + return Boolean.valueOf(((Number) super.decode(encoded, offset)).intValue() != 0); + } } - @Override - public byte[] encode(Object value) { - if (!(value instanceof byte[])) - throw new RuntimeException("Expected byte[] value for FunctionType"); - if (((byte[]) value).length != 24) - throw new RuntimeException("Expected byte[24] for FunctionType"); - return super.encode(ByteUtil.merge((byte[]) value, new byte[8])); + public static class FunctionType extends Bytes32Type { + public FunctionType() { + super("function"); + } + + @Override + public byte[] encode(Object value) { + if (!(value instanceof byte[])) + throw new RuntimeException("Expected byte[] value for FunctionType"); + if (((byte[]) value).length != 24) + throw new RuntimeException("Expected byte[24] for FunctionType"); + return super.encode(ByteUtil.merge((byte[]) value, new byte[8])); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/CompilationResult.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/CompilationResult.java index 22e918ecd..6c4397109 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/CompilationResult.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/CompilationResult.java @@ -32,119 +32,119 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class CompilationResult { - @JsonProperty("contracts") - private Map contracts; + @JsonProperty("contracts") + private Map contracts; - @JsonProperty("version") - public String version; + @JsonProperty("version") + public String version; - @JsonIgnore - public static CompilationResult parse(String rawJson) throws IOException { - if (rawJson == null || rawJson.isEmpty()) { - CompilationResult empty = new CompilationResult(); - empty.contracts = Collections.emptyMap(); - empty.version = ""; + @JsonIgnore + public static CompilationResult parse(String rawJson) throws IOException { + if (rawJson == null || rawJson.isEmpty()) { + CompilationResult empty = new CompilationResult(); + empty.contracts = Collections.emptyMap(); + empty.version = ""; - return empty; - } else { - return new ObjectMapper().readValue(rawJson, CompilationResult.class); + return empty; + } else { + return new ObjectMapper().readValue(rawJson, CompilationResult.class); + } } - } - /** @return the contract's path given this compilation result contains exactly one contract */ - @JsonIgnore - public Path getContractPath() { - if (contracts.size() > 1) { - throw new UnsupportedOperationException( - "Source contains more than 1 contact. Please specify the contract name. Available keys (" - + getContractKeys() - + ")."); - } else { - String key = contracts.keySet().iterator().next(); - return Paths.get(key.substring(0, key.lastIndexOf(':'))); + /** @return the contract's path given this compilation result contains exactly one contract */ + @JsonIgnore + public Path getContractPath() { + if (contracts.size() > 1) { + throw new UnsupportedOperationException( + "Source contains more than 1 contact. Please specify the contract name. Available keys (" + + getContractKeys() + + ")."); + } else { + String key = contracts.keySet().iterator().next(); + return Paths.get(key.substring(0, key.lastIndexOf(':'))); + } } - } - /** @return the contract's name given this compilation result contains exactly one contract */ - @JsonIgnore - public String getContractName() { - if (contracts.size() > 1) { - throw new UnsupportedOperationException( - "Source contains more than 1 contact. Please specify the contract name. Available keys (" - + getContractKeys() - + ")."); - } else { - String key = contracts.keySet().iterator().next(); - return key.substring(key.lastIndexOf(':') + 1); + /** @return the contract's name given this compilation result contains exactly one contract */ + @JsonIgnore + public String getContractName() { + if (contracts.size() > 1) { + throw new UnsupportedOperationException( + "Source contains more than 1 contact. Please specify the contract name. Available keys (" + + getContractKeys() + + ")."); + } else { + String key = contracts.keySet().iterator().next(); + return key.substring(key.lastIndexOf(':') + 1); + } } - } - /** - * @param contractName The contract name - * @return the first contract found for a given contract name; use {@link #getContract(Path, - * String)} if this compilation result contains more than one contract with the same name - */ - @JsonIgnore - public ContractMetadata getContract(String contractName) { - if (contractName == null && contracts.size() == 1) { - return contracts.values().iterator().next(); - } else if (contractName == null || contractName.isEmpty()) { - throw new UnsupportedOperationException( - "Source contains more than 1 contact. Please specify the contract name. Available keys (" - + getContractKeys() - + ")."); + /** + * @param contractName The contract name + * @return the first contract found for a given contract name; use {@link #getContract(Path, + * String)} if this compilation result contains more than one contract with the same name + */ + @JsonIgnore + public ContractMetadata getContract(String contractName) { + if (contractName == null && contracts.size() == 1) { + return contracts.values().iterator().next(); + } else if (contractName == null || contractName.isEmpty()) { + throw new UnsupportedOperationException( + "Source contains more than 1 contact. Please specify the contract name. Available keys (" + + getContractKeys() + + ")."); + } + for (Map.Entry entry : contracts.entrySet()) { + String key = entry.getKey(); + String name = key.substring(key.lastIndexOf(':') + 1); + if (contractName.equals(name)) { + return entry.getValue(); + } + } + throw new UnsupportedOperationException( + "No contract found with name '" + + contractName + + "'. Please specify a valid contract name. Available keys (" + + getContractKeys() + + ")."); } - for (Map.Entry entry : contracts.entrySet()) { - String key = entry.getKey(); - String name = key.substring(key.lastIndexOf(':') + 1); - if (contractName.equals(name)) { - return entry.getValue(); - } - } - throw new UnsupportedOperationException( - "No contract found with name '" - + contractName - + "'. Please specify a valid contract name. Available keys (" - + getContractKeys() - + ")."); - } - /** - * @param contractPath The contract path - * @param contractName The contract name - * @return the contract with key {@code contractPath:contractName} if it exists; {@code null} - * otherwise - */ - @JsonIgnore - public ContractMetadata getContract(Path contractPath, String contractName) { - return contracts.get(contractPath.toAbsolutePath().toString() + ':' + contractName); - } + /** + * @param contractPath The contract path + * @param contractName The contract name + * @return the contract with key {@code contractPath:contractName} if it exists; {@code null} + * otherwise + */ + @JsonIgnore + public ContractMetadata getContract(Path contractPath, String contractName) { + return contracts.get(contractPath.toAbsolutePath().toString() + ':' + contractName); + } - /** @return all contracts from this compilation result */ - @JsonIgnore - public List getContracts() { - return new ArrayList<>(contracts.values()); - } + /** @return all contracts from this compilation result */ + @JsonIgnore + public List getContracts() { + return new ArrayList<>(contracts.values()); + } - /** @return all keys from this compilation result */ - @JsonIgnore - public List getContractKeys() { - return new ArrayList<>(contracts.keySet()); - } + /** @return all keys from this compilation result */ + @JsonIgnore + public List getContractKeys() { + return new ArrayList<>(contracts.keySet()); + } - @JsonIgnoreProperties(ignoreUnknown = true) - public static class ContractMetadata { - public String abi; - public String bin; - public String solInterface; - public String metadata; + @JsonIgnoreProperties(ignoreUnknown = true) + public static class ContractMetadata { + public String abi; + public String bin; + public String solInterface; + public String metadata; - public String getInterface() { - return solInterface; - } + public String getInterface() { + return solInterface; + } - public void setInterface(String solInterface) { - this.solInterface = solInterface; + public void setInterface(String solInterface) { + this.solInterface = solInterface; + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/ContractException.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/ContractException.java index a30bdc8ac..9c1817c5f 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/ContractException.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/ContractException.java @@ -19,27 +19,27 @@ public class ContractException extends RuntimeException { - public ContractException(String message) { - super(message); - } + public ContractException(String message) { + super(message); + } - public static ContractException permissionError(String msg, Object... args) { - return error("contract permission error", msg, args); - } + public static ContractException permissionError(String msg, Object... args) { + return error("contract permission error", msg, args); + } - public static ContractException compilationError(String msg, Object... args) { - return error("contract compilation error", msg, args); - } + public static ContractException compilationError(String msg, Object... args) { + return error("contract compilation error", msg, args); + } - public static ContractException validationError(String msg, Object... args) { - return error("contract validation error", msg, args); - } + public static ContractException validationError(String msg, Object... args) { + return error("contract validation error", msg, args); + } - public static ContractException assembleError(String msg, Object... args) { - return error("contract assemble error", msg, args); - } + public static ContractException assembleError(String msg, Object... args) { + return error("contract assemble error", msg, args); + } - private static ContractException error(String title, String message, Object... args) { - return new ContractException(title + ": " + String.format(message, args)); - } + private static ContractException error(String title, String message, Object... args) { + return new ContractException(title + ": " + String.format(message, args)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Solc.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Solc.java index 26898e9c9..b7aa6b009 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Solc.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Solc.java @@ -27,50 +27,51 @@ /** Created by Anton Nashatyrev on 03.03.2016. */ public class Solc { - private File solc = null; + private File solc = null; - Solc() { - try { - initBundled(); - } catch (IOException e) { - throw new RuntimeException("Can't init solc compiler: ", e); + Solc() { + try { + initBundled(); + } catch (IOException e) { + throw new RuntimeException("Can't init solc compiler: ", e); + } } - } - private void initBundled() throws IOException { - File tmpDir = new File(System.getProperty("user.home"), "solc"); - tmpDir.mkdirs(); + private void initBundled() throws IOException { + File tmpDir = new File(System.getProperty("user.home"), "solc"); + tmpDir.mkdirs(); - InputStream is = getClass().getResourceAsStream("/native/" + getOS() + "/solc/file.list"); - try (Scanner scanner = new Scanner(is)) { - while (scanner.hasNext()) { - String s = scanner.next(); - File targetFile = new File(tmpDir, s); - InputStream fis = getClass().getResourceAsStream("/native/" + getOS() + "/solc/" + s); - Files.copy(fis, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - if (solc == null) { - // first file in the list denotes executable - solc = targetFile; - solc.setExecutable(true); + InputStream is = getClass().getResourceAsStream("/native/" + getOS() + "/solc/file.list"); + try (Scanner scanner = new Scanner(is)) { + while (scanner.hasNext()) { + String s = scanner.next(); + File targetFile = new File(tmpDir, s); + InputStream fis = + getClass().getResourceAsStream("/native/" + getOS() + "/solc/" + s); + Files.copy(fis, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + if (solc == null) { + // first file in the list denotes executable + solc = targetFile; + solc.setExecutable(true); + } + } } - } } - } - private String getOS() { - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("win")) { - return "win"; - } else if (osName.contains("linux")) { - return "linux"; - } else if (osName.contains("mac")) { - return "mac"; - } else { - throw new RuntimeException("Can't find solc compiler: unrecognized OS: " + osName); + private String getOS() { + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("win")) { + return "win"; + } else if (osName.contains("linux")) { + return "linux"; + } else if (osName.contains("mac")) { + return "mac"; + } else { + throw new RuntimeException("Can't find solc compiler: unrecognized OS: " + osName); + } } - } - public File getExecutable() { - return solc; - } + public File getExecutable() { + return solc; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SolidityCompiler.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SolidityCompiler.java index 997d0f73d..c93214dde 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SolidityCompiler.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SolidityCompiler.java @@ -30,401 +30,404 @@ @Component public class SolidityCompiler { - private Solc solc; - - private static SolidityCompiler INSTANCE; - - @Autowired - public SolidityCompiler() { - solc = new Solc(); - } - - public static Result compile(File sourceDirectory, boolean combinedJson, Option... options) - throws IOException { - return getInstance().compileSrc(sourceDirectory, false, combinedJson, options); - } - - /** - * This class is mainly here for backwards compatibility; however we are now reusing it making it - * the solely public interface listing all the supported options. - */ - public static final class Options { - public static final OutputOption AST = OutputOption.AST; - public static final OutputOption BIN = OutputOption.BIN; - public static final OutputOption INTERFACE = OutputOption.INTERFACE; - public static final OutputOption ABI = OutputOption.ABI; - public static final OutputOption METADATA = OutputOption.METADATA; - public static final OutputOption ASTJSON = OutputOption.ASTJSON; - - private static final NameOnlyOption OPTIMIZE = NameOnlyOption.OPTIMIZE; - private static final NameOnlyOption VERSION = NameOnlyOption.VERSION; - - private static class CombinedJson extends ListOption { - private CombinedJson(List values) { - super("combined-json", values); - } - } + private Solc solc; + + private static SolidityCompiler INSTANCE; - public static class AllowPaths extends ListOption { - public AllowPaths(List values) { - super("allow-paths", values); - } + @Autowired + public SolidityCompiler() { + solc = new Solc(); } - } - public interface Option extends Serializable { - String getValue(); + public static Result compile(File sourceDirectory, boolean combinedJson, Option... options) + throws IOException { + return getInstance().compileSrc(sourceDirectory, false, combinedJson, options); + } - String getName(); - } + /** + * This class is mainly here for backwards compatibility; however we are now reusing it making + * it the solely public interface listing all the supported options. + */ + public static final class Options { + public static final OutputOption AST = OutputOption.AST; + public static final OutputOption BIN = OutputOption.BIN; + public static final OutputOption INTERFACE = OutputOption.INTERFACE; + public static final OutputOption ABI = OutputOption.ABI; + public static final OutputOption METADATA = OutputOption.METADATA; + public static final OutputOption ASTJSON = OutputOption.ASTJSON; - private static class ListOption implements Option { - private String name; - private List values; + private static final NameOnlyOption OPTIMIZE = NameOnlyOption.OPTIMIZE; + private static final NameOnlyOption VERSION = NameOnlyOption.VERSION; - private ListOption(String name, List values) { - this.name = name; - this.values = values; - } + private static class CombinedJson extends ListOption { + private CombinedJson(List values) { + super("combined-json", values); + } + } - @Override - public String getValue() { - StringBuilder result = new StringBuilder(); - for (Object value : values) { - if (OutputOption.class.isAssignableFrom(value.getClass())) { - result.append( - (result.length() == 0) - ? ((OutputOption) value).getName() - : ',' + ((OutputOption) value).getName()); - } else if (Path.class.isAssignableFrom(value.getClass())) { - result.append( - (result.length() == 0) - ? ((Path) value).toAbsolutePath().toString() - : ',' + ((Path) value).toAbsolutePath().toString()); - } else if (File.class.isAssignableFrom(value.getClass())) { - result.append( - (result.length() == 0) - ? ((File) value).getAbsolutePath() - : ',' + ((File) value).getAbsolutePath()); - } else if (String.class.isAssignableFrom(value.getClass())) { - result.append((result.length() == 0) ? value : "," + value); - } else { - throw new UnsupportedOperationException( - "Unexpected type, value '" + value + "' cannot be retrieved."); + public static class AllowPaths extends ListOption { + public AllowPaths(List values) { + super("allow-paths", values); + } } - } - return result.toString(); } - @Override - public String getName() { - return name; - } + public interface Option extends Serializable { + String getValue(); - @Override - public String toString() { - return name; + String getName(); } - } - private enum NameOnlyOption implements Option { - OPTIMIZE("optimize"), - VERSION("version"); + private static class ListOption implements Option { + private String name; + private List values; - private String name; + private ListOption(String name, List values) { + this.name = name; + this.values = values; + } - NameOnlyOption(String name) { - this.name = name; - } + @Override + public String getValue() { + StringBuilder result = new StringBuilder(); + for (Object value : values) { + if (OutputOption.class.isAssignableFrom(value.getClass())) { + result.append( + (result.length() == 0) + ? ((OutputOption) value).getName() + : ',' + ((OutputOption) value).getName()); + } else if (Path.class.isAssignableFrom(value.getClass())) { + result.append( + (result.length() == 0) + ? ((Path) value).toAbsolutePath().toString() + : ',' + ((Path) value).toAbsolutePath().toString()); + } else if (File.class.isAssignableFrom(value.getClass())) { + result.append( + (result.length() == 0) + ? ((File) value).getAbsolutePath() + : ',' + ((File) value).getAbsolutePath()); + } else if (String.class.isAssignableFrom(value.getClass())) { + result.append((result.length() == 0) ? value : "," + value); + } else { + throw new UnsupportedOperationException( + "Unexpected type, value '" + value + "' cannot be retrieved."); + } + } + return result.toString(); + } - @Override - public String getValue() { - return ""; - } + @Override + public String getName() { + return name; + } - @Override - public String getName() { - return name; + @Override + public String toString() { + return name; + } } - @Override - public String toString() { - return name; - } - } + private enum NameOnlyOption implements Option { + OPTIMIZE("optimize"), + VERSION("version"); - private enum OutputOption implements Option { - AST("ast"), - BIN("bin"), - INTERFACE("interface"), - ABI("abi"), - METADATA("metadata"), - ASTJSON("ast-json"); + private String name; - private String name; + NameOnlyOption(String name) { + this.name = name; + } - OutputOption(String name) { - this.name = name; - } + @Override + public String getValue() { + return ""; + } - @Override - public String getValue() { - return ""; - } + @Override + public String getName() { + return name; + } - @Override - public String getName() { - return name; + @Override + public String toString() { + return name; + } } - @Override - public String toString() { - return name; - } - } - - public static class CustomOption implements Option { - private String name; - private String value; - - public CustomOption(String name) { - if (name.startsWith("--")) { - this.name = name.substring(2); - } else { - this.name = name; - } - } + private enum OutputOption implements Option { + AST("ast"), + BIN("bin"), + INTERFACE("interface"), + ABI("abi"), + METADATA("metadata"), + ASTJSON("ast-json"); - public CustomOption(String name, String value) { - this(name); - this.value = value; - } + private String name; - @Override - public String getValue() { - return value; - } + OutputOption(String name) { + this.name = name; + } - @Override - public String getName() { - return name; - } - } + @Override + public String getValue() { + return ""; + } - public static class Result { - public String errors; - public String output; - private boolean success; + @Override + public String getName() { + return name; + } - public Result(String errors, String output, boolean success) { - this.errors = errors; - this.output = output; - this.success = success; + @Override + public String toString() { + return name; + } } - public boolean isFailed() { - return !success; + public static class CustomOption implements Option { + private String name; + private String value; + + public CustomOption(String name) { + if (name.startsWith("--")) { + this.name = name.substring(2); + } else { + this.name = name; + } + } + + public CustomOption(String name, String value) { + this(name); + this.value = value; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String getName() { + return name; + } } - } - private static class ParallelReader extends Thread { + public static class Result { + public String errors; + public String output; + private boolean success; - private InputStream stream; - private StringBuilder content = new StringBuilder(); + public Result(String errors, String output, boolean success) { + this.errors = errors; + this.output = output; + this.success = success; + } - ParallelReader(InputStream stream) { - this.stream = stream; + public boolean isFailed() { + return !success; + } } - public String getContent() { - return getContent(true); + private static class ParallelReader extends Thread { + + private InputStream stream; + private StringBuilder content = new StringBuilder(); + + ParallelReader(InputStream stream) { + this.stream = stream; + } + + public String getContent() { + return getContent(true); + } + + public synchronized String getContent(boolean waitForComplete) { + if (waitForComplete) { + while (stream != null) { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + } + return content.toString(); + } + + public void run() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { + String line; + while ((line = reader.readLine()) != null) { + content.append(line).append("\n"); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + synchronized (this) { + stream = null; + notifyAll(); + } + } + } } - public synchronized String getContent(boolean waitForComplete) { - if (waitForComplete) { - while (stream != null) { - try { - wait(); - } catch (InterruptedException e) { + public static Result compile(byte[] source, boolean combinedJson, Option... options) + throws IOException { + return getInstance().compileSrc(source, false, combinedJson, options); + } + + public Result compileSrc(File source, boolean optimize, boolean combinedJson, Option... options) + throws IOException { + List commandParts = prepareCommandOptions(optimize, combinedJson, options); + + commandParts.add(source.getAbsolutePath()); + // new in solidity 0.5.0: using stdin requires an explicit "-". The following output + // of 'solc' if no file is provided, e.g.,: solc --combined-json abi,bin,interface,metadata + // + // No input files given. If you wish to use the standard input please specify "-" + // explicitly. + // + // For older solc version "-" is not an issue as it is accepet as well + // commandParts.add("-"); + ProcessBuilder processBuilder = + new ProcessBuilder(commandParts).directory(solc.getExecutable().getParentFile()); + processBuilder + .environment() + .put("LD_LIBRARY_PATH", solc.getExecutable().getParentFile().getCanonicalPath()); + + Process process = processBuilder.start(); + + ParallelReader error = new ParallelReader(process.getErrorStream()); + ParallelReader output = new ParallelReader(process.getInputStream()); + error.start(); + output.start(); + + try { + process.waitFor(); + } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); - } } - } - return content.toString(); + boolean success = process.exitValue() == 0; + + return new Result(error.getContent(), output.getContent(), success); } - public void run() { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { - String line; - while ((line = reader.readLine()) != null) { - content.append(line).append("\n"); + private List prepareCommandOptions( + boolean optimize, boolean combinedJson, Option... options) throws IOException { + List commandParts = new ArrayList<>(); + commandParts.add(solc.getExecutable().getCanonicalPath()); + if (optimize) { + commandParts.add("--" + Options.OPTIMIZE.getName()); + } + if (combinedJson) { + Option combinedJsonOption = + new Options.CombinedJson(getElementsOf(OutputOption.class, options)); + commandParts.add("--" + combinedJsonOption.getName()); + commandParts.add(combinedJsonOption.getValue()); + } else { + for (Option option : getElementsOf(OutputOption.class, options)) { + commandParts.add("--" + option.getName()); + } } - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - synchronized (this) { - stream = null; - notifyAll(); + for (Option option : getElementsOf(ListOption.class, options)) { + commandParts.add("--" + option.getName()); + commandParts.add(option.getValue()); } - } - } - } - - public static Result compile(byte[] source, boolean combinedJson, Option... options) - throws IOException { - return getInstance().compileSrc(source, false, combinedJson, options); - } - - public Result compileSrc(File source, boolean optimize, boolean combinedJson, Option... options) - throws IOException { - List commandParts = prepareCommandOptions(optimize, combinedJson, options); - - commandParts.add(source.getAbsolutePath()); - // new in solidity 0.5.0: using stdin requires an explicit "-". The following output - // of 'solc' if no file is provided, e.g.,: solc --combined-json abi,bin,interface,metadata - // - // No input files given. If you wish to use the standard input please specify "-" explicitly. - // - // For older solc version "-" is not an issue as it is accepet as well - // commandParts.add("-"); - ProcessBuilder processBuilder = - new ProcessBuilder(commandParts).directory(solc.getExecutable().getParentFile()); - processBuilder - .environment() - .put("LD_LIBRARY_PATH", solc.getExecutable().getParentFile().getCanonicalPath()); - - Process process = processBuilder.start(); - - ParallelReader error = new ParallelReader(process.getErrorStream()); - ParallelReader output = new ParallelReader(process.getInputStream()); - error.start(); - output.start(); - - try { - process.waitFor(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - boolean success = process.exitValue() == 0; - return new Result(error.getContent(), output.getContent(), success); - } + for (Option option : getElementsOf(CustomOption.class, options)) { + commandParts.add("--" + option.getName()); + if (option.getValue() != null) { + commandParts.add(option.getValue()); + } + } + // new in solidity 0.5.0: using stdin requires an explicit "-". The following output + // of 'solc' if no file is provided, e.g.,: solc --combined-json abi,bin,interface,metadata + // + // No input files given. If you wish to use the standard input please specify "-" + // explicitly. + // + // For older solc version "-" is not an issue as it is accepet as well + // commandParts.add("-"); - private List prepareCommandOptions( - boolean optimize, boolean combinedJson, Option... options) throws IOException { - List commandParts = new ArrayList<>(); - commandParts.add(solc.getExecutable().getCanonicalPath()); - if (optimize) { - commandParts.add("--" + Options.OPTIMIZE.getName()); - } - if (combinedJson) { - Option combinedJsonOption = - new Options.CombinedJson(getElementsOf(OutputOption.class, options)); - commandParts.add("--" + combinedJsonOption.getName()); - commandParts.add(combinedJsonOption.getValue()); - } else { - for (Option option : getElementsOf(OutputOption.class, options)) { - commandParts.add("--" + option.getName()); - } - } - for (Option option : getElementsOf(ListOption.class, options)) { - commandParts.add("--" + option.getName()); - commandParts.add(option.getValue()); + return commandParts; } - for (Option option : getElementsOf(CustomOption.class, options)) { - commandParts.add("--" + option.getName()); - if (option.getValue() != null) { - commandParts.add(option.getValue()); - } - } - // new in solidity 0.5.0: using stdin requires an explicit "-". The following output - // of 'solc' if no file is provided, e.g.,: solc --combined-json abi,bin,interface,metadata - // - // No input files given. If you wish to use the standard input please specify "-" explicitly. - // - // For older solc version "-" is not an issue as it is accepet as well - // commandParts.add("-"); - - return commandParts; - } - - private static List getElementsOf(Class clazz, Option... options) { - return Arrays.stream(options).filter(clazz::isInstance).map(clazz::cast).collect(toList()); - } - - public Result compileSrc(byte[] source, boolean optimize, boolean combinedJson, Option... options) - throws IOException { - List commandParts = prepareCommandOptions(optimize, combinedJson, options); - - ProcessBuilder processBuilder = - new ProcessBuilder(commandParts).directory(solc.getExecutable().getParentFile()); - processBuilder - .environment() - .put("LD_LIBRARY_PATH", solc.getExecutable().getParentFile().getCanonicalPath()); - - Process process = processBuilder.start(); - - try (BufferedOutputStream stream = new BufferedOutputStream(process.getOutputStream())) { - stream.write(source); + private static List getElementsOf(Class clazz, Option... options) { + return Arrays.stream(options).filter(clazz::isInstance).map(clazz::cast).collect(toList()); } - ParallelReader error = new ParallelReader(process.getErrorStream()); - ParallelReader output = new ParallelReader(process.getInputStream()); - error.start(); - output.start(); + public Result compileSrc( + byte[] source, boolean optimize, boolean combinedJson, Option... options) + throws IOException { + List commandParts = prepareCommandOptions(optimize, combinedJson, options); - try { - process.waitFor(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - boolean success = process.exitValue() == 0; - - return new Result(error.getContent(), output.getContent(), success); - } - - public static String runGetVersionOutput() throws IOException { - List commandParts = new ArrayList<>(); - commandParts.add(getInstance().solc.getExecutable().getCanonicalPath()); - commandParts.add("--" + Options.VERSION.getName()); - - ProcessBuilder processBuilder = - new ProcessBuilder(commandParts) - .directory(getInstance().solc.getExecutable().getParentFile()); - processBuilder - .environment() - .put( - "LD_LIBRARY_PATH", - getInstance().solc.getExecutable().getParentFile().getCanonicalPath()); - - Process process = processBuilder.start(); - - ParallelReader error = new ParallelReader(process.getErrorStream()); - ParallelReader output = new ParallelReader(process.getInputStream()); - error.start(); - output.start(); - - try { - process.waitFor(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - if (process.exitValue() == 0) { - return output.getContent(); + ProcessBuilder processBuilder = + new ProcessBuilder(commandParts).directory(solc.getExecutable().getParentFile()); + processBuilder + .environment() + .put("LD_LIBRARY_PATH", solc.getExecutable().getParentFile().getCanonicalPath()); + + Process process = processBuilder.start(); + + try (BufferedOutputStream stream = new BufferedOutputStream(process.getOutputStream())) { + stream.write(source); + } + + ParallelReader error = new ParallelReader(process.getErrorStream()); + ParallelReader output = new ParallelReader(process.getInputStream()); + error.start(); + output.start(); + + try { + process.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + boolean success = process.exitValue() == 0; + + return new Result(error.getContent(), output.getContent(), success); } - throw new RuntimeException("Problem getting solc version: " + error.getContent()); - } + public static String runGetVersionOutput() throws IOException { + List commandParts = new ArrayList<>(); + commandParts.add(getInstance().solc.getExecutable().getCanonicalPath()); + commandParts.add("--" + Options.VERSION.getName()); + + ProcessBuilder processBuilder = + new ProcessBuilder(commandParts) + .directory(getInstance().solc.getExecutable().getParentFile()); + processBuilder + .environment() + .put( + "LD_LIBRARY_PATH", + getInstance().solc.getExecutable().getParentFile().getCanonicalPath()); + + Process process = processBuilder.start(); - public static SolidityCompiler getInstance() { - if (INSTANCE == null) { - INSTANCE = new SolidityCompiler(); + ParallelReader error = new ParallelReader(process.getErrorStream()); + ParallelReader output = new ParallelReader(process.getInputStream()); + error.start(); + output.start(); + + try { + process.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + if (process.exitValue() == 0) { + return output.getContent(); + } + + throw new RuntimeException("Problem getting solc version: " + error.getContent()); + } + + public static SolidityCompiler getInstance() { + if (INSTANCE == null) { + INSTANCE = new SolidityCompiler(); + } + return INSTANCE; } - return INSTANCE; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SourceArtifact.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SourceArtifact.java index 04866b6b4..5b696ec94 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SourceArtifact.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/SourceArtifact.java @@ -29,75 +29,75 @@ public class SourceArtifact { - private String name; - private List dependencies; - private String source; - - private final Set injectedDependencies = new HashSet<>(); - private final Set dependentArtifacts = new HashSet<>(); - - public SourceArtifact(String name, String source) { - this.name = name; - this.dependencies = extractDependencies(source); - this.source = source.replaceAll("import\\s\"\\.*?\\.sol\";", ""); - } - - public SourceArtifact(File f) {} - - private static List extractDependencies(String source) { - String[] deps = substringsBetween(source, "import \"", "\";"); - return deps == null ? Collections.emptyList() : asList(deps); - } - - // public SourceArtifact(MultipartFile srcFile) throws IOException { - // this(srcFile.getOriginalFilename(), new String(srcFile.getBytes(), "UTF-8")); - // } - - public void injectDependency(SourceArtifact srcArtifact) { - injectedDependencies.add(srcArtifact); - srcArtifact.addDependentArtifact(this); - } - - private void addDependentArtifact(SourceArtifact srcArtifact) { - dependentArtifacts.add(srcArtifact); - } - - public boolean hasDependentArtifacts() { - return !dependentArtifacts.isEmpty(); - } - - private Collection getUnresolvedDependencies() { - Set ret = new HashSet<>(); - for (SourceArtifact injectedDependency : injectedDependencies) { - ret.add(injectedDependency.getName()); + private String name; + private List dependencies; + private String source; + + private final Set injectedDependencies = new HashSet<>(); + private final Set dependentArtifacts = new HashSet<>(); + + public SourceArtifact(String name, String source) { + this.name = name; + this.dependencies = extractDependencies(source); + this.source = source.replaceAll("import\\s\"\\.*?\\.sol\";", ""); + } + + public SourceArtifact(File f) {} + + private static List extractDependencies(String source) { + String[] deps = substringsBetween(source, "import \"", "\";"); + return deps == null ? Collections.emptyList() : asList(deps); } - return disjunction(dependencies, ret); - } + // public SourceArtifact(MultipartFile srcFile) throws IOException { + // this(srcFile.getOriginalFilename(), new String(srcFile.getBytes(), "UTF-8")); + // } - public String plainSource() { - Collection unresolvedDeps = getUnresolvedDependencies(); - if (isNotEmpty(unresolvedDeps)) { - throw assembleError("Followed dependencies aren't resolved: %s", unresolvedDeps); + public void injectDependency(SourceArtifact srcArtifact) { + injectedDependencies.add(srcArtifact); + srcArtifact.addDependentArtifact(this); } - String result = this.source; - for (SourceArtifact dependencyArtifact : injectedDependencies) { - String importDefinition = format("import \"%s\";", dependencyArtifact.getName()); - String dependencySrc = - format("// %s\n%s", importDefinition, dependencyArtifact.plainSource()); + private void addDependentArtifact(SourceArtifact srcArtifact) { + dependentArtifacts.add(srcArtifact); + } - result = result.replace(importDefinition, dependencySrc); + public boolean hasDependentArtifacts() { + return !dependentArtifacts.isEmpty(); } - return result; - } + private Collection getUnresolvedDependencies() { + Set ret = new HashSet<>(); + for (SourceArtifact injectedDependency : injectedDependencies) { + ret.add(injectedDependency.getName()); + } + + return disjunction(dependencies, ret); + } - public String getName() { - return name; - } + public String plainSource() { + Collection unresolvedDeps = getUnresolvedDependencies(); + if (isNotEmpty(unresolvedDeps)) { + throw assembleError("Followed dependencies aren't resolved: %s", unresolvedDeps); + } - public List getDependencies() { - return dependencies; - } + String result = this.source; + for (SourceArtifact dependencyArtifact : injectedDependencies) { + String importDefinition = format("import \"%s\";", dependencyArtifact.getName()); + String dependencySrc = + format("// %s\n%s", importDefinition, dependencyArtifact.plainSource()); + + result = result.replace(importDefinition, dependencySrc); + } + + return result; + } + + public String getName() { + return name; + } + + public List getDependencies() { + return dependencies; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Sources.java b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Sources.java index 1ec9782fd..5a8f8ad1b 100644 --- a/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Sources.java +++ b/src/main/java/org/fisco/bcos/web3j/solidity/compiler/Sources.java @@ -25,36 +25,37 @@ public class Sources { - private final Map artifacts = new HashMap<>(); - private String targetArtifact; + private final Map artifacts = new HashMap<>(); + private String targetArtifact; - public Sources(File[] files) { - for (File file : files) { - artifacts.put(file.getName(), new SourceArtifact(file)); - } - } - - public void resolveDependencies() { - for (String srcName : artifacts.keySet()) { - SourceArtifact src = artifacts.get(srcName); - for (String dep : src.getDependencies()) { - SourceArtifact depArtifact = artifacts.get(dep); - if (depArtifact == null) { - throw assembleError("can't resolve dependency: dependency '%s' not found.", dep); + public Sources(File[] files) { + for (File file : files) { + artifacts.put(file.getName(), new SourceArtifact(file)); } - src.injectDependency(depArtifact); - } - ; } - for (SourceArtifact artifact : artifacts.values()) { - if (!artifact.hasDependentArtifacts()) { - targetArtifact = artifact.getName(); - } + public void resolveDependencies() { + for (String srcName : artifacts.keySet()) { + SourceArtifact src = artifacts.get(srcName); + for (String dep : src.getDependencies()) { + SourceArtifact depArtifact = artifacts.get(dep); + if (depArtifact == null) { + throw assembleError( + "can't resolve dependency: dependency '%s' not found.", dep); + } + src.injectDependency(depArtifact); + } + ; + } + + for (SourceArtifact artifact : artifacts.values()) { + if (!artifact.hasDependentArtifacts()) { + targetArtifact = artifact.getName(); + } + } } - } - public String plainSource() { - return artifacts.get(targetArtifact).plainSource(); - } + public String plainSource() { + return artifacts.get(targetArtifact).plainSource(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/EmptyTuple.java b/src/main/java/org/fisco/bcos/web3j/tuples/EmptyTuple.java index 0a6d34a52..97e4347d5 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/EmptyTuple.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/EmptyTuple.java @@ -3,8 +3,8 @@ /** Empty Tuple type. */ public class EmptyTuple implements Tuple { - @Override - public int getSize() { - return 0; - } + @Override + public int getSize() { + return 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/Tuple.java b/src/main/java/org/fisco/bcos/web3j/tuples/Tuple.java index 4e55178bf..5840d89da 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/Tuple.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/Tuple.java @@ -3,5 +3,5 @@ /** Tuple abstraction. */ public interface Tuple { - int getSize(); + int getSize(); } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple1.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple1.java index b68be67c8..00a3f8002 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple1.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple1.java @@ -11,43 +11,43 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple1 implements Tuple { - private static final int SIZE = 1; + private static final int SIZE = 1; - private final T1 value1; + private final T1 value1; - public Tuple1(T1 value1) { - this.value1 = value1; - } + public Tuple1(T1 value1) { + this.value1 = value1; + } + + public T1 getValue1() { + return value1; + } - public T1 getValue1() { - return value1; - } + @Override + public int getSize() { + return SIZE; + } - @Override - public int getSize() { - return SIZE; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple1 tuple1 = (Tuple1) o; + return value1 != null ? value1.equals(tuple1.value1) : tuple1.value1 == null; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + @Override + public int hashCode() { + int result = value1.hashCode(); + return result; } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public String toString() { + return "Tuple1{" + "value1=" + value1 + "}"; } - Tuple1 tuple1 = (Tuple1) o; - return value1 != null ? value1.equals(tuple1.value1) : tuple1.value1 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - return result; - } - - @Override - public String toString() { - return "Tuple1{" + "value1=" + value1 + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple10.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple10.java index 858b35330..e20f9b4a3 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple10.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple10.java @@ -11,173 +11,173 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple10 implements Tuple { - private static final int SIZE = 10; + private static final int SIZE = 10; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - public Tuple10( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } + public Tuple10( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + } - public T9 getValue9() { - return value9; - } + public T1 getValue1() { + return value1; + } - public T10 getValue10() { - return value10; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple10 tuple10 = (Tuple10) o; - if (value1 != null ? !value1.equals(tuple10.value1) : tuple10.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple10.value2) : tuple10.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple10.value3) : tuple10.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple10.value4) : tuple10.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple10.value5) : tuple10.value5 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value6 != null ? !value6.equals(tuple10.value6) : tuple10.value6 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value7 != null ? !value7.equals(tuple10.value7) : tuple10.value7 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple10 tuple10 = (Tuple10) o; + if (value1 != null ? !value1.equals(tuple10.value1) : tuple10.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple10.value2) : tuple10.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple10.value3) : tuple10.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple10.value4) : tuple10.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple10.value5) : tuple10.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple10.value6) : tuple10.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple10.value7) : tuple10.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple10.value8) : tuple10.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple10.value9) : tuple10.value9 != null) { + return false; + } + return value10 != null ? value10.equals(tuple10.value10) : tuple10.value10 == null; } - if (value8 != null ? !value8.equals(tuple10.value8) : tuple10.value8 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + return result; } - if (value9 != null ? !value9.equals(tuple10.value9) : tuple10.value9 != null) { - return false; + + @Override + public String toString() { + return "Tuple10{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + "}"; } - return value10 != null ? value10.equals(tuple10.value10) : tuple10.value10 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple10{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple11.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple11.java index be010c7c8..de1fbfe7c 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple11.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple11.java @@ -11,187 +11,188 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple11 implements Tuple { - private static final int SIZE = 11; + private static final int SIZE = 11; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - public Tuple11( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - } + public Tuple11( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + } + + public T1 getValue1() { + return value1; + } + + public T2 getValue2() { + return value2; + } + + public T3 getValue3() { + return value3; + } + + public T4 getValue4() { + return value4; + } + + public T5 getValue5() { + return value5; + } + + public T6 getValue6() { + return value6; + } + + public T7 getValue7() { + return value7; + } + + public T8 getValue8() { + return value8; + } + + public T9 getValue9() { + return value9; + } + + public T10 getValue10() { + return value10; + } - public T1 getValue1() { - return value1; - } + public T11 getValue11() { + return value11; + } + + @Override + public int getSize() { + return SIZE; + } - public T2 getValue2() { - return value2; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple11 tuple11 = + (Tuple11) o; + if (value1 != null ? !value1.equals(tuple11.value1) : tuple11.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple11.value2) : tuple11.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple11.value3) : tuple11.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple11.value4) : tuple11.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple11.value5) : tuple11.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple11.value6) : tuple11.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple11.value7) : tuple11.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple11.value8) : tuple11.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple11.value9) : tuple11.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple11.value10) : tuple11.value10 != null) { + return false; + } + return value11 != null ? value11.equals(tuple11.value11) : tuple11.value11 == null; + } - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Tuple11 tuple11 = (Tuple11) o; - if (value1 != null ? !value1.equals(tuple11.value1) : tuple11.value1 != null) { - return false; - } - if (value2 != null ? !value2.equals(tuple11.value2) : tuple11.value2 != null) { - return false; - } - if (value3 != null ? !value3.equals(tuple11.value3) : tuple11.value3 != null) { - return false; - } - if (value4 != null ? !value4.equals(tuple11.value4) : tuple11.value4 != null) { - return false; - } - if (value5 != null ? !value5.equals(tuple11.value5) : tuple11.value5 != null) { - return false; - } - if (value6 != null ? !value6.equals(tuple11.value6) : tuple11.value6 != null) { - return false; - } - if (value7 != null ? !value7.equals(tuple11.value7) : tuple11.value7 != null) { - return false; - } - if (value8 != null ? !value8.equals(tuple11.value8) : tuple11.value8 != null) { - return false; - } - if (value9 != null ? !value9.equals(tuple11.value9) : tuple11.value9 != null) { - return false; - } - if (value10 != null ? !value10.equals(tuple11.value10) : tuple11.value10 != null) { - return false; - } - return value11 != null ? value11.equals(tuple11.value11) : tuple11.value11 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple11{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + "}"; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Tuple11{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple12.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple12.java index 3fb1cf80d..3b7436667 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple12.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple12.java @@ -11,202 +11,202 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple12 implements Tuple { - private static final int SIZE = 12; + private static final int SIZE = 12; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - public Tuple12( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - } + public Tuple12( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + } + + public T1 getValue1() { + return value1; + } + + public T2 getValue2() { + return value2; + } + + public T3 getValue3() { + return value3; + } + + public T4 getValue4() { + return value4; + } + + public T5 getValue5() { + return value5; + } + + public T6 getValue6() { + return value6; + } + + public T7 getValue7() { + return value7; + } + + public T8 getValue8() { + return value8; + } + + public T9 getValue9() { + return value9; + } + + public T10 getValue10() { + return value10; + } - public T1 getValue1() { - return value1; - } + public T11 getValue11() { + return value11; + } - public T2 getValue2() { - return value2; - } + public T12 getValue12() { + return value12; + } - public T3 getValue3() { - return value3; - } + @Override + public int getSize() { + return SIZE; + } - public T4 getValue4() { - return value4; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple12 tuple12 = + (Tuple12) o; + if (value1 != null ? !value1.equals(tuple12.value1) : tuple12.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple12.value2) : tuple12.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple12.value3) : tuple12.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple12.value4) : tuple12.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple12.value5) : tuple12.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple12.value6) : tuple12.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple12.value7) : tuple12.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple12.value8) : tuple12.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple12.value9) : tuple12.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple12.value10) : tuple12.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple12.value11) : tuple12.value11 != null) { + return false; + } + return value12 != null ? value12.equals(tuple12.value12) : tuple12.value12 == null; + } - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Tuple12 tuple12 = - (Tuple12) o; - if (value1 != null ? !value1.equals(tuple12.value1) : tuple12.value1 != null) { - return false; - } - if (value2 != null ? !value2.equals(tuple12.value2) : tuple12.value2 != null) { - return false; - } - if (value3 != null ? !value3.equals(tuple12.value3) : tuple12.value3 != null) { - return false; - } - if (value4 != null ? !value4.equals(tuple12.value4) : tuple12.value4 != null) { - return false; - } - if (value5 != null ? !value5.equals(tuple12.value5) : tuple12.value5 != null) { - return false; - } - if (value6 != null ? !value6.equals(tuple12.value6) : tuple12.value6 != null) { - return false; - } - if (value7 != null ? !value7.equals(tuple12.value7) : tuple12.value7 != null) { - return false; - } - if (value8 != null ? !value8.equals(tuple12.value8) : tuple12.value8 != null) { - return false; - } - if (value9 != null ? !value9.equals(tuple12.value9) : tuple12.value9 != null) { - return false; - } - if (value10 != null ? !value10.equals(tuple12.value10) : tuple12.value10 != null) { - return false; - } - if (value11 != null ? !value11.equals(tuple12.value11) : tuple12.value11 != null) { - return false; - } - return value12 != null ? value12.equals(tuple12.value12) : tuple12.value12 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple12{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + "}"; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Tuple12{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple13.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple13.java index 5208f197e..ebc64df99 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple13.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple13.java @@ -11,217 +11,217 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple13 - implements Tuple { - private static final int SIZE = 13; + implements Tuple { + private static final int SIZE = 13; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - public Tuple13( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - } + public Tuple13( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + } + + public T1 getValue1() { + return value1; + } + + public T2 getValue2() { + return value2; + } + + public T3 getValue3() { + return value3; + } + + public T4 getValue4() { + return value4; + } + + public T5 getValue5() { + return value5; + } + + public T6 getValue6() { + return value6; + } + + public T7 getValue7() { + return value7; + } + + public T8 getValue8() { + return value8; + } + + public T9 getValue9() { + return value9; + } + + public T10 getValue10() { + return value10; + } - public T1 getValue1() { - return value1; - } + public T11 getValue11() { + return value11; + } - public T2 getValue2() { - return value2; - } + public T12 getValue12() { + return value12; + } - public T3 getValue3() { - return value3; - } + public T13 getValue13() { + return value13; + } - public T4 getValue4() { - return value4; - } + @Override + public int getSize() { + return SIZE; + } - public T5 getValue5() { - return value5; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple13 tuple13 = + (Tuple13) o; + if (value1 != null ? !value1.equals(tuple13.value1) : tuple13.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple13.value2) : tuple13.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple13.value3) : tuple13.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple13.value4) : tuple13.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple13.value5) : tuple13.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple13.value6) : tuple13.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple13.value7) : tuple13.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple13.value8) : tuple13.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple13.value9) : tuple13.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple13.value10) : tuple13.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple13.value11) : tuple13.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple13.value12) : tuple13.value12 != null) { + return false; + } + return value13 != null ? value13.equals(tuple13.value13) : tuple13.value13 == null; + } - public T6 getValue6() { - return value6; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + return result; + } - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Tuple13 tuple13 = - (Tuple13) o; - if (value1 != null ? !value1.equals(tuple13.value1) : tuple13.value1 != null) { - return false; - } - if (value2 != null ? !value2.equals(tuple13.value2) : tuple13.value2 != null) { - return false; - } - if (value3 != null ? !value3.equals(tuple13.value3) : tuple13.value3 != null) { - return false; - } - if (value4 != null ? !value4.equals(tuple13.value4) : tuple13.value4 != null) { - return false; - } - if (value5 != null ? !value5.equals(tuple13.value5) : tuple13.value5 != null) { - return false; - } - if (value6 != null ? !value6.equals(tuple13.value6) : tuple13.value6 != null) { - return false; - } - if (value7 != null ? !value7.equals(tuple13.value7) : tuple13.value7 != null) { - return false; - } - if (value8 != null ? !value8.equals(tuple13.value8) : tuple13.value8 != null) { - return false; - } - if (value9 != null ? !value9.equals(tuple13.value9) : tuple13.value9 != null) { - return false; - } - if (value10 != null ? !value10.equals(tuple13.value10) : tuple13.value10 != null) { - return false; - } - if (value11 != null ? !value11.equals(tuple13.value11) : tuple13.value11 != null) { - return false; - } - if (value12 != null ? !value12.equals(tuple13.value12) : tuple13.value12 != null) { - return false; - } - return value13 != null ? value13.equals(tuple13.value13) : tuple13.value13 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple13{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + "}"; - } + @Override + public String toString() { + return "Tuple13{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple14.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple14.java index 7241db13d..23cb84495 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple14.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple14.java @@ -11,231 +11,231 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple14 - implements Tuple { - private static final int SIZE = 14; + implements Tuple { + private static final int SIZE = 14; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - private final T14 value14; + private final T14 value14; - public Tuple14( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - } + public Tuple14( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + } + + public T1 getValue1() { + return value1; + } + + public T2 getValue2() { + return value2; + } + + public T3 getValue3() { + return value3; + } + + public T4 getValue4() { + return value4; + } + + public T5 getValue5() { + return value5; + } + + public T6 getValue6() { + return value6; + } + + public T7 getValue7() { + return value7; + } + + public T8 getValue8() { + return value8; + } - public T1 getValue1() { - return value1; - } + public T9 getValue9() { + return value9; + } - public T2 getValue2() { - return value2; - } + public T10 getValue10() { + return value10; + } + + public T11 getValue11() { + return value11; + } - public T3 getValue3() { - return value3; - } + public T12 getValue12() { + return value12; + } - public T4 getValue4() { - return value4; - } + public T13 getValue13() { + return value13; + } - public T5 getValue5() { - return value5; - } + public T14 getValue14() { + return value14; + } - public T6 getValue6() { - return value6; - } + @Override + public int getSize() { + return SIZE; + } - public T7 getValue7() { - return value7; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple14 tuple14 = + (Tuple14) o; + if (value1 != null ? !value1.equals(tuple14.value1) : tuple14.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple14.value2) : tuple14.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple14.value3) : tuple14.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple14.value4) : tuple14.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple14.value5) : tuple14.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple14.value6) : tuple14.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple14.value7) : tuple14.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple14.value8) : tuple14.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple14.value9) : tuple14.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple14.value10) : tuple14.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple14.value11) : tuple14.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple14.value12) : tuple14.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple14.value13) : tuple14.value13 != null) { + return false; + } + return value14 != null ? value14.equals(tuple14.value14) : tuple14.value14 == null; + } - public T8 getValue8() { - return value8; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + return result; + } - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Tuple14 tuple14 = - (Tuple14) o; - if (value1 != null ? !value1.equals(tuple14.value1) : tuple14.value1 != null) { - return false; - } - if (value2 != null ? !value2.equals(tuple14.value2) : tuple14.value2 != null) { - return false; - } - if (value3 != null ? !value3.equals(tuple14.value3) : tuple14.value3 != null) { - return false; - } - if (value4 != null ? !value4.equals(tuple14.value4) : tuple14.value4 != null) { - return false; - } - if (value5 != null ? !value5.equals(tuple14.value5) : tuple14.value5 != null) { - return false; - } - if (value6 != null ? !value6.equals(tuple14.value6) : tuple14.value6 != null) { - return false; - } - if (value7 != null ? !value7.equals(tuple14.value7) : tuple14.value7 != null) { - return false; - } - if (value8 != null ? !value8.equals(tuple14.value8) : tuple14.value8 != null) { - return false; - } - if (value9 != null ? !value9.equals(tuple14.value9) : tuple14.value9 != null) { - return false; - } - if (value10 != null ? !value10.equals(tuple14.value10) : tuple14.value10 != null) { - return false; - } - if (value11 != null ? !value11.equals(tuple14.value11) : tuple14.value11 != null) { - return false; - } - if (value12 != null ? !value12.equals(tuple14.value12) : tuple14.value12 != null) { - return false; - } - if (value13 != null ? !value13.equals(tuple14.value13) : tuple14.value13 != null) { - return false; - } - return value14 != null ? value14.equals(tuple14.value14) : tuple14.value14 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple14{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + "}"; - } + @Override + public String toString() { + return "Tuple14{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple15.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple15.java index edf3399bd..75a911a94 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple15.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple15.java @@ -11,245 +11,245 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple15 - implements Tuple { - private static final int SIZE = 15; + implements Tuple { + private static final int SIZE = 15; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - private final T14 value14; + private final T14 value14; - private final T15 value15; + private final T15 value15; - public Tuple15( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - } + public Tuple15( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + } - public T1 getValue1() { - return value1; - } + public T1 getValue1() { + return value1; + } - public T2 getValue2() { - return value2; - } + public T2 getValue2() { + return value2; + } - public T3 getValue3() { - return value3; - } + public T3 getValue3() { + return value3; + } - public T4 getValue4() { - return value4; - } + public T4 getValue4() { + return value4; + } - public T5 getValue5() { - return value5; - } + public T5 getValue5() { + return value5; + } - public T6 getValue6() { - return value6; - } + public T6 getValue6() { + return value6; + } - public T7 getValue7() { - return value7; - } + public T7 getValue7() { + return value7; + } - public T8 getValue8() { - return value8; - } + public T8 getValue8() { + return value8; + } + + public T9 getValue9() { + return value9; + } - public T9 getValue9() { - return value9; - } + public T10 getValue10() { + return value10; + } - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Tuple15 tuple15 = - (Tuple15) o; - if (value1 != null ? !value1.equals(tuple15.value1) : tuple15.value1 != null) { - return false; - } - if (value2 != null ? !value2.equals(tuple15.value2) : tuple15.value2 != null) { - return false; - } - if (value3 != null ? !value3.equals(tuple15.value3) : tuple15.value3 != null) { - return false; - } - if (value4 != null ? !value4.equals(tuple15.value4) : tuple15.value4 != null) { - return false; - } - if (value5 != null ? !value5.equals(tuple15.value5) : tuple15.value5 != null) { - return false; - } - if (value6 != null ? !value6.equals(tuple15.value6) : tuple15.value6 != null) { - return false; - } - if (value7 != null ? !value7.equals(tuple15.value7) : tuple15.value7 != null) { - return false; - } - if (value8 != null ? !value8.equals(tuple15.value8) : tuple15.value8 != null) { - return false; - } - if (value9 != null ? !value9.equals(tuple15.value9) : tuple15.value9 != null) { - return false; - } - if (value10 != null ? !value10.equals(tuple15.value10) : tuple15.value10 != null) { - return false; - } - if (value11 != null ? !value11.equals(tuple15.value11) : tuple15.value11 != null) { - return false; - } - if (value12 != null ? !value12.equals(tuple15.value12) : tuple15.value12 != null) { - return false; - } - if (value13 != null ? !value13.equals(tuple15.value13) : tuple15.value13 != null) { - return false; - } - if (value14 != null ? !value14.equals(tuple15.value14) : tuple15.value14 != null) { - return false; - } - return value15 != null ? value15.equals(tuple15.value15) : tuple15.value15 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple15{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + "}"; - } + public T11 getValue11() { + return value11; + } + + public T12 getValue12() { + return value12; + } + + public T13 getValue13() { + return value13; + } + + public T14 getValue14() { + return value14; + } + + public T15 getValue15() { + return value15; + } + + @Override + public int getSize() { + return SIZE; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple15 tuple15 = + (Tuple15) o; + if (value1 != null ? !value1.equals(tuple15.value1) : tuple15.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple15.value2) : tuple15.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple15.value3) : tuple15.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple15.value4) : tuple15.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple15.value5) : tuple15.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple15.value6) : tuple15.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple15.value7) : tuple15.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple15.value8) : tuple15.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple15.value9) : tuple15.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple15.value10) : tuple15.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple15.value11) : tuple15.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple15.value12) : tuple15.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple15.value13) : tuple15.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple15.value14) : tuple15.value14 != null) { + return false; + } + return value15 != null ? value15.equals(tuple15.value15) : tuple15.value15 == null; + } + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Tuple15{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple16.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple16.java index fdd3a33d7..614129395 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple16.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple16.java @@ -11,259 +11,259 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple16 - implements Tuple { - private static final int SIZE = 16; + implements Tuple { + private static final int SIZE = 16; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - private final T14 value14; + private final T14 value14; - private final T15 value15; + private final T15 value15; - private final T16 value16; + private final T16 value16; - public Tuple16( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15, - T16 value16) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - this.value16 = value16; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } + public Tuple16( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + this.value16 = value16; + } - public T6 getValue6() { - return value6; - } + public T1 getValue1() { + return value1; + } - public T7 getValue7() { - return value7; - } + public T2 getValue2() { + return value2; + } - public T8 getValue8() { - return value8; - } + public T3 getValue3() { + return value3; + } - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - public T16 getValue16() { - return value16; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple16 tuple16 = - (Tuple16) o; - if (value1 != null ? !value1.equals(tuple16.value1) : tuple16.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple16.value2) : tuple16.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple16.value3) : tuple16.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple16.value4) : tuple16.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple16.value5) : tuple16.value5 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value6 != null ? !value6.equals(tuple16.value6) : tuple16.value6 != null) { - return false; + + public T11 getValue11() { + return value11; } - if (value7 != null ? !value7.equals(tuple16.value7) : tuple16.value7 != null) { - return false; + + public T12 getValue12() { + return value12; } - if (value8 != null ? !value8.equals(tuple16.value8) : tuple16.value8 != null) { - return false; + + public T13 getValue13() { + return value13; } - if (value9 != null ? !value9.equals(tuple16.value9) : tuple16.value9 != null) { - return false; + + public T14 getValue14() { + return value14; } - if (value10 != null ? !value10.equals(tuple16.value10) : tuple16.value10 != null) { - return false; + + public T15 getValue15() { + return value15; } - if (value11 != null ? !value11.equals(tuple16.value11) : tuple16.value11 != null) { - return false; + + public T16 getValue16() { + return value16; } - if (value12 != null ? !value12.equals(tuple16.value12) : tuple16.value12 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value13 != null ? !value13.equals(tuple16.value13) : tuple16.value13 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple16 tuple16 = + (Tuple16) o; + if (value1 != null ? !value1.equals(tuple16.value1) : tuple16.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple16.value2) : tuple16.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple16.value3) : tuple16.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple16.value4) : tuple16.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple16.value5) : tuple16.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple16.value6) : tuple16.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple16.value7) : tuple16.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple16.value8) : tuple16.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple16.value9) : tuple16.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple16.value10) : tuple16.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple16.value11) : tuple16.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple16.value12) : tuple16.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple16.value13) : tuple16.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple16.value14) : tuple16.value14 != null) { + return false; + } + if (value15 != null ? !value15.equals(tuple16.value15) : tuple16.value15 != null) { + return false; + } + return value16 != null ? value16.equals(tuple16.value16) : tuple16.value16 == null; } - if (value14 != null ? !value14.equals(tuple16.value14) : tuple16.value14 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + result = 31 * result + (value16 != null ? value16.hashCode() : 0); + return result; } - if (value15 != null ? !value15.equals(tuple16.value15) : tuple16.value15 != null) { - return false; + + @Override + public String toString() { + return "Tuple16{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + ", value16=" + + value16 + + "}"; } - return value16 != null ? value16.equals(tuple16.value16) : tuple16.value16 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - result = 31 * result + (value16 != null ? value16.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple16{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + ", value16=" - + value16 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple17.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple17.java index 8b6f225d2..33ee9fc6a 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple17.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple17.java @@ -11,274 +11,274 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple17< - T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17> - implements Tuple { - private static final int SIZE = 17; + T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17> + implements Tuple { + private static final int SIZE = 17; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - private final T14 value14; + private final T14 value14; - private final T15 value15; + private final T15 value15; - private final T16 value16; + private final T16 value16; - private final T17 value17; + private final T17 value17; - public Tuple17( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15, - T16 value16, - T17 value17) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - this.value16 = value16; - this.value17 = value17; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } + public Tuple17( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16, + T17 value17) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + this.value16 = value16; + this.value17 = value17; + } + + public T1 getValue1() { + return value1; + } + + public T2 getValue2() { + return value2; + } + + public T3 getValue3() { + return value3; + } - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - public T16 getValue16() { - return value16; - } - - public T17 getValue17() { - return value17; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple17 tuple17 = - (Tuple17) o; - if (value1 != null ? !value1.equals(tuple17.value1) : tuple17.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple17.value2) : tuple17.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple17.value3) : tuple17.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple17.value4) : tuple17.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple17.value5) : tuple17.value5 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value6 != null ? !value6.equals(tuple17.value6) : tuple17.value6 != null) { - return false; + + public T11 getValue11() { + return value11; } - if (value7 != null ? !value7.equals(tuple17.value7) : tuple17.value7 != null) { - return false; + + public T12 getValue12() { + return value12; } - if (value8 != null ? !value8.equals(tuple17.value8) : tuple17.value8 != null) { - return false; + + public T13 getValue13() { + return value13; } - if (value9 != null ? !value9.equals(tuple17.value9) : tuple17.value9 != null) { - return false; + + public T14 getValue14() { + return value14; } - if (value10 != null ? !value10.equals(tuple17.value10) : tuple17.value10 != null) { - return false; + + public T15 getValue15() { + return value15; } - if (value11 != null ? !value11.equals(tuple17.value11) : tuple17.value11 != null) { - return false; + + public T16 getValue16() { + return value16; } - if (value12 != null ? !value12.equals(tuple17.value12) : tuple17.value12 != null) { - return false; + + public T17 getValue17() { + return value17; } - if (value13 != null ? !value13.equals(tuple17.value13) : tuple17.value13 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value14 != null ? !value14.equals(tuple17.value14) : tuple17.value14 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple17 tuple17 = + (Tuple17) o; + if (value1 != null ? !value1.equals(tuple17.value1) : tuple17.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple17.value2) : tuple17.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple17.value3) : tuple17.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple17.value4) : tuple17.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple17.value5) : tuple17.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple17.value6) : tuple17.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple17.value7) : tuple17.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple17.value8) : tuple17.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple17.value9) : tuple17.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple17.value10) : tuple17.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple17.value11) : tuple17.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple17.value12) : tuple17.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple17.value13) : tuple17.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple17.value14) : tuple17.value14 != null) { + return false; + } + if (value15 != null ? !value15.equals(tuple17.value15) : tuple17.value15 != null) { + return false; + } + if (value16 != null ? !value16.equals(tuple17.value16) : tuple17.value16 != null) { + return false; + } + return value17 != null ? value17.equals(tuple17.value17) : tuple17.value17 == null; } - if (value15 != null ? !value15.equals(tuple17.value15) : tuple17.value15 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + result = 31 * result + (value16 != null ? value16.hashCode() : 0); + result = 31 * result + (value17 != null ? value17.hashCode() : 0); + return result; } - if (value16 != null ? !value16.equals(tuple17.value16) : tuple17.value16 != null) { - return false; + + @Override + public String toString() { + return "Tuple17{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + ", value16=" + + value16 + + ", value17=" + + value17 + + "}"; } - return value17 != null ? value17.equals(tuple17.value17) : tuple17.value17 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - result = 31 * result + (value16 != null ? value16.hashCode() : 0); - result = 31 * result + (value17 != null ? value17.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple17{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + ", value16=" - + value16 - + ", value17=" - + value17 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple18.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple18.java index 1ebbd210a..7a11cd637 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple18.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple18.java @@ -11,288 +11,288 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple18< - T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18> - implements Tuple { - private static final int SIZE = 18; + T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18> + implements Tuple { + private static final int SIZE = 18; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - private final T10 value10; + private final T10 value10; - private final T11 value11; + private final T11 value11; - private final T12 value12; + private final T12 value12; - private final T13 value13; + private final T13 value13; - private final T14 value14; + private final T14 value14; - private final T15 value15; + private final T15 value15; - private final T16 value16; + private final T16 value16; - private final T17 value17; + private final T17 value17; - private final T18 value18; + private final T18 value18; - public Tuple18( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15, - T16 value16, - T17 value17, - T18 value18) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - this.value16 = value16; - this.value17 = value17; - this.value18 = value18; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } + public Tuple18( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16, + T17 value17, + T18 value18) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + this.value16 = value16; + this.value17 = value17; + this.value18 = value18; + } - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - public T16 getValue16() { - return value16; - } - - public T17 getValue17() { - return value17; - } - - public T18 getValue18() { - return value18; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T1 getValue1() { + return value1; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T2 getValue2() { + return value2; } - Tuple18 tuple18 = - (Tuple18) o; - if (value1 != null ? !value1.equals(tuple18.value1) : tuple18.value1 != null) { - return false; + + public T3 getValue3() { + return value3; } - if (value2 != null ? !value2.equals(tuple18.value2) : tuple18.value2 != null) { - return false; + + public T4 getValue4() { + return value4; } - if (value3 != null ? !value3.equals(tuple18.value3) : tuple18.value3 != null) { - return false; + + public T5 getValue5() { + return value5; } - if (value4 != null ? !value4.equals(tuple18.value4) : tuple18.value4 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value5 != null ? !value5.equals(tuple18.value5) : tuple18.value5 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value6 != null ? !value6.equals(tuple18.value6) : tuple18.value6 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value7 != null ? !value7.equals(tuple18.value7) : tuple18.value7 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value8 != null ? !value8.equals(tuple18.value8) : tuple18.value8 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value9 != null ? !value9.equals(tuple18.value9) : tuple18.value9 != null) { - return false; + + public T11 getValue11() { + return value11; } - if (value10 != null ? !value10.equals(tuple18.value10) : tuple18.value10 != null) { - return false; + + public T12 getValue12() { + return value12; } - if (value11 != null ? !value11.equals(tuple18.value11) : tuple18.value11 != null) { - return false; + + public T13 getValue13() { + return value13; } - if (value12 != null ? !value12.equals(tuple18.value12) : tuple18.value12 != null) { - return false; + + public T14 getValue14() { + return value14; + } + + public T15 getValue15() { + return value15; + } + + public T16 getValue16() { + return value16; + } + + public T17 getValue17() { + return value17; } - if (value13 != null ? !value13.equals(tuple18.value13) : tuple18.value13 != null) { - return false; + + public T18 getValue18() { + return value18; } - if (value14 != null ? !value14.equals(tuple18.value14) : tuple18.value14 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value15 != null ? !value15.equals(tuple18.value15) : tuple18.value15 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple18 tuple18 = + (Tuple18) o; + if (value1 != null ? !value1.equals(tuple18.value1) : tuple18.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple18.value2) : tuple18.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple18.value3) : tuple18.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple18.value4) : tuple18.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple18.value5) : tuple18.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple18.value6) : tuple18.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple18.value7) : tuple18.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple18.value8) : tuple18.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple18.value9) : tuple18.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple18.value10) : tuple18.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple18.value11) : tuple18.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple18.value12) : tuple18.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple18.value13) : tuple18.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple18.value14) : tuple18.value14 != null) { + return false; + } + if (value15 != null ? !value15.equals(tuple18.value15) : tuple18.value15 != null) { + return false; + } + if (value16 != null ? !value16.equals(tuple18.value16) : tuple18.value16 != null) { + return false; + } + if (value17 != null ? !value17.equals(tuple18.value17) : tuple18.value17 != null) { + return false; + } + return value18 != null ? value18.equals(tuple18.value18) : tuple18.value18 == null; } - if (value16 != null ? !value16.equals(tuple18.value16) : tuple18.value16 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + result = 31 * result + (value16 != null ? value16.hashCode() : 0); + result = 31 * result + (value17 != null ? value17.hashCode() : 0); + result = 31 * result + (value18 != null ? value18.hashCode() : 0); + return result; } - if (value17 != null ? !value17.equals(tuple18.value17) : tuple18.value17 != null) { - return false; + + @Override + public String toString() { + return "Tuple18{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + ", value16=" + + value16 + + ", value17=" + + value17 + + ", value18=" + + value18 + + "}"; } - return value18 != null ? value18.equals(tuple18.value18) : tuple18.value18 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - result = 31 * result + (value16 != null ? value16.hashCode() : 0); - result = 31 * result + (value17 != null ? value17.hashCode() : 0); - result = 31 * result + (value18 != null ? value18.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple18{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + ", value16=" - + value16 - + ", value17=" - + value17 - + ", value18=" - + value18 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple19.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple19.java index e2b40bbea..8df6091f3 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple19.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple19.java @@ -11,302 +11,320 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple19< - T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> - implements Tuple { - private static final int SIZE = 19; - - private final T1 value1; - - private final T2 value2; - - private final T3 value3; - - private final T4 value4; - - private final T5 value5; - - private final T6 value6; - - private final T7 value7; - - private final T8 value8; - - private final T9 value9; - - private final T10 value10; - - private final T11 value11; - - private final T12 value12; - - private final T13 value13; - - private final T14 value14; - - private final T15 value15; - - private final T16 value16; - - private final T17 value17; + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19> + implements Tuple { + private static final int SIZE = 19; + + private final T1 value1; + + private final T2 value2; + + private final T3 value3; + + private final T4 value4; + + private final T5 value5; + + private final T6 value6; + + private final T7 value7; + + private final T8 value8; + + private final T9 value9; + + private final T10 value10; + + private final T11 value11; + + private final T12 value12; + + private final T13 value13; + + private final T14 value14; + + private final T15 value15; + + private final T16 value16; + + private final T17 value17; + + private final T18 value18; + + private final T19 value19; + + public Tuple19( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16, + T17 value17, + T18 value18, + T19 value19) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + this.value16 = value16; + this.value17 = value17; + this.value18 = value18; + this.value19 = value19; + } - private final T18 value18; + public T1 getValue1() { + return value1; + } - private final T19 value19; + public T2 getValue2() { + return value2; + } - public Tuple19( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15, - T16 value16, - T17 value17, - T18 value18, - T19 value19) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - this.value16 = value16; - this.value17 = value17; - this.value18 = value18; - this.value19 = value19; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } + public T3 getValue3() { + return value3; + } - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - public T16 getValue16() { - return value16; - } - - public T17 getValue17() { - return value17; - } - - public T18 getValue18() { - return value18; - } - - public T19 getValue19() { - return value19; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple19 tuple19 = - (Tuple19) o; - if (value1 != null ? !value1.equals(tuple19.value1) : tuple19.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple19.value2) : tuple19.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple19.value3) : tuple19.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple19.value4) : tuple19.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple19.value5) : tuple19.value5 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value6 != null ? !value6.equals(tuple19.value6) : tuple19.value6 != null) { - return false; + + public T11 getValue11() { + return value11; } - if (value7 != null ? !value7.equals(tuple19.value7) : tuple19.value7 != null) { - return false; + + public T12 getValue12() { + return value12; } - if (value8 != null ? !value8.equals(tuple19.value8) : tuple19.value8 != null) { - return false; + + public T13 getValue13() { + return value13; } - if (value9 != null ? !value9.equals(tuple19.value9) : tuple19.value9 != null) { - return false; + + public T14 getValue14() { + return value14; } - if (value10 != null ? !value10.equals(tuple19.value10) : tuple19.value10 != null) { - return false; + + public T15 getValue15() { + return value15; } - if (value11 != null ? !value11.equals(tuple19.value11) : tuple19.value11 != null) { - return false; + + public T16 getValue16() { + return value16; } - if (value12 != null ? !value12.equals(tuple19.value12) : tuple19.value12 != null) { - return false; + + public T17 getValue17() { + return value17; } - if (value13 != null ? !value13.equals(tuple19.value13) : tuple19.value13 != null) { - return false; + + public T18 getValue18() { + return value18; } - if (value14 != null ? !value14.equals(tuple19.value14) : tuple19.value14 != null) { - return false; + + public T19 getValue19() { + return value19; } - if (value15 != null ? !value15.equals(tuple19.value15) : tuple19.value15 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value16 != null ? !value16.equals(tuple19.value16) : tuple19.value16 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple19 tuple19 = + (Tuple19) o; + if (value1 != null ? !value1.equals(tuple19.value1) : tuple19.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple19.value2) : tuple19.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple19.value3) : tuple19.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple19.value4) : tuple19.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple19.value5) : tuple19.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple19.value6) : tuple19.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple19.value7) : tuple19.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple19.value8) : tuple19.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple19.value9) : tuple19.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple19.value10) : tuple19.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple19.value11) : tuple19.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple19.value12) : tuple19.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple19.value13) : tuple19.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple19.value14) : tuple19.value14 != null) { + return false; + } + if (value15 != null ? !value15.equals(tuple19.value15) : tuple19.value15 != null) { + return false; + } + if (value16 != null ? !value16.equals(tuple19.value16) : tuple19.value16 != null) { + return false; + } + if (value17 != null ? !value17.equals(tuple19.value17) : tuple19.value17 != null) { + return false; + } + if (value18 != null ? !value18.equals(tuple19.value18) : tuple19.value18 != null) { + return false; + } + return value19 != null ? value19.equals(tuple19.value19) : tuple19.value19 == null; } - if (value17 != null ? !value17.equals(tuple19.value17) : tuple19.value17 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + result = 31 * result + (value16 != null ? value16.hashCode() : 0); + result = 31 * result + (value17 != null ? value17.hashCode() : 0); + result = 31 * result + (value18 != null ? value18.hashCode() : 0); + result = 31 * result + (value19 != null ? value19.hashCode() : 0); + return result; } - if (value18 != null ? !value18.equals(tuple19.value18) : tuple19.value18 != null) { - return false; + + @Override + public String toString() { + return "Tuple19{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + ", value16=" + + value16 + + ", value17=" + + value17 + + ", value18=" + + value18 + + ", value19=" + + value19 + + "}"; } - return value19 != null ? value19.equals(tuple19.value19) : tuple19.value19 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - result = 31 * result + (value16 != null ? value16.hashCode() : 0); - result = 31 * result + (value17 != null ? value17.hashCode() : 0); - result = 31 * result + (value18 != null ? value18.hashCode() : 0); - result = 31 * result + (value19 != null ? value19.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple19{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + ", value16=" - + value16 - + ", value17=" - + value17 - + ", value18=" - + value18 - + ", value19=" - + value19 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple2.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple2.java index 60d4229dd..f5599232c 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple2.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple2.java @@ -11,54 +11,54 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple2 implements Tuple { - private static final int SIZE = 2; + private static final int SIZE = 2; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - public Tuple2(T1 value1, T2 value2) { - this.value1 = value1; - this.value2 = value2; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } + public Tuple2(T1 value1, T2 value2) { + this.value1 = value1; + this.value2 = value2; + } - @Override - public int getSize() { - return SIZE; - } + public T1 getValue1() { + return value1; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T2 getValue2() { + return value2; } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public int getSize() { + return SIZE; } - Tuple2 tuple2 = (Tuple2) o; - if (value1 != null ? !value1.equals(tuple2.value1) : tuple2.value1 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple2 tuple2 = (Tuple2) o; + if (value1 != null ? !value1.equals(tuple2.value1) : tuple2.value1 != null) { + return false; + } + return value2 != null ? value2.equals(tuple2.value2) : tuple2.value2 == null; } - return value2 != null ? value2.equals(tuple2.value2) : tuple2.value2 == null; - } - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - return result; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + return result; + } - @Override - public String toString() { - return "Tuple2{" + "value1=" + value1 + ", value2=" + value2 + "}"; - } + @Override + public String toString() { + return "Tuple2{" + "value1=" + value1 + ", value2=" + value2 + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple20.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple20.java index 3e05d81e4..d8931f6f0 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple20.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple20.java @@ -11,316 +11,335 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple20< - T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20> - implements Tuple { - private static final int SIZE = 20; - - private final T1 value1; - - private final T2 value2; - - private final T3 value3; - - private final T4 value4; - - private final T5 value5; - - private final T6 value6; - - private final T7 value7; - - private final T8 value8; - - private final T9 value9; - - private final T10 value10; - - private final T11 value11; - - private final T12 value12; - - private final T13 value13; - - private final T14 value14; - - private final T15 value15; - - private final T16 value16; - - private final T17 value17; - - private final T18 value18; + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20> + implements Tuple { + private static final int SIZE = 20; + + private final T1 value1; + + private final T2 value2; + + private final T3 value3; + + private final T4 value4; + + private final T5 value5; + + private final T6 value6; + + private final T7 value7; + + private final T8 value8; + + private final T9 value9; + + private final T10 value10; + + private final T11 value11; + + private final T12 value12; + + private final T13 value13; + + private final T14 value14; + + private final T15 value15; + + private final T16 value16; + + private final T17 value17; + + private final T18 value18; + + private final T19 value19; + + private final T20 value20; + + public Tuple20( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16, + T17 value17, + T18 value18, + T19 value19, + T20 value20) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + this.value10 = value10; + this.value11 = value11; + this.value12 = value12; + this.value13 = value13; + this.value14 = value14; + this.value15 = value15; + this.value16 = value16; + this.value17 = value17; + this.value18 = value18; + this.value19 = value19; + this.value20 = value20; + } - private final T19 value19; + public T1 getValue1() { + return value1; + } - private final T20 value20; + public T2 getValue2() { + return value2; + } - public Tuple20( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9, - T10 value10, - T11 value11, - T12 value12, - T13 value13, - T14 value14, - T15 value15, - T16 value16, - T17 value17, - T18 value18, - T19 value19, - T20 value20) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - this.value10 = value10; - this.value11 = value11; - this.value12 = value12; - this.value13 = value13; - this.value14 = value14; - this.value15 = value15; - this.value16 = value16; - this.value17 = value17; - this.value18 = value18; - this.value19 = value19; - this.value20 = value20; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } + public T3 getValue3() { + return value3; + } - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } - - public T8 getValue8() { - return value8; - } - - public T9 getValue9() { - return value9; - } - - public T10 getValue10() { - return value10; - } - - public T11 getValue11() { - return value11; - } - - public T12 getValue12() { - return value12; - } - - public T13 getValue13() { - return value13; - } - - public T14 getValue14() { - return value14; - } - - public T15 getValue15() { - return value15; - } - - public T16 getValue16() { - return value16; - } - - public T17 getValue17() { - return value17; - } - - public T18 getValue18() { - return value18; - } - - public T19 getValue19() { - return value19; - } - - public T20 getValue20() { - return value20; - } - - @Override - public int getSize() { - return SIZE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple20 tuple20 = - (Tuple20) o; - if (value1 != null ? !value1.equals(tuple20.value1) : tuple20.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple20.value2) : tuple20.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple20.value3) : tuple20.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple20.value4) : tuple20.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple20.value5) : tuple20.value5 != null) { - return false; + + public T10 getValue10() { + return value10; } - if (value6 != null ? !value6.equals(tuple20.value6) : tuple20.value6 != null) { - return false; + + public T11 getValue11() { + return value11; } - if (value7 != null ? !value7.equals(tuple20.value7) : tuple20.value7 != null) { - return false; + + public T12 getValue12() { + return value12; } - if (value8 != null ? !value8.equals(tuple20.value8) : tuple20.value8 != null) { - return false; + + public T13 getValue13() { + return value13; } - if (value9 != null ? !value9.equals(tuple20.value9) : tuple20.value9 != null) { - return false; + + public T14 getValue14() { + return value14; } - if (value10 != null ? !value10.equals(tuple20.value10) : tuple20.value10 != null) { - return false; + + public T15 getValue15() { + return value15; } - if (value11 != null ? !value11.equals(tuple20.value11) : tuple20.value11 != null) { - return false; + + public T16 getValue16() { + return value16; } - if (value12 != null ? !value12.equals(tuple20.value12) : tuple20.value12 != null) { - return false; + + public T17 getValue17() { + return value17; } - if (value13 != null ? !value13.equals(tuple20.value13) : tuple20.value13 != null) { - return false; + + public T18 getValue18() { + return value18; } - if (value14 != null ? !value14.equals(tuple20.value14) : tuple20.value14 != null) { - return false; + + public T19 getValue19() { + return value19; } - if (value15 != null ? !value15.equals(tuple20.value15) : tuple20.value15 != null) { - return false; + + public T20 getValue20() { + return value20; } - if (value16 != null ? !value16.equals(tuple20.value16) : tuple20.value16 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value17 != null ? !value17.equals(tuple20.value17) : tuple20.value17 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple20 tuple20 = + (Tuple20) o; + if (value1 != null ? !value1.equals(tuple20.value1) : tuple20.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple20.value2) : tuple20.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple20.value3) : tuple20.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple20.value4) : tuple20.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple20.value5) : tuple20.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple20.value6) : tuple20.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple20.value7) : tuple20.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple20.value8) : tuple20.value8 != null) { + return false; + } + if (value9 != null ? !value9.equals(tuple20.value9) : tuple20.value9 != null) { + return false; + } + if (value10 != null ? !value10.equals(tuple20.value10) : tuple20.value10 != null) { + return false; + } + if (value11 != null ? !value11.equals(tuple20.value11) : tuple20.value11 != null) { + return false; + } + if (value12 != null ? !value12.equals(tuple20.value12) : tuple20.value12 != null) { + return false; + } + if (value13 != null ? !value13.equals(tuple20.value13) : tuple20.value13 != null) { + return false; + } + if (value14 != null ? !value14.equals(tuple20.value14) : tuple20.value14 != null) { + return false; + } + if (value15 != null ? !value15.equals(tuple20.value15) : tuple20.value15 != null) { + return false; + } + if (value16 != null ? !value16.equals(tuple20.value16) : tuple20.value16 != null) { + return false; + } + if (value17 != null ? !value17.equals(tuple20.value17) : tuple20.value17 != null) { + return false; + } + if (value18 != null ? !value18.equals(tuple20.value18) : tuple20.value18 != null) { + return false; + } + if (value19 != null ? !value19.equals(tuple20.value19) : tuple20.value19 != null) { + return false; + } + return value20 != null ? value20.equals(tuple20.value20) : tuple20.value20 == null; } - if (value18 != null ? !value18.equals(tuple20.value18) : tuple20.value18 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + result = 31 * result + (value10 != null ? value10.hashCode() : 0); + result = 31 * result + (value11 != null ? value11.hashCode() : 0); + result = 31 * result + (value12 != null ? value12.hashCode() : 0); + result = 31 * result + (value13 != null ? value13.hashCode() : 0); + result = 31 * result + (value14 != null ? value14.hashCode() : 0); + result = 31 * result + (value15 != null ? value15.hashCode() : 0); + result = 31 * result + (value16 != null ? value16.hashCode() : 0); + result = 31 * result + (value17 != null ? value17.hashCode() : 0); + result = 31 * result + (value18 != null ? value18.hashCode() : 0); + result = 31 * result + (value19 != null ? value19.hashCode() : 0); + result = 31 * result + (value20 != null ? value20.hashCode() : 0); + return result; } - if (value19 != null ? !value19.equals(tuple20.value19) : tuple20.value19 != null) { - return false; + + @Override + public String toString() { + return "Tuple20{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + ", value10=" + + value10 + + ", value11=" + + value11 + + ", value12=" + + value12 + + ", value13=" + + value13 + + ", value14=" + + value14 + + ", value15=" + + value15 + + ", value16=" + + value16 + + ", value17=" + + value17 + + ", value18=" + + value18 + + ", value19=" + + value19 + + ", value20=" + + value20 + + "}"; } - return value20 != null ? value20.equals(tuple20.value20) : tuple20.value20 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - result = 31 * result + (value10 != null ? value10.hashCode() : 0); - result = 31 * result + (value11 != null ? value11.hashCode() : 0); - result = 31 * result + (value12 != null ? value12.hashCode() : 0); - result = 31 * result + (value13 != null ? value13.hashCode() : 0); - result = 31 * result + (value14 != null ? value14.hashCode() : 0); - result = 31 * result + (value15 != null ? value15.hashCode() : 0); - result = 31 * result + (value16 != null ? value16.hashCode() : 0); - result = 31 * result + (value17 != null ? value17.hashCode() : 0); - result = 31 * result + (value18 != null ? value18.hashCode() : 0); - result = 31 * result + (value19 != null ? value19.hashCode() : 0); - result = 31 * result + (value20 != null ? value20.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple20{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + ", value10=" - + value10 - + ", value11=" - + value11 - + ", value12=" - + value12 - + ", value13=" - + value13 - + ", value14=" - + value14 - + ", value15=" - + value15 - + ", value16=" - + value16 - + ", value17=" - + value17 - + ", value18=" - + value18 - + ", value19=" - + value19 - + ", value20=" - + value20 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple3.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple3.java index dcbefd47b..bdd1de9a2 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple3.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple3.java @@ -11,65 +11,65 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple3 implements Tuple { - private static final int SIZE = 3; + private static final int SIZE = 3; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - public Tuple3(T1 value1, T2 value2, T3 value3) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } + public Tuple3(T1 value1, T2 value2, T3 value3) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + } - @Override - public int getSize() { - return SIZE; - } + public T1 getValue1() { + return value1; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T2 getValue2() { + return value2; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T3 getValue3() { + return value3; } - Tuple3 tuple3 = (Tuple3) o; - if (value1 != null ? !value1.equals(tuple3.value1) : tuple3.value1 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value2 != null ? !value2.equals(tuple3.value2) : tuple3.value2 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple3 tuple3 = (Tuple3) o; + if (value1 != null ? !value1.equals(tuple3.value1) : tuple3.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple3.value2) : tuple3.value2 != null) { + return false; + } + return value3 != null ? value3.equals(tuple3.value3) : tuple3.value3 == null; } - return value3 != null ? value3.equals(tuple3.value3) : tuple3.value3 == null; - } - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - return result; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + return result; + } - @Override - public String toString() { - return "Tuple3{" + "value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "}"; - } + @Override + public String toString() { + return "Tuple3{" + "value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple4.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple4.java index 8fce304a1..0214ea0f4 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple4.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple4.java @@ -11,85 +11,85 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple4 implements Tuple { - private static final int SIZE = 4; + private static final int SIZE = 4; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - public Tuple4(T1 value1, T2 value2, T3 value3, T4 value4) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } + public Tuple4(T1 value1, T2 value2, T3 value3, T4 value4) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + } - @Override - public int getSize() { - return SIZE; - } + public T1 getValue1() { + return value1; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T2 getValue2() { + return value2; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T3 getValue3() { + return value3; } - Tuple4 tuple4 = (Tuple4) o; - if (value1 != null ? !value1.equals(tuple4.value1) : tuple4.value1 != null) { - return false; + + public T4 getValue4() { + return value4; } - if (value2 != null ? !value2.equals(tuple4.value2) : tuple4.value2 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value3 != null ? !value3.equals(tuple4.value3) : tuple4.value3 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple4 tuple4 = (Tuple4) o; + if (value1 != null ? !value1.equals(tuple4.value1) : tuple4.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple4.value2) : tuple4.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple4.value3) : tuple4.value3 != null) { + return false; + } + return value4 != null ? value4.equals(tuple4.value4) : tuple4.value4 == null; } - return value4 != null ? value4.equals(tuple4.value4) : tuple4.value4 == null; - } - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - return result; - } + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + return result; + } - @Override - public String toString() { - return "Tuple4{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + "}"; - } + @Override + public String toString() { + return "Tuple4{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + "}"; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple5.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple5.java index 0b459ac4c..f59b9c5a1 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple5.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple5.java @@ -11,98 +11,98 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple5 implements Tuple { - private static final int SIZE = 5; + private static final int SIZE = 5; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - public Tuple5(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } + public Tuple5(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + } - public T4 getValue4() { - return value4; - } + public T1 getValue1() { + return value1; + } - public T5 getValue5() { - return value5; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple5 tuple5 = (Tuple5) o; - if (value1 != null ? !value1.equals(tuple5.value1) : tuple5.value1 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value2 != null ? !value2.equals(tuple5.value2) : tuple5.value2 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple5 tuple5 = (Tuple5) o; + if (value1 != null ? !value1.equals(tuple5.value1) : tuple5.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple5.value2) : tuple5.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple5.value3) : tuple5.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple5.value4) : tuple5.value4 != null) { + return false; + } + return value5 != null ? value5.equals(tuple5.value5) : tuple5.value5 == null; } - if (value3 != null ? !value3.equals(tuple5.value3) : tuple5.value3 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + return result; } - if (value4 != null ? !value4.equals(tuple5.value4) : tuple5.value4 != null) { - return false; + + @Override + public String toString() { + return "Tuple5{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + "}"; } - return value5 != null ? value5.equals(tuple5.value5) : tuple5.value5 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple5{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple6.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple6.java index 92e41f5da..18be4e793 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple6.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple6.java @@ -11,111 +11,111 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple6 implements Tuple { - private static final int SIZE = 6; + private static final int SIZE = 6; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - public Tuple6(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } + public Tuple6(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + } - public T5 getValue5() { - return value5; - } + public T1 getValue1() { + return value1; + } - public T6 getValue6() { - return value6; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple6 tuple6 = (Tuple6) o; - if (value1 != null ? !value1.equals(tuple6.value1) : tuple6.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple6.value2) : tuple6.value2 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value3 != null ? !value3.equals(tuple6.value3) : tuple6.value3 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple6 tuple6 = (Tuple6) o; + if (value1 != null ? !value1.equals(tuple6.value1) : tuple6.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple6.value2) : tuple6.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple6.value3) : tuple6.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple6.value4) : tuple6.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple6.value5) : tuple6.value5 != null) { + return false; + } + return value6 != null ? value6.equals(tuple6.value6) : tuple6.value6 == null; } - if (value4 != null ? !value4.equals(tuple6.value4) : tuple6.value4 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + return result; } - if (value5 != null ? !value5.equals(tuple6.value5) : tuple6.value5 != null) { - return false; + + @Override + public String toString() { + return "Tuple6{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + "}"; } - return value6 != null ? value6.equals(tuple6.value6) : tuple6.value6 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple6{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple7.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple7.java index ffee92d23..bc347c3a6 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple7.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple7.java @@ -11,124 +11,124 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple7 implements Tuple { - private static final int SIZE = 7; + private static final int SIZE = 7; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - public Tuple7(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } + public Tuple7(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + } - public T6 getValue6() { - return value6; - } + public T1 getValue1() { + return value1; + } - public T7 getValue7() { - return value7; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple7 tuple7 = (Tuple7) o; - if (value1 != null ? !value1.equals(tuple7.value1) : tuple7.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple7.value2) : tuple7.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple7.value3) : tuple7.value3 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value4 != null ? !value4.equals(tuple7.value4) : tuple7.value4 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple7 tuple7 = (Tuple7) o; + if (value1 != null ? !value1.equals(tuple7.value1) : tuple7.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple7.value2) : tuple7.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple7.value3) : tuple7.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple7.value4) : tuple7.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple7.value5) : tuple7.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple7.value6) : tuple7.value6 != null) { + return false; + } + return value7 != null ? value7.equals(tuple7.value7) : tuple7.value7 == null; } - if (value5 != null ? !value5.equals(tuple7.value5) : tuple7.value5 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + return result; } - if (value6 != null ? !value6.equals(tuple7.value6) : tuple7.value6 != null) { - return false; + + @Override + public String toString() { + return "Tuple7{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + "}"; } - return value7 != null ? value7.equals(tuple7.value7) : tuple7.value7 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple7{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple8.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple8.java index 8a177f049..105cf9d1f 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple8.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple8.java @@ -11,138 +11,145 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple8 implements Tuple { - private static final int SIZE = 8; + private static final int SIZE = 8; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - public Tuple8( - T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } + public Tuple8( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + } - public T7 getValue7() { - return value7; - } + public T1 getValue1() { + return value1; + } - public T8 getValue8() { - return value8; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple8 tuple8 = (Tuple8) o; - if (value1 != null ? !value1.equals(tuple8.value1) : tuple8.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple8.value2) : tuple8.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple8.value3) : tuple8.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple8.value4) : tuple8.value4 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value5 != null ? !value5.equals(tuple8.value5) : tuple8.value5 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple8 tuple8 = (Tuple8) o; + if (value1 != null ? !value1.equals(tuple8.value1) : tuple8.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple8.value2) : tuple8.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple8.value3) : tuple8.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple8.value4) : tuple8.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple8.value5) : tuple8.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple8.value6) : tuple8.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple8.value7) : tuple8.value7 != null) { + return false; + } + return value8 != null ? value8.equals(tuple8.value8) : tuple8.value8 == null; } - if (value6 != null ? !value6.equals(tuple8.value6) : tuple8.value6 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + return result; } - if (value7 != null ? !value7.equals(tuple8.value7) : tuple8.value7 != null) { - return false; + + @Override + public String toString() { + return "Tuple8{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + "}"; } - return value8 != null ? value8.equals(tuple8.value8) : tuple8.value8 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple8{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple9.java b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple9.java index 93d412985..208422305 100644 --- a/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple9.java +++ b/src/main/java/org/fisco/bcos/web3j/tuples/generated/Tuple9.java @@ -11,159 +11,159 @@ * href="/web3j/web3j/tree/master/codegen">codegen module to update. */ public final class Tuple9 implements Tuple { - private static final int SIZE = 9; + private static final int SIZE = 9; - private final T1 value1; + private final T1 value1; - private final T2 value2; + private final T2 value2; - private final T3 value3; + private final T3 value3; - private final T4 value4; + private final T4 value4; - private final T5 value5; + private final T5 value5; - private final T6 value6; + private final T6 value6; - private final T7 value7; + private final T7 value7; - private final T8 value8; + private final T8 value8; - private final T9 value9; + private final T9 value9; - public Tuple9( - T1 value1, - T2 value2, - T3 value3, - T4 value4, - T5 value5, - T6 value6, - T7 value7, - T8 value8, - T9 value9) { - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - this.value8 = value8; - this.value9 = value9; - } - - public T1 getValue1() { - return value1; - } - - public T2 getValue2() { - return value2; - } - - public T3 getValue3() { - return value3; - } - - public T4 getValue4() { - return value4; - } - - public T5 getValue5() { - return value5; - } - - public T6 getValue6() { - return value6; - } - - public T7 getValue7() { - return value7; - } + public Tuple9( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + this.value8 = value8; + this.value9 = value9; + } - public T8 getValue8() { - return value8; - } + public T1 getValue1() { + return value1; + } - public T9 getValue9() { - return value9; - } + public T2 getValue2() { + return value2; + } - @Override - public int getSize() { - return SIZE; - } + public T3 getValue3() { + return value3; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public T4 getValue4() { + return value4; } - if (o == null || getClass() != o.getClass()) { - return false; + + public T5 getValue5() { + return value5; } - Tuple9 tuple9 = (Tuple9) o; - if (value1 != null ? !value1.equals(tuple9.value1) : tuple9.value1 != null) { - return false; + + public T6 getValue6() { + return value6; } - if (value2 != null ? !value2.equals(tuple9.value2) : tuple9.value2 != null) { - return false; + + public T7 getValue7() { + return value7; } - if (value3 != null ? !value3.equals(tuple9.value3) : tuple9.value3 != null) { - return false; + + public T8 getValue8() { + return value8; } - if (value4 != null ? !value4.equals(tuple9.value4) : tuple9.value4 != null) { - return false; + + public T9 getValue9() { + return value9; } - if (value5 != null ? !value5.equals(tuple9.value5) : tuple9.value5 != null) { - return false; + + @Override + public int getSize() { + return SIZE; } - if (value6 != null ? !value6.equals(tuple9.value6) : tuple9.value6 != null) { - return false; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tuple9 tuple9 = (Tuple9) o; + if (value1 != null ? !value1.equals(tuple9.value1) : tuple9.value1 != null) { + return false; + } + if (value2 != null ? !value2.equals(tuple9.value2) : tuple9.value2 != null) { + return false; + } + if (value3 != null ? !value3.equals(tuple9.value3) : tuple9.value3 != null) { + return false; + } + if (value4 != null ? !value4.equals(tuple9.value4) : tuple9.value4 != null) { + return false; + } + if (value5 != null ? !value5.equals(tuple9.value5) : tuple9.value5 != null) { + return false; + } + if (value6 != null ? !value6.equals(tuple9.value6) : tuple9.value6 != null) { + return false; + } + if (value7 != null ? !value7.equals(tuple9.value7) : tuple9.value7 != null) { + return false; + } + if (value8 != null ? !value8.equals(tuple9.value8) : tuple9.value8 != null) { + return false; + } + return value9 != null ? value9.equals(tuple9.value9) : tuple9.value9 == null; } - if (value7 != null ? !value7.equals(tuple9.value7) : tuple9.value7 != null) { - return false; + + @Override + public int hashCode() { + int result = value1.hashCode(); + result = 31 * result + (value2 != null ? value2.hashCode() : 0); + result = 31 * result + (value3 != null ? value3.hashCode() : 0); + result = 31 * result + (value4 != null ? value4.hashCode() : 0); + result = 31 * result + (value5 != null ? value5.hashCode() : 0); + result = 31 * result + (value6 != null ? value6.hashCode() : 0); + result = 31 * result + (value7 != null ? value7.hashCode() : 0); + result = 31 * result + (value8 != null ? value8.hashCode() : 0); + result = 31 * result + (value9 != null ? value9.hashCode() : 0); + return result; } - if (value8 != null ? !value8.equals(tuple9.value8) : tuple9.value8 != null) { - return false; + + @Override + public String toString() { + return "Tuple9{" + + "value1=" + + value1 + + ", value2=" + + value2 + + ", value3=" + + value3 + + ", value4=" + + value4 + + ", value5=" + + value5 + + ", value6=" + + value6 + + ", value7=" + + value7 + + ", value8=" + + value8 + + ", value9=" + + value9 + + "}"; } - return value9 != null ? value9.equals(tuple9.value9) : tuple9.value9 == null; - } - - @Override - public int hashCode() { - int result = value1.hashCode(); - result = 31 * result + (value2 != null ? value2.hashCode() : 0); - result = 31 * result + (value3 != null ? value3.hashCode() : 0); - result = 31 * result + (value4 != null ? value4.hashCode() : 0); - result = 31 * result + (value5 != null ? value5.hashCode() : 0); - result = 31 * result + (value6 != null ? value6.hashCode() : 0); - result = 31 * result + (value7 != null ? value7.hashCode() : 0); - result = 31 * result + (value8 != null ? value8.hashCode() : 0); - result = 31 * result + (value9 != null ? value9.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Tuple9{" - + "value1=" - + value1 - + ", value2=" - + value2 - + ", value3=" - + value3 - + ", value4=" - + value4 - + ", value5=" - + value5 - + ", value6=" - + value6 - + ", value7=" - + value7 - + ", value8=" - + value8 - + ", value9=" - + value9 - + "}"; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/ChainId.java b/src/main/java/org/fisco/bcos/web3j/tx/ChainId.java index 424c108ac..b36503771 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/ChainId.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/ChainId.java @@ -2,14 +2,14 @@ /** Ethereum chain ids. */ public class ChainId { - public static final byte NONE = -1; - public static final byte MAINNET = 1; - public static final byte EXPANSE_MAINNET = 2; - public static final byte ROPSTEN = 3; - public static final byte RINKEBY = 4; - public static final byte ROOTSTOCK_MAINNET = 30; - public static final byte ROOTSTOCK_TESTNET = 31; - public static final byte KOVAN = 42; - public static final byte ETHEREUM_CLASSIC_MAINNET = 61; - public static final byte ETHEREUM_CLASSIC_TESTNET = 62; + public static final byte NONE = -1; + public static final byte MAINNET = 1; + public static final byte EXPANSE_MAINNET = 2; + public static final byte ROPSTEN = 3; + public static final byte RINKEBY = 4; + public static final byte ROOTSTOCK_MAINNET = 30; + public static final byte ROOTSTOCK_TESTNET = 31; + public static final byte KOVAN = 42; + public static final byte ETHEREUM_CLASSIC_MAINNET = 61; + public static final byte ETHEREUM_CLASSIC_TESTNET = 62; } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/ClientTransactionManager.java b/src/main/java/org/fisco/bcos/web3j/tx/ClientTransactionManager.java index 05beaa560..a2e7a80d4 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/ClientTransactionManager.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/ClientTransactionManager.java @@ -23,75 +23,81 @@ *

Note: accounts must be unlocked on the node for transactions to be successful. */ public class ClientTransactionManager extends TransactionManager { - static Logger logger = LoggerFactory.getLogger(RawTransactionManager.class); - private final Web3j web3j; - protected TxHashVerifier txHashVerifier = new TxHashVerifier(); + static Logger logger = LoggerFactory.getLogger(RawTransactionManager.class); + private final Web3j web3j; + protected TxHashVerifier txHashVerifier = new TxHashVerifier(); - public ClientTransactionManager(Web3j web3j, Credentials credentials) { - super(web3j, credentials); - this.web3j = web3j; - } + public ClientTransactionManager(Web3j web3j, Credentials credentials) { + super(web3j, credentials); + this.web3j = web3j; + } - public ClientTransactionManager( - Web3j web3j, Credentials credentials, int attempts, int sleepDuration) { - super(web3j, attempts, sleepDuration, credentials); - this.web3j = web3j; - } + public ClientTransactionManager( + Web3j web3j, Credentials credentials, int attempts, int sleepDuration) { + super(web3j, attempts, sleepDuration, credentials); + this.web3j = web3j; + } - public ClientTransactionManager( - Web3j web3j, - Credentials credentials, - TransactionReceiptProcessor transactionReceiptProcessor) { - super(transactionReceiptProcessor, credentials); - this.web3j = web3j; - } + public ClientTransactionManager( + Web3j web3j, + Credentials credentials, + TransactionReceiptProcessor transactionReceiptProcessor) { + super(transactionReceiptProcessor, credentials); + this.web3j = web3j; + } - @Override - public SendTransaction sendTransaction( - BigInteger gasPrice, BigInteger gasLimit, String to, String data, BigInteger value, String extraData) - throws IOException { + @Override + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException { - Random r = new SecureRandom(); - BigInteger randomid = new BigInteger(250, r); - BigInteger blockLimit = getBlockLimit(); - logger.info("sendTransaction randomid: {} blockLimit:{}", randomid, blockLimit); - RawTransaction rawTransaction = - RawTransaction.createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data); + Random r = new SecureRandom(); + BigInteger randomid = new BigInteger(250, r); + BigInteger blockLimit = getBlockLimit(); + logger.info("sendTransaction randomid: {} blockLimit:{}", randomid, blockLimit); + RawTransaction rawTransaction = + RawTransaction.createTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value, data); - return signAndSend(rawTransaction); - } + return signAndSend(rawTransaction); + } - // public EthSendTransaction sendTransaction(BigInteger gasPrice, BigInteger gasLimit, String - // to, String data, BigInteger value, TransactionSucCallback callback) throws IOException { - // Transaction transaction = new Transaction( - // getFromAddress(), null, gasPrice, gasLimit, to, value, data); - // - // Request request = web3j.ethSendTransaction(transaction); - // request.setNeedTransCallback(true); - // request.setTransactionSucCallback(callback); - // return request.send(); - // } + // public EthSendTransaction sendTransaction(BigInteger gasPrice, BigInteger gasLimit, String + // to, String data, BigInteger value, TransactionSucCallback callback) throws IOException { + // Transaction transaction = new Transaction( + // getFromAddress(), null, gasPrice, gasLimit, to, value, data); + // + // Request request = web3j.ethSendTransaction(transaction); + // request.setNeedTransCallback(true); + // request.setTransactionSucCallback(callback); + // return request.send(); + // } - public SendTransaction signAndSend(RawTransaction rawTransaction) throws IOException { + public SendTransaction signAndSend(RawTransaction rawTransaction) throws IOException { - byte[] signedMessage; + byte[] signedMessage; - signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); - String hexValue = Numeric.toHexString(signedMessage); - SendTransaction sendTransaction = web3j.sendRawTransaction(hexValue).send(); + String hexValue = Numeric.toHexString(signedMessage); + SendTransaction sendTransaction = web3j.sendRawTransaction(hexValue).send(); - if (sendTransaction != null && !sendTransaction.hasError()) { - String txHashLocal = Hash.sha3(hexValue); - String txHashRemote = sendTransaction.getTransactionHash(); - if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { - throw new TxHashMismatchException(txHashLocal, txHashRemote); - } + if (sendTransaction != null && !sendTransaction.hasError()) { + String txHashLocal = Hash.sha3(hexValue); + String txHashRemote = sendTransaction.getTransactionHash(); + if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { + throw new TxHashMismatchException(txHashLocal, txHashRemote); + } + } + return sendTransaction; } - return sendTransaction; - } - BigInteger getBlockLimit() throws IOException { - return web3j.getBlockNumberCache(); - } + BigInteger getBlockLimit() throws IOException { + return web3j.getBlockNumberCache(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/Contract.java b/src/main/java/org/fisco/bcos/web3j/tx/Contract.java index 965656d09..c580325a6 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/Contract.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/Contract.java @@ -6,10 +6,6 @@ import java.util.*; import java.util.concurrent.Semaphore; import java.util.stream.Collectors; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.channel.client.TransactionSucCallback; import org.fisco.bcos.web3j.abi.EventEncoder; import org.fisco.bcos.web3j.abi.EventValues; @@ -27,10 +23,7 @@ import org.fisco.bcos.web3j.protocol.core.JsonRpc2_0Web3j; import org.fisco.bcos.web3j.protocol.core.RemoteCall; import org.fisco.bcos.web3j.protocol.core.methods.request.Transaction; -import org.fisco.bcos.web3j.protocol.core.methods.response.Call; -import org.fisco.bcos.web3j.protocol.core.methods.response.Code; -import org.fisco.bcos.web3j.protocol.core.methods.response.Log; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.protocol.core.methods.response.*; import org.fisco.bcos.web3j.protocol.exceptions.TransactionException; import org.fisco.bcos.web3j.tx.exceptions.ContractCallException; import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; @@ -45,759 +38,807 @@ */ public abstract class Contract extends ManagedTransaction { - /** - * @see DefaultGasProvider - * @deprecated ... - */ - static Logger logger = LoggerFactory.getLogger(Contract.class); - public static final BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000); - - public static final String BIN_NOT_PROVIDED = "Bin file was not provided"; - public static final String FUNC_DEPLOY = "deploy"; - - protected final String contractBinary; - protected String contractAddress; - protected ContractGasProvider gasProvider; - protected TransactionReceipt transactionReceipt; - protected Map deployedAddresses; - protected DefaultBlockParameter defaultBlockParameter = DefaultBlockParameterName.LATEST; - - protected Contract( - String contractBinary, - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider gasProvider) { - super(web3j, transactionManager); - this.contractAddress = cnsService.getAddressByContractNameAndVersion(contractAddress); - this.contractBinary = contractBinary; - this.gasProvider = gasProvider; - } - - //************ - protected Contract( - String contractBinary, - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider gasProvider) { - this( - contractBinary, - contractAddress, - web3j, - getTheTransactionManager(web3j, credentials), - gasProvider); -// if (!Service.clientVersion.equals("2.0.0-rc1")) { -// this.extendedTransactionManager = new ExtendedRawTransactionManager(web3j, credentials, new BigInteger("1"), Service.chainId); -// } - } - - public static TransactionManager getTheTransactionManager( Web3j web3j, Credentials credentials) { - JsonRpc2_0Web3j jsonRpc2_0Web3j = (JsonRpc2_0Web3j) web3j; - int groupId = jsonRpc2_0Web3j.getGroupId(); - String clientVersion =null; - String chainId= "1"; - String versionContent; - if (clientVersion == null) { - try { - versionContent= web3j.getNodeVersion().sendForReturnString(); - logger.info("***version***"); - if (versionContent.contains("2.0.0-rc1")) { - clientVersion = "2.0.0-rc1"; + /** + * @see DefaultGasProvider + * @deprecated ... + */ + static Logger logger = LoggerFactory.getLogger(Contract.class); + + public static final BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000); + + public static final String BIN_NOT_PROVIDED = "Bin file was not provided"; + public static final String FUNC_DEPLOY = "deploy"; + public static final String BCOS_RC1 = "2.0.0-rc1"; + protected final String contractBinary; + protected String contractAddress; + protected ContractGasProvider gasProvider; + protected TransactionReceipt transactionReceipt; + protected Map deployedAddresses; + protected DefaultBlockParameter defaultBlockParameter = DefaultBlockParameterName.LATEST; + + protected Contract( + String contractBinary, + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider gasProvider) { + super(web3j, transactionManager); + this.contractAddress = cnsService.getAddressByContractNameAndVersion(contractAddress); + this.contractBinary = contractBinary; + this.gasProvider = gasProvider; + } + + // ************ + protected Contract( + String contractBinary, + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider gasProvider) { + this( + contractBinary, + contractAddress, + web3j, + getTheTransactionManager(web3j, credentials), + gasProvider); + } + + public static TransactionManager getTheTransactionManager( + Web3j web3j, Credentials credentials) { + JsonRpc2_0Web3j jsonRpc2_0Web3j = (JsonRpc2_0Web3j) web3j; + int groupId = jsonRpc2_0Web3j.getGroupId(); + String chainId = "1"; + String version = ""; + String supportedVersion = ""; + try { + NodeVersion.Version nodeVersion = web3j.getNodeVersion().send().getNodeVersion(); + version = nodeVersion.getVersion(); + supportedVersion = nodeVersion.getSupportedVersion(); + if (BCOS_RC1.equals(version) || BCOS_RC1.equals(supportedVersion)) { + version = BCOS_RC1; + logger.info("fisco-bcos version:{}", version); + } else { + chainId = nodeVersion.getChainID(); + logger.info( + "fisco-bcos version:{}, supported version:{}", version, supportedVersion); + } + } catch (IOException e) { + logger.error("Query fisco-bcos version failed", e); } - JSONObject jsonObject = JSONObject.parseObject(versionContent); - chainId = (String)jsonObject.get("Chain Id"); - } catch (IOException e) { - - logger.info("can not get node version "); - } - } ; - - return "2.0.0-rc1".equals(clientVersion) ? new RawTransactionManager(web3j, credentials) : new ExtendedRawTransactionManager(web3j, credentials, BigInteger.valueOf(groupId), new BigInteger(chainId)); - - } - - - @Deprecated - protected Contract( - String contractBinary, - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - this( - contractBinary, - contractAddress, - web3j, - transactionManager, - new StaticGasProvider(gasPrice, gasLimit)); - } - - @Deprecated - protected Contract( - String contractBinary, - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - this( - contractBinary, - contractAddress, - web3j, - getTheTransactionManager(web3j,credentials), - gasPrice, - gasLimit); - } - - @Deprecated - protected Contract( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - this("", contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - @Deprecated - protected Contract( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - this( - "", - contractAddress, - web3j, - getTheTransactionManager(web3j,credentials), - gasPrice, - gasLimit); - } - - public void setContractAddress(String contractAddress) { - this.contractAddress = contractAddress; - } - - public String getContractAddress() { - return contractAddress; - } - - public void setTransactionReceipt(TransactionReceipt transactionReceipt) { - this.transactionReceipt = transactionReceipt; - } - - public String getContractBinary() { - return contractBinary; - } - - public void setGasProvider(ContractGasProvider gasProvider) { - this.gasProvider = gasProvider; - } - - /** - * Allow {@code gasPrice} to be set. - * - * @param newPrice gas price to use for subsequent transactions - * @deprecated use ContractGasProvider - */ - public void setGasPrice(BigInteger newPrice) { - this.gasProvider = new StaticGasProvider(newPrice, gasProvider.getGasLimit()); - } - - /** - * Get the current {@code gasPrice} value this contract uses when executing transactions. - * - * @return the gas price set on this contract - * @deprecated use ContractGasProvider - */ - public BigInteger getGasPrice() { - return gasProvider.getGasPrice(); - } - - /** - * Check that the contract deployed at the address associated with this smart contract wrapper is - * in fact the contract you believe it is. - * - *

This method uses the eth_getCode method to get the - * contract byte code and validates it against the byte code stored in this smart contract - * wrapper. - * - * @return true if the contract is valid - * @throws IOException if unable to connect to web3j node - */ - public boolean isValid() throws IOException { - if (contractBinary.equals(BIN_NOT_PROVIDED)) { - throw new UnsupportedOperationException( - "Contract binary not present in contract wrapper, " - + "please generate your wrapper using -abiFile="); - } - - if (contractAddress.equals("")) { - throw new UnsupportedOperationException( - "Contract binary not present, you will need to regenerate your smart " - + "contract wrapper with web3j v2.2.0+"); - } - - Code gcode = web3j.getCode(contractAddress, DefaultBlockParameterName.LATEST).send(); - if (gcode.hasError()) { - return false; - } - - String code = Numeric.cleanHexPrefix(gcode.getCode()); - // There may be multiple contracts in the Solidity bytecode, hence we only - // check for a match with a subset - return !code.isEmpty() && contractBinary.contains(code); - } - - /** - * If this Contract instance was created at deployment, the TransactionReceipt associated with the - * initial creation will be provided, e.g. via a deploy method. This will not persist for - * Contracts instances constructed via a load method. - * - * @return the TransactionReceipt generated at contract deployment - */ - public Optional getTransactionReceipt() { - return Optional.ofNullable(transactionReceipt); - } - - /** - * Sets the default block parameter. This use useful if one wants to query historical state of a - * contract. - * - * @param defaultBlockParameter the default block parameter - */ - public void setDefaultBlockParameter(DefaultBlockParameter defaultBlockParameter) { - this.defaultBlockParameter = defaultBlockParameter; - } - - /** - * Execute constant function call - i.e. a call that does not change state of the contract - * - * @param function to call - * @return {@link List} of values returned by function call - */ - private List executeCall(Function function) throws IOException { - String encodedFunction = FunctionEncoder.encode(function); - Call ethCall = - web3j - .call( - Transaction.createEthCallTransaction( - transactionManager.getFromAddress(), contractAddress, encodedFunction), - defaultBlockParameter) - .send(); - - String value = ethCall.getValue().getOutput(); - return FunctionReturnDecoder.decode(value, function.getOutputParameters()); - } - - @SuppressWarnings("unchecked") - protected T executeCallSingleValueReturn(Function function) throws IOException { - List values = executeCall(function); - if (!values.isEmpty()) { - return (T) values.get(0); - } else { - return null; - } - } - - @SuppressWarnings("unchecked") - protected R executeCallSingleValueReturn( - Function function, Class returnType) throws IOException { - T result = executeCallSingleValueReturn(function); - if (result == null) { - throw new ContractCallException("Empty value (0x) returned from contract"); - } - - Object value = result.getValue(); - if (returnType.isAssignableFrom(value.getClass())) { - return (R) value; - } else if (result.getClass().equals(Address.class) && returnType.equals(String.class)) { - return (R) result.toString(); // cast isn't necessary - } else { - throw new ContractCallException( - "Unable to convert response: " - + value - + " to expected type: " - + returnType.getSimpleName()); - } - } - - protected List executeCallMultipleValueReturn(Function function) throws IOException { - return executeCall(function); - } - - protected TransactionReceipt executeTransaction(Function function) - throws IOException, TransactionException { - - class Callback extends TransactionSucCallback { - Callback() { + + return BCOS_RC1.equals(version) + ? new RawTransactionManager(web3j, credentials) + : new ExtendedRawTransactionManager( + web3j, credentials, BigInteger.valueOf(groupId), new BigInteger(chainId)); + } + + @Deprecated + protected Contract( + String contractBinary, + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + this( + contractBinary, + contractAddress, + web3j, + transactionManager, + new StaticGasProvider(gasPrice, gasLimit)); + } + + @Deprecated + protected Contract( + String contractBinary, + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + this( + contractBinary, + contractAddress, + web3j, + getTheTransactionManager(web3j, credentials), + gasPrice, + gasLimit); + } + + @Deprecated + protected Contract( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + this("", contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + @Deprecated + protected Contract( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + this( + "", + contractAddress, + web3j, + getTheTransactionManager(web3j, credentials), + gasPrice, + gasLimit); + } + + public void setContractAddress(String contractAddress) { + this.contractAddress = contractAddress; + } + + public String getContractAddress() { + return contractAddress; + } + + public void setTransactionReceipt(TransactionReceipt transactionReceipt) { + this.transactionReceipt = transactionReceipt; + } + + public String getContractBinary() { + return contractBinary; + } + + public void setGasProvider(ContractGasProvider gasProvider) { + this.gasProvider = gasProvider; + } + + /** + * Allow {@code gasPrice} to be set. + * + * @param newPrice gas price to use for subsequent transactions + * @deprecated use ContractGasProvider + */ + public void setGasPrice(BigInteger newPrice) { + this.gasProvider = new StaticGasProvider(newPrice, gasProvider.getGasLimit()); + } + + /** + * Get the current {@code gasPrice} value this contract uses when executing transactions. + * + * @return the gas price set on this contract + * @deprecated use ContractGasProvider + */ + public BigInteger getGasPrice() { + return gasProvider.getGasPrice(); + } + + /** + * Check that the contract deployed at the address associated with this smart contract wrapper + * is in fact the contract you believe it is. + * + *

This method uses the eth_getCode method to get + * the contract byte code and validates it against the byte code stored in this smart contract + * wrapper. + * + * @return true if the contract is valid + * @throws IOException if unable to connect to web3j node + */ + public boolean isValid() throws IOException { + if (contractBinary.equals(BIN_NOT_PROVIDED)) { + throw new UnsupportedOperationException( + "Contract binary not present in contract wrapper, " + + "please generate your wrapper using -abiFile="); + } + + if (contractAddress.equals("")) { + throw new UnsupportedOperationException( + "Contract binary not present, you will need to regenerate your smart " + + "contract wrapper with web3j v2.2.0+"); + } + + Code gcode = web3j.getCode(contractAddress, DefaultBlockParameterName.LATEST).send(); + if (gcode.hasError()) { + return false; + } + + String code = Numeric.cleanHexPrefix(gcode.getCode()); + // There may be multiple contracts in the Solidity bytecode, hence we only + // check for a match with a subset + return !code.isEmpty() && contractBinary.contains(code); + } + + /** + * If this Contract instance was created at deployment, the TransactionReceipt associated with + * the initial creation will be provided, e.g. via a deploy method. This will not + * persist for Contracts instances constructed via a load method. + * + * @return the TransactionReceipt generated at contract deployment + */ + public Optional getTransactionReceipt() { + return Optional.ofNullable(transactionReceipt); + } + + /** + * Sets the default block parameter. This use useful if one wants to query historical state of a + * contract. + * + * @param defaultBlockParameter the default block parameter + */ + public void setDefaultBlockParameter(DefaultBlockParameter defaultBlockParameter) { + this.defaultBlockParameter = defaultBlockParameter; + } + + /** + * Execute constant function call - i.e. a call that does not change state of the contract + * + * @param function to call + * @return {@link List} of values returned by function call + */ + private List executeCall(Function function) throws IOException { + String encodedFunction = FunctionEncoder.encode(function); + Call ethCall = + web3j.call( + Transaction.createEthCallTransaction( + transactionManager.getFromAddress(), + contractAddress, + encodedFunction), + defaultBlockParameter) + .send(); + + String value = ethCall.getValue().getOutput(); + return FunctionReturnDecoder.decode(value, function.getOutputParameters()); + } + + @SuppressWarnings("unchecked") + protected T executeCallSingleValueReturn(Function function) + throws IOException { + List values = executeCall(function); + if (!values.isEmpty()) { + return (T) values.get(0); + } else { + return null; + } + } + + @SuppressWarnings("unchecked") + protected R executeCallSingleValueReturn( + Function function, Class returnType) throws IOException { + T result = executeCallSingleValueReturn(function); + if (result == null) { + throw new ContractCallException("Empty value (0x) returned from contract"); + } + + Object value = result.getValue(); + if (returnType.isAssignableFrom(value.getClass())) { + return (R) value; + } else if (result.getClass().equals(Address.class) && returnType.equals(String.class)) { + return (R) result.toString(); // cast isn't necessary + } else { + throw new ContractCallException( + "Unable to convert response: " + + value + + " to expected type: " + + returnType.getSimpleName()); + } + } + + protected List executeCallMultipleValueReturn(Function function) throws IOException { + return executeCall(function); + } + + protected TransactionReceipt executeTransaction(Function function) + throws IOException, TransactionException { + + class Callback extends TransactionSucCallback { + Callback() { + try { + semaphore.acquire(1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + @Override + public void onResponse(TransactionReceipt receipt) { + this.receipt = receipt; + semaphore.release(); + } + + public TransactionReceipt receipt; + public Semaphore semaphore = new Semaphore(1, true); + }; + + Callback callback = new Callback(); + + asyncExecuteTransaction(function, callback); try { - semaphore.acquire(1); + callback.semaphore.acquire(1); } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + Thread.currentThread().interrupt(); + } + + return callback.receipt; + } + + /** + * Given the duration required to execute a transaction. + * + * @param data to send in transaction + * @param weiValue in Wei to send in transaction + * @return {@link Optional} containing our transaction receipt + * @throws IOException if the call to the node fails + * @throws TransactionException if the transaction was not mined while waiting + */ + protected TransactionReceipt executeTransaction( + String data, BigInteger weiValue, String funcName) + throws TransactionException, IOException { + TransactionReceipt receipt = + send( + contractAddress, + data, + weiValue, + gasProvider.getGasPrice(funcName), + gasProvider.getGasLimit(funcName)); + + if (!receipt.isStatusOK()) { + String status = receipt.getStatus(); + BigInteger gasUsed = receipt.getGasUsed(); + String message = + String.format( + "Transaction has failed with status: %s. " + + "Gas used: %d. (not-enough gas?)", + status, gasUsed); + throw new TransactionException(message, status, gasUsed, receipt.getTransactionHash()); + } + + return receipt; + } + + protected void asyncExecuteTransaction(Function function, TransactionSucCallback callback) { + try { + sendOnly( + contractAddress, + FunctionEncoder.encode(function), + BigInteger.ZERO, + gasProvider.getGasPrice(function.getName()), + gasProvider.getGasLimit(function.getName()), + callback); + } catch (IOException e) { + e.printStackTrace(); + } catch (TransactionException e) { + e.printStackTrace(); + } + } + + protected String createTransactionSeq(Function function) { + try { + String signedTransaction = + createSeq( + contractAddress, + FunctionEncoder.encode(function), + BigInteger.ZERO, + gasProvider.getGasPrice(function.getName()), + gasProvider.getGasLimit(function.getName())); + return signedTransaction; + } catch (IOException e) { + e.printStackTrace(); + return ""; + } + } + + protected RemoteCall executeRemoteCallSingleValueReturn(Function function) { + return new RemoteCall<>(() -> executeCallSingleValueReturn(function)); + } + + protected RemoteCall executeRemoteCallSingleValueReturn( + Function function, Class returnType) { + return new RemoteCall<>(() -> executeCallSingleValueReturn(function, returnType)); + } + + protected RemoteCall> executeRemoteCallMultipleValueReturn(Function function) { + return new RemoteCall<>(() -> executeCallMultipleValueReturn(function)); + } + + protected RemoteCall executeRemoteCallTransaction(Function function) { + return new RemoteCall<>(() -> executeTransaction(function)); + } + + private static T create( + T contract, String binary, String encodedConstructor, BigInteger value) + throws IOException, TransactionException { + TransactionReceipt transactionReceipt = + contract.executeTransaction(binary + encodedConstructor, value, FUNC_DEPLOY); + + String contractAddress = transactionReceipt.getContractAddress(); + if (contractAddress == null) { + throw new RuntimeException("Empty contract address returned"); + } + contract.setContractAddress(contractAddress); + contract.setTransactionReceipt(transactionReceipt); + + return contract; + } + + protected static T deploy( + Class type, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor, + BigInteger value) + throws RuntimeException, TransactionException { + + try { + Constructor constructor = + type.getDeclaredConstructor( + String.class, + Web3j.class, + Credentials.class, + ContractGasProvider.class); + constructor.setAccessible(true); + + // we want to use null here to ensure that "to" parameter on message is + // not populated + T contract = constructor.newInstance(null, web3j, credentials, contractGasProvider); + + return create(contract, binary, encodedConstructor, value); + } catch (TransactionException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected static T deploy( + Class type, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor, + BigInteger value) + throws RuntimeException, TransactionException { + + try { + Constructor constructor = + type.getDeclaredConstructor( + String.class, + Web3j.class, + TransactionManager.class, + ContractGasProvider.class); + constructor.setAccessible(true); + + // we want to use null here to ensure that "to" parameter on message is + // not populated + T contract = + constructor.newInstance(null, web3j, transactionManager, contractGasProvider); + return create(contract, binary, encodedConstructor, value); + } catch (TransactionException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); } - } - - @Override - public void onResponse(TransactionReceipt receipt) { - this.receipt = receipt; - semaphore.release(); - } - - public TransactionReceipt receipt; - public Semaphore semaphore = new Semaphore(1, true); - }; - - Callback callback = new Callback(); - - asyncExecuteTransaction(function, callback); - try { - callback.semaphore.acquire(1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - - return callback.receipt; - } - - /** - * Given the duration required to execute a transaction. - * - * @param data to send in transaction - * @param weiValue in Wei to send in transaction - * @return {@link Optional} containing our transaction receipt - * @throws IOException if the call to the node fails - * @throws TransactionException if the transaction was not mined while waiting - */ - protected TransactionReceipt executeTransaction(String data, BigInteger weiValue, String funcName) - throws TransactionException, IOException { - TransactionReceipt receipt = - send( - contractAddress, - data, - weiValue, - gasProvider.getGasPrice(funcName), - gasProvider.getGasLimit(funcName)); - - if (!receipt.isStatusOK()) { - String status = receipt.getStatus(); - BigInteger gasUsed = receipt.getGasUsed(); - String message = - String.format( - "Transaction has failed with status: %s. " + "Gas used: %d. (not-enough gas?)", - status, gasUsed); - throw new TransactionException(message, status, gasUsed, receipt.getTransactionHash()); - } - - return receipt; - } - - protected void asyncExecuteTransaction(Function function, TransactionSucCallback callback) { - try { - sendOnly( - contractAddress, - FunctionEncoder.encode(function), - BigInteger.ZERO, - gasProvider.getGasPrice(function.getName()), - gasProvider.getGasLimit(function.getName()), - callback); - } catch (IOException e) { - e.printStackTrace(); - } catch (TransactionException e) { - e.printStackTrace(); - } - } - - protected RemoteCall executeRemoteCallSingleValueReturn(Function function) { - return new RemoteCall<>(() -> executeCallSingleValueReturn(function)); - } - - protected RemoteCall executeRemoteCallSingleValueReturn( - Function function, Class returnType) { - return new RemoteCall<>(() -> executeCallSingleValueReturn(function, returnType)); - } - - protected RemoteCall> executeRemoteCallMultipleValueReturn(Function function) { - return new RemoteCall<>(() -> executeCallMultipleValueReturn(function)); - } - - protected RemoteCall executeRemoteCallTransaction(Function function) { - return new RemoteCall<>(() -> executeTransaction(function)); - } - - private static T create( - T contract, String binary, String encodedConstructor, BigInteger value) - throws IOException, TransactionException { - TransactionReceipt transactionReceipt = - contract.executeTransaction(binary + encodedConstructor, value, FUNC_DEPLOY); - - String contractAddress = transactionReceipt.getContractAddress(); - if (contractAddress == null) { - throw new RuntimeException("Empty contract address returned"); - } - contract.setContractAddress(contractAddress); - contract.setTransactionReceipt(transactionReceipt); - - return contract; - } - - protected static T deploy( - Class type, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor, - BigInteger value) - throws RuntimeException, TransactionException { - - try { - Constructor constructor = - type.getDeclaredConstructor( - String.class, Web3j.class, Credentials.class, ContractGasProvider.class); - constructor.setAccessible(true); - - // we want to use null here to ensure that "to" parameter on message is - // not populated - T contract = constructor.newInstance(null, web3j, credentials, contractGasProvider); - - return create(contract, binary, encodedConstructor, value); - } catch (TransactionException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected static T deploy( - Class type, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor, - BigInteger value) - throws RuntimeException, TransactionException { - - try { - Constructor constructor = - type.getDeclaredConstructor( - String.class, Web3j.class, TransactionManager.class, ContractGasProvider.class); - constructor.setAccessible(true); - - // we want to use null here to ensure that "to" parameter on message is - // not populated - T contract = constructor.newInstance(null, web3j, transactionManager, contractGasProvider); - return create(contract, binary, encodedConstructor, value); - } catch (TransactionException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Deprecated - protected static T deploy( - Class type, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor, - BigInteger value) - throws RuntimeException, TransactionException { - - return deploy( - type, - web3j, - credentials, - new StaticGasProvider(gasPrice, gasLimit), - binary, - encodedConstructor, - value); - } - - @Deprecated - protected static T deploy( - Class type, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor, - BigInteger value) - throws RuntimeException, TransactionException { - - return deploy( - type, - web3j, - transactionManager, - new StaticGasProvider(gasPrice, gasLimit), - binary, - encodedConstructor, - value); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor, - BigInteger value) { - return new RemoteCall<>( - () -> - deploy( - type, web3j, credentials, gasPrice, gasLimit, binary, encodedConstructor, value)); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor) { - return deployRemoteCall( - type, web3j, credentials, gasPrice, gasLimit, binary, encodedConstructor, BigInteger.ZERO); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor, - BigInteger value) { - return new RemoteCall<>( - () -> - deploy( - type, web3j, credentials, contractGasProvider, binary, encodedConstructor, value)); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor) { - return new RemoteCall<>( - () -> - deploy( + } + + @Deprecated + protected static T deploy( + Class type, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor, + BigInteger value) + throws RuntimeException, TransactionException { + + return deploy( type, web3j, credentials, - contractGasProvider, + new StaticGasProvider(gasPrice, gasLimit), binary, encodedConstructor, - BigInteger.ZERO)); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor, - BigInteger value) { - return new RemoteCall<>( - () -> - deploy( + value); + } + + @Deprecated + protected static T deploy( + Class type, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor, + BigInteger value) + throws RuntimeException, TransactionException { + + return deploy( type, web3j, transactionManager, - gasPrice, - gasLimit, + new StaticGasProvider(gasPrice, gasLimit), binary, encodedConstructor, - value)); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit, - String binary, - String encodedConstructor) { - return deployRemoteCall( - type, - web3j, - transactionManager, - gasPrice, - gasLimit, - binary, - encodedConstructor, - BigInteger.ZERO); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor, - BigInteger value) { - return new RemoteCall<>( - () -> - deploy( + value); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor, + BigInteger value) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + credentials, + gasPrice, + gasLimit, + binary, + encodedConstructor, + value)); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor) { + return deployRemoteCall( type, web3j, - transactionManager, - contractGasProvider, + credentials, + gasPrice, + gasLimit, binary, encodedConstructor, - value)); - } - - public static RemoteCall deployRemoteCall( - Class type, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider, - String binary, - String encodedConstructor) { - return new RemoteCall<>( - () -> - deploy( + BigInteger.ZERO); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor, + BigInteger value) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + credentials, + contractGasProvider, + binary, + encodedConstructor, + value)); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + credentials, + contractGasProvider, + binary, + encodedConstructor, + BigInteger.ZERO)); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor, + BigInteger value) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + transactionManager, + gasPrice, + gasLimit, + binary, + encodedConstructor, + value)); + } + + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit, + String binary, + String encodedConstructor) { + return deployRemoteCall( type, web3j, transactionManager, - contractGasProvider, + gasPrice, + gasLimit, binary, encodedConstructor, - BigInteger.ZERO)); - } - - public static EventValues staticExtractEventParameters(Event event, Log log) { - - List topics = log.getTopics(); - String encodedEventSignature = EventEncoder.encode(event); - if (!topics.get(0).equals(encodedEventSignature)) { - return null; - } + BigInteger.ZERO); + } - List indexedValues = new ArrayList<>(); - List nonIndexedValues = - FunctionReturnDecoder.decode(log.getData(), event.getNonIndexedParameters()); + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor, + BigInteger value) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + transactionManager, + contractGasProvider, + binary, + encodedConstructor, + value)); + } - List> indexedParameters = event.getIndexedParameters(); - for (int i = 0; i < indexedParameters.size(); i++) { - Type value = - FunctionReturnDecoder.decodeIndexedValue(topics.get(i + 1), indexedParameters.get(i)); - indexedValues.add(value); + public static RemoteCall deployRemoteCall( + Class type, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider, + String binary, + String encodedConstructor) { + return new RemoteCall<>( + () -> + deploy( + type, + web3j, + transactionManager, + contractGasProvider, + binary, + encodedConstructor, + BigInteger.ZERO)); } - return new EventValues(indexedValues, nonIndexedValues); - } - protected EventValues extractEventParameters(Event event, Log log) { - return staticExtractEventParameters(event, log); - } + public static EventValues staticExtractEventParameters(Event event, Log log) { - protected List extractEventParameters( - Event event, TransactionReceipt transactionReceipt) { - return transactionReceipt - .getLogs() - .stream() - .map(log -> extractEventParameters(event, log)) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } + List topics = log.getTopics(); + String encodedEventSignature = EventEncoder.encode(event); + if (!topics.get(0).equals(encodedEventSignature)) { + return null; + } - protected EventValuesWithLog extractEventParametersWithLog(Event event, Log log) { - final EventValues eventValues = staticExtractEventParameters(event, log); - return (eventValues == null) ? null : new EventValuesWithLog(eventValues, log); - } + List indexedValues = new ArrayList<>(); + List nonIndexedValues = + FunctionReturnDecoder.decode(log.getData(), event.getNonIndexedParameters()); - protected List extractEventParametersWithLog( - Event event, TransactionReceipt transactionReceipt) { - return transactionReceipt - .getLogs() - .stream() - .map(log -> extractEventParametersWithLog(event, log)) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } + List> indexedParameters = event.getIndexedParameters(); + for (int i = 0; i < indexedParameters.size(); i++) { + Type value = + FunctionReturnDecoder.decodeIndexedValue( + topics.get(i + 1), indexedParameters.get(i)); + indexedValues.add(value); + } + return new EventValues(indexedValues, nonIndexedValues); + } - /** - * Subclasses should implement this method to return pre-existing addresses for deployed - * contracts. - * - * @param networkId the network id, for example "1" for the main-net, "3" for ropsten, etc. - * @return the deployed address of the contract, if known, and null otherwise. - */ - protected String getStaticDeployedAddress(String networkId) { - return null; - } + protected EventValues extractEventParameters(Event event, Log log) { + return staticExtractEventParameters(event, log); + } - public final void setDeployedAddress(String networkId, String address) { - if (deployedAddresses == null) { - deployedAddresses = new HashMap<>(); + protected List extractEventParameters( + Event event, TransactionReceipt transactionReceipt) { + return transactionReceipt + .getLogs() + .stream() + .map(log -> extractEventParameters(event, log)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } - deployedAddresses.put(networkId, address); - } - public final String getDeployedAddress(String networkId) { - String addr = null; - if (deployedAddresses != null) { - addr = deployedAddresses.get(networkId); + protected EventValuesWithLog extractEventParametersWithLog(Event event, Log log) { + final EventValues eventValues = staticExtractEventParameters(event, log); + return (eventValues == null) ? null : new EventValuesWithLog(eventValues, log); } - return addr == null ? getStaticDeployedAddress(networkId) : addr; - } - /** Adds a log field to {@link EventValues}. */ - public static class EventValuesWithLog { - private final EventValues eventValues; - private final Log log; + protected List extractEventParametersWithLog( + Event event, TransactionReceipt transactionReceipt) { + return transactionReceipt + .getLogs() + .stream() + .map(log -> extractEventParametersWithLog(event, log)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } - private EventValuesWithLog(EventValues eventValues, Log log) { - this.eventValues = eventValues; - this.log = log; + /** + * Subclasses should implement this method to return pre-existing addresses for deployed + * contracts. + * + * @param networkId the network id, for example "1" for the main-net, "3" for ropsten, etc. + * @return the deployed address of the contract, if known, and null otherwise. + */ + protected String getStaticDeployedAddress(String networkId) { + return null; } - public List getIndexedValues() { - return eventValues.getIndexedValues(); + public final void setDeployedAddress(String networkId, String address) { + if (deployedAddresses == null) { + deployedAddresses = new HashMap<>(); + } + deployedAddresses.put(networkId, address); } - public List getNonIndexedValues() { - return eventValues.getNonIndexedValues(); + public final String getDeployedAddress(String networkId) { + String addr = null; + if (deployedAddresses != null) { + addr = deployedAddresses.get(networkId); + } + return addr == null ? getStaticDeployedAddress(networkId) : addr; + } + + /** Adds a log field to {@link EventValues}. */ + public static class EventValuesWithLog { + private final EventValues eventValues; + private final Log log; + + private EventValuesWithLog(EventValues eventValues, Log log) { + this.eventValues = eventValues; + this.log = log; + } + + public List getIndexedValues() { + return eventValues.getIndexedValues(); + } + + public List getNonIndexedValues() { + return eventValues.getNonIndexedValues(); + } + + public Log getLog() { + return log; + } } - public Log getLog() { - return log; + @SuppressWarnings("unchecked") + protected static List convertToNative(List arr) { + List out = new ArrayList(); + for (Iterator it = arr.iterator(); it.hasNext(); ) { + out.add((T) it.next().getValue()); + } + return out; } - } - @SuppressWarnings("unchecked") - protected static List convertToNative(List arr) { - List out = new ArrayList(); - for (Iterator it = arr.iterator(); it.hasNext(); ) { - out.add((T) it.next().getValue()); - } - return out; - } - - public TransactionManager getTransactionManager() { - return transactionManager; - } - - public void setTransactionManager(TransactionManager transactionManager) { - this.transactionManager = transactionManager; - } + public TransactionManager getTransactionManager() { + return transactionManager; + } + public void setTransactionManager(TransactionManager transactionManager) { + this.transactionManager = transactionManager; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/ExtendedRawTransactionManager.java b/src/main/java/org/fisco/bcos/web3j/tx/ExtendedRawTransactionManager.java index a421e1655..95b2de6b4 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/ExtendedRawTransactionManager.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/ExtendedRawTransactionManager.java @@ -1,5 +1,9 @@ package org.fisco.bcos.web3j.tx; +import java.io.IOException; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Random; import org.fisco.bcos.channel.client.TransactionSucCallback; import org.fisco.bcos.web3j.crypto.*; import org.fisco.bcos.web3j.protocol.Web3j; @@ -9,11 +13,6 @@ import org.fisco.bcos.web3j.utils.Numeric; import org.fisco.bcos.web3j.utils.TxHashVerifier; -import java.io.IOException; -import java.math.BigInteger; -import java.security.SecureRandom; -import java.util.Random; - /** * TransactionManager implementation using Ethereum wallet file to create and sign transactions * locally. @@ -22,136 +21,199 @@ * EIP155. */ public class ExtendedRawTransactionManager extends TransactionManager { - private final Web3j web3j; - final Credentials credentials; - - private final byte chainId; - - private final BigInteger groupId; - private final BigInteger fiscoChainId; - - protected TxHashVerifier txHashVerifier = new TxHashVerifier(); - - - public ExtendedRawTransactionManager(Web3j web3j, Credentials credentials, byte chainId, BigInteger groupId, BigInteger fiscoChainId) { - super(web3j, credentials); - this.web3j = web3j; - this.credentials = credentials; - this.chainId = chainId; - this.groupId = groupId; - this.fiscoChainId = fiscoChainId; - } - - public ExtendedRawTransactionManager(Web3j web3j, Credentials credentials, byte chainId, int attempts, int sleepDuration,BigInteger groupId, BigInteger fiscoChainId) { - super(web3j, attempts, sleepDuration, credentials); - this.web3j = web3j; - this.credentials = credentials; - this.chainId = chainId; - this.groupId = groupId; - this.fiscoChainId = fiscoChainId; - } - - public ExtendedRawTransactionManager(Web3j web3j, Credentials credentials,BigInteger groupId, BigInteger fiscoChainId) { - this(web3j, credentials, ChainId.NONE, groupId , fiscoChainId); - } - - public ExtendedRawTransactionManager( - Web3j web3j, Credentials credentials, int attempts, int sleepDuration ,BigInteger groupId, BigInteger fiscoChainId) { - this(web3j, credentials, ChainId.NONE, attempts, sleepDuration, groupId, fiscoChainId); - } - - BigInteger getBlockLimit() throws IOException { - return web3j.getBlockNumberCache(); - } - - public TxHashVerifier getTxHashVerifier() { - return txHashVerifier; - } - - public void setTxHashVerifier(TxHashVerifier txHashVerifier) { - this.txHashVerifier = txHashVerifier; - } - - @Override - public SendTransaction sendTransaction( - BigInteger gasPrice, BigInteger gasLimit, String to, String data, BigInteger value, String extraData) - throws IOException { - - Random r = new SecureRandom(); - BigInteger randomid = new BigInteger(250, r); - BigInteger blockLimit = getBlockLimit(); - ExtendedRawTransaction rawTransaction = - ExtendedRawTransaction.createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data, fiscoChainId, groupId, extraData); - - return signAndSend(rawTransaction); - } - - @Override - public SendTransaction sendTransaction( - BigInteger gasPrice, - BigInteger gasLimit, - String to, - String data, - BigInteger value, - String extraData, - TransactionSucCallback callback) - throws IOException { - Random r = new SecureRandom(); - BigInteger randomid = new BigInteger(250, r); - BigInteger blockLimit = getBlockLimit(); - ExtendedRawTransaction extendedRawTransaction = - ExtendedRawTransaction.createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data, fiscoChainId, groupId, extraData); - - return signAndSend(extendedRawTransaction, callback); - } - - public SendTransaction signAndSend(ExtendedRawTransaction rawTransaction) throws IOException { - - byte[] signedMessage; - - if (chainId > ChainId.NONE) { - signedMessage = ExtendedTransactionEncoder.signMessage(rawTransaction, chainId, credentials); - } else { - signedMessage = ExtendedTransactionEncoder.signMessage(rawTransaction, credentials); + private final Web3j web3j; + final Credentials credentials; + + private final byte chainId; + + private final BigInteger groupId; + private final BigInteger fiscoChainId; + + protected TxHashVerifier txHashVerifier = new TxHashVerifier(); + + public ExtendedRawTransactionManager( + Web3j web3j, + Credentials credentials, + byte chainId, + BigInteger groupId, + BigInteger fiscoChainId) { + super(web3j, credentials); + this.web3j = web3j; + this.credentials = credentials; + this.chainId = chainId; + this.groupId = groupId; + this.fiscoChainId = fiscoChainId; } - String hexValue = Numeric.toHexString(signedMessage); - SendTransaction sendTransaction = web3j.sendRawTransaction(hexValue).send(); - if (sendTransaction != null && !sendTransaction.hasError()) { - String txHashLocal = Hash.sha3(hexValue); - String txHashRemote = sendTransaction.getTransactionHash(); - if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { - throw new TxHashMismatchException(txHashLocal, txHashRemote); - } + public ExtendedRawTransactionManager( + Web3j web3j, + Credentials credentials, + byte chainId, + int attempts, + int sleepDuration, + BigInteger groupId, + BigInteger fiscoChainId) { + super(web3j, attempts, sleepDuration, credentials); + this.web3j = web3j; + this.credentials = credentials; + this.chainId = chainId; + this.groupId = groupId; + this.fiscoChainId = fiscoChainId; } - return sendTransaction; - } - public SendTransaction signAndSend(ExtendedRawTransaction rawTransaction, TransactionSucCallback callback) - throws IOException { + public ExtendedRawTransactionManager( + Web3j web3j, Credentials credentials, BigInteger groupId, BigInteger fiscoChainId) { + this(web3j, credentials, ChainId.NONE, groupId, fiscoChainId); + } + + public ExtendedRawTransactionManager( + Web3j web3j, + Credentials credentials, + int attempts, + int sleepDuration, + BigInteger groupId, + BigInteger fiscoChainId) { + this(web3j, credentials, ChainId.NONE, attempts, sleepDuration, groupId, fiscoChainId); + } + + BigInteger getBlockLimit() throws IOException { + return web3j.getBlockNumberCache(); + } - byte[] signedMessage; + public TxHashVerifier getTxHashVerifier() { + return txHashVerifier; + } - if (chainId > ChainId.NONE) { - signedMessage = ExtendedTransactionEncoder.signMessage(rawTransaction, chainId, credentials); - } else { - signedMessage = ExtendedTransactionEncoder.signMessage(rawTransaction, credentials); + public void setTxHashVerifier(TxHashVerifier txHashVerifier) { + this.txHashVerifier = txHashVerifier; } - String hexValue = Numeric.toHexString(signedMessage); - Request request = web3j.sendRawTransaction(hexValue); - request.setNeedTransCallback(true); - request.setTransactionSucCallback(callback); - SendTransaction ethSendTransaction = request.send(); - - if (ethSendTransaction != null && !ethSendTransaction.hasError()) { - String txHashLocal = Hash.sha3(hexValue); - String txHashRemote = ethSendTransaction.getTransactionHash(); - if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { - throw new TxHashMismatchException(txHashLocal, txHashRemote); - } + @Override + public ExtendedRawTransaction createTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException { + Random r = new SecureRandom(); + BigInteger randomid = new BigInteger(250, r); + BigInteger blockLimit = getBlockLimit(); + ExtendedRawTransaction rawTransaction = + ExtendedRawTransaction.createTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + to, + value, + data, + fiscoChainId, + groupId, + extraData); + return rawTransaction; } - return ethSendTransaction; - } + @Override + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException { + + ExtendedRawTransaction rawTransaction = + createTransaction(gasPrice, gasLimit, to, data, value, extraData); + + return signAndSend(rawTransaction); + } + + @Override + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData, + TransactionSucCallback callback) + throws IOException { + + ExtendedRawTransaction rawTransaction = + createTransaction(gasPrice, gasLimit, to, data, value, extraData); + return signAndSend(rawTransaction, callback); + } + + @Override + public SendTransaction sendTransaction(String signedTransaction) + throws IOException, TxHashMismatchException { + SendTransaction sendTransaction = web3j.sendRawTransaction(signedTransaction).send(); + if (sendTransaction != null && !sendTransaction.hasError()) { + String txHashLocal = Hash.sha3(signedTransaction); + String txHashRemote = sendTransaction.getTransactionHash(); + if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { + throw new TxHashMismatchException(txHashLocal, txHashRemote); + } + } + + return sendTransaction; + } + + @Override + public SendTransaction sendTransaction( + String signedTransaction, TransactionSucCallback callback) + throws IOException, TxHashMismatchException { + Request request = web3j.sendRawTransaction(signedTransaction); + request.setNeedTransCallback(true); + request.setTransactionSucCallback(callback); + + request.sendOnly(); + + return null; + + /* + if (ethSendTransaction != null && !ethSendTransaction.hasError()) { + String txHashLocal = Hash.sha3(signedTransaction); + String txHashRemote = ethSendTransaction.getTransactionHash(); + if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { + throw new TxHashMismatchException(txHashLocal, txHashRemote); + } + } + + return ethSendTransaction; + */ + } + + @Override + public String sign(ExtendedRawTransaction rawTransaction) { + byte[] signedMessage; + + if (chainId > ChainId.NONE) { + signedMessage = + ExtendedTransactionEncoder.signMessage(rawTransaction, chainId, credentials); + } else { + signedMessage = ExtendedTransactionEncoder.signMessage(rawTransaction, credentials); + } + + String signedData = Numeric.toHexString(signedMessage); + + return signedData; + } + + public SendTransaction signAndSend(ExtendedRawTransaction rawTransaction) throws IOException { + String signedTransaction = sign(rawTransaction); + SendTransaction result = sendTransaction(signedTransaction); + return result; + } + + public SendTransaction signAndSend( + ExtendedRawTransaction rawTransaction, TransactionSucCallback callback) + throws IOException { + String signedTransaction = sign(rawTransaction); + SendTransaction result = sendTransaction(signedTransaction, callback); + return result; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/FastRawTransactionManager.java b/src/main/java/org/fisco/bcos/web3j/tx/FastRawTransactionManager.java index fc8cf5f80..2d490d8ed 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/FastRawTransactionManager.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/FastRawTransactionManager.java @@ -10,21 +10,21 @@ */ public class FastRawTransactionManager extends RawTransactionManager { - private volatile BigInteger nonce = BigInteger.valueOf(-1); + private volatile BigInteger nonce = BigInteger.valueOf(-1); - public FastRawTransactionManager(Web3j web3j, Credentials credentials, byte chainId) { - super(web3j, credentials, chainId); - } + public FastRawTransactionManager(Web3j web3j, Credentials credentials, byte chainId) { + super(web3j, credentials, chainId); + } - public FastRawTransactionManager(Web3j web3j, Credentials credentials) { - super(web3j, credentials); - } + public FastRawTransactionManager(Web3j web3j, Credentials credentials) { + super(web3j, credentials); + } - public BigInteger getCurrentNonce() { - return nonce; - } + public BigInteger getCurrentNonce() { + return nonce; + } - public synchronized void setNonce(BigInteger value) { - nonce = value; - } + public synchronized void setNonce(BigInteger value) { + nonce = value; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/ManagedTransaction.java b/src/main/java/org/fisco/bcos/web3j/tx/ManagedTransaction.java index 8ba498768..fd1000d77 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/ManagedTransaction.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/ManagedTransaction.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.math.BigInteger; import org.fisco.bcos.channel.client.TransactionSucCallback; +import org.fisco.bcos.web3j.crypto.ExtendedRawTransaction; import org.fisco.bcos.web3j.precompile.cns.CnsService; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; @@ -11,43 +12,51 @@ /** Generic transaction manager. */ public abstract class ManagedTransaction { - public static final BigInteger GAS_PRICE = BigInteger.valueOf(22_000_000_000L); - - protected Web3j web3j; - - protected TransactionManager transactionManager ; - - protected CnsService cnsService; - - protected ManagedTransaction(Web3j web3j, TransactionManager transactionManager) { - this.transactionManager = transactionManager; - this.web3j = web3j; - this.cnsService = new CnsService(web3j, transactionManager.credentials); - } - - public long getSyncThreshold() { - return cnsService.getSyncThreshold(); - } - - public void setSyncThreshold(long syncThreshold) { - cnsService.setSyncThreshold(syncThreshold); - } - - protected TransactionReceipt send( - String to, String data, BigInteger value, BigInteger gasPrice, BigInteger gasLimit) - throws IOException, TransactionException { - - return transactionManager.executeTransaction(gasPrice, gasLimit, to, data, value,null); - } - - protected void sendOnly( - String to, - String data, - BigInteger value, - BigInteger gasPrice, - BigInteger gasLimit, - TransactionSucCallback callback) - throws IOException, TransactionException { - transactionManager.sendTransaction(gasPrice, gasLimit, to, data, value, null, callback); - } + public static final BigInteger GAS_PRICE = BigInteger.valueOf(22_000_000_000L); + + protected Web3j web3j; + + protected TransactionManager transactionManager; + + protected CnsService cnsService; + + protected ManagedTransaction(Web3j web3j, TransactionManager transactionManager) { + this.transactionManager = transactionManager; + this.web3j = web3j; + this.cnsService = new CnsService(web3j, transactionManager.credentials); + } + + public long getSyncThreshold() { + return cnsService.getSyncThreshold(); + } + + public void setSyncThreshold(long syncThreshold) { + cnsService.setSyncThreshold(syncThreshold); + } + + protected TransactionReceipt send( + String to, String data, BigInteger value, BigInteger gasPrice, BigInteger gasLimit) + throws IOException, TransactionException { + + return transactionManager.executeTransaction(gasPrice, gasLimit, to, data, value, null); + } + + protected void sendOnly( + String to, + String data, + BigInteger value, + BigInteger gasPrice, + BigInteger gasLimit, + TransactionSucCallback callback) + throws IOException, TransactionException { + transactionManager.sendTransaction(gasPrice, gasLimit, to, data, value, null, callback); + } + + protected String createSeq( + String to, String data, BigInteger value, BigInteger gasPrice, BigInteger gasLimit) + throws IOException { + ExtendedRawTransaction rawTransaction = + transactionManager.createTransaction(gasPrice, gasLimit, to, data, value, null); + return transactionManager.sign(rawTransaction); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/RawTransactionManager.java b/src/main/java/org/fisco/bcos/web3j/tx/RawTransactionManager.java index 2137f0f07..bb12e9f1d 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/RawTransactionManager.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/RawTransactionManager.java @@ -15,8 +15,6 @@ import org.fisco.bcos.web3j.tx.exceptions.TxHashMismatchException; import org.fisco.bcos.web3j.utils.Numeric; import org.fisco.bcos.web3j.utils.TxHashVerifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * TransactionManager implementation using Ethereum wallet file to create and sign transactions @@ -26,131 +24,130 @@ * EIP155. */ public class RawTransactionManager extends TransactionManager { - private final Web3j web3j; - final Credentials credentials; - - private final byte chainId; - - protected TxHashVerifier txHashVerifier = new TxHashVerifier(); - - public RawTransactionManager(Web3j web3j, Credentials credentials, byte chainId) { - super(web3j, credentials); - this.web3j = web3j; - this.credentials = credentials; - - this.chainId = chainId; - } - - public RawTransactionManager( - Web3j web3j, Credentials credentials, byte chainId, int attempts, int sleepDuration) { - super(web3j, attempts, sleepDuration, credentials); - this.web3j = web3j; - this.credentials = credentials; - - this.chainId = chainId; - } - - public RawTransactionManager(Web3j web3j, Credentials credentials) { - this(web3j, credentials, ChainId.NONE); - } - - public RawTransactionManager( - Web3j web3j, Credentials credentials, int attempts, int sleepDuration) { - this(web3j, credentials, ChainId.NONE, attempts, sleepDuration); - } - - BigInteger getBlockLimit() throws IOException { - return web3j.getBlockNumberCache(); - } - - public TxHashVerifier getTxHashVerifier() { - return txHashVerifier; - } - - public void setTxHashVerifier(TxHashVerifier txHashVerifier) { - this.txHashVerifier = txHashVerifier; - } - - @Override - public SendTransaction sendTransaction( - BigInteger gasPrice, BigInteger gasLimit, String to, String data, BigInteger value, String extraData) - throws IOException { - - Random r = new SecureRandom(); - BigInteger randomid = new BigInteger(250, r); - BigInteger blockLimit = getBlockLimit(); - RawTransaction rawTransaction = - RawTransaction.createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data); - - return signAndSend(rawTransaction); - } - - @Override - public SendTransaction sendTransaction( - BigInteger gasPrice, - BigInteger gasLimit, - String to, - String data, - BigInteger value, - String extraData, - TransactionSucCallback callback) - throws IOException { - Random r = new SecureRandom(); - BigInteger randomid = new BigInteger(250, r); - BigInteger blockLimit = getBlockLimit(); - RawTransaction rawTransaction = - RawTransaction.createTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value, data); - - return signAndSend(rawTransaction, callback); - } - - public SendTransaction signAndSend(RawTransaction rawTransaction) throws IOException { - - byte[] signedMessage; - - if (chainId > ChainId.NONE) { - signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); - } else { - signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + private final Web3j web3j; + final Credentials credentials; + + private final byte chainId; + + protected TxHashVerifier txHashVerifier = new TxHashVerifier(); + + public RawTransactionManager(Web3j web3j, Credentials credentials, byte chainId) { + super(web3j, credentials); + this.web3j = web3j; + this.credentials = credentials; + + this.chainId = chainId; + } + + public RawTransactionManager( + Web3j web3j, Credentials credentials, byte chainId, int attempts, int sleepDuration) { + super(web3j, attempts, sleepDuration, credentials); + this.web3j = web3j; + this.credentials = credentials; + + this.chainId = chainId; + } + + public RawTransactionManager(Web3j web3j, Credentials credentials) { + this(web3j, credentials, ChainId.NONE); + } + + public RawTransactionManager( + Web3j web3j, Credentials credentials, int attempts, int sleepDuration) { + this(web3j, credentials, ChainId.NONE, attempts, sleepDuration); } - String hexValue = Numeric.toHexString(signedMessage); - SendTransaction sendTransaction = web3j.sendRawTransaction(hexValue).send(); - if (sendTransaction != null && !sendTransaction.hasError()) { - String txHashLocal = Hash.sha3(hexValue); - String txHashRemote = sendTransaction.getTransactionHash(); - if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { - throw new TxHashMismatchException(txHashLocal, txHashRemote); - } + BigInteger getBlockLimit() throws IOException { + return web3j.getBlockNumberCache(); } - return sendTransaction; - } - public SendTransaction signAndSend(RawTransaction rawTransaction, TransactionSucCallback callback) - throws IOException { + public TxHashVerifier getTxHashVerifier() { + return txHashVerifier; + } - byte[] signedMessage; + public void setTxHashVerifier(TxHashVerifier txHashVerifier) { + this.txHashVerifier = txHashVerifier; + } + + @Override + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException { + + Random r = new SecureRandom(); + BigInteger randomid = new BigInteger(250, r); + BigInteger blockLimit = getBlockLimit(); + RawTransaction rawTransaction = + RawTransaction.createTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value, data); + + return signAndSend(rawTransaction); + } - if (chainId > ChainId.NONE) { - signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); - } else { - signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + @Override + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData, + TransactionSucCallback callback) + throws IOException { + Random r = new SecureRandom(); + BigInteger randomid = new BigInteger(250, r); + BigInteger blockLimit = getBlockLimit(); + RawTransaction rawTransaction = + RawTransaction.createTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value, data); + + return signAndSend(rawTransaction, callback); } - String hexValue = Numeric.toHexString(signedMessage); - Request request = web3j.sendRawTransaction(hexValue); - request.setNeedTransCallback(true); - request.setTransactionSucCallback(callback); - SendTransaction ethSendTransaction = request.send(); - - if (ethSendTransaction != null && !ethSendTransaction.hasError()) { - String txHashLocal = Hash.sha3(hexValue); - String txHashRemote = ethSendTransaction.getTransactionHash(); - if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { - throw new TxHashMismatchException(txHashLocal, txHashRemote); - } + public SendTransaction signAndSend(RawTransaction rawTransaction) throws IOException { + + byte[] signedMessage; + + if (chainId > ChainId.NONE) { + signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); + } else { + signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + } + + String hexValue = Numeric.toHexString(signedMessage); + SendTransaction sendTransaction = web3j.sendRawTransaction(hexValue).send(); + if (sendTransaction != null && !sendTransaction.hasError()) { + String txHashLocal = Hash.sha3(hexValue); + String txHashRemote = sendTransaction.getTransactionHash(); + if (!txHashVerifier.verify(txHashLocal, txHashRemote)) { + throw new TxHashMismatchException(txHashLocal, txHashRemote); + } + } + return sendTransaction; } - return ethSendTransaction; - } + public SendTransaction signAndSend( + RawTransaction rawTransaction, TransactionSucCallback callback) throws IOException { + + byte[] signedMessage; + + if (chainId > ChainId.NONE) { + signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials); + } else { + signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); + } + + String hexValue = Numeric.toHexString(signedMessage); + Request request = web3j.sendRawTransaction(hexValue); + request.setNeedTransCallback(true); + request.setTransactionSucCallback(callback); + request.sendOnly(); + + return null; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/TransactionConstant.java b/src/main/java/org/fisco/bcos/web3j/tx/TransactionConstant.java index 979895b6e..e7c64485c 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/TransactionConstant.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/TransactionConstant.java @@ -4,7 +4,7 @@ /** Created by mingzhenliu on 2017/11/15. */ public class TransactionConstant { - public static final BigInteger version = BigInteger.ONE; - public static final BigInteger callType = BigInteger.ZERO; - public static final BigInteger creatType = BigInteger.ONE; + public static final BigInteger version = BigInteger.ONE; + public static final BigInteger callType = BigInteger.ZERO; + public static final BigInteger creatType = BigInteger.ONE; } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/TransactionManager.java b/src/main/java/org/fisco/bcos/web3j/tx/TransactionManager.java index 62ea22ed7..84183e5ec 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/TransactionManager.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/TransactionManager.java @@ -4,10 +4,12 @@ import java.math.BigInteger; import org.fisco.bcos.channel.client.TransactionSucCallback; import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.crypto.ExtendedRawTransaction; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.core.methods.response.SendTransaction; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.fisco.bcos.web3j.protocol.exceptions.TransactionException; +import org.fisco.bcos.web3j.tx.exceptions.TxHashMismatchException; import org.fisco.bcos.web3j.tx.response.PollingTransactionReceiptProcessor; import org.fisco.bcos.web3j.tx.response.TransactionReceiptProcessor; import org.fisco.bcos.web3j.utils.AttemptsConf; @@ -18,68 +20,106 @@ */ public abstract class TransactionManager { - // configurable - public static final int DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH = AttemptsConf.sleepDuration; - public static final int DEFAULT_POLLING_FREQUENCY = AttemptsConf.attempts; // 15 * 100 - - private final TransactionReceiptProcessor transactionReceiptProcessor; - final Credentials credentials; - - protected TransactionManager( - TransactionReceiptProcessor transactionReceiptProcessor, Credentials credentials) { - this.transactionReceiptProcessor = transactionReceiptProcessor; - this.credentials = credentials; - } - - protected TransactionManager(Web3j web3j, Credentials credentials) { - this( - new PollingTransactionReceiptProcessor( - web3j, DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH ,DEFAULT_POLLING_FREQUENCY), - credentials); - } - - protected TransactionManager( - Web3j web3j, int attempts, long sleepDuration, Credentials credentials) { - this(new PollingTransactionReceiptProcessor(web3j, sleepDuration, attempts), credentials); - } - - protected TransactionReceipt executeTransaction( - BigInteger gasPrice, BigInteger gasLimit, String to, String data, BigInteger value, String extraData) - throws IOException, TransactionException { - - SendTransaction sendTransaction = sendTransaction(gasPrice, gasLimit, to, data, value, extraData); - return processResponse(sendTransaction); - } - - public abstract SendTransaction sendTransaction( - BigInteger gasPrice, BigInteger gasLimit, String to, String data, BigInteger value, String extraData) - throws IOException; - - public SendTransaction sendTransaction( - BigInteger gasPrice, - BigInteger gasLimit, - String to, - String data, - BigInteger value, - String extraData, - TransactionSucCallback callback) - throws IOException { - return null; - }; - - public String getFromAddress() { - return credentials.getAddress(); - } - - private TransactionReceipt processResponse(SendTransaction transactionResponse) - throws IOException, TransactionException { - if (transactionResponse.hasError()) { - throw new RuntimeException( - "Error processing transaction request: " + transactionResponse.getError().getMessage()); + // configurable + public static final int DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH = AttemptsConf.sleepDuration; + public static final int DEFAULT_POLLING_FREQUENCY = AttemptsConf.attempts; // 15 * 100 + + private final TransactionReceiptProcessor transactionReceiptProcessor; + final Credentials credentials; + + protected TransactionManager( + TransactionReceiptProcessor transactionReceiptProcessor, Credentials credentials) { + this.transactionReceiptProcessor = transactionReceiptProcessor; + this.credentials = credentials; + } + + protected TransactionManager(Web3j web3j, Credentials credentials) { + this( + new PollingTransactionReceiptProcessor( + web3j, DEFAULT_POLLING_ATTEMPTS_PER_TX_HASH, DEFAULT_POLLING_FREQUENCY), + credentials); + } + + protected TransactionManager( + Web3j web3j, int attempts, long sleepDuration, Credentials credentials) { + this(new PollingTransactionReceiptProcessor(web3j, sleepDuration, attempts), credentials); } - String transactionHash = transactionResponse.getTransactionHash(); + protected TransactionReceipt executeTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException, TransactionException { + + SendTransaction sendTransaction = + sendTransaction(gasPrice, gasLimit, to, data, value, extraData); + return processResponse(sendTransaction); + } + + public abstract SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException; + + public SendTransaction sendTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData, + TransactionSucCallback callback) + throws IOException { + return null; + }; + + public SendTransaction sendTransaction(String signedTransaction) + throws IOException, TxHashMismatchException { + return null; + } - return transactionReceiptProcessor.waitForTransactionReceipt(transactionHash); - } + public SendTransaction sendTransaction( + String signedTransaction, TransactionSucCallback callback) + throws IOException, TxHashMismatchException { + return null; + } + + public ExtendedRawTransaction createTransaction( + BigInteger gasPrice, + BigInteger gasLimit, + String to, + String data, + BigInteger value, + String extraData) + throws IOException { + return null; + } + + public String sign(ExtendedRawTransaction transaction) { + return null; + } + + public String getFromAddress() { + return credentials.getAddress(); + } + + private TransactionReceipt processResponse(SendTransaction transactionResponse) + throws IOException, TransactionException { + if (transactionResponse.hasError()) { + throw new RuntimeException( + "Error processing transaction request: " + + transactionResponse.getError().getMessage()); + } + + String transactionHash = transactionResponse.getTransactionHash(); + + return transactionReceiptProcessor.waitForTransactionReceipt(transactionHash); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/Transfer.java b/src/main/java/org/fisco/bcos/web3j/tx/Transfer.java index 659b11c8c..147f2f2dd 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/Transfer.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/Transfer.java @@ -18,94 +18,102 @@ /** Class for performing Ether transactions on the Ethereum blockchain. */ public class Transfer extends ManagedTransaction { - // This is the cost to send Ether between parties - public static final BigInteger GAS_LIMIT = BigInteger.valueOf(21000); - public static final BigInteger GAS_PRICE = BigInteger.valueOf(1); - - public Transfer(Web3j web3j, TransactionManager transactionManager) { - super(web3j, transactionManager); - } - - /** - * Given the duration required to execute a transaction, asyncronous execution is strongly - * recommended via {@link Transfer#sendFundsAsync(String, BigDecimal, Convert.Unit)}. - * - * @param toAddress destination address - * @param value amount to send - * @param unit of specified send - * @return {@link Optional} containing our transaction receipt - * @throws ExecutionException if the computation threw an exception - * @throws InterruptedException if the current thread was interrupted while waiting - * @throws TransactionTimeoutException if the transaction was not mined while waiting - */ - private TransactionReceipt send(String toAddress, BigDecimal value, Convert.Unit unit) - throws IOException, TransactionException { - - return send(toAddress, value, unit, GAS_PRICE, GAS_LIMIT); - } - - private TransactionReceipt send( - String toAddress, - BigDecimal value, - Convert.Unit unit, - BigInteger gasPrice, - BigInteger gasLimit) - throws IOException, TransactionException { - - BigDecimal weiValue = Convert.toWei(value, unit); - if (!Numeric.isIntegerValue(weiValue)) { - throw new UnsupportedOperationException( - "Non decimal Wei value provided: " - + value - + " " - + unit.toString() - + " = " - + weiValue - + " Wei"); + // This is the cost to send Ether between parties + public static final BigInteger GAS_LIMIT = BigInteger.valueOf(21000); + public static final BigInteger GAS_PRICE = BigInteger.valueOf(1); + + public Transfer(Web3j web3j, TransactionManager transactionManager) { + super(web3j, transactionManager); + } + + /** + * Given the duration required to execute a transaction, asyncronous execution is strongly + * recommended via {@link Transfer#sendFundsAsync(String, BigDecimal, Convert.Unit)}. + * + * @param toAddress destination address + * @param value amount to send + * @param unit of specified send + * @return {@link Optional} containing our transaction receipt + * @throws ExecutionException if the computation threw an exception + * @throws InterruptedException if the current thread was interrupted while waiting + * @throws TransactionTimeoutException if the transaction was not mined while waiting + */ + private TransactionReceipt send(String toAddress, BigDecimal value, Convert.Unit unit) + throws IOException, TransactionException { + + return send(toAddress, value, unit, GAS_PRICE, GAS_LIMIT); + } + + private TransactionReceipt send( + String toAddress, + BigDecimal value, + Convert.Unit unit, + BigInteger gasPrice, + BigInteger gasLimit) + throws IOException, TransactionException { + + BigDecimal weiValue = Convert.toWei(value, unit); + if (!Numeric.isIntegerValue(weiValue)) { + throw new UnsupportedOperationException( + "Non decimal Wei value provided: " + + value + + " " + + unit.toString() + + " = " + + weiValue + + " Wei"); + } + String resolvedAddress = cnsService.getAddressByContractNameAndVersion(toAddress); + + return send(resolvedAddress, "", weiValue.toBigIntegerExact(), gasPrice, gasLimit); + } + + public static TransactionReceipt sendFunds( + Web3j web3j, + Credentials credentials, + String toAddress, + BigDecimal value, + Convert.Unit unit) + throws IOException, TransactionException { + + TransactionManager transactionManager = new RawTransactionManager(web3j, credentials); + + return new Transfer(web3j, transactionManager).send(toAddress, value, unit); + } + + /** + * Execute the provided function as a transaction asynchronously. This is intended for one-off + * fund transfers. For multiple, create an instance. + * + * @param toAddress destination address + * @param value amount to send + * @param unit of specified send + * @return {@link Future} containing executing transaction + */ + public Future sendFundsAsync( + String toAddress, BigDecimal value, Convert.Unit unit) { + return Async.run(() -> send(toAddress, value, unit)); + } + + public Future sendFundsAsync( + String toAddress, + BigDecimal value, + Convert.Unit unit, + BigInteger gasPrice, + BigInteger gasLimit) { + return Async.run(() -> send(toAddress, value, unit, gasPrice, gasLimit)); + } + + public static Future sendFundsAsync( + Web3j web3j, + Credentials credentials, + String toAddress, + BigDecimal value, + Convert.Unit unit) + throws InterruptedException, ExecutionException, TransactionTimeoutException { + + TransactionManager transactionManager = new RawTransactionManager(web3j, credentials); + + return new Transfer(web3j, transactionManager).sendFundsAsync(toAddress, value, unit); } - String resolvedAddress = cnsService.getAddressByContractNameAndVersion(toAddress); - - return send(resolvedAddress, "", weiValue.toBigIntegerExact(), gasPrice, gasLimit); - } - - public static TransactionReceipt sendFunds( - Web3j web3j, Credentials credentials, String toAddress, BigDecimal value, Convert.Unit unit) - throws IOException, TransactionException { - - TransactionManager transactionManager = new RawTransactionManager(web3j, credentials); - - return new Transfer(web3j, transactionManager).send(toAddress, value, unit); - } - - /** - * Execute the provided function as a transaction asynchronously. This is intended for one-off - * fund transfers. For multiple, create an instance. - * - * @param toAddress destination address - * @param value amount to send - * @param unit of specified send - * @return {@link Future} containing executing transaction - */ - public Future sendFundsAsync( - String toAddress, BigDecimal value, Convert.Unit unit) { - return Async.run(() -> send(toAddress, value, unit)); - } - - public Future sendFundsAsync( - String toAddress, - BigDecimal value, - Convert.Unit unit, - BigInteger gasPrice, - BigInteger gasLimit) { - return Async.run(() -> send(toAddress, value, unit, gasPrice, gasLimit)); - } - - public static Future sendFundsAsync( - Web3j web3j, Credentials credentials, String toAddress, BigDecimal value, Convert.Unit unit) - throws InterruptedException, ExecutionException, TransactionTimeoutException { - - TransactionManager transactionManager = new RawTransactionManager(web3j, credentials); - - return new Transfer(web3j, transactionManager).sendFundsAsync(toAddress, value, unit); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/exceptions/ContractCallException.java b/src/main/java/org/fisco/bcos/web3j/tx/exceptions/ContractCallException.java index c1dd00793..a9d04ddf5 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/exceptions/ContractCallException.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/exceptions/ContractCallException.java @@ -3,11 +3,11 @@ /** Exception resulting from issues calling methods on Smart Contracts. */ public class ContractCallException extends RuntimeException { - public ContractCallException(String message) { - super(message); - } + public ContractCallException(String message) { + super(message); + } - public ContractCallException(String message, Throwable cause) { - super(message, cause); - } + public ContractCallException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/exceptions/TxHashMismatchException.java b/src/main/java/org/fisco/bcos/web3j/tx/exceptions/TxHashMismatchException.java index 50c85cf36..ff8810519 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/exceptions/TxHashMismatchException.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/exceptions/TxHashMismatchException.java @@ -3,19 +3,19 @@ import java.io.IOException; public class TxHashMismatchException extends IOException { - private String txHashLocal; - private String txHashRemote; + private String txHashLocal; + private String txHashRemote; - public TxHashMismatchException(String txHashLocal, String txHashRemote) { - this.txHashLocal = txHashLocal; - this.txHashRemote = txHashRemote; - } + public TxHashMismatchException(String txHashLocal, String txHashRemote) { + this.txHashLocal = txHashLocal; + this.txHashRemote = txHashRemote; + } - public String getTxHashLocal() { - return txHashLocal; - } + public String getTxHashLocal() { + return txHashLocal; + } - public String getTxHashRemote() { - return txHashRemote; - } + public String getTxHashRemote() { + return txHashRemote; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/gas/ContractGasProvider.java b/src/main/java/org/fisco/bcos/web3j/tx/gas/ContractGasProvider.java index da3811b0d..58c65e37f 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/gas/ContractGasProvider.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/gas/ContractGasProvider.java @@ -3,13 +3,13 @@ import java.math.BigInteger; public interface ContractGasProvider { - BigInteger getGasPrice(String contractFunc); + BigInteger getGasPrice(String contractFunc); - @Deprecated - BigInteger getGasPrice(); + @Deprecated + BigInteger getGasPrice(); - BigInteger getGasLimit(String contractFunc); + BigInteger getGasLimit(String contractFunc); - @Deprecated - BigInteger getGasLimit(); + @Deprecated + BigInteger getGasLimit(); } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/gas/DefaultGasProvider.java b/src/main/java/org/fisco/bcos/web3j/tx/gas/DefaultGasProvider.java index 921e5b78a..01a5cc31c 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/gas/DefaultGasProvider.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/gas/DefaultGasProvider.java @@ -5,10 +5,10 @@ import org.fisco.bcos.web3j.tx.ManagedTransaction; public class DefaultGasProvider extends StaticGasProvider { - public static final BigInteger GAS_LIMIT = Contract.GAS_LIMIT; - public static final BigInteger GAS_PRICE = ManagedTransaction.GAS_PRICE; + public static final BigInteger GAS_LIMIT = Contract.GAS_LIMIT; + public static final BigInteger GAS_PRICE = ManagedTransaction.GAS_PRICE; - public DefaultGasProvider() { - super(GAS_PRICE, GAS_LIMIT); - } + public DefaultGasProvider() { + super(GAS_PRICE, GAS_LIMIT); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/gas/StaticGasProvider.java b/src/main/java/org/fisco/bcos/web3j/tx/gas/StaticGasProvider.java index 52f99c852..bf27e3a96 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/gas/StaticGasProvider.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/gas/StaticGasProvider.java @@ -3,31 +3,31 @@ import java.math.BigInteger; public class StaticGasProvider implements ContractGasProvider { - private BigInteger gasPrice; - private BigInteger gasLimit; + private BigInteger gasPrice; + private BigInteger gasLimit; - public StaticGasProvider(BigInteger gasPrice, BigInteger gasLimit) { - this.gasPrice = gasPrice; - this.gasLimit = gasLimit; - } + public StaticGasProvider(BigInteger gasPrice, BigInteger gasLimit) { + this.gasPrice = gasPrice; + this.gasLimit = gasLimit; + } - @Override - public BigInteger getGasPrice(String contractFunc) { - return gasPrice; - } + @Override + public BigInteger getGasPrice(String contractFunc) { + return gasPrice; + } - @Override - public BigInteger getGasPrice() { - return gasPrice; - } + @Override + public BigInteger getGasPrice() { + return gasPrice; + } - @Override - public BigInteger getGasLimit(String contractFunc) { - return gasLimit; - } + @Override + public BigInteger getGasLimit(String contractFunc) { + return gasLimit; + } - @Override - public BigInteger getGasLimit() { - return gasLimit; - } + @Override + public BigInteger getGasLimit() { + return gasLimit; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/Callback.java b/src/main/java/org/fisco/bcos/web3j/tx/response/Callback.java index af884f532..220a44994 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/Callback.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/Callback.java @@ -4,7 +4,7 @@ /** Transaction receipt processor callback. */ public interface Callback { - void accept(TransactionReceipt transactionReceipt); + void accept(TransactionReceipt transactionReceipt); - void exception(Exception exception); + void exception(Exception exception); } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/EmptyTransactionReceipt.java b/src/main/java/org/fisco/bcos/web3j/tx/response/EmptyTransactionReceipt.java index edbb8e95d..058f412ae 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/EmptyTransactionReceipt.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/EmptyTransactionReceipt.java @@ -11,184 +11,169 @@ */ public class EmptyTransactionReceipt extends TransactionReceipt { - public EmptyTransactionReceipt(String transactionHash) { - super(); - this.setTransactionHash(transactionHash); - } - - @Override - public String getTransactionHash() { - return super.getTransactionHash(); - } - - @Override - public void setTransactionHash(String transactionHash) { - super.setTransactionHash(transactionHash); - } - - private UnsupportedOperationException unsupportedOperation() { - return new UnsupportedOperationException( - "Empty transaction receipt, only transaction hash is available"); - } - - @Override - public BigInteger getTransactionIndex() { - throw unsupportedOperation(); - } - - @Override - public String getTransactionIndexRaw() { - throw unsupportedOperation(); - } - - @Override - public void setTransactionIndex(String transactionIndex) { - throw unsupportedOperation(); - } - - @Override - public String getBlockHash() { - throw unsupportedOperation(); - } - - @Override - public void setBlockHash(String blockHash) { - throw unsupportedOperation(); - } - - @Override - public BigInteger getBlockNumber() { - throw unsupportedOperation(); - } - - @Override - public String getBlockNumberRaw() { - throw unsupportedOperation(); - } - - @Override - public void setBlockNumber(String blockNumber) { - throw unsupportedOperation(); - } - - @Override - public BigInteger getCumulativeGasUsed() { - throw unsupportedOperation(); - } - - @Override - public String getCumulativeGasUsedRaw() { - throw unsupportedOperation(); - } - - @Override - public void setCumulativeGasUsed(String cumulativeGasUsed) { - throw unsupportedOperation(); - } - - @Override - public BigInteger getGasUsed() { - throw unsupportedOperation(); - } - - @Override - public String getGasUsedRaw() { - throw unsupportedOperation(); - } - - @Override - public void setGasUsed(String gasUsed) { - throw unsupportedOperation(); - } - - @Override - public String getContractAddress() { - throw unsupportedOperation(); - } - - @Override - public void setContractAddress(String contractAddress) { - throw unsupportedOperation(); - } - - @Override - public String getRoot() { - throw unsupportedOperation(); - } - - @Override - public void setRoot(String root) { - throw unsupportedOperation(); - } - - @Override - public String getStatus() { - throw unsupportedOperation(); - } - - @Override - public void setStatus(String status) { - throw unsupportedOperation(); - } - - @Override - public String getFrom() { - throw unsupportedOperation(); - } - - @Override - public void setFrom(String from) { - throw unsupportedOperation(); - } - - @Override - public String getTo() { - throw unsupportedOperation(); - } - - @Override - public void setTo(String to) { - throw unsupportedOperation(); - } - - @Override - public List getLogs() { - throw unsupportedOperation(); - } - - @Override - public void setLogs(List logs) { - throw unsupportedOperation(); - } - - @Override - public String getLogsBloom() { - throw unsupportedOperation(); - } - - @Override - public void setLogsBloom(String logsBloom) { - throw unsupportedOperation(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof TransactionReceipt)) { - return false; - } - - TransactionReceipt that = (TransactionReceipt) o; - - return getTransactionHash() != null - ? getTransactionHash().equals(that.getTransactionHash()) - : that.getTransactionHash() == null; - } - - @Override - public int hashCode() { - return getTransactionHash() != null ? getTransactionHash().hashCode() : 0; - } + public EmptyTransactionReceipt(String transactionHash) { + super(); + this.setTransactionHash(transactionHash); + } + + @Override + public String getTransactionHash() { + return super.getTransactionHash(); + } + + @Override + public void setTransactionHash(String transactionHash) { + super.setTransactionHash(transactionHash); + } + + private UnsupportedOperationException unsupportedOperation() { + return new UnsupportedOperationException( + "Empty transaction receipt, only transaction hash is available"); + } + + @Override + public BigInteger getTransactionIndex() { + throw unsupportedOperation(); + } + + @Override + public String getTransactionIndexRaw() { + throw unsupportedOperation(); + } + + @Override + public void setTransactionIndex(String transactionIndex) { + throw unsupportedOperation(); + } + + @Override + public String getBlockHash() { + throw unsupportedOperation(); + } + + @Override + public void setBlockHash(String blockHash) { + throw unsupportedOperation(); + } + + @Override + public BigInteger getBlockNumber() { + throw unsupportedOperation(); + } + + @Override + public String getBlockNumberRaw() { + throw unsupportedOperation(); + } + + @Override + public void setBlockNumber(String blockNumber) { + throw unsupportedOperation(); + } + + @Override + public BigInteger getGasUsed() { + throw unsupportedOperation(); + } + + @Override + public String getGasUsedRaw() { + throw unsupportedOperation(); + } + + @Override + public void setGasUsed(String gasUsed) { + throw unsupportedOperation(); + } + + @Override + public String getContractAddress() { + throw unsupportedOperation(); + } + + @Override + public void setContractAddress(String contractAddress) { + throw unsupportedOperation(); + } + + @Override + public String getRoot() { + throw unsupportedOperation(); + } + + @Override + public void setRoot(String root) { + throw unsupportedOperation(); + } + + @Override + public String getStatus() { + throw unsupportedOperation(); + } + + @Override + public void setStatus(String status) { + throw unsupportedOperation(); + } + + @Override + public String getFrom() { + throw unsupportedOperation(); + } + + @Override + public void setFrom(String from) { + throw unsupportedOperation(); + } + + @Override + public String getTo() { + throw unsupportedOperation(); + } + + @Override + public void setTo(String to) { + throw unsupportedOperation(); + } + + @Override + public List getLogs() { + throw unsupportedOperation(); + } + + @Override + public void setLogs(List logs) { + throw unsupportedOperation(); + } + + @Override + public String getLogsBloom() { + throw unsupportedOperation(); + } + + @Override + public void setLogsBloom(String logsBloom) { + throw unsupportedOperation(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TransactionReceipt)) { + return false; + } + + TransactionReceipt that = (TransactionReceipt) o; + + return getTransactionHash() != null + ? getTransactionHash().equals(that.getTransactionHash()) + : that.getTransactionHash() == null; + } + + @Override + public int hashCode() { + return getTransactionHash() != null ? getTransactionHash().hashCode() : 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/NoOpProcessor.java b/src/main/java/org/fisco/bcos/web3j/tx/response/NoOpProcessor.java index 254b29c01..29ade82f3 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/NoOpProcessor.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/NoOpProcessor.java @@ -11,13 +11,13 @@ */ public class NoOpProcessor extends TransactionReceiptProcessor { - public NoOpProcessor(Web3j web3j) { - super(web3j); - } + public NoOpProcessor(Web3j web3j) { + super(web3j); + } - @Override - public TransactionReceipt waitForTransactionReceipt(String transactionHash) - throws IOException, TransactionException { - return new EmptyTransactionReceipt(transactionHash); - } + @Override + public TransactionReceipt waitForTransactionReceipt(String transactionHash) + throws IOException, TransactionException { + return new EmptyTransactionReceipt(transactionHash); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/PollingTransactionReceiptProcessor.java b/src/main/java/org/fisco/bcos/web3j/tx/response/PollingTransactionReceiptProcessor.java index c1a9d9d42..de7557766 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/PollingTransactionReceiptProcessor.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/PollingTransactionReceiptProcessor.java @@ -9,44 +9,47 @@ /** With each provided transaction hash, poll until we obtain a transaction receipt. */ public class PollingTransactionReceiptProcessor extends TransactionReceiptProcessor { - private final long sleepDuration; - private final int attempts; - - public PollingTransactionReceiptProcessor(Web3j web3j, long sleepDuration, int attempts) { - super(web3j); - this.sleepDuration = sleepDuration; - this.attempts = attempts; - } - - @Override - public TransactionReceipt waitForTransactionReceipt(String transactionHash) - throws IOException, TransactionException { - - return getTransactionReceipt(transactionHash, sleepDuration, attempts); - } - - private TransactionReceipt getTransactionReceipt( - String transactionHash, long sleepDuration, int attempts) - throws IOException, TransactionException { - - Optional receiptOptional = sendTransactionReceiptRequest(transactionHash); - for (int i = 0; i < attempts; i++) { - if (!receiptOptional.isPresent()) { - try { - Thread.sleep(sleepDuration); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new TransactionException(e); - } - receiptOptional = sendTransactionReceiptRequest(transactionHash); - } else { - return receiptOptional.get(); - } + private final long sleepDuration; + private final int attempts; + + public PollingTransactionReceiptProcessor(Web3j web3j, long sleepDuration, int attempts) { + super(web3j); + this.sleepDuration = sleepDuration; + this.attempts = attempts; + } + + @Override + public TransactionReceipt waitForTransactionReceipt(String transactionHash) + throws IOException, TransactionException { + + return getTransactionReceipt(transactionHash, sleepDuration, attempts); } - throw new TransactionException( - "Transaction receipt was not generated after " - + ((sleepDuration * attempts) / 1000 + " seconds for transaction: " + transactionHash), - transactionHash); - } + private TransactionReceipt getTransactionReceipt( + String transactionHash, long sleepDuration, int attempts) + throws IOException, TransactionException { + + Optional receiptOptional = + sendTransactionReceiptRequest(transactionHash); + for (int i = 0; i < attempts; i++) { + if (!receiptOptional.isPresent()) { + try { + Thread.sleep(sleepDuration); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TransactionException(e); + } + receiptOptional = sendTransactionReceiptRequest(transactionHash); + } else { + return receiptOptional.get(); + } + } + + throw new TransactionException( + "Transaction receipt was not generated after " + + ((sleepDuration * attempts) / 1000 + + " seconds for transaction: " + + transactionHash), + transactionHash); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/QueuingTransactionReceiptProcessor.java b/src/main/java/org/fisco/bcos/web3j/tx/response/QueuingTransactionReceiptProcessor.java index 38815842e..f7361e235 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/QueuingTransactionReceiptProcessor.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/QueuingTransactionReceiptProcessor.java @@ -20,110 +20,110 @@ */ public class QueuingTransactionReceiptProcessor extends TransactionReceiptProcessor { - private final int pollingAttemptsPerTxHash; - - private final ScheduledExecutorService scheduledExecutorService; - private final Callback callback; - private final BlockingQueue pendingTransactions; - - public QueuingTransactionReceiptProcessor( - Web3j web3j, Callback callback, int pollingAttemptsPerTxHash, long pollingFrequency) { - super(web3j); - this.scheduledExecutorService = Async.defaultExecutorService(); - this.callback = callback; - this.pendingTransactions = new LinkedBlockingQueue<>(); - this.pollingAttemptsPerTxHash = pollingAttemptsPerTxHash; - - scheduledExecutorService.scheduleAtFixedRate( - this::sendTransactionReceiptRequests, - pollingFrequency, - pollingFrequency, - TimeUnit.MILLISECONDS); - } - - @Override - public TransactionReceipt waitForTransactionReceipt(String transactionHash) - throws IOException, TransactionException { - pendingTransactions.add(new RequestWrapper(transactionHash)); - - return new EmptyTransactionReceipt(transactionHash); - } - - private void sendTransactionReceiptRequests() { - for (RequestWrapper requestWrapper : pendingTransactions) { - try { - String transactionHash = requestWrapper.getTransactionHash(); - Optional transactionReceipt = - sendTransactionReceiptRequest(transactionHash); - if (transactionReceipt.isPresent()) { - callback.accept(transactionReceipt.get()); - pendingTransactions.remove(requestWrapper); - } else { - if (requestWrapper.getCount() == pollingAttemptsPerTxHash) { - throw new TransactionException( - "No transaction receipt for txHash: " - + transactionHash - + "received after " - + pollingAttemptsPerTxHash - + " attempts", - transactionHash); - } else { - requestWrapper.incrementCount(); - } - } - } catch (IOException | TransactionException e) { - pendingTransactions.remove(requestWrapper); - callback.exception(e); - } - } - } - - /** - * Java doesn't provide a concurrent linked hash set, so we use a simple wrapper to store details - * of the number of requests we've made against this specific transaction hash. This is so we can - * preserve submission order as we interate over the outstanding transactions. - * - *

Note - the equals/hashcode methods only operate on the transactionHash field. This is - * intentional. - */ - private static class RequestWrapper { - private final String transactionHash; - private int count; - - RequestWrapper(String transactionHash) { - this.transactionHash = transactionHash; - this.count = 0; + private final int pollingAttemptsPerTxHash; + + private final ScheduledExecutorService scheduledExecutorService; + private final Callback callback; + private final BlockingQueue pendingTransactions; + + public QueuingTransactionReceiptProcessor( + Web3j web3j, Callback callback, int pollingAttemptsPerTxHash, long pollingFrequency) { + super(web3j); + this.scheduledExecutorService = Async.defaultExecutorService(); + this.callback = callback; + this.pendingTransactions = new LinkedBlockingQueue<>(); + this.pollingAttemptsPerTxHash = pollingAttemptsPerTxHash; + + scheduledExecutorService.scheduleAtFixedRate( + this::sendTransactionReceiptRequests, + pollingFrequency, + pollingFrequency, + TimeUnit.MILLISECONDS); } - String getTransactionHash() { - return transactionHash; - } + @Override + public TransactionReceipt waitForTransactionReceipt(String transactionHash) + throws IOException, TransactionException { + pendingTransactions.add(new RequestWrapper(transactionHash)); - int getCount() { - return count; + return new EmptyTransactionReceipt(transactionHash); } - void incrementCount() { - this.count += 1; + private void sendTransactionReceiptRequests() { + for (RequestWrapper requestWrapper : pendingTransactions) { + try { + String transactionHash = requestWrapper.getTransactionHash(); + Optional transactionReceipt = + sendTransactionReceiptRequest(transactionHash); + if (transactionReceipt.isPresent()) { + callback.accept(transactionReceipt.get()); + pendingTransactions.remove(requestWrapper); + } else { + if (requestWrapper.getCount() == pollingAttemptsPerTxHash) { + throw new TransactionException( + "No transaction receipt for txHash: " + + transactionHash + + "received after " + + pollingAttemptsPerTxHash + + " attempts", + transactionHash); + } else { + requestWrapper.incrementCount(); + } + } + } catch (IOException | TransactionException e) { + pendingTransactions.remove(requestWrapper); + callback.exception(e); + } + } } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + /** + * Java doesn't provide a concurrent linked hash set, so we use a simple wrapper to store + * details of the number of requests we've made against this specific transaction hash. This is + * so we can preserve submission order as we interate over the outstanding transactions. + * + *

Note - the equals/hashcode methods only operate on the transactionHash field. This is + * intentional. + */ + private static class RequestWrapper { + private final String transactionHash; + private int count; + + RequestWrapper(String transactionHash) { + this.transactionHash = transactionHash; + this.count = 0; + } - RequestWrapper that = (RequestWrapper) o; + String getTransactionHash() { + return transactionHash; + } - return transactionHash.equals(that.transactionHash); - } + int getCount() { + return count; + } - @Override - public int hashCode() { - return transactionHash.hashCode(); + void incrementCount() { + this.count += 1; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RequestWrapper that = (RequestWrapper) o; + + return transactionHash.equals(that.transactionHash); + } + + @Override + public int hashCode() { + return transactionHash.hashCode(); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/tx/response/TransactionReceiptProcessor.java b/src/main/java/org/fisco/bcos/web3j/tx/response/TransactionReceiptProcessor.java index 67a72167c..782ba2f55 100644 --- a/src/main/java/org/fisco/bcos/web3j/tx/response/TransactionReceiptProcessor.java +++ b/src/main/java/org/fisco/bcos/web3j/tx/response/TransactionReceiptProcessor.java @@ -10,23 +10,24 @@ /** Abstraction for managing how we wait for transaction receipts to be generated on the network. */ public abstract class TransactionReceiptProcessor { - private final Web3j web3j; + private final Web3j web3j; - public TransactionReceiptProcessor(Web3j web3j) { - this.web3j = web3j; - } + public TransactionReceiptProcessor(Web3j web3j) { + this.web3j = web3j; + } - public abstract TransactionReceipt waitForTransactionReceipt(String transactionHash) - throws IOException, TransactionException; + public abstract TransactionReceipt waitForTransactionReceipt(String transactionHash) + throws IOException, TransactionException; - Optional sendTransactionReceiptRequest(String transactionHash) - throws IOException, TransactionException { - BcosTransactionReceipt transactionReceipt = web3j.getTransactionReceipt(transactionHash).send(); - if (transactionReceipt.hasError()) { - throw new TransactionException( - "Error processing request: " + transactionReceipt.getError().getMessage()); - } + Optional sendTransactionReceiptRequest(String transactionHash) + throws IOException, TransactionException { + BcosTransactionReceipt transactionReceipt = + web3j.getTransactionReceipt(transactionHash).send(); + if (transactionReceipt.hasError()) { + throw new TransactionException( + "Error processing request: " + transactionReceipt.getError().getMessage()); + } - return transactionReceipt.getTransactionReceipt(); - } + return transactionReceipt.getTransactionReceipt(); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Account.java b/src/main/java/org/fisco/bcos/web3j/utils/Account.java new file mode 100644 index 000000000..67270c96f --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/utils/Account.java @@ -0,0 +1,53 @@ +package org.fisco.bcos.web3j.utils; + +public class Account { + + public String address; + public String privateKey; + public String publicKey; + public String encryptType; + + public Account() { + super(); + } + + public Account(String address, String privateKey, String publicKey, String encryptType) { + super(); + this.address = address; + this.privateKey = privateKey; + this.publicKey = publicKey; + this.encryptType = encryptType; + } + + public String getAddress() { + return address; + } + + public String getPrivateKey() { + return privateKey; + } + + public String getPublicKey() { + return publicKey; + } + + public String getEncryptType() { + return encryptType; + } + + public void setAddress(String address) { + this.address = address; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public void setEncryptType(String encryptType) { + this.encryptType = encryptType; + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/utils/AccountUtils.java b/src/main/java/org/fisco/bcos/web3j/utils/AccountUtils.java new file mode 100644 index 000000000..a010a22cb --- /dev/null +++ b/src/main/java/org/fisco/bcos/web3j/utils/AccountUtils.java @@ -0,0 +1,86 @@ +package org.fisco.bcos.web3j.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.crypto.EncryptType; +import org.fisco.bcos.web3j.crypto.gm.GenCredential; +import org.fisco.bcos.web3j.protocol.ObjectMapperFactory; + +public class AccountUtils { + + public static void main(String[] args) throws Exception { + String destDir = "accounts"; + File destDirFile = createDir(destDir); + Account account = null; + if (args.length >= 1) { + if ("-g".equals(args[0])) { + account = newAccount(true); + } else { + System.out.println("ERROR: Please set -g option."); + return; + } + } else { + account = newAccount(false); + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss'--'"); + LocalDateTime localDateTime = + ZonedDateTime.now(ZoneOffset.systemDefault()).toLocalDateTime(); + String now = localDateTime.format(formatter); + String fileName = now + account.getAddress() + "--" + account.getEncryptType() + ".json"; + File accoutFile = new File(destDirFile, fileName); + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + objectMapper.writeValue(accoutFile, account); + System.out.println("address:" + account.getAddress()); + System.out.println("privateKey:" + account.getPrivateKey()); + System.out.println("publicKey:" + account.getPublicKey()); + System.out.println("encryptType:" + account.getEncryptType()); + System.out.println(); + System.out.println( + "Account file " + fileName + " successfully created in the directory: " + destDir); + } + + private static File createDir(String destinationDir) { + File destination = new File(destinationDir); + if (!destination.exists()) { + if (!destination.mkdirs()) { + System.out.println( + "Unable to create destination directory [" + + destinationDir + + "], exiting..."); + } + } + return destination; + } + + public static Account newAccount(boolean flag) + throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, + NoSuchProviderException { + // guomi + Account account = new Account(); + if (flag) { + EncryptType.encryptType = 1; + account.setEncryptType("guomi"); + } else { + EncryptType.encryptType = 0; + account.setEncryptType("standard"); + } + Credentials credentials = GenCredential.create(); + + String address = credentials.getAddress(); + String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16); + String publicKey = credentials.getEcKeyPair().getPublicKey().toString(16); + + account.setAddress(address); + account.setPrivateKey(privateKey); + account.setPublicKey(publicKey); + return account; + } +} diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Assertions.java b/src/main/java/org/fisco/bcos/web3j/utils/Assertions.java index 5af383752..84966b426 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Assertions.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Assertions.java @@ -3,15 +3,15 @@ /** Assertion utility functions. */ public class Assertions { - /** - * Verify that the provided precondition holds true. - * - * @param assertionResult assertion value - * @param errorMessage error message if precondition failure - */ - public static void verifyPrecondition(boolean assertionResult, String errorMessage) { - if (!assertionResult) { - throw new RuntimeException(errorMessage); + /** + * Verify that the provided precondition holds true. + * + * @param assertionResult assertion value + * @param errorMessage error message if precondition failure + */ + public static void verifyPrecondition(boolean assertionResult, String errorMessage) { + if (!assertionResult) { + throw new RuntimeException(errorMessage); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Async.java b/src/main/java/org/fisco/bcos/web3j/utils/Async.java index 761d3224f..608df39c0 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Async.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Async.java @@ -6,65 +6,65 @@ /** Async task facilitation. */ public class Async { - private static final ExecutorService executor = Executors.newFixedThreadPool(web3AsyncPoolSize); + private static final ExecutorService executor = Executors.newFixedThreadPool(web3AsyncPoolSize); - static { - Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(executor))); - } + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(executor))); + } - public static CompletableFuture run(Callable callable) { - CompletableFuture result = new CompletableFuture<>(); - CompletableFuture.runAsync( - () -> { - // we need to explicitly catch any exceptions, - // otherwise they will be silently discarded - try { - result.complete(callable.call()); - } catch (Throwable e) { - result.completeExceptionally(e); - } - }, - executor); - return result; - } + public static CompletableFuture run(Callable callable) { + CompletableFuture result = new CompletableFuture<>(); + CompletableFuture.runAsync( + () -> { + // we need to explicitly catch any exceptions, + // otherwise they will be silently discarded + try { + result.complete(callable.call()); + } catch (Throwable e) { + result.completeExceptionally(e); + } + }, + executor); + return result; + } - private static int getCpuCount() { - return Runtime.getRuntime().availableProcessors(); - } + private static int getCpuCount() { + return Runtime.getRuntime().availableProcessors(); + } - /** - * Provide a new ScheduledExecutorService instance. - * - *

A shutdown hook is created to terminate the thread pool on application termination. - * - * @return new ScheduledExecutorService - */ - public static ScheduledExecutorService defaultExecutorService() { - ScheduledExecutorService scheduledExecutorService = - Executors.newScheduledThreadPool(getCpuCount()); + /** + * Provide a new ScheduledExecutorService instance. + * + *

A shutdown hook is created to terminate the thread pool on application termination. + * + * @return new ScheduledExecutorService + */ + public static ScheduledExecutorService defaultExecutorService() { + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(getCpuCount()); - Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(scheduledExecutorService))); + Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(scheduledExecutorService))); - return scheduledExecutorService; - } + return scheduledExecutorService; + } - /** - * Shutdown as per {@link ExecutorService} Javadoc recommendation. - * - * @param executorService executor service we wish to shut down. - */ - private static void shutdown(ExecutorService executorService) { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { - System.err.println("Thread pool did not terminate"); + /** + * Shutdown as per {@link ExecutorService} Javadoc recommendation. + * + * @param executorService executor service we wish to shut down. + */ + private static void shutdown(ExecutorService executorService) { + executorService.shutdown(); + try { + if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { + System.err.println("Thread pool did not terminate"); + } + } + } catch (InterruptedException ie) { + executorService.shutdownNow(); + Thread.currentThread().interrupt(); } - } - } catch (InterruptedException ie) { - executorService.shutdownNow(); - Thread.currentThread().interrupt(); } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/AttemptsConf.java b/src/main/java/org/fisco/bcos/web3j/utils/AttemptsConf.java index 938438367..a8b9e9642 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/AttemptsConf.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/AttemptsConf.java @@ -1,27 +1,27 @@ package org.fisco.bcos.web3j.utils; public class AttemptsConf { - public static Integer sleepDuration = 1500; - public static Integer attempts = 40; + public static Integer sleepDuration = 1500; + public static Integer attempts = 40; - public AttemptsConf(int sleepDuration, int attempts) { - this.sleepDuration = sleepDuration; - this.attempts = attempts; - } + public AttemptsConf(int sleepDuration, int attempts) { + this.sleepDuration = sleepDuration; + this.attempts = attempts; + } - public int getSleepDuration() { - return sleepDuration; - } + public int getSleepDuration() { + return sleepDuration; + } - public void setSleepDuration(int sleepDuration) { - AttemptsConf.sleepDuration = sleepDuration; - } + public void setSleepDuration(int sleepDuration) { + AttemptsConf.sleepDuration = sleepDuration; + } - public int getAttempts() { - return attempts; - } + public int getAttempts() { + return attempts; + } - public void setAttempts(int attempts) { - AttemptsConf.attempts = attempts; - } + public void setAttempts(int attempts) { + AttemptsConf.attempts = attempts; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/BlockLimit.java b/src/main/java/org/fisco/bcos/web3j/utils/BlockLimit.java index bd24e1119..e9db8814f 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/BlockLimit.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/BlockLimit.java @@ -2,17 +2,17 @@ /** Created by mingzhenliu on 2018/8/24. */ public class BlockLimit { - public static Integer blockLimit = 500; + public static Integer blockLimit = 600; - public BlockLimit(int blockLimit) { - this.blockLimit = blockLimit; - } + public BlockLimit(int blockLimit) { + this.blockLimit = blockLimit; + } - public int getBlockLimit() { - return blockLimit; - } + public int getBlockLimit() { + return blockLimit; + } - public void setBlockLimit(int blockLimit) { - BlockLimit.blockLimit = blockLimit; - } + public void setBlockLimit(int blockLimit) { + BlockLimit.blockLimit = blockLimit; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/ByteUtil.java b/src/main/java/org/fisco/bcos/web3j/utils/ByteUtil.java index bd8907435..ab774ef4a 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/ByteUtil.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/ByteUtil.java @@ -30,651 +30,653 @@ public class ByteUtil { - public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - public static final byte[] ZERO_BYTE_ARRAY = new byte[] {0}; - - /** Creates a copy of bytes and appends b to the end of it */ - public static byte[] appendByte(byte[] bytes, byte b) { - byte[] result = Arrays.copyOf(bytes, bytes.length + 1); - result[result.length - 1] = b; - return result; - } - - /** - * The regular {@link BigInteger#toByteArray()} method isn't quite what we often need: it appends - * a leading zero to indicate that the number is positive and may need padding. - * - * @param b the integer to format into a byte array - * @param numBytes the desired size of the resulting byte array - * @return numBytes byte long array. - */ - public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { - if (b == null) return null; - byte[] bytes = new byte[numBytes]; - byte[] biBytes = b.toByteArray(); - int start = (biBytes.length == numBytes + 1) ? 1 : 0; - int length = Math.min(biBytes.length, numBytes); - System.arraycopy(biBytes, start, bytes, numBytes - length, length); - return bytes; - } - - public static byte[] bigIntegerToBytesSigned(BigInteger b, int numBytes) { - if (b == null) return null; - byte[] bytes = new byte[numBytes]; - Arrays.fill(bytes, b.signum() < 0 ? (byte) 0xFF : 0x00); - byte[] biBytes = b.toByteArray(); - int start = (biBytes.length == numBytes + 1) ? 1 : 0; - int length = Math.min(biBytes.length, numBytes); - System.arraycopy(biBytes, start, bytes, numBytes - length, length); - return bytes; - } - - public static byte[] bigIntegerToBytes(BigInteger value) { - if (value == null) return null; - - byte[] data = value.toByteArray(); - - if (data.length != 1 && data[0] == 0) { - byte[] tmp = new byte[data.length - 1]; - System.arraycopy(data, 1, tmp, 0, tmp.length); - data = tmp; - } - return data; - } - - /** - * Cast hex encoded value from byte[] to BigInteger null is parsed like byte[0] - * - * @param bb byte array contains the values - * @return unsigned positive BigInteger value. - */ - public static BigInteger bytesToBigInteger(byte[] bb) { - return (bb == null || bb.length == 0) ? BigInteger.ZERO : new BigInteger(1, bb); - } - - /** - * Returns the amount of nibbles that match each other from 0 ... amount will never be larger than - * smallest input - * - * @param a - first input - * @param b - second input - * @return Number of bytes that match - */ - public static int matchingNibbleLength(byte[] a, byte[] b) { - int i = 0; - int length = a.length < b.length ? a.length : b.length; - while (i < length) { - if (a[i] != b[i]) return i; - i++; - } - return i; - } - - /** - * Converts a long value into a byte array. - * - * @param val - long value to convert - * @return byte[] of length 8, representing the long value - */ - public static byte[] longToBytes(long val) { - return ByteBuffer.allocate(Long.BYTES).putLong(val).array(); - } - - /** - * Converts a long value into a byte array. - * - * @param val - long value to convert - * @return decimal value with leading byte that are zeroes striped - */ - public static byte[] longToBytesNoLeadZeroes(long val) { - - // todo: improve performance by while strip numbers until (long >> 8 == 0) - if (val == 0) return EMPTY_BYTE_ARRAY; - - byte[] data = ByteBuffer.allocate(Long.BYTES).putLong(val).array(); - - return stripLeadingZeroes(data); - } - - /** - * Converts int value into a byte array. - * - * @param val - int value to convert - * @return byte[] of length 4, representing the int value - */ - public static byte[] intToBytes(int val) { - return ByteBuffer.allocate(Integer.BYTES).putInt(val).array(); - } - - /** - * Converts a int value into a byte array. - * - * @param val - int value to convert - * @return value with leading byte that are zeroes striped - */ - public static byte[] intToBytesNoLeadZeroes(int val) { - - if (val == 0) return EMPTY_BYTE_ARRAY; - - int lenght = 0; - - int tmpVal = val; - while (tmpVal != 0) { - tmpVal = tmpVal >>> 8; - ++lenght; - } - - byte[] result = new byte[lenght]; - - int index = result.length - 1; - while (val != 0) { - - result[index] = (byte) (val & 0xFF); - val = val >>> 8; - index -= 1; - } - - return result; - } - - /** - * Convert a byte-array into a hex String.
- * Works similar to {@link Hex#toHexString} but allows for null - * - * @param data - byte-array to convert to a hex-string - * @return hex representation of the data.
- * Returns an empty String if the input is null - * @see Hex#toHexString - */ - public static String toHexString(byte[] data) { - return data == null ? "" : Hex.toHexString(data); - } - - /** - * Calculate packet length - * - * @param msg byte[] - * @return byte-array with 4 elements - */ - public static byte[] calcPacketLength(byte[] msg) { - int msgLen = msg.length; - return new byte[] { - (byte) ((msgLen >> 24) & 0xFF), - (byte) ((msgLen >> 16) & 0xFF), - (byte) ((msgLen >> 8) & 0xFF), - (byte) ((msgLen) & 0xFF) - }; - } - - /** - * Cast hex encoded value from byte[] to int null is parsed like byte[0] - * - *

Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes) - * - * @param b array contains the values - * @return unsigned positive int value. - */ - public static int byteArrayToInt(byte[] b) { - if (b == null || b.length == 0) return 0; - return new BigInteger(1, b).intValue(); - } - - /** - * Cast hex encoded value from byte[] to long null is parsed like byte[0] - * - *

Limited to Long.MAX_VALUE: 263-1 (8 bytes) - * - * @param b array contains the values - * @return unsigned positive long value. - */ - public static long byteArrayToLong(byte[] b) { - if (b == null || b.length == 0) return 0; - return new BigInteger(1, b).longValue(); - } - - /** - * Turn nibbles to a pretty looking output string - * - *

Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45' - * - * @param nibbles - getting byte of data [ 04 ] and turning it to a '\x04' representation - * @return pretty string of nibbles - */ - public static String nibblesToPrettyString(byte[] nibbles) { - StringBuilder builder = new StringBuilder(); - for (byte nibble : nibbles) { - final String nibbleString = oneByteToHexString(nibble); - builder.append("\\x").append(nibbleString); - } - return builder.toString(); - } - - public static String oneByteToHexString(byte value) { - String retVal = Integer.toString(value & 0xFF, 16); - if (retVal.length() == 1) retVal = "0" + retVal; - return retVal; - } - - /** - * Calculate the number of bytes need to encode the number - * - * @param val - number - * @return number of min bytes used to encode the number - */ - public static int numBytes(String val) { - - BigInteger bInt = new BigInteger(val); - int bytes = 0; - - while (!bInt.equals(BigInteger.ZERO)) { - bInt = bInt.shiftRight(8); - ++bytes; - } - if (bytes == 0) ++bytes; - return bytes; - } - - /** - * @param arg - not more that 32 bits - * @return - bytes of the value pad with complete to 32 zeroes - */ - public static byte[] encodeValFor32Bits(Object arg) { - - byte[] data; - - // check if the string is numeric - if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?")) - data = new BigInteger(arg.toString().trim()).toByteArray(); - // check if it's hex number - else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+")) - data = new BigInteger(arg.toString().trim().substring(2), 16).toByteArray(); - else data = arg.toString().trim().getBytes(); - - if (data.length > 32) throw new RuntimeException("values can't be more than 32 byte"); - - byte[] val = new byte[32]; - - int j = 0; - for (int i = data.length; i > 0; --i) { - val[31 - j] = data[i - 1]; - ++j; - } - return val; - } - - /** - * encode the values and concatenate together - * - * @param args Object - * @return byte[] - */ - public static byte[] encodeDataList(Object... args) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (Object arg : args) { - byte[] val = encodeValFor32Bits(arg); - try { - baos.write(val); - } catch (IOException e) { - throw new Error("Happen something that should never happen ", e); - } - } - return baos.toByteArray(); - } - - public static int firstNonZeroByte(byte[] data) { - for (int i = 0; i < data.length; ++i) { - if (data[i] != 0) { + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + public static final byte[] ZERO_BYTE_ARRAY = new byte[] {0}; + + /** Creates a copy of bytes and appends b to the end of it */ + public static byte[] appendByte(byte[] bytes, byte b) { + byte[] result = Arrays.copyOf(bytes, bytes.length + 1); + result[result.length - 1] = b; + return result; + } + + /** + * The regular {@link BigInteger#toByteArray()} method isn't quite what we often need: it + * appends a leading zero to indicate that the number is positive and may need padding. + * + * @param b the integer to format into a byte array + * @param numBytes the desired size of the resulting byte array + * @return numBytes byte long array. + */ + public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { + if (b == null) return null; + byte[] bytes = new byte[numBytes]; + byte[] biBytes = b.toByteArray(); + int start = (biBytes.length == numBytes + 1) ? 1 : 0; + int length = Math.min(biBytes.length, numBytes); + System.arraycopy(biBytes, start, bytes, numBytes - length, length); + return bytes; + } + + public static byte[] bigIntegerToBytesSigned(BigInteger b, int numBytes) { + if (b == null) return null; + byte[] bytes = new byte[numBytes]; + Arrays.fill(bytes, b.signum() < 0 ? (byte) 0xFF : 0x00); + byte[] biBytes = b.toByteArray(); + int start = (biBytes.length == numBytes + 1) ? 1 : 0; + int length = Math.min(biBytes.length, numBytes); + System.arraycopy(biBytes, start, bytes, numBytes - length, length); + return bytes; + } + + public static byte[] bigIntegerToBytes(BigInteger value) { + if (value == null) return null; + + byte[] data = value.toByteArray(); + + if (data.length != 1 && data[0] == 0) { + byte[] tmp = new byte[data.length - 1]; + System.arraycopy(data, 1, tmp, 0, tmp.length); + data = tmp; + } + return data; + } + + /** + * Cast hex encoded value from byte[] to BigInteger null is parsed like byte[0] + * + * @param bb byte array contains the values + * @return unsigned positive BigInteger value. + */ + public static BigInteger bytesToBigInteger(byte[] bb) { + return (bb == null || bb.length == 0) ? BigInteger.ZERO : new BigInteger(1, bb); + } + + /** + * Returns the amount of nibbles that match each other from 0 ... amount will never be larger + * than smallest input + * + * @param a - first input + * @param b - second input + * @return Number of bytes that match + */ + public static int matchingNibbleLength(byte[] a, byte[] b) { + int i = 0; + int length = a.length < b.length ? a.length : b.length; + while (i < length) { + if (a[i] != b[i]) return i; + i++; + } return i; - } } - return -1; - } - public static byte[] stripLeadingZeroes(byte[] data) { + /** + * Converts a long value into a byte array. + * + * @param val - long value to convert + * @return byte[] of length 8, representing the long value + */ + public static byte[] longToBytes(long val) { + return ByteBuffer.allocate(Long.BYTES).putLong(val).array(); + } + + /** + * Converts a long value into a byte array. + * + * @param val - long value to convert + * @return decimal value with leading byte that are zeroes striped + */ + public static byte[] longToBytesNoLeadZeroes(long val) { + + // todo: improve performance by while strip numbers until (long >> 8 == 0) + if (val == 0) return EMPTY_BYTE_ARRAY; + + byte[] data = ByteBuffer.allocate(Long.BYTES).putLong(val).array(); + + return stripLeadingZeroes(data); + } + + /** + * Converts int value into a byte array. + * + * @param val - int value to convert + * @return byte[] of length 4, representing the int value + */ + public static byte[] intToBytes(int val) { + return ByteBuffer.allocate(Integer.BYTES).putInt(val).array(); + } + + /** + * Converts a int value into a byte array. + * + * @param val - int value to convert + * @return value with leading byte that are zeroes striped + */ + public static byte[] intToBytesNoLeadZeroes(int val) { + + if (val == 0) return EMPTY_BYTE_ARRAY; + + int lenght = 0; + + int tmpVal = val; + while (tmpVal != 0) { + tmpVal = tmpVal >>> 8; + ++lenght; + } + + byte[] result = new byte[lenght]; + + int index = result.length - 1; + while (val != 0) { + + result[index] = (byte) (val & 0xFF); + val = val >>> 8; + index -= 1; + } + + return result; + } + + /** + * Convert a byte-array into a hex String.
+ * Works similar to {@link Hex#toHexString} but allows for null + * + * @param data - byte-array to convert to a hex-string + * @return hex representation of the data.
+ * Returns an empty String if the input is null + * @see Hex#toHexString + */ + public static String toHexString(byte[] data) { + return data == null ? "" : Hex.toHexString(data); + } + + /** + * Calculate packet length + * + * @param msg byte[] + * @return byte-array with 4 elements + */ + public static byte[] calcPacketLength(byte[] msg) { + int msgLen = msg.length; + return new byte[] { + (byte) ((msgLen >> 24) & 0xFF), + (byte) ((msgLen >> 16) & 0xFF), + (byte) ((msgLen >> 8) & 0xFF), + (byte) ((msgLen) & 0xFF) + }; + } + + /** + * Cast hex encoded value from byte[] to int null is parsed like byte[0] + * + *

Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes) + * + * @param b array contains the values + * @return unsigned positive int value. + */ + public static int byteArrayToInt(byte[] b) { + if (b == null || b.length == 0) return 0; + return new BigInteger(1, b).intValue(); + } + + /** + * Cast hex encoded value from byte[] to long null is parsed like byte[0] + * + *

Limited to Long.MAX_VALUE: 263-1 (8 bytes) + * + * @param b array contains the values + * @return unsigned positive long value. + */ + public static long byteArrayToLong(byte[] b) { + if (b == null || b.length == 0) return 0; + return new BigInteger(1, b).longValue(); + } + + /** + * Turn nibbles to a pretty looking output string + * + *

Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45' + * + * @param nibbles - getting byte of data [ 04 ] and turning it to a '\x04' representation + * @return pretty string of nibbles + */ + public static String nibblesToPrettyString(byte[] nibbles) { + StringBuilder builder = new StringBuilder(); + for (byte nibble : nibbles) { + final String nibbleString = oneByteToHexString(nibble); + builder.append("\\x").append(nibbleString); + } + return builder.toString(); + } + + public static String oneByteToHexString(byte value) { + String retVal = Integer.toString(value & 0xFF, 16); + if (retVal.length() == 1) retVal = "0" + retVal; + return retVal; + } + + /** + * Calculate the number of bytes need to encode the number + * + * @param val - number + * @return number of min bytes used to encode the number + */ + public static int numBytes(String val) { + + BigInteger bInt = new BigInteger(val); + int bytes = 0; + + while (!bInt.equals(BigInteger.ZERO)) { + bInt = bInt.shiftRight(8); + ++bytes; + } + if (bytes == 0) ++bytes; + return bytes; + } + + /** + * @param arg - not more that 32 bits + * @return - bytes of the value pad with complete to 32 zeroes + */ + public static byte[] encodeValFor32Bits(Object arg) { + + byte[] data; + + // check if the string is numeric + if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?")) + data = new BigInteger(arg.toString().trim()).toByteArray(); + // check if it's hex number + else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+")) + data = new BigInteger(arg.toString().trim().substring(2), 16).toByteArray(); + else data = arg.toString().trim().getBytes(); + + if (data.length > 32) throw new RuntimeException("values can't be more than 32 byte"); + + byte[] val = new byte[32]; + + int j = 0; + for (int i = data.length; i > 0; --i) { + val[31 - j] = data[i - 1]; + ++j; + } + return val; + } + + /** + * encode the values and concatenate together + * + * @param args Object + * @return byte[] + */ + public static byte[] encodeDataList(Object... args) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (Object arg : args) { + byte[] val = encodeValFor32Bits(arg); + try { + baos.write(val); + } catch (IOException e) { + throw new Error("Happen something that should never happen ", e); + } + } + return baos.toByteArray(); + } + + public static int firstNonZeroByte(byte[] data) { + for (int i = 0; i < data.length; ++i) { + if (data[i] != 0) { + return i; + } + } + return -1; + } + + public static byte[] stripLeadingZeroes(byte[] data) { + + if (data == null) return null; + + final int firstNonZero = firstNonZeroByte(data); + switch (firstNonZero) { + case -1: + return ZERO_BYTE_ARRAY; + + case 0: + return data; + + default: + byte[] result = new byte[data.length - firstNonZero]; + System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero); + + return result; + } + } + + /** + * increment byte array as a number until max is reached + * + * @param bytes byte[] + * @return boolean + */ + public static boolean increment(byte[] bytes) { + final int startIndex = 0; + int i; + for (i = bytes.length - 1; i >= startIndex; i--) { + bytes[i]++; + if (bytes[i] != 0) break; + } + // we return false when all bytes are 0 again + return (i >= startIndex || bytes[startIndex] != 0); + } + + /** + * Utility function to copy a byte array into a new byte array with given size. If the src + * length is smaller than the given size, the result will be left-padded with zeros. + * + * @param value - a BigInteger with a maximum value of 2^256-1 + * @return Byte array of given size with a copy of the src + */ + public static byte[] copyToArray(BigInteger value) { + byte[] src = ByteUtil.bigIntegerToBytes(value); + byte[] dest = ByteBuffer.allocate(32).array(); + if (src != null) { + System.arraycopy(src, 0, dest, dest.length - src.length, src.length); + } + return dest; + } + + // public static ByteArrayWrapper wrap(byte[] data) { + // return new ByteArrayWrapper(data); + // } - if (data == null) return null; + public static byte[] setBit(byte[] data, int pos, int val) { - final int firstNonZero = firstNonZeroByte(data); - switch (firstNonZero) { - case -1: - return ZERO_BYTE_ARRAY; + if ((data.length * 8) - 1 < pos) throw new Error("outside byte array limit, pos: " + pos); - case 0: + int posByte = data.length - 1 - (pos) / 8; + int posBit = (pos) % 8; + byte setter = (byte) (1 << (posBit)); + byte toBeSet = data[posByte]; + byte result; + if (val == 1) result = (byte) (toBeSet | setter); + else result = (byte) (toBeSet & ~setter); + + data[posByte] = result; return data; + } + + public static int getBit(byte[] data, int pos) { + + if ((data.length * 8) - 1 < pos) throw new Error("outside byte array limit, pos: " + pos); + + int posByte = data.length - 1 - pos / 8; + int posBit = pos % 8; + byte dataByte = data[posByte]; + return Math.min(1, ((dataByte & 0xff) & (1 << (posBit)))); + } + + public static byte[] and(byte[] b1, byte[] b2) { + if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); + byte[] ret = new byte[b1.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = (byte) (b1[i] & b2[i]); + } + return ret; + } + + public static byte[] or(byte[] b1, byte[] b2) { + if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); + byte[] ret = new byte[b1.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = (byte) (b1[i] | b2[i]); + } + return ret; + } + + public static byte[] xor(byte[] b1, byte[] b2) { + if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); + byte[] ret = new byte[b1.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = (byte) (b1[i] ^ b2[i]); + } + return ret; + } - default: - byte[] result = new byte[data.length - firstNonZero]; - System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero); + /** + * XORs byte arrays of different lengths by aligning length of the shortest via adding zeros at + * beginning + */ + public static byte[] xorAlignRight(byte[] b1, byte[] b2) { + if (b1.length > b2.length) { + byte[] b2_ = new byte[b1.length]; + System.arraycopy(b2, 0, b2_, b1.length - b2.length, b2.length); + b2 = b2_; + } else if (b2.length > b1.length) { + byte[] b1_ = new byte[b2.length]; + System.arraycopy(b1, 0, b1_, b2.length - b1.length, b1.length); + b1 = b1_; + } + + return xor(b1, b2); + } + + /** + * @param arrays - arrays to merge + * @return - merged array + */ + public static byte[] merge(byte[]... arrays) { + int count = 0; + for (byte[] array : arrays) { + count += array.length; + } + + // Create new array and copy all array contents + byte[] mergedArray = new byte[count]; + int start = 0; + for (byte[] array : arrays) { + System.arraycopy(array, 0, mergedArray, start, array.length); + start += array.length; + } + return mergedArray; + } + + public static boolean isNullOrZeroArray(byte[] array) { + return (array == null) || (array.length == 0); + } + + public static boolean isSingleZero(byte[] array) { + return (array.length == 1 && array[0] == 0); + } + + public static Set difference(Set setA, Set setB) { + + Set result = new HashSet<>(); + + for (byte[] elementA : setA) { + boolean found = false; + for (byte[] elementB : setB) { + + if (Arrays.equals(elementA, elementB)) { + found = true; + break; + } + } + if (!found) result.add(elementA); + } return result; } - } - - /** - * increment byte array as a number until max is reached - * - * @param bytes byte[] - * @return boolean - */ - public static boolean increment(byte[] bytes) { - final int startIndex = 0; - int i; - for (i = bytes.length - 1; i >= startIndex; i--) { - bytes[i]++; - if (bytes[i] != 0) break; - } - // we return false when all bytes are 0 again - return (i >= startIndex || bytes[startIndex] != 0); - } - - /** - * Utility function to copy a byte array into a new byte array with given size. If the src length - * is smaller than the given size, the result will be left-padded with zeros. - * - * @param value - a BigInteger with a maximum value of 2^256-1 - * @return Byte array of given size with a copy of the src - */ - public static byte[] copyToArray(BigInteger value) { - byte[] src = ByteUtil.bigIntegerToBytes(value); - byte[] dest = ByteBuffer.allocate(32).array(); - if (src != null) { - System.arraycopy(src, 0, dest, dest.length - src.length, src.length); - } - return dest; - } - - // public static ByteArrayWrapper wrap(byte[] data) { - // return new ByteArrayWrapper(data); - // } - - public static byte[] setBit(byte[] data, int pos, int val) { - - if ((data.length * 8) - 1 < pos) throw new Error("outside byte array limit, pos: " + pos); - - int posByte = data.length - 1 - (pos) / 8; - int posBit = (pos) % 8; - byte setter = (byte) (1 << (posBit)); - byte toBeSet = data[posByte]; - byte result; - if (val == 1) result = (byte) (toBeSet | setter); - else result = (byte) (toBeSet & ~setter); - - data[posByte] = result; - return data; - } - - public static int getBit(byte[] data, int pos) { - - if ((data.length * 8) - 1 < pos) throw new Error("outside byte array limit, pos: " + pos); - - int posByte = data.length - 1 - pos / 8; - int posBit = pos % 8; - byte dataByte = data[posByte]; - return Math.min(1, ((dataByte & 0xff) & (1 << (posBit)))); - } - - public static byte[] and(byte[] b1, byte[] b2) { - if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); - byte[] ret = new byte[b1.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = (byte) (b1[i] & b2[i]); - } - return ret; - } - - public static byte[] or(byte[] b1, byte[] b2) { - if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); - byte[] ret = new byte[b1.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = (byte) (b1[i] | b2[i]); - } - return ret; - } - - public static byte[] xor(byte[] b1, byte[] b2) { - if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); - byte[] ret = new byte[b1.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = (byte) (b1[i] ^ b2[i]); - } - return ret; - } - - /** - * XORs byte arrays of different lengths by aligning length of the shortest via adding zeros at - * beginning - */ - public static byte[] xorAlignRight(byte[] b1, byte[] b2) { - if (b1.length > b2.length) { - byte[] b2_ = new byte[b1.length]; - System.arraycopy(b2, 0, b2_, b1.length - b2.length, b2.length); - b2 = b2_; - } else if (b2.length > b1.length) { - byte[] b1_ = new byte[b2.length]; - System.arraycopy(b1, 0, b1_, b2.length - b1.length, b1.length); - b1 = b1_; - } - - return xor(b1, b2); - } - - /** - * @param arrays - arrays to merge - * @return - merged array - */ - public static byte[] merge(byte[]... arrays) { - int count = 0; - for (byte[] array : arrays) { - count += array.length; - } - - // Create new array and copy all array contents - byte[] mergedArray = new byte[count]; - int start = 0; - for (byte[] array : arrays) { - System.arraycopy(array, 0, mergedArray, start, array.length); - start += array.length; - } - return mergedArray; - } - - public static boolean isNullOrZeroArray(byte[] array) { - return (array == null) || (array.length == 0); - } - - public static boolean isSingleZero(byte[] array) { - return (array.length == 1 && array[0] == 0); - } - - public static Set difference(Set setA, Set setB) { - - Set result = new HashSet<>(); - - for (byte[] elementA : setA) { - boolean found = false; - for (byte[] elementB : setB) { - - if (Arrays.equals(elementA, elementB)) { - found = true; - break; + + public static int length(byte[]... bytes) { + int result = 0; + for (byte[] array : bytes) { + result += (array == null) ? 0 : array.length; } - } - if (!found) result.add(elementA); - } - - return result; - } - - public static int length(byte[]... bytes) { - int result = 0; - for (byte[] array : bytes) { - result += (array == null) ? 0 : array.length; - } - return result; - } - - public static byte[] intsToBytes(int[] arr, boolean bigEndian) { - byte[] ret = new byte[arr.length * 4]; - intsToBytes(arr, ret, bigEndian); - return ret; - } - - public static int[] bytesToInts(byte[] arr, boolean bigEndian) { - int[] ret = new int[arr.length / 4]; - bytesToInts(arr, ret, bigEndian); - return ret; - } - - public static void bytesToInts(byte[] b, int[] arr, boolean bigEndian) { - if (!bigEndian) { - int off = 0; - for (int i = 0; i < arr.length; i++) { - int ii = b[off++] & 0x000000FF; - ii |= (b[off++] << 8) & 0x0000FF00; - ii |= (b[off++] << 16) & 0x00FF0000; - ii |= (b[off++] << 24); - arr[i] = ii; - } - } else { - int off = 0; - for (int i = 0; i < arr.length; i++) { - int ii = b[off++] << 24; - ii |= (b[off++] << 16) & 0x00FF0000; - ii |= (b[off++] << 8) & 0x0000FF00; - ii |= b[off++] & 0x000000FF; - arr[i] = ii; - } - } - } - - public static void intsToBytes(int[] arr, byte[] b, boolean bigEndian) { - if (!bigEndian) { - int off = 0; - for (int i = 0; i < arr.length; i++) { - int ii = arr[i]; - b[off++] = (byte) (ii & 0xFF); - b[off++] = (byte) ((ii >> 8) & 0xFF); - b[off++] = (byte) ((ii >> 16) & 0xFF); - b[off++] = (byte) ((ii >> 24) & 0xFF); - } - } else { - int off = 0; - for (int i = 0; i < arr.length; i++) { - int ii = arr[i]; - b[off++] = (byte) ((ii >> 24) & 0xFF); - b[off++] = (byte) ((ii >> 16) & 0xFF); - b[off++] = (byte) ((ii >> 8) & 0xFF); - b[off++] = (byte) (ii & 0xFF); - } - } - } - - public static short bigEndianToShort(byte[] bs) { - return bigEndianToShort(bs, 0); - } - - public static short bigEndianToShort(byte[] bs, int off) { - int n = bs[off] << 8; - ++off; - n |= bs[off] & 0xFF; - return (short) n; - } - - public static byte[] shortToBytes(short n) { - return ByteBuffer.allocate(2).putShort(n).array(); - } - - /** - * Converts string hex representation to data bytes Accepts following hex: - with or without 0x - * prefix - * - * @param data String like '0xa5e..' or just 'a5e..' - * @return decoded bytes array - */ - public static byte[] hexStringToBytes(String data) { - if (data == null) return EMPTY_BYTE_ARRAY; - if (data.startsWith("0x")) data = data.substring(2); - if (data.length() % 2 == 1) data = "0" + data; - return Hex.decode(data); - } - - /** Converts string representation of host/ip to 4-bytes byte[] IPv4 */ - public static byte[] hostToBytes(String ip) { - byte[] bytesIp; - try { - bytesIp = InetAddress.getByName(ip).getAddress(); - } catch (UnknownHostException e) { - bytesIp = new byte[4]; // fall back to invalid 0.0.0.0 address - } - - return bytesIp; - } - - /** Converts 4 bytes IPv4 IP to String representation */ - public static String bytesToIp(byte[] bytesIp) { - - StringBuilder sb = new StringBuilder(); - sb.append(bytesIp[0] & 0xFF); - sb.append("."); - sb.append(bytesIp[1] & 0xFF); - sb.append("."); - sb.append(bytesIp[2] & 0xFF); - sb.append("."); - sb.append(bytesIp[3] & 0xFF); - - String ip = sb.toString(); - return ip; - } - - /** - * Returns a number of zero bits preceding the highest-order ("leftmost") one-bit interpreting - * input array as a big-endian integer value - */ - public static int numberOfLeadingZeros(byte[] bytes) { - - int i = firstNonZeroByte(bytes); - - if (i == -1) { - return bytes.length * 8; - } else { - int byteLeadingZeros = Integer.numberOfLeadingZeros((int) bytes[i] & 0xff) - 24; - return i * 8 + byteLeadingZeros; - } - } - - /** - * Parses fixed number of bytes starting from {@code offset} in {@code input} array. If {@code - * input} has not enough bytes return array will be right padded with zero bytes. I.e. if {@code - * offset} is higher than {@code input.length} then zero byte array of length {@code len} will be - * returned - */ - public static byte[] parseBytes(byte[] input, int offset, int len) { - - if (offset >= input.length || len == 0) return EMPTY_BYTE_ARRAY; - - byte[] bytes = new byte[len]; - System.arraycopy(input, offset, bytes, 0, Math.min(input.length - offset, len)); - return bytes; - } - - /** - * Parses 32-bytes word from given input. Uses {@link #parseBytes(byte[], int, int)} method, thus, - * result will be right-padded with zero bytes if there is not enough bytes in {@code input} - * - * @param idx an index of the word starting from {@code 0} - */ - public static byte[] parseWord(byte[] input, int idx) { - return parseBytes(input, 32 * idx, 32); - } - - /** - * Parses 32-bytes word from given input. Uses {@link #parseBytes(byte[], int, int)} method, thus, - * result will be right-padded with zero bytes if there is not enough bytes in {@code input} - * - * @param idx an index of the word starting from {@code 0} - * @param offset an offset in {@code input} array to start parsing from - */ - public static byte[] parseWord(byte[] input, int offset, int idx) { - return parseBytes(input, offset + 32 * idx, 32); - } + return result; + } + + public static byte[] intsToBytes(int[] arr, boolean bigEndian) { + byte[] ret = new byte[arr.length * 4]; + intsToBytes(arr, ret, bigEndian); + return ret; + } + + public static int[] bytesToInts(byte[] arr, boolean bigEndian) { + int[] ret = new int[arr.length / 4]; + bytesToInts(arr, ret, bigEndian); + return ret; + } + + public static void bytesToInts(byte[] b, int[] arr, boolean bigEndian) { + if (!bigEndian) { + int off = 0; + for (int i = 0; i < arr.length; i++) { + int ii = b[off++] & 0x000000FF; + ii |= (b[off++] << 8) & 0x0000FF00; + ii |= (b[off++] << 16) & 0x00FF0000; + ii |= (b[off++] << 24); + arr[i] = ii; + } + } else { + int off = 0; + for (int i = 0; i < arr.length; i++) { + int ii = b[off++] << 24; + ii |= (b[off++] << 16) & 0x00FF0000; + ii |= (b[off++] << 8) & 0x0000FF00; + ii |= b[off++] & 0x000000FF; + arr[i] = ii; + } + } + } + + public static void intsToBytes(int[] arr, byte[] b, boolean bigEndian) { + if (!bigEndian) { + int off = 0; + for (int i = 0; i < arr.length; i++) { + int ii = arr[i]; + b[off++] = (byte) (ii & 0xFF); + b[off++] = (byte) ((ii >> 8) & 0xFF); + b[off++] = (byte) ((ii >> 16) & 0xFF); + b[off++] = (byte) ((ii >> 24) & 0xFF); + } + } else { + int off = 0; + for (int i = 0; i < arr.length; i++) { + int ii = arr[i]; + b[off++] = (byte) ((ii >> 24) & 0xFF); + b[off++] = (byte) ((ii >> 16) & 0xFF); + b[off++] = (byte) ((ii >> 8) & 0xFF); + b[off++] = (byte) (ii & 0xFF); + } + } + } + + public static short bigEndianToShort(byte[] bs) { + return bigEndianToShort(bs, 0); + } + + public static short bigEndianToShort(byte[] bs, int off) { + int n = bs[off] << 8; + ++off; + n |= bs[off] & 0xFF; + return (short) n; + } + + public static byte[] shortToBytes(short n) { + return ByteBuffer.allocate(2).putShort(n).array(); + } + + /** + * Converts string hex representation to data bytes Accepts following hex: - with or without 0x + * prefix + * + * @param data String like '0xa5e..' or just 'a5e..' + * @return decoded bytes array + */ + public static byte[] hexStringToBytes(String data) { + if (data == null) return EMPTY_BYTE_ARRAY; + if (data.startsWith("0x")) data = data.substring(2); + if (data.length() % 2 == 1) data = "0" + data; + return Hex.decode(data); + } + + /** Converts string representation of host/ip to 4-bytes byte[] IPv4 */ + public static byte[] hostToBytes(String ip) { + byte[] bytesIp; + try { + bytesIp = InetAddress.getByName(ip).getAddress(); + } catch (UnknownHostException e) { + bytesIp = new byte[4]; // fall back to invalid 0.0.0.0 address + } + + return bytesIp; + } + + /** Converts 4 bytes IPv4 IP to String representation */ + public static String bytesToIp(byte[] bytesIp) { + + StringBuilder sb = new StringBuilder(); + sb.append(bytesIp[0] & 0xFF); + sb.append("."); + sb.append(bytesIp[1] & 0xFF); + sb.append("."); + sb.append(bytesIp[2] & 0xFF); + sb.append("."); + sb.append(bytesIp[3] & 0xFF); + + String ip = sb.toString(); + return ip; + } + + /** + * Returns a number of zero bits preceding the highest-order ("leftmost") one-bit interpreting + * input array as a big-endian integer value + */ + public static int numberOfLeadingZeros(byte[] bytes) { + + int i = firstNonZeroByte(bytes); + + if (i == -1) { + return bytes.length * 8; + } else { + int byteLeadingZeros = Integer.numberOfLeadingZeros((int) bytes[i] & 0xff) - 24; + return i * 8 + byteLeadingZeros; + } + } + + /** + * Parses fixed number of bytes starting from {@code offset} in {@code input} array. If {@code + * input} has not enough bytes return array will be right padded with zero bytes. I.e. if {@code + * offset} is higher than {@code input.length} then zero byte array of length {@code len} will + * be returned + */ + public static byte[] parseBytes(byte[] input, int offset, int len) { + + if (offset >= input.length || len == 0) return EMPTY_BYTE_ARRAY; + + byte[] bytes = new byte[len]; + System.arraycopy(input, offset, bytes, 0, Math.min(input.length - offset, len)); + return bytes; + } + + /** + * Parses 32-bytes word from given input. Uses {@link #parseBytes(byte[], int, int)} method, + * thus, result will be right-padded with zero bytes if there is not enough bytes in {@code + * input} + * + * @param idx an index of the word starting from {@code 0} + */ + public static byte[] parseWord(byte[] input, int idx) { + return parseBytes(input, 32 * idx, 32); + } + + /** + * Parses 32-bytes word from given input. Uses {@link #parseBytes(byte[], int, int)} method, + * thus, result will be right-padded with zero bytes if there is not enough bytes in {@code + * input} + * + * @param idx an index of the word starting from {@code 0} + * @param offset an offset in {@code input} array to start parsing from + */ + public static byte[] parseWord(byte[] input, int offset, int idx) { + return parseBytes(input, offset + 32 * idx, 32); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Bytes.java b/src/main/java/org/fisco/bcos/web3j/utils/Bytes.java index a66912175..bbc8c5608 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Bytes.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Bytes.java @@ -5,19 +5,19 @@ /** Byte array utility functions. */ public class Bytes { - private Bytes() {} + private Bytes() {} - public static byte[] trimLeadingBytes(byte[] bytes, byte b) { - int offset = 0; - for (; offset < bytes.length - 1; offset++) { - if (bytes[offset] != b) { - break; - } + public static byte[] trimLeadingBytes(byte[] bytes, byte b) { + int offset = 0; + for (; offset < bytes.length - 1; offset++) { + if (bytes[offset] != b) { + break; + } + } + return Arrays.copyOfRange(bytes, offset, bytes.length); } - return Arrays.copyOfRange(bytes, offset, bytes.length); - } - public static byte[] trimLeadingZeroes(byte[] bytes) { - return trimLeadingBytes(bytes, (byte) 0); - } + public static byte[] trimLeadingZeroes(byte[] bytes) { + return trimLeadingBytes(bytes, (byte) 0); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Collection.java b/src/main/java/org/fisco/bcos/web3j/utils/Collection.java index 42b6c4be9..d3a5b2e5f 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Collection.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Collection.java @@ -5,43 +5,43 @@ /** Utility functions for working with Collections. */ public class Collection { - static String[] EMPTY_STRING_ARRAY = {}; + static String[] EMPTY_STRING_ARRAY = {}; - public static String[] tail(String[] args) { - if (args.length == 0) { - return EMPTY_STRING_ARRAY; - } else { - return Arrays.copyOfRange(args, 1, args.length); + public static String[] tail(String[] args) { + if (args.length == 0) { + return EMPTY_STRING_ARRAY; + } else { + return Arrays.copyOfRange(args, 1, args.length); + } } - } - public static T[] create(T... args) { - return args; - } + public static T[] create(T... args) { + return args; + } - public static String join(List list, String separator, Function function) { - String result = ""; - for (int i = 0; i < list.size(); i++) { - result += function.apply(list.get(i)).trim(); - if (i + 1 < list.size()) { - result += separator; - } + public static String join(List list, String separator, Function function) { + String result = ""; + for (int i = 0; i < list.size(); i++) { + result += function.apply(list.get(i)).trim(); + if (i + 1 < list.size()) { + result += separator; + } + } + return result; } - return result; - } - public static String join(List list, String separator) { - String result = ""; - for (int i = 0; i < list.size(); i++) { - result += list.get(i).trim(); - if (i + 1 < list.size()) { - result += separator; - } + public static String join(List list, String separator) { + String result = ""; + for (int i = 0; i < list.size(); i++) { + result += list.get(i).trim(); + if (i + 1 < list.size()) { + result += separator; + } + } + return result; } - return result; - } - public interface Function { - S apply(R r); - } + public interface Function { + S apply(R r); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/CompileSolToJava.java b/src/main/java/org/fisco/bcos/web3j/utils/CompileSolToJava.java index 4bfd95f00..f1f11b4cd 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/CompileSolToJava.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/CompileSolToJava.java @@ -7,7 +7,6 @@ import java.io.File; import java.util.Arrays; - import org.apache.commons.io.FileUtils; import org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator; import org.fisco.bcos.web3j.solidity.compiler.CompilationResult; @@ -15,51 +14,50 @@ public class CompileSolToJava { - public static void main(String[] args) throws Exception { - if (args.length < 1) { - System.out.println("Please provide a package name."); - return; - } + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.out.println("Please provide a package name."); + return; + } - File solFileList = new File("contracts"); - File[] solFiles = solFileList.listFiles(); - if(solFiles.length == 0) - { - System.out.println("The contracts directory is empty."); - return; - } - for (File solFile : solFiles) { - if(!solFile.getName().endsWith(".sol")) - { - continue; - } - SolidityCompiler.Result res = - SolidityCompiler.compile(solFile, true, ABI, BIN, INTERFACE, METADATA); - if("".equals(res.output)) - { - System.out.println("Compile error: " + res.errors); - return; - } - CompilationResult result = CompilationResult.parse(res.output); - String contractname = solFile.getName().split("\\.")[0]; - CompilationResult.ContractMetadata a = result.getContract(solFile.getName().split("\\.")[0]); - FileUtils.writeStringToFile(new File("abi/" + contractname + ".abi"), a.abi); - FileUtils.writeStringToFile(new File("bin/" + contractname + ".bin"), a.bin); - String binFile; - String abiFile; - String tempDirPath = new File("java").getAbsolutePath(); - String packageName = args[0]; - String filename = contractname; - abiFile = "abi/" + filename + ".abi"; - binFile = "bin/" + filename + ".bin"; - SolidityFunctionWrapperGenerator.main( - Arrays.asList( - "-a", abiFile, - "-b", binFile, - "-p", packageName, - "-o", tempDirPath) - .toArray(new String[0])); + File solFileList = new File("contracts"); + File[] solFiles = solFileList.listFiles(); + if (solFiles.length == 0) { + System.out.println("The contracts directory is empty."); + return; + } + for (File solFile : solFiles) { + if (!solFile.getName().endsWith(".sol") || solFile.getName().contains("Lib")) { + continue; + } + SolidityCompiler.Result res = + SolidityCompiler.compile(solFile, true, ABI, BIN, INTERFACE, METADATA); + if ("".equals(res.output)) { + System.out.println("Compile error: " + res.errors); + return; + } + CompilationResult result = CompilationResult.parse(res.output); + String contractname = solFile.getName().split("\\.")[0]; + CompilationResult.ContractMetadata a = + result.getContract(solFile.getName().split("\\.")[0]); + FileUtils.writeStringToFile(new File("abi/" + contractname + ".abi"), a.abi); + FileUtils.writeStringToFile(new File("bin/" + contractname + ".bin"), a.bin); + String binFile; + String abiFile; + String tempDirPath = new File("java").getAbsolutePath(); + String packageName = args[0]; + String filename = contractname; + abiFile = "abi/" + filename + ".abi"; + binFile = "bin/" + filename + ".bin"; + SolidityFunctionWrapperGenerator.main( + Arrays.asList( + "-a", abiFile, + "-b", binFile, + "-p", packageName, + "-o", tempDirPath) + .toArray(new String[0])); + } + System.out.println( + "\nCompile solidity contract files to java contract files successfully!"); } - System.out.println("\nCompile solidity contract files to java contract files successfully!"); - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Console.java b/src/main/java/org/fisco/bcos/web3j/utils/Console.java index a54d0ccb6..0456d76d9 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Console.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Console.java @@ -2,17 +2,17 @@ /** Command line utility classes. */ public class Console { - public static void exitError(String message) { - System.err.println(message); - System.exit(1); - } + public static void exitError(String message) { + System.err.println(message); + System.exit(1); + } - public static void exitError(Throwable throwable) { - exitError(throwable.getMessage()); - } + public static void exitError(Throwable throwable) { + exitError(throwable.getMessage()); + } - public static void exitSuccess(String message) { - System.out.println(message); - System.exit(0); - } + public static void exitSuccess(String message) { + System.out.println(message); + System.exit(0); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Convert.java b/src/main/java/org/fisco/bcos/web3j/utils/Convert.java index eb3853254..13c05e1ec 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Convert.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Convert.java @@ -4,62 +4,62 @@ /** Ethereum unit conversion functions. */ public final class Convert { - private Convert() {} + private Convert() {} - public static BigDecimal fromWei(String number, Unit unit) { - return fromWei(new BigDecimal(number), unit); - } + public static BigDecimal fromWei(String number, Unit unit) { + return fromWei(new BigDecimal(number), unit); + } - public static BigDecimal fromWei(BigDecimal number, Unit unit) { - return number.divide(unit.getWeiFactor()); - } + public static BigDecimal fromWei(BigDecimal number, Unit unit) { + return number.divide(unit.getWeiFactor()); + } - public static BigDecimal toWei(String number, Unit unit) { - return toWei(new BigDecimal(number), unit); - } + public static BigDecimal toWei(String number, Unit unit) { + return toWei(new BigDecimal(number), unit); + } - public static BigDecimal toWei(BigDecimal number, Unit unit) { - return number.multiply(unit.getWeiFactor()); - } + public static BigDecimal toWei(BigDecimal number, Unit unit) { + return number.multiply(unit.getWeiFactor()); + } - public enum Unit { - WEI("wei", 0), - KWEI("kwei", 3), - MWEI("mwei", 6), - GWEI("gwei", 9), - SZABO("szabo", 12), - FINNEY("finney", 15), - ETHER("ether", 18), - KETHER("kether", 21), - METHER("mether", 24), - GETHER("gether", 27); + public enum Unit { + WEI("wei", 0), + KWEI("kwei", 3), + MWEI("mwei", 6), + GWEI("gwei", 9), + SZABO("szabo", 12), + FINNEY("finney", 15), + ETHER("ether", 18), + KETHER("kether", 21), + METHER("mether", 24), + GETHER("gether", 27); - private String name; - private BigDecimal weiFactor; + private String name; + private BigDecimal weiFactor; - Unit(String name, int factor) { - this.name = name; - this.weiFactor = BigDecimal.TEN.pow(factor); - } + Unit(String name, int factor) { + this.name = name; + this.weiFactor = BigDecimal.TEN.pow(factor); + } - public BigDecimal getWeiFactor() { - return weiFactor; - } + public BigDecimal getWeiFactor() { + return weiFactor; + } - @Override - public String toString() { - return name; - } + @Override + public String toString() { + return name; + } - public static Unit fromString(String name) { - if (name != null) { - for (Unit unit : Unit.values()) { - if (name.equalsIgnoreCase(unit.name)) { - return unit; - } + public static Unit fromString(String name) { + if (name != null) { + for (Unit unit : Unit.values()) { + if (name.equalsIgnoreCase(unit.name)) { + return unit; + } + } + } + return Unit.valueOf(name); } - } - return Unit.valueOf(name); } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Files.java b/src/main/java/org/fisco/bcos/web3j/utils/Files.java index ef66eea45..2264d8d6e 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Files.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Files.java @@ -8,29 +8,29 @@ /** File utility functions. */ public class Files { - static Logger logger = LoggerFactory.getLogger(Files.class); + static Logger logger = LoggerFactory.getLogger(Files.class); - private Files() {} + private Files() {} - public static byte[] readBytes(File file) throws IOException { - byte[] bytes = new byte[(int) file.length()]; - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(file); - int count = fileInputStream.read(bytes); - logger.debug("readBytes count :", count); - } catch (Exception e) { - logger.error("readBytes error :", e); - throw e; - } finally { - if (fileInputStream != null) { - fileInputStream.close(); - } + public static byte[] readBytes(File file) throws IOException { + byte[] bytes = new byte[(int) file.length()]; + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + int count = fileInputStream.read(bytes); + logger.debug("readBytes count :", count); + } catch (Exception e) { + logger.error("readBytes error :", e); + throw e; + } finally { + if (fileInputStream != null) { + fileInputStream.close(); + } + } + return bytes; } - return bytes; - } - public static String readString(File file) throws IOException { - return new String(readBytes(file)); - } + public static String readString(File file) throws IOException { + return new String(readBytes(file)); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Flowables.java b/src/main/java/org/fisco/bcos/web3j/utils/Flowables.java index a7735beb9..75adb7d88 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Flowables.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Flowables.java @@ -7,54 +7,56 @@ /** Flowable utility functions. */ public class Flowables { - public static Flowable range(final BigInteger startValue, final BigInteger endValue) { - return range(startValue, endValue, true); - } - - /** - * Simple {@link Flowable} implementation to emit a range of BigInteger values. - * - * @param startValue first value to emit in range - * @param endValue final value to emit in range - * @param ascending direction to iterate through range - * @return a {@link Flowable} instance to emit this range of values - */ - public static Flowable range( - final BigInteger startValue, final BigInteger endValue, final boolean ascending) { - if (startValue.compareTo(BigInteger.ZERO) < 0) { - throw new IllegalArgumentException("Negative start index cannot be used"); - } else if (startValue.compareTo(endValue) > 0) { - throw new IllegalArgumentException("Negative start index cannot be greater then end index"); + public static Flowable range( + final BigInteger startValue, final BigInteger endValue) { + return range(startValue, endValue, true); } - if (ascending) { - return Flowable.create( - subscriber -> { - for (BigInteger i = startValue; - i.compareTo(endValue) < 1 && !subscriber.isCancelled(); - i = i.add(BigInteger.ONE)) { - subscriber.onNext(i); - } + /** + * Simple {@link Flowable} implementation to emit a range of BigInteger values. + * + * @param startValue first value to emit in range + * @param endValue final value to emit in range + * @param ascending direction to iterate through range + * @return a {@link Flowable} instance to emit this range of values + */ + public static Flowable range( + final BigInteger startValue, final BigInteger endValue, final boolean ascending) { + if (startValue.compareTo(BigInteger.ZERO) < 0) { + throw new IllegalArgumentException("Negative start index cannot be used"); + } else if (startValue.compareTo(endValue) > 0) { + throw new IllegalArgumentException( + "Negative start index cannot be greater then end index"); + } + + if (ascending) { + return Flowable.create( + subscriber -> { + for (BigInteger i = startValue; + i.compareTo(endValue) < 1 && !subscriber.isCancelled(); + i = i.add(BigInteger.ONE)) { + subscriber.onNext(i); + } - if (!subscriber.isCancelled()) { - subscriber.onComplete(); - } - }, - BackpressureStrategy.BUFFER); - } else { - return Flowable.create( - subscriber -> { - for (BigInteger i = endValue; - i.compareTo(startValue) > -1 && !subscriber.isCancelled(); - i = i.subtract(BigInteger.ONE)) { - subscriber.onNext(i); - } + if (!subscriber.isCancelled()) { + subscriber.onComplete(); + } + }, + BackpressureStrategy.BUFFER); + } else { + return Flowable.create( + subscriber -> { + for (BigInteger i = endValue; + i.compareTo(startValue) > -1 && !subscriber.isCancelled(); + i = i.subtract(BigInteger.ONE)) { + subscriber.onNext(i); + } - if (!subscriber.isCancelled()) { - subscriber.onComplete(); - } - }, - BackpressureStrategy.BUFFER); + if (!subscriber.isCancelled()) { + subscriber.onComplete(); + } + }, + BackpressureStrategy.BUFFER); + } } - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Numeric.java b/src/main/java/org/fisco/bcos/web3j/utils/Numeric.java index 81c79c2af..f6efc3e1b 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Numeric.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Numeric.java @@ -13,218 +13,220 @@ */ public final class Numeric { - private static final String HEX_PREFIX = "0x"; + private static final String HEX_PREFIX = "0x"; - private Numeric() {} + private Numeric() {} - public static String encodeQuantity(BigInteger value) { - if (value.signum() != -1) { - return HEX_PREFIX + value.toString(16); - } else { - throw new MessageEncodingException("Negative values are not supported"); + public static String encodeQuantity(BigInteger value) { + if (value.signum() != -1) { + return HEX_PREFIX + value.toString(16); + } else { + throw new MessageEncodingException("Negative values are not supported"); + } } - } - public static BigInteger decodeQuantity(String value) { - if (!isValidHexQuantity(value)) { - try { - return new BigInteger(value); - } catch (NumberFormatException e) { - throw new MessageDecodingException("Negative ", e); - } - } else { - try { - return new BigInteger(value.substring(2), 16); - } catch (NumberFormatException e) { - throw new MessageDecodingException("value is not a hex number or a decimal number"); - } + public static BigInteger decodeQuantity(String value) { + if (!isValidHexQuantity(value)) { + try { + if (value == null) return new BigInteger("0"); + return new BigInteger(value); + } catch (NumberFormatException e) { + throw new MessageDecodingException("Negative ", e); + } + } else { + try { + return new BigInteger(value.substring(2), 16); + } catch (NumberFormatException e) { + throw new MessageDecodingException("value is not a hex number or a decimal number"); + } + } } - } - private static boolean isValidHexQuantity(String value) { - if (value == null) { - return false; - } + private static boolean isValidHexQuantity(String value) { + if (value == null) { + return false; + } - if (value.length() < 3) { - return false; - } + if (value.length() < 3) { + return false; + } - if (!value.startsWith(HEX_PREFIX)) { - return false; - } + if (!value.startsWith(HEX_PREFIX)) { + return false; + } - // If TestRpc resolves the following issue, we can reinstate this code - // https://github.com/ethereumjs/testrpc/issues/220 - // if (value.length() > 3 && value.charAt(2) == '0') { - // return false; - // } + // If TestRpc resolves the following issue, we can reinstate this code + // https://github.com/ethereumjs/testrpc/issues/220 + // if (value.length() > 3 && value.charAt(2) == '0') { + // return false; + // } - return true; - } + return true; + } - public static String cleanHexPrefix(String input) { - if (containsHexPrefix(input)) { - return input.substring(2); - } else { - return input; + public static String cleanHexPrefix(String input) { + if (containsHexPrefix(input)) { + return input.substring(2); + } else { + return input; + } } - } - public static String prependHexPrefix(String input) { - if (!containsHexPrefix(input)) { - return HEX_PREFIX + input; - } else { - return input; + public static String prependHexPrefix(String input) { + if (!containsHexPrefix(input)) { + return HEX_PREFIX + input; + } else { + return input; + } } - } - public static boolean containsHexPrefix(String input) { - return !Strings.isEmpty(input) - && input.length() > 1 - && input.charAt(0) == '0' - && input.charAt(1) == 'x'; - } + public static boolean containsHexPrefix(String input) { + return !Strings.isEmpty(input) + && input.length() > 1 + && input.charAt(0) == '0' + && input.charAt(1) == 'x'; + } - public static BigInteger toBigInt(byte[] value, int offset, int length) { - return toBigInt((Arrays.copyOfRange(value, offset, offset + length))); - } + public static BigInteger toBigInt(byte[] value, int offset, int length) { + return toBigInt((Arrays.copyOfRange(value, offset, offset + length))); + } - public static BigInteger toBigInt(byte[] value) { - return new BigInteger(1, value); - } + public static BigInteger toBigInt(byte[] value) { + return new BigInteger(1, value); + } - public static BigInteger toBigInt(String hexValue) { - String cleanValue = cleanHexPrefix(hexValue); - return toBigIntNoPrefix(cleanValue); - } + public static BigInteger toBigInt(String hexValue) { + String cleanValue = cleanHexPrefix(hexValue); + return toBigIntNoPrefix(cleanValue); + } - public static BigInteger toBigIntNoPrefix(String hexValue) { - return new BigInteger(hexValue, 16); - } + public static BigInteger toBigIntNoPrefix(String hexValue) { + return new BigInteger(hexValue, 16); + } - public static String toHexStringWithPrefix(BigInteger value) { - return HEX_PREFIX + value.toString(16); - } + public static String toHexStringWithPrefix(BigInteger value) { + return HEX_PREFIX + value.toString(16); + } - public static String toHexStringNoPrefix(BigInteger value) { - return value.toString(16); - } + public static String toHexStringNoPrefix(BigInteger value) { + return value.toString(16); + } - public static String toHexStringNoPrefix(byte[] input) { - return toHexString(input, 0, input.length, false); - } + public static String toHexStringNoPrefix(byte[] input) { + return toHexString(input, 0, input.length, false); + } - public static String toHexStringWithPrefixZeroPadded(BigInteger value, int size) { - return toHexStringZeroPadded(value, size, true); - } + public static String toHexStringWithPrefixZeroPadded(BigInteger value, int size) { + return toHexStringZeroPadded(value, size, true); + } - public static String toHexStringWithPrefixSafe(BigInteger value) { - String result = toHexStringNoPrefix(value); - if (result.length() < 2) { - result = Strings.zeros(1) + result; + public static String toHexStringWithPrefixSafe(BigInteger value) { + String result = toHexStringNoPrefix(value); + if (result.length() < 2) { + result = Strings.zeros(1) + result; + } + return HEX_PREFIX + result; } - return HEX_PREFIX + result; - } - public static String toHexStringNoPrefixZeroPadded(BigInteger value, int size) { - return toHexStringZeroPadded(value, size, false); - } + public static String toHexStringNoPrefixZeroPadded(BigInteger value, int size) { + return toHexStringZeroPadded(value, size, false); + } - private static String toHexStringZeroPadded(BigInteger value, int size, boolean withPrefix) { - String result = toHexStringNoPrefix(value); + private static String toHexStringZeroPadded(BigInteger value, int size, boolean withPrefix) { + String result = toHexStringNoPrefix(value); - int length = result.length(); - if (length > size) { - throw new UnsupportedOperationException("Value " + result + "is larger then length " + size); - } else if (value.signum() < 0) { - throw new UnsupportedOperationException("Value cannot be negative"); - } + int length = result.length(); + if (length > size) { + throw new UnsupportedOperationException( + "Value " + result + "is larger then length " + size); + } else if (value.signum() < 0) { + throw new UnsupportedOperationException("Value cannot be negative"); + } - if (length < size) { - result = Strings.zeros(size - length) + result; - } + if (length < size) { + result = Strings.zeros(size - length) + result; + } - if (withPrefix) { - return HEX_PREFIX + result; - } else { - return result; + if (withPrefix) { + return HEX_PREFIX + result; + } else { + return result; + } } - } - public static byte[] toBytesPadded(BigInteger value, int length) { - byte[] result = new byte[length]; - byte[] bytes = value.toByteArray(); + public static byte[] toBytesPadded(BigInteger value, int length) { + byte[] result = new byte[length]; + byte[] bytes = value.toByteArray(); - int bytesLength; - int srcOffset; - if (bytes[0] == 0) { - bytesLength = bytes.length - 1; - srcOffset = 1; - } else { - bytesLength = bytes.length; - srcOffset = 0; - } + int bytesLength; + int srcOffset; + if (bytes[0] == 0) { + bytesLength = bytes.length - 1; + srcOffset = 1; + } else { + bytesLength = bytes.length; + srcOffset = 0; + } + + if (bytesLength > length) { + throw new RuntimeException("Input is too large to put in byte array of size " + length); + } - if (bytesLength > length) { - throw new RuntimeException("Input is too large to put in byte array of size " + length); + int destOffset = length - bytesLength; + System.arraycopy(bytes, srcOffset, result, destOffset, bytesLength); + return result; } - int destOffset = length - bytesLength; - System.arraycopy(bytes, srcOffset, result, destOffset, bytesLength); - return result; - } + public static byte[] hexStringToByteArray(String input) { + String cleanInput = cleanHexPrefix(input); - public static byte[] hexStringToByteArray(String input) { - String cleanInput = cleanHexPrefix(input); + int len = cleanInput.length(); - int len = cleanInput.length(); + if (len == 0) { + return new byte[] {}; + } - if (len == 0) { - return new byte[] {}; - } + byte[] data; + int startIdx; + if (len % 2 != 0) { + data = new byte[(len / 2) + 1]; + data[0] = (byte) Character.digit(cleanInput.charAt(0), 16); + startIdx = 1; + } else { + data = new byte[len / 2]; + startIdx = 0; + } - byte[] data; - int startIdx; - if (len % 2 != 0) { - data = new byte[(len / 2) + 1]; - data[0] = (byte) Character.digit(cleanInput.charAt(0), 16); - startIdx = 1; - } else { - data = new byte[len / 2]; - startIdx = 0; + for (int i = startIdx; i < len; i += 2) { + data[(i + 1) / 2] = + (byte) + ((Character.digit(cleanInput.charAt(i), 16) << 4) + + Character.digit(cleanInput.charAt(i + 1), 16)); + } + return data; } - for (int i = startIdx; i < len; i += 2) { - data[(i + 1) / 2] = - (byte) - ((Character.digit(cleanInput.charAt(i), 16) << 4) - + Character.digit(cleanInput.charAt(i + 1), 16)); - } - return data; - } + public static String toHexString(byte[] input, int offset, int length, boolean withPrefix) { + StringBuilder stringBuilder = new StringBuilder(); + if (withPrefix) { + stringBuilder.append("0x"); + } + for (int i = offset; i < offset + length; i++) { + stringBuilder.append(String.format("%02x", input[i] & 0xFF)); + } - public static String toHexString(byte[] input, int offset, int length, boolean withPrefix) { - StringBuilder stringBuilder = new StringBuilder(); - if (withPrefix) { - stringBuilder.append("0x"); - } - for (int i = offset; i < offset + length; i++) { - stringBuilder.append(String.format("%02x", input[i] & 0xFF)); + return stringBuilder.toString(); } - return stringBuilder.toString(); - } - - public static String toHexString(byte[] input) { - return toHexString(input, 0, input.length, true); - } + public static String toHexString(byte[] input) { + return toHexString(input, 0, input.length, true); + } - public static byte asByte(int m, int n) { - return (byte) ((m << 4) | n); - } + public static byte asByte(int m, int n) { + return (byte) ((m << 4) | n); + } - public static boolean isIntegerValue(BigDecimal value) { - return value.signum() == 0 || value.scale() <= 0 || value.stripTrailingZeros().scale() <= 0; - } + public static boolean isIntegerValue(BigDecimal value) { + return value.signum() == 0 || value.scale() <= 0 || value.stripTrailingZeros().scale() <= 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Strings.java b/src/main/java/org/fisco/bcos/web3j/utils/Strings.java index 3376836e4..f51b1f753 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Strings.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Strings.java @@ -5,42 +5,42 @@ /** String utility functions. */ public class Strings { - private Strings() {} - - public static String toCsv(List src) { - // return src == null ? null : String.join(", ", src.toArray(new String[0])); - return join(src, ", "); - } - - public static String join(List src, String delimiter) { - return src == null ? null : String.join(delimiter, src.toArray(new String[0])); - } - - public static String capitaliseFirstLetter(String string) { - if (string == null || string.length() == 0) { - return string; - } else { - return string.substring(0, 1).toUpperCase() + string.substring(1); + private Strings() {} + + public static String toCsv(List src) { + // return src == null ? null : String.join(", ", src.toArray(new String[0])); + return join(src, ", "); + } + + public static String join(List src, String delimiter) { + return src == null ? null : String.join(delimiter, src.toArray(new String[0])); + } + + public static String capitaliseFirstLetter(String string) { + if (string == null || string.length() == 0) { + return string; + } else { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } } - } - public static String lowercaseFirstLetter(String string) { - if (string == null || string.length() == 0) { - return string; - } else { - return string.substring(0, 1).toLowerCase() + string.substring(1); + public static String lowercaseFirstLetter(String string) { + if (string == null || string.length() == 0) { + return string; + } else { + return string.substring(0, 1).toLowerCase() + string.substring(1); + } } - } - public static String zeros(int n) { - return repeat('0', n); - } + public static String zeros(int n) { + return repeat('0', n); + } - public static String repeat(char value, int n) { - return new String(new char[n]).replace("\0", String.valueOf(value)); - } + public static String repeat(char value, int n) { + return new String(new char[n]).replace("\0", String.valueOf(value)); + } - public static boolean isEmpty(String s) { - return s == null || s.length() == 0; - } + public static boolean isEmpty(String s) { + return s == null || s.length() == 0; + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/TxHashVerifier.java b/src/main/java/org/fisco/bcos/web3j/utils/TxHashVerifier.java index 9c34f9dea..d194ef521 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/TxHashVerifier.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/TxHashVerifier.java @@ -1,7 +1,7 @@ package org.fisco.bcos.web3j.utils; public class TxHashVerifier { - public boolean verify(String hash1, String hash2) { - return hash1.equals(hash2); - } + public boolean verify(String hash1, String hash2) { + return hash1.equals(hash2); + } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Version.java b/src/main/java/org/fisco/bcos/web3j/utils/Version.java index 950e0bce0..a74d594ea 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Version.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Version.java @@ -7,32 +7,32 @@ /** Build version utility method. */ public class Version { - private Version() {} - - public static final String DEFAULT = "none"; - - private static final String TIMESTAMP = "timestamp"; - private static final String VERSION = "version"; - - public static String getVersion() throws IOException { - return loadProperties().getProperty(VERSION); - } - - public static String getTimestamp() throws IOException { - return loadProperties().getProperty(TIMESTAMP); - } - - private static Properties loadProperties() throws IOException { - Properties properties = new Properties(); - InputStream in = null; - try { - in = Version.class.getResourceAsStream("/version.properties"); - properties.load(in); - } finally { - if (in != null) { - in.close(); - } + private Version() {} + + public static final String DEFAULT = "none"; + + private static final String TIMESTAMP = "timestamp"; + private static final String VERSION = "version"; + + public static String getVersion() throws IOException { + return loadProperties().getProperty(VERSION); + } + + public static String getTimestamp() throws IOException { + return loadProperties().getProperty(TIMESTAMP); + } + + private static Properties loadProperties() throws IOException { + Properties properties = new Properties(); + InputStream in = null; + try { + in = Version.class.getResourceAsStream("/version.properties"); + properties.load(in); + } finally { + if (in != null) { + in.close(); + } + } + return properties; } - return properties; - } } diff --git a/src/main/java/org/fisco/bcos/web3j/utils/Web3AsyncThreadPoolSize.java b/src/main/java/org/fisco/bcos/web3j/utils/Web3AsyncThreadPoolSize.java index 8e718ee11..f12bf5e1f 100644 --- a/src/main/java/org/fisco/bcos/web3j/utils/Web3AsyncThreadPoolSize.java +++ b/src/main/java/org/fisco/bcos/web3j/utils/Web3AsyncThreadPoolSize.java @@ -2,11 +2,11 @@ /** Created by mingzhenliu on 2018/8/24. */ public class Web3AsyncThreadPoolSize { - public static Integer web3AsyncPoolSize = 2000; - public static Integer web3AsyncCorePoolSize = 2000; + public static Integer web3AsyncPoolSize = 2000; + public static Integer web3AsyncCorePoolSize = 2000; - public Web3AsyncThreadPoolSize(int web3AsyncPoolSize, int web3AsyncCorePoolSize) { - this.web3AsyncPoolSize = web3AsyncPoolSize; - this.web3AsyncCorePoolSize = web3AsyncCorePoolSize; - } + public Web3AsyncThreadPoolSize(int web3AsyncPoolSize, int web3AsyncCorePoolSize) { + this.web3AsyncPoolSize = web3AsyncPoolSize; + this.web3AsyncCorePoolSize = web3AsyncCorePoolSize; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/BasicTest.java b/src/test/java/org/fisco/bcos/channel/test/BasicTest.java deleted file mode 100644 index f3c3cf606..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/BasicTest.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.fisco.bcos.channel.test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.List; -import org.fisco.bcos.channel.test.contract.Ok; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.fisco.bcos.web3j.protocol.core.methods.response.*; -import org.fisco.bcos.web3j.tx.Contract; -import org.fisco.bcos.web3j.tx.ExtendedRawTransactionManager; -import org.junit.Ignore; -import org.junit.Test; - -public class BasicTest extends TestBase { - private static BigInteger gasPrice = new BigInteger("300000000"); - private static BigInteger gasLimit = new BigInteger("300000000"); - - @Ignore - @Test - public void pbftViewTest() throws Exception { - int i = web3j.getPbftView().send().getPbftView().intValue(); - System.out.println(i); - assertNotNull(i > 0); - } - - @Test - public void consensusStatusTest() throws Exception { - System.out.println(web3j.getConsensusStatus().sendForReturnString()); - assertNotNull(web3j.getConsensusStatus().sendForReturnString()); - } - - @Test - public void syncTest() throws Exception { - System.out.println(web3j.getSyncStatus().send().isSyncing()); - assertNotNull(web3j.getSyncStatus().send().isSyncing()); - } - - @Test - public void versionTest() throws Exception { - String web3ClientVersion = web3j.getNodeVersion().sendForReturnString(); - System.out.println(web3ClientVersion); - assertNotNull(web3ClientVersion); - } - - // getPeers - @Ignore - @Test - public void peersTest() throws Exception { - Peers ethPeers = web3j.getPeers().send(); - System.out.println(ethPeers.getValue().get(0).getNodeID()); - assertNotNull(ethPeers); - } - - @Test - public void groupPeersTest() throws Exception { - GroupPeers groupPeers = web3j.getGroupPeers().send(); - groupPeers.getGroupPeers().stream().forEach(System.out::println); - assertNotNull(groupPeers.getResult()); - } - - @Test - public void groupListTest() throws Exception { - GroupList groupList = web3j.getGroupList().send(); - groupList.getGroupList().stream().forEach(System.out::println); - assertTrue((groupList.getGroupList().size() > 0)); - } - - @Ignore - @Test - public void getTransactionByBlockNumberAndIndexTest() throws IOException { - Transaction transaction = - web3j - .getTransactionByBlockNumberAndIndex( - DefaultBlockParameter.valueOf(new BigInteger("1")), new BigInteger("0")) - .send() - .getTransaction() - .get(); - assertTrue(transaction.getBlockNumber().intValue() == 1); - } - - @Test - public void basicTest() throws Exception { - try { - testDeployContract(web3j, credentials); - } catch (Exception e) { - e.printStackTrace(); - throw new Exception("Execute basic test failed"); - } - } - - @Test - public void basicExtendedTransactionTest() throws Exception { - try { - testExtendedTransactionDeployContract(web3j, credentials); - } catch (Exception e) { - e.printStackTrace(); - throw new Exception("Execute basic test failed"); - } - } - - private void testDeployContract(Web3j web3j, Credentials credentials) throws Exception { - Ok okDemo = Ok.deploy(web3j, credentials, gasPrice, gasLimit).send(); - if (okDemo != null) { - System.out.println( - "####get nonce from Block: " - + web3j - .getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("0")), true) - .send() - .getBlock() - .getNonce()); - System.out.println( - "####get block number by index from Block: " - + web3j - .getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("1")), true) - .send() - .getBlock() - .getNumber()); - - System.out.println("####contract address is: " + okDemo.getContractAddress()); - // TransactionReceipt receipt = okDemo.trans(new - // BigInteger("4")).sendAsync().get(60000, TimeUnit.MILLISECONDS); - Ok okDemo1= Ok.load(okDemo.getContractAddress(),web3j,credentials,gasPrice,gasLimit); - okDemo1.trans(new BigInteger("4")).send(); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - List events = okDemo.getTransEventEvents(receipt); - events.stream().forEach(System.out::println); - - System.out.println("###callback trans success"); - - System.out.println( - "####get block number from TransactionReceipt: " + receipt.getBlockNumber()); - System.out.println( - "####get transaction index from TransactionReceipt: " + receipt.getTransactionIndex()); - System.out.println("####get gas used from TransactionReceipt: " + receipt.getGasUsed()); - // System.out.println("####get cumulative gas used from TransactionReceipt: " + - // receipt.getCumulativeGasUsed()); - - BigInteger toBalance = okDemo.get().send(); - System.out.println("============to balance:" + toBalance.intValue()); - } - } - - private void testExtendedTransactionDeployContract(Web3j web3j, Credentials credentials) throws Exception { - - Ok okDemo = Ok.deploy(web3j, credentials, gasPrice, gasLimit).send(); - - - if (okDemo != null) { - System.out.println( - "####get nonce from Block: " - + web3j - .getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("0")), true) - .send() - .getBlock() - .getNonce()); - System.out.println( - "####get block number by index from Block: " - + web3j - .getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("1")), true) - .send() - .getBlock() - .getNumber()); - - System.out.println("####contract address is: " + okDemo.getContractAddress()); - // TransactionReceipt receipt = okDemo.trans(new - // BigInteger("4")).sendAsync().get(60000, TimeUnit.MILLISECONDS); - Ok okDemo1= Ok.load(okDemo.getContractAddress(),web3j,credentials,gasPrice,gasLimit); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - okDemo1.trans(new BigInteger("4")).send(); - List events = okDemo.getTransEventEvents(receipt); - events.stream().forEach(System.out::println); - - System.out.println("###callback trans success"); - - System.out.println( - "####get block number from TransactionReceipt: " + receipt.getBlockNumber()); - System.out.println( - "####get transaction index from TransactionReceipt: " + receipt.getTransactionIndex()); - System.out.println("####get gas used from TransactionReceipt: " + receipt.getGasUsed()); - // System.out.println("####get cumulative gas used from TransactionReceipt: " + - // receipt.getCumulativeGasUsed()); - - BigInteger toBalance = okDemo.get().send(); - System.out.println("============to balance:" + toBalance.intValue()); - } - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/TestOkTransaction.java b/src/test/java/org/fisco/bcos/channel/test/TestOkTransaction.java deleted file mode 100644 index a181ce11e..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/TestOkTransaction.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.fisco.bcos.channel.test; - -import static java.lang.System.exit; - -import java.math.BigInteger; -import org.fisco.bcos.channel.client.Service; -import org.fisco.bcos.channel.test.contract.Ok; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -public class TestOkTransaction { - public static void main(String[] args) throws Exception { - - String groupId = args[0]; - String method = args[1]; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - channelEthereumService.setTimeout(10000); - Web3j web3 = Web3j.build(channelEthereumService, service.getGroupId()); - BigInteger gasPrice = new BigInteger("300000000"); - BigInteger gasLimit = new BigInteger("300000000"); - BigInteger initialWeiValue = new BigInteger("0"); - Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - if ("deploy".equals(method)) { - System.out.println("####create credential succ, begin deploy contract"); - - final Ok okDemo = Ok.deploy(web3, credentials, gasPrice, gasLimit).send(); - if (okDemo != null) { - System.out.println("deploy success , contract address is: " + okDemo.getContractAddress()); - } - } - if ("transaction".equals(method)) { - String address = args[2]; - Ok okDemo = Ok.load(address, web3, credentials, gasPrice, gasLimit); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - System.out.println("transaction success , receipt is " + receipt.getTransactionHash()); - } - exit(0); - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/account/AccountTest.java b/src/test/java/org/fisco/bcos/channel/test/account/AccountTest.java new file mode 100644 index 000000000..8d9102d8a --- /dev/null +++ b/src/test/java/org/fisco/bcos/channel/test/account/AccountTest.java @@ -0,0 +1,66 @@ +package org.fisco.bcos.channel.test.account; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import org.bouncycastle.jce.interfaces.ECPublicKey; +import org.fisco.bcos.channel.client.P12Manager; +import org.fisco.bcos.channel.client.PEMManager; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.crypto.ECKeyPair; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class AccountTest { + private static Logger logger = LoggerFactory.getLogger(AccountTest.class); + + // openssl pkcs12 -export -name client -in "$node_dir/data/node.crt" -inkey + // "$node_dir/data/node.key" -out "$node_dir/keystore.p12" + + public final String PRIVATE_KEY = + "bc516b2600eec3a216f457dc14cf83a01ed22d0fc2149fc911dc2ec486fe57a3"; + public final String PUBLIC_KEY = + "dbbfee4f76f5a3bc3dbc2e6127c4a1f50b7614bff4138a44a79aed3d42f67f9c7aa70570205f9b60a5888c6415b6a830012677b4415a79ccd1533fe5637861df"; + public final String ADDRESS = "0x0fc3c4bb89bd90299db4c62be0174c4966286c00"; + + @Test + public void accountTest() + throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, + InvalidKeySpecException, NoSuchProviderException { + ApplicationContext context = + new ClassPathXmlApplicationContext( + "classpath:applicationContext-keystore-sample.xml"); + // test p12 + P12Manager p12 = context.getBean(P12Manager.class); + ECKeyPair p12KeyPair = p12.getECKeyPair(p12.getPassword()); + assertEquals(p12KeyPair.getPrivateKey().toString(16), PRIVATE_KEY); + assertEquals(p12KeyPair.getPublicKey().toString(16), PUBLIC_KEY); + + ECPublicKey publicKey = (ECPublicKey) p12.getPublicKey(p12.getPassword()); + byte[] publicKeyBytes = publicKey.getQ().getEncoded(false); + BigInteger publicKeyValue = + new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length)); + assertEquals(publicKeyValue.toString(16), PUBLIC_KEY); + + Credentials credentials = Credentials.create(p12KeyPair); + assertEquals(credentials.getAddress(), ADDRESS); + + // test pem + PEMManager pem = context.getBean(PEMManager.class); + ECKeyPair pemKeyPair = pem.getECKeyPair(); + assertEquals(pemKeyPair.getPrivateKey().toString(16), PRIVATE_KEY); + assertEquals(pemKeyPair.getPublicKey().toString(16), PUBLIC_KEY); + + Credentials credentialsPEM = Credentials.create(pemKeyPair); + assertEquals(credentialsPEM.getAddress(), ADDRESS); + } +} diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Client.java b/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Client.java index bad84ae04..7f1558144 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Client.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Client.java @@ -2,7 +2,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; - import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.channel.dto.ChannelRequest; import org.fisco.bcos.channel.dto.ChannelResponse; @@ -12,62 +11,62 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class Channel2Client { - static Logger logger = LoggerFactory.getLogger(Channel2Client.class); + static Logger logger = LoggerFactory.getLogger(Channel2Client.class); - public static void main(String[] args) throws Exception { - if (args.length < 2) { - System.out.println("param: target topic total number of request"); - return; - } - String topic = args[0]; - Integer count = Integer.parseInt(args[1]); + public static void main(String[] args) throws Exception { + if (args.length < 2) { + System.out.println("param: target topic total number of request"); + return; + } + String topic = args[0]; + Integer count = Integer.parseInt(args[1]); - DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - logger.debug("init client"); + logger.debug("init client"); - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); + Service service = context.getBean(Service.class); + service.run(); - System.out.println("3s ..."); - Thread.sleep(1000); - System.out.println("2s ..."); - Thread.sleep(1000); - System.out.println("1s ..."); - Thread.sleep(1000); + System.out.println("3s ..."); + Thread.sleep(1000); + System.out.println("2s ..."); + Thread.sleep(1000); + System.out.println("1s ..."); + Thread.sleep(1000); - System.out.println("start test"); - System.out.println("==================================================================="); + System.out.println("start test"); + System.out.println("==================================================================="); - for (Integer i = 0; i < count; ++i) { - Thread.sleep(2000); - ChannelRequest request = new ChannelRequest(); - request.setToTopic(topic); - request.setMessageID(service.newSeq()); - request.setTimeout(5000); + for (Integer i = 0; i < count; ++i) { + Thread.sleep(2000); + ChannelRequest request = new ChannelRequest(); + request.setToTopic(topic); + request.setMessageID(service.newSeq()); + request.setTimeout(5000); - request.setContent("request seq:" + request.getMessageID()); + request.setContent("request seq:" + request.getMessageID()); - System.out.println( - df.format(LocalDateTime.now()) - + " request seq:" - + String.valueOf(request.getMessageID()) - + ", Content:" - + request.getContent()); + System.out.println( + df.format(LocalDateTime.now()) + + " request seq:" + + String.valueOf(request.getMessageID()) + + ", Content:" + + request.getContent()); - ChannelResponse response = service.sendChannelMessage2(request); + ChannelResponse response = service.sendChannelMessage2(request); - System.out.println( - df.format(LocalDateTime.now()) - + "response seq:" - + String.valueOf(response.getMessageID()) - + ", ErrorCode:" - + response.getErrorCode() - + ", Content:" - + response.getContent()); + System.out.println( + df.format(LocalDateTime.now()) + + "response seq:" + + String.valueOf(response.getMessageID()) + + ", ErrorCode:" + + response.getErrorCode() + + ", Content:" + + response.getContent()); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Server.java b/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Server.java index ebc87ffda..4070bf895 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Server.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/Channel2Server.java @@ -9,41 +9,41 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class Channel2Server { - static Logger logger = LoggerFactory.getLogger(Channel2Server.class); + static Logger logger = LoggerFactory.getLogger(Channel2Server.class); - public static void main(String[] args) throws Exception { - if (args.length < 1) { - System.out.println("Param: topic"); - return; - } + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.out.println("Param: topic"); + return; + } - String topic = args[0]; + String topic = args[0]; - logger.debug("init Server"); + logger.debug("init Server"); - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); + Service service = context.getBean(Service.class); - Set topics = new HashSet(); - topics.add(topic); - service.setTopics(topics); + Set topics = new HashSet(); + topics.add(topic); + service.setTopics(topics); - PushCallback cb = new PushCallback(); + PushCallback cb = new PushCallback(); - service.setPushCallback(cb); + service.setPushCallback(cb); - System.out.println("3s..."); - Thread.sleep(1000); - System.out.println("2s..."); - Thread.sleep(1000); - System.out.println("1s..."); - Thread.sleep(1000); + System.out.println("3s..."); + Thread.sleep(1000); + System.out.println("2s..."); + Thread.sleep(1000); + System.out.println("1s..."); + Thread.sleep(1000); - System.out.println("start test"); - System.out.println("==================================================================="); + System.out.println("start test"); + System.out.println("==================================================================="); - service.run(); - } + service.run(); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCallback.java b/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCallback.java index 99ed671c9..cccac82a0 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCallback.java @@ -4,10 +4,10 @@ import org.fisco.bcos.channel.dto.ChannelResponse; public class PerformanceCallback extends ChannelResponseCallback { - @Override - public void onResponseMessage(ChannelResponse response) { - collector.onMessage(response); - } + @Override + public void onResponseMessage(ChannelResponse response) { + collector.onMessage(response); + } - public PerformanceCollector collector; + public PerformanceCollector collector; } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCollector.java b/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCollector.java index c6468e34f..52a3014e7 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCollector.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/PerformanceCollector.java @@ -7,123 +7,169 @@ import org.slf4j.LoggerFactory; public class PerformanceCollector { - static Logger logger = LoggerFactory.getLogger(PerformanceCollector.class); - public Map resultMap; - public Integer total; - public AtomicInteger received = new AtomicInteger(0); - public AtomicInteger error = new AtomicInteger(0); - public Long startTimestamp = (long) 0; - public Integer tps = 0; - public Integer packageSize = 0; - - public void onMessage(ChannelResponse response) { - try { - Integer currentError = 0; - - if (response.getErrorCode() != 0) { - System.out - .println("response error:" + String.valueOf(response.getErrorCode()) + ", " + response.getErrorMessage()); - - currentError = 1; - } - - RequestTimer timer = null; - if (response.getMessageID() != null) { - timer = resultMap.get(response.getMessageID()); - if (timer == null) { - System.out.println("response error,seq:" + String.valueOf(response.getMessageID()) + " not found"); - currentError = 1; + static Logger logger = LoggerFactory.getLogger(PerformanceCollector.class); + public Map resultMap; + public Integer total; + public AtomicInteger received = new AtomicInteger(0); + public AtomicInteger error = new AtomicInteger(0); + public Long startTimestamp = (long) 0; + public Integer tps = 0; + public Integer packageSize = 0; + + public void onMessage(ChannelResponse response) { + try { + Integer currentError = 0; + + if (response.getErrorCode() != 0) { + System.out.println( + "response error:" + + String.valueOf(response.getErrorCode()) + + ", " + + response.getErrorMessage()); + + currentError = 1; + } + + RequestTimer timer = null; + if (response.getMessageID() != null) { + timer = resultMap.get(response.getMessageID()); + if (timer == null) { + System.out.println( + "response error,seq:" + + String.valueOf(response.getMessageID()) + + " not found"); + currentError = 1; + } + } else { + currentError = 1; + } + + error.addAndGet(currentError); + + if (timer != null) { + timer.recvTimestamp = System.currentTimeMillis(); + } + + received.incrementAndGet(); + + logger.debug( + "response: {} {} {}, total:{}/{}", + response.getErrorCode(), + response.getMessageID(), + response.getContent(), + received, + total); + + if ((received.get() + 1) % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf((received.get() + 1) * 100 / total) + + "%"); + } + + if (received.intValue() >= total) { + System.out.println("total"); + + // 总耗时 + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + Integer less50 = 0; + Integer less100 = 0; + Integer less200 = 0; + Integer less400 = 0; + Integer less1000 = 0; + Integer less2000 = 0; + Integer timeout2000 = 0; + + Long totalCost = (long) 0; + // 汇总信息并输出 + for (RequestTimer v : resultMap.values()) { + Long cost = (long) 0; + + if (v.recvTimestamp > 0 && v.sendTimestamp > 0) { + cost = v.recvTimestamp - v.sendTimestamp; + } + + totalCost += cost; + + // 耗时分段统计 + if (cost < 50) { + ++less50; + } else if (cost < 100) { + ++less100; + } else if (cost < 200) { + ++less200; + } else if (cost < 400) { + ++less400; + } else if (cost < 1000) { + ++less1000; + } else if (cost < 2000) { + ++less2000; + } else { + ++timeout2000; + } + } + + System.out.println("total: " + String.valueOf(total)); + System.out.println("packageSize: " + String.valueOf(packageSize) + " byte"); + System.out.println("tps: " + String.valueOf(tps)); + System.out.println( + "total/totalTime: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println("totalCost/total:" + String.valueOf(totalCost / total) + "ms"); + System.out.println( + "error/received: " + + String.valueOf((error.get() / received.get()) * 100) + + "%"); + + System.out.println("time:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50 / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100 / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200 / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400 / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000 / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000 / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000 / total * 100) + + "%"); + } + } catch (Exception e) { + logger.error("error:", e); } - } else { - currentError = 1; - } - - error.addAndGet(currentError); - - if (timer != null) { - timer.recvTimestamp = System.currentTimeMillis(); - } - - received.incrementAndGet(); - - logger.debug("response: {} {} {}, total:{}/{}", response.getErrorCode(), response.getMessageID(), - response.getContent(), received, total); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println(" |received:" - + String.valueOf((received.get() + 1) * 100 / total) + "%"); - } - - if (received.intValue() >= total) { - System.out.println("total"); - - // 总耗时 - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - Integer less50 = 0; - Integer less100 = 0; - Integer less200 = 0; - Integer less400 = 0; - Integer less1000 = 0; - Integer less2000 = 0; - Integer timeout2000 = 0; - - Long totalCost = (long) 0; - // 汇总信息并输出 - for (RequestTimer v : resultMap.values()) { - Long cost = (long) 0; - - if (v.recvTimestamp > 0 && v.sendTimestamp > 0) { - cost = v.recvTimestamp - v.sendTimestamp; - } - - totalCost += cost; - - // 耗时分段统计 - if (cost < 50) { - ++less50; - } else if (cost < 100) { - ++less100; - } else if (cost < 200) { - ++less200; - } else if (cost < 400) { - ++less400; - } else if (cost < 1000) { - ++less1000; - } else if (cost < 2000) { - ++less2000; - } else { - ++timeout2000; - } - } - - System.out.println("total: " + String.valueOf(total)); - System.out.println("packageSize: " + String.valueOf(packageSize) + " byte"); - System.out.println("tps: " + String.valueOf(tps)); - System.out.println("total/totalTime: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("totalCost/total:" + String.valueOf(totalCost / total) + "ms"); - System.out.println("error/received: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - - System.out.println("time:"); - System.out.println("0 < time < 50ms : " + String.valueOf(less50) + " : " - + String.valueOf((double) less50 / total * 100) + "%"); - System.out.println("50 < time < 100ms : " + String.valueOf(less100) + " : " - + String.valueOf((double) less100 / total * 100) + "%"); - System.out.println("100 < time < 200ms : " + String.valueOf(less200) + " : " - + String.valueOf((double) less200 / total * 100) + "%"); - System.out.println("200 < time < 400ms : " + String.valueOf(less400) + " : " - + String.valueOf((double) less400 / total * 100) + "%"); - System.out.println("400 < time < 1000ms : " + String.valueOf(less1000) + " : " - + String.valueOf((double) less1000 / total * 100) + "%"); - System.out.println("1000 < time < 2000ms : " + String.valueOf(less2000) + " : " - + String.valueOf((double) less2000 / total * 100) + "%"); - System.out.println("2000 < time : " + String.valueOf(timeout2000) + " : " - + String.valueOf((double) timeout2000 / total * 100) + "%"); - } - } catch (Exception e) { - logger.error("error:", e); } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/PingTest.java b/src/test/java/org/fisco/bcos/channel/test/amop/PingTest.java index 5f42d14e4..d9b66b0b5 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/PingTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/PingTest.java @@ -2,12 +2,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import org.fisco.bcos.channel.client.ChannelPushCallback; import org.fisco.bcos.channel.client.Service; @@ -22,270 +17,282 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class PingTest { - private static Logger logger = LoggerFactory.getLogger(PingTest.class); - - private List localNodes; - private List checkNodes; - - private Map services = new HashMap(); - private Map allSummary = new HashMap(); - - public void start() { - for (String nodeDesc : localNodes) { - ChannelConnections connections = new ChannelConnections(); - List nodeArray = new ArrayList(); - nodeArray.add(nodeDesc); - - connections.setConnectionsStr(nodeArray); - ConcurrentHashMap allConnections = - new ConcurrentHashMap(); - allConnections.put("PingTest", connections); - GroupChannelConnectionsConfig groupChannelConnectionsConfig = - new GroupChannelConnectionsConfig(); - List ilist = new ArrayList<>(); - ilist.add(connections); - groupChannelConnectionsConfig.setAllChannelConnections(ilist); - - Service service = new Service(); - service.setAllChannelConnections(groupChannelConnectionsConfig); - - String[] nodeSplit = nodeDesc.split("@"); - if (nodeSplit.length != 2) { - System.out.println("Invalid node desc: " + nodeDesc); - System.exit(1); - } - - Set topics = new HashSet(); - topics.add(nodeSplit[0]); - - service.setTopics(topics); - service.setOrgID("PingTest"); - - service.setPushCallback( - new ChannelPushCallback() { - @Override - public void onPush(ChannelPush push) { - ChannelResponse response = new ChannelResponse(); - response.setErrorCode(0); - response.setErrorMessage(""); - response.setMessageID(push.getMessageID()); - response.setContent("Pong"); - - push.sendResponse(response); + private static Logger logger = LoggerFactory.getLogger(PingTest.class); + + private List localNodes; + private List checkNodes; + + private Map services = new HashMap(); + private Map allSummary = new HashMap(); + + public void start() { + for (String nodeDesc : localNodes) { + ChannelConnections connections = new ChannelConnections(); + List nodeArray = new ArrayList(); + nodeArray.add(nodeDesc); + + connections.setConnectionsStr(nodeArray); + ConcurrentHashMap allConnections = + new ConcurrentHashMap(); + allConnections.put("PingTest", connections); + GroupChannelConnectionsConfig groupChannelConnectionsConfig = + new GroupChannelConnectionsConfig(); + List ilist = new ArrayList<>(); + ilist.add(connections); + groupChannelConnectionsConfig.setAllChannelConnections(ilist); + + Service service = new Service(); + service.setAllChannelConnections(groupChannelConnectionsConfig); + + String[] nodeSplit = nodeDesc.split("@"); + if (nodeSplit.length != 2) { + System.out.println("Invalid node desc: " + nodeDesc); + System.exit(1); } - }); - try { - service.run(); - } catch (Exception e) { - logger.error("ERROR while start", e); - System.out.println("Connect to node: " + nodeDesc + " failed, exit"); + Set topics = new HashSet(); + topics.add(nodeSplit[0]); + + service.setTopics(topics); + service.setAgencyName("PingTest"); + + service.setPushCallback( + new ChannelPushCallback() { + @Override + public void onPush(ChannelPush push) { + ChannelResponse response = new ChannelResponse(); + response.setErrorCode(0); + response.setErrorMessage(""); + response.setMessageID(push.getMessageID()); + response.setContent("Pong"); + + push.sendResponse(response); + } + }); + + try { + service.run(); + } catch (Exception e) { + logger.error("ERROR while start", e); + System.out.println("Connect to node: " + nodeDesc + " failed, exit"); + + System.exit(1); + } + + services.put(nodeSplit[0], service); + } - System.exit(1); - } + for (String check : checkNodes) { + allSummary.put(check, new Summary()); + } - services.put(nodeSplit[0], service); + System.out.println("Success, start monitor"); } - for (String check : checkNodes) { - allSummary.put(check, new Summary()); + public void check() { + for (String nodeDesc : services.keySet()) { + Service service = services.get(nodeDesc); + + for (String check : checkNodes) { + if (nodeDesc.equals(check)) { + continue; + } + + Summary summary = allSummary.get(check); + ++summary.totalRequest; + + Long current = System.currentTimeMillis(); + + ChannelRequest request = new ChannelRequest(); + request.setToTopic(check); + request.setMessageID(service.newSeq()); + request.setTimeout(5000); + request.setContent("Ping"); + + ChannelResponse response = service.sendChannelMessage2(request); + if (response.getErrorCode() != 0) { + logger.error( + "AMOP test error: {} {}", + response.getErrorCode(), + response.getErrorMessage()); + + if (response.getErrorCode() == 102) { + ++summary.totalTimeout; + } else { + ++summary.totalFatal; + } + } else { + Long cost = System.currentTimeMillis() - current; + + ++summary.totalSuccess; + summary.totalTime += cost; + + if (cost < 50) { + ++summary.less50; + } else if (cost < 100) { + ++summary.less100; + } else if (cost < 200) { + ++summary.less200; + } else if (cost < 400) { + ++summary.less400; + } else if (cost < 1000) { + ++summary.less1000; + } else if (cost < 2000) { + ++summary.less2000; + } else { + ++summary.timeout2000; + } + } + } + } } - System.out.println("Success, start monitor"); - } + public void outputSummary() { + for (String check : allSummary.keySet()) { + Summary summary = allSummary.get(check); + + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + System.out.println(""); + System.out.println( + df.format(LocalDateTime.now()) + + " Node: " + + String.valueOf(check) + + " --------------------------------------"); + System.out.println("Total request: " + String.valueOf(summary.totalRequest)); + System.out.println("Total success: " + String.valueOf(summary.totalSuccess)); + + if (summary.totalRequest > 0) { + System.out.println( + "Success rate: " + + String.valueOf( + ((double) summary.totalSuccess / summary.totalRequest) + * 100) + + "%"); + } - public void check() { - for (String nodeDesc : services.keySet()) { - Service service = services.get(nodeDesc); + if (summary.totalSuccess > 0) { + System.out.println( + "Avg time cost: " + + String.valueOf( + ((double) summary.totalTime / summary.totalSuccess)) + + " ms"); + } - for (String check : checkNodes) { - if (nodeDesc.equals(check)) { - continue; - } + System.out.println("Total fail: " + String.valueOf(summary.totalFatal)); + System.out.println("Total timeout: " + String.valueOf(summary.totalTimeout)); + + System.out.println(""); + + if (summary.totalSuccess > 0) { + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(summary.less50) + + " : " + + String.valueOf( + (double) summary.less50 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(summary.less100) + + " : " + + String.valueOf( + (double) summary.less100 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(summary.less200) + + " : " + + String.valueOf( + (double) summary.less200 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(summary.less400) + + " : " + + String.valueOf( + (double) summary.less400 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(summary.less1000) + + " : " + + String.valueOf( + (double) summary.less1000 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(summary.less2000) + + " : " + + String.valueOf( + (double) summary.less2000 / summary.totalSuccess * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(summary.timeout2000) + + " : " + + String.valueOf( + (double) summary.timeout2000 / summary.totalSuccess * 100) + + "%"); + } - Summary summary = allSummary.get(check); - ++summary.totalRequest; - - Long current = System.currentTimeMillis(); - - ChannelRequest request = new ChannelRequest(); - request.setToTopic(check); - request.setMessageID(service.newSeq()); - request.setTimeout(5000); - request.setContent("Ping"); - - ChannelResponse response = service.sendChannelMessage2(request); - if (response.getErrorCode() != 0) { - logger.error( - "AMOP test error: {} {}", response.getErrorCode(), response.getErrorMessage()); - - if (response.getErrorCode() == 102) { - ++summary.totalTimeout; - } else { - ++summary.totalFatal; - } - } else { - Long cost = System.currentTimeMillis() - current; - - ++summary.totalSuccess; - summary.totalTime += cost; - - if (cost < 50) { - ++summary.less50; - } else if (cost < 100) { - ++summary.less100; - } else if (cost < 200) { - ++summary.less200; - } else if (cost < 400) { - ++summary.less400; - } else if (cost < 1000) { - ++summary.less1000; - } else if (cost < 2000) { - ++summary.less2000; - } else { - ++summary.timeout2000; - } + System.out.println(""); } - } - } - } - - public void outputSummary() { - for (String check : allSummary.keySet()) { - Summary summary = allSummary.get(check); - - DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - System.out.println(""); - System.out.println( - df.format(LocalDateTime.now()) - + " Node: " - + String.valueOf(check) - + " --------------------------------------"); - System.out.println("Total request: " + String.valueOf(summary.totalRequest)); - System.out.println("Total success: " + String.valueOf(summary.totalSuccess)); - - if (summary.totalRequest > 0) { - System.out.println( - "Success rate: " - + String.valueOf(((double) summary.totalSuccess / summary.totalRequest) * 100) - + "%"); - } - - if (summary.totalSuccess > 0) { - System.out.println( - "Avg time cost: " - + String.valueOf(((double) summary.totalTime / summary.totalSuccess)) - + " ms"); - } - - System.out.println("Total fail: " + String.valueOf(summary.totalFatal)); - System.out.println("Total timeout: " + String.valueOf(summary.totalTimeout)); - - System.out.println(""); - - if (summary.totalSuccess > 0) { - System.out.println("Time area:"); - System.out.println( - "0 < time < 50ms : " - + String.valueOf(summary.less50) - + " : " - + String.valueOf((double) summary.less50 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "50 < time < 100ms : " - + String.valueOf(summary.less100) - + " : " - + String.valueOf((double) summary.less100 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "100 < time < 200ms : " - + String.valueOf(summary.less200) - + " : " - + String.valueOf((double) summary.less200 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "200 < time < 400ms : " - + String.valueOf(summary.less400) - + " : " - + String.valueOf((double) summary.less400 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "400 < time < 1000ms : " - + String.valueOf(summary.less1000) - + " : " - + String.valueOf((double) summary.less1000 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "1000 < time < 2000ms : " - + String.valueOf(summary.less2000) - + " : " - + String.valueOf((double) summary.less2000 / summary.totalSuccess * 100) - + "%"); - System.out.println( - "2000 < time : " - + String.valueOf(summary.timeout2000) - + " : " - + String.valueOf((double) summary.timeout2000 / summary.totalSuccess * 100) - + "%"); - } - - System.out.println(""); } - } - - public static void main(String[] args) { - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - PingTest pingTest = context.getBean(PingTest.class); - - pingTest.start(); - - Runtime.getRuntime() - .addShutdownHook( - new Thread() { - public void run() { - _pingTest.outputSummary(); - } - - private PingTest _pingTest = pingTest; - }); - - Integer count = 0; - while (true) { - try { - Thread.sleep(5 * 1000L); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - System.out.println("Thread exception"); - e.printStackTrace(); - - System.exit(1); - } - - pingTest.check(); - ++count; - if (count == Integer.MAX_VALUE) { - break; - } - - pingTest.outputSummary(); + + public static void main(String[] args) { + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + PingTest pingTest = context.getBean(PingTest.class); + + pingTest.start(); + + Runtime.getRuntime() + .addShutdownHook( + new Thread() { + public void run() { + _pingTest.outputSummary(); + } + + private PingTest _pingTest = pingTest; + }); + + Integer count = 0; + while (true) { + try { + Thread.sleep(5 * 1000L); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("Thread exception"); + e.printStackTrace(); + + System.exit(1); + } + + pingTest.check(); + ++count; + if (count == Integer.MAX_VALUE) { + break; + } + + pingTest.outputSummary(); + } } - } - public List getLocalNodes() { - return localNodes; - } + public List getLocalNodes() { + return localNodes; + } - public void setLocalNodes(List localNodes) { - this.localNodes = localNodes; - } + public void setLocalNodes(List localNodes) { + this.localNodes = localNodes; + } - public List getCheckNodes() { - return checkNodes; - } + public List getCheckNodes() { + return checkNodes; + } - public void setCheckNodes(List checkNodes) { - this.checkNodes = checkNodes; - } + public void setCheckNodes(List checkNodes) { + this.checkNodes = checkNodes; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/ProxyServer.java b/src/test/java/org/fisco/bcos/channel/test/amop/ProxyServer.java index 43aba1ff0..ff41f8d78 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/ProxyServer.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/ProxyServer.java @@ -3,25 +3,24 @@ import static java.lang.System.exit; import org.fisco.bcos.channel.proxy.Server; -import org.junit.Ignore; -import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ProxyServer { - @Ignore - @Test - public void testProxyServer() throws Exception { + public static void main(String[] args) throws Exception { - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Server server = context.getBean(Server.class); - System.out.println("start testing"); - System.out.println("==================================================================="); + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Server server1 = (Server) context.getBean("proxyServer1"); + Server server2 = (Server) context.getBean("proxyServer2"); + System.out.println("start testing"); + System.out.println("==================================================================="); - server.run(); - Thread.sleep(5000); - exit(1); - } + server1.run(); + server2.run(); + + Thread.sleep(500000); + exit(1); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback.java b/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback.java index b5deeae13..c1c55422e 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback.java @@ -9,18 +9,18 @@ import org.slf4j.LoggerFactory; class PushCallback extends ChannelPushCallback { - static Logger logger = LoggerFactory.getLogger(PushCallback.class); + static Logger logger = LoggerFactory.getLogger(PushCallback.class); - @Override - public void onPush(ChannelPush push) { - DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - logger.debug("push:" + push.getContent()); + @Override + public void onPush(ChannelPush push) { + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + logger.debug("push:" + push.getContent()); - System.out.println(df.format(LocalDateTime.now()) + "server:push:" + push.getContent()); - ChannelResponse response = new ChannelResponse(); - response.setContent("receive request seq:" + String.valueOf(push.getMessageID())); - response.setErrorCode(0); + System.out.println(df.format(LocalDateTime.now()) + "server:push:" + push.getContent()); + ChannelResponse response = new ChannelResponse(); + response.setContent("receive request seq:" + String.valueOf(push.getMessageID())); + response.setErrorCode(0); - push.sendResponse(response); - } + push.sendResponse(response); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback2.java b/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback2.java index 442263e1e..6ddb8acae 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback2.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/PushCallback2.java @@ -9,18 +9,18 @@ import org.slf4j.LoggerFactory; class PushCallback2 extends ChannelPushCallback { - static Logger logger = LoggerFactory.getLogger(PushCallback2.class); + static Logger logger = LoggerFactory.getLogger(PushCallback2.class); - @Override - public void onPush(ChannelPush push) { - DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - logger.debug("push:" + push.getContent()); - System.out.println(df.format(LocalDateTime.now()) + "server:push:" + push.getContent()); + @Override + public void onPush(ChannelPush push) { + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + logger.debug("push:" + push.getContent()); + System.out.println(df.format(LocalDateTime.now()) + "server:push:" + push.getContent()); - ChannelResponse response = new ChannelResponse(); - response.setContent("receive request seq:" + String.valueOf(push.getMessageID())); - response.setErrorCode(0); + ChannelResponse response = new ChannelResponse(); + response.setContent("receive request seq:" + String.valueOf(push.getMessageID())); + response.setErrorCode(0); - push.sendResponse(response); - } + push.sendResponse(response); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/RequestTimer.java b/src/test/java/org/fisco/bcos/channel/test/amop/RequestTimer.java index 598ef80fd..3f60e255b 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/RequestTimer.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/RequestTimer.java @@ -1,6 +1,6 @@ package org.fisco.bcos.channel.test.amop; public class RequestTimer { - public long sendTimestamp = 0; - public long recvTimestamp = 0; + public long sendTimestamp = 0; + public long recvTimestamp = 0; } diff --git a/src/test/java/org/fisco/bcos/channel/test/amop/Summary.java b/src/test/java/org/fisco/bcos/channel/test/amop/Summary.java index 8132346ce..5bc1c4cb9 100644 --- a/src/test/java/org/fisco/bcos/channel/test/amop/Summary.java +++ b/src/test/java/org/fisco/bcos/channel/test/amop/Summary.java @@ -1,17 +1,17 @@ package org.fisco.bcos.channel.test.amop; public class Summary { - public Long totalRequest = (long) 0; - public Long totalSuccess = (long) 0; - public Long totalTimeout = (long) 0; - public Long totalFatal = (long) 0; - public Long totalTime = (long) 0; + public Long totalRequest = (long) 0; + public Long totalSuccess = (long) 0; + public Long totalTimeout = (long) 0; + public Long totalFatal = (long) 0; + public Long totalTime = (long) 0; - public Long less50 = (long) 0; - public Long less100 = (long) 0; - public Long less200 = (long) 0; - public Long less400 = (long) 0; - public Long less1000 = (long) 0; - public Long less2000 = (long) 0; - public Long timeout2000 = (long) 0; + public Long less50 = (long) 0; + public Long less100 = (long) 0; + public Long less200 = (long) 0; + public Long less400 = (long) 0; + public Long less1000 = (long) 0; + public Long less2000 = (long) 0; + public Long timeout2000 = (long) 0; } diff --git a/src/test/java/org/fisco/bcos/channel/test/block/BlockTest.java b/src/test/java/org/fisco/bcos/channel/test/block/BlockTest.java deleted file mode 100644 index 07a620a11..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/block/BlockTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.fisco.bcos.channel.test.block; - -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.math.BigInteger; -import org.fisco.bcos.channel.test.TestBase; -import org.fisco.bcos.web3j.utils.Numeric; -import org.junit.Test; - -public class BlockTest extends TestBase { - - @Test - public void getBlockNumber() throws IOException { - final String blockNumber = web3j.getBlockNumber().sendForReturnString(); - System.out.println(blockNumber); - assertTrue(Numeric.decodeQuantity(blockNumber).compareTo(new BigInteger("0")) >= 0); - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/block/MockBlockTest.java b/src/test/java/org/fisco/bcos/channel/test/block/MockBlockTest.java index 515ea4c6e..d5f354f0a 100644 --- a/src/test/java/org/fisco/bcos/channel/test/block/MockBlockTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/block/MockBlockTest.java @@ -20,26 +20,27 @@ public class MockBlockTest { - private Web3jService web3jService = mock(Web3jService.class); - private ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - private final String rawResponse = - "{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":{\"extraData\":[],\"gasLimit\":\"0x0\",\"gasUsed\":\"0x0\",\"hash\":\"0xb1b1612e3d2e6571304e53136002b6c79ae53fcfa207dbe350b61c4a6d0f157f\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"number\":\"0x1\",\"parentHash\":\"0xe325463b4ed6746dfc4a127e979fd6b95c7d32c754a21e7afbcb8f16b5d0880c\",\"sealer\":\"0x0\",\"stateRoot\":\"0x06ca72b2a5d14f8497412150ecc2d3744c85c26c43a639ba73879f5106ac64d0\",\"timestamp\":\"0x1684a53a6fb\",\"transactions\":[{\"blockHash\":\"0xb1b1612e3d2e6571304e53136002b6c79ae53fcfa207dbe350b61c4a6d0f157f\",\"blockNumber\":\"0x1\",\"from\":\"0x148947262ec5e21739fe3a931c29e8b84ee34a0f\",\"gas\":\"0x11e1a300\",\"gasPrice\":\"0x11e1a300\",\"hash\":\"0xcf9de56878da55b2fb4156bc6268e65d519b87d2b8a320c9f08a966651aa44b1\",\"input\":\"0x60606040525b6001600060005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055506402540be4006000600050600101600050819055506002600260005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060006002600050600101600050819055505b6104168061009e6000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806366c99139146100475780636d4ce63c1461006457610042565b610002565b3461000257610062600480803590602001909190505061008c565b005b346100025761007660048050506103fe565b6040518082815260200191505060405180910390f35b80600060005060010160005054036000600050600101600050819055508060026000506001016000828282505401925050819055507fb797d73164cc7b1c119ca7507c18ac67eac964ca7eed3b0fbdd4e63caab2ca65816040518082815260200191505060405180910390a16004600050805480600101828181548183558181151161020c5760040281600402836000526020600020918201910161020b9190610131565b8082111561020757600060008201600050805460018160011615610100020316600290046000825580601f1061016757506101a4565b601f0160209004906000526020600020908101906101a39190610185565b8082111561019f5760008181506000905550600101610185565b5090565b5b506001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000506000905550600401610131565b5090565b5b5050509190906000526020600020906004020160005b608060405190810160405280604060405190810160405280600881526020017f32303137303431330000000000000000000000000000000000000000000000008152602001508152602001600060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168152602001600260005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681526020018581526020015090919091506000820151816000016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032a57805160ff191683800117855561035b565b8280016001018555821561035b579182015b8281111561035a57825182600050559160200191906001019061033c565b5b5090506103869190610368565b808211156103825760008181506000905550600101610368565b5090565b505060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550606082015181600301600050555050505b50565b60006002600050600101600050549050610413565b9056ef\",\"nonce\":\"0x3df8ad22eff71f4a835e6dd61c6f60b71aded81a86fc4771b5ddba5b48256e0\",\"to\":null,\"transactionIndex\":\"0x0\",\"value\":\"0x0\"}],\"transactionsRoot\":\"0x0aa79ed38e5ea8ff8828f379fa671b0f018b3f38f4e2a4f36062bc35bd55b8ff\"}}\n"; + private Web3jService web3jService = mock(Web3jService.class); + private ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + private final String rawResponse = + "{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":{\"extraData\":[],\"gasLimit\":\"0x0\",\"gasUsed\":\"0x0\",\"hash\":\"0xb1b1612e3d2e6571304e53136002b6c79ae53fcfa207dbe350b61c4a6d0f157f\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"number\":\"0x1\",\"parentHash\":\"0xe325463b4ed6746dfc4a127e979fd6b95c7d32c754a21e7afbcb8f16b5d0880c\",\"sealer\":\"0x0\",\"stateRoot\":\"0x06ca72b2a5d14f8497412150ecc2d3744c85c26c43a639ba73879f5106ac64d0\",\"timestamp\":\"0x1684a53a6fb\",\"transactions\":[{\"blockHash\":\"0xb1b1612e3d2e6571304e53136002b6c79ae53fcfa207dbe350b61c4a6d0f157f\",\"blockNumber\":\"0x1\",\"from\":\"0x148947262ec5e21739fe3a931c29e8b84ee34a0f\",\"gas\":\"0x11e1a300\",\"gasPrice\":\"0x11e1a300\",\"hash\":\"0xcf9de56878da55b2fb4156bc6268e65d519b87d2b8a320c9f08a966651aa44b1\",\"input\":\"0x60606040525b6001600060005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055506402540be4006000600050600101600050819055506002600260005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060006002600050600101600050819055505b6104168061009e6000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806366c99139146100475780636d4ce63c1461006457610042565b610002565b3461000257610062600480803590602001909190505061008c565b005b346100025761007660048050506103fe565b6040518082815260200191505060405180910390f35b80600060005060010160005054036000600050600101600050819055508060026000506001016000828282505401925050819055507fb797d73164cc7b1c119ca7507c18ac67eac964ca7eed3b0fbdd4e63caab2ca65816040518082815260200191505060405180910390a16004600050805480600101828181548183558181151161020c5760040281600402836000526020600020918201910161020b9190610131565b8082111561020757600060008201600050805460018160011615610100020316600290046000825580601f1061016757506101a4565b601f0160209004906000526020600020908101906101a39190610185565b8082111561019f5760008181506000905550600101610185565b5090565b5b506001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000506000905550600401610131565b5090565b5b5050509190906000526020600020906004020160005b608060405190810160405280604060405190810160405280600881526020017f32303137303431330000000000000000000000000000000000000000000000008152602001508152602001600060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168152602001600260005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681526020018581526020015090919091506000820151816000016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032a57805160ff191683800117855561035b565b8280016001018555821561035b579182015b8281111561035a57825182600050559160200191906001019061033c565b5b5090506103869190610368565b808211156103825760008181506000905550600101610368565b5090565b505060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550606082015181600301600050555050505b50565b60006002600050600101600050549050610413565b9056ef\",\"nonce\":\"0x3df8ad22eff71f4a835e6dd61c6f60b71aded81a86fc4771b5ddba5b48256e0\",\"to\":null,\"transactionIndex\":\"0x0\",\"value\":\"0x0\"}],\"transactionsRoot\":\"0x0aa79ed38e5ea8ff8828f379fa671b0f018b3f38f4e2a4f36062bc35bd55b8ff\"}}\n"; - public MockBlockTest() throws IOException {} + public MockBlockTest() throws IOException {} - @Test - public void getBlockNumber() throws IOException { + @Test + public void getBlockNumber() throws IOException { - BcosBlock block = objectMapper.readValue(rawResponse, BcosBlock.class); - block.setRawResponse(rawResponse); + BcosBlock block = objectMapper.readValue(rawResponse, BcosBlock.class); + block.setRawResponse(rawResponse); - Web3j web3j = Web3j.build(web3jService); - when(web3jService.send(any(Request.class), eq(BcosBlock.class))).thenReturn(block); + Web3j web3j = Web3j.build(web3jService); + when(web3jService.send(any(Request.class), eq(BcosBlock.class))).thenReturn(block); - BcosBlock mockBlocks = - web3j.getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("1")), true).send(); - BcosBlock.Block mockBlock = mockBlocks.getBlock(); - assertEquals(mockBlock.getNonce(), new BigInteger("0")); - assertTrue(mockBlock.getNumber().intValue() == 1); - } + BcosBlock mockBlocks = + web3j.getBlockByNumber(DefaultBlockParameter.valueOf(new BigInteger("1")), true) + .send(); + BcosBlock.Block mockBlock = mockBlocks.getBlock(); + assertEquals(mockBlock.getNonce(), new BigInteger("0")); + assertTrue(mockBlock.getNumber().intValue() == 1); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/DBTest.java b/src/test/java/org/fisco/bcos/channel/test/contract/DBTest.java index ba615cfe8..794b6f987 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/DBTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/DBTest.java @@ -39,436 +39,463 @@ *

Generated with web3j version none. */ public class DBTest extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b50612183806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a1014610072578063616ffe831461013f578063c4f41ab31461028d578063ebf3b24f14610314578063efc81a8c146103e1575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103f8565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101a6600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610aee565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156101f15780820151818401526020810190506101d6565b50505050905001848103835286818151815260200191508051906020019060200280838360005b83811015610233578082015181840152602081019050610218565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561027557808201518184015260208101905061025a565b50505050905001965050505050505060405180910390f35b34801561029957600080fd5b506102fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506114ad565b6040518082815260200191505060405180910390f35b34801561032057600080fd5b506103cb600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506119a6565b6040518082815260200191505060405180910390f35b3480156103ed57600080fd5b506103f6611fc5565b005b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104a657600080fd5b505af11580156104ba573d6000803e3d6000fd5b505050506040513d60208110156104d057600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561054757600080fd5b505af115801561055b573d6000803e3d6000fd5b505050506040513d602081101561057157600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610644578082015181840152602081019050610629565b50505050905090810190601f1680156106715780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561070d57600080fd5b505af1158015610721573d6000803e3d6000fd5b505050506040513d602081101561073757600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561080a5780820151818401526020810190506107ef565b50505050905090810190601f1680156108375780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561085757600080fd5b505af115801561086b573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a1d578082015181840152602081019050610a02565b50505050905090810190601f168015610a4a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b505050506040513d6020811015610a9557600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610ba657600080fd5b505af1158015610bba573d6000803e3d6000fd5b505050506040513d6020811015610bd057600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c4757600080fd5b505af1158015610c5b573d6000803e3d6000fd5b505050506040513d6020811015610c7157600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610d3f578082015181840152602081019050610d24565b50505050905090810190601f168015610d6c5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610d8c57600080fd5b505af1158015610da0573d6000803e3d6000fd5b505050506040513d6020811015610db657600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610e2d57600080fd5b505af1158015610e41573d6000803e3d6000fd5b505050506040513d6020811015610e5757600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610e965781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610f665781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610fcd57600080fd5b505af1158015610fe1573d6000803e3d6000fd5b505050506040513d6020811015610ff757600080fd5b81019080805190602001909291905050506040519080825280602002602001820160405280156110365781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156110a257600080fd5b505af11580156110b6573d6000803e3d6000fd5b505050506040513d60208110156110cc57600080fd5b8101908080519060200190929190505050821215611494578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561115357600080fd5b505af1158015611167573d6000803e3d6000fd5b505050506040513d602081101561117d57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561123057600080fd5b505af1158015611244573d6000803e3d6000fd5b505050506040513d602081101561125a57600080fd5b8101908080519060200190929190505050858381518110151561127957fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561133157600080fd5b505af1158015611345573d6000803e3d6000fd5b505050506040513d602081101561135b57600080fd5b8101908080519060200190929190505050848381518110151561137a57fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561142857600080fd5b505af115801561143c573d6000803e3d6000fd5b505050506040513d602081101561145257600080fd5b8101908080519060200190929190505050838381518110151561147157fe5b90602001906020020190600019169081600019168152505081600101915061103e565b8484849b509b509b505050505050505050509193909250565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561155a57600080fd5b505af115801561156e573d6000803e3d6000fd5b505050506040513d602081101561158457600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156115fb57600080fd5b505af115801561160f573d6000803e3d6000fd5b505050506040513d602081101561162557600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b838110156116f85780820151818401526020810190506116dd565b50505050905090810190601f1680156117255780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561174557600080fd5b505af1158015611759573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156118d85780820151818401526020810190506118bd565b50505050905090810190601f1680156119055780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b505050506040513d602081101561194f57600080fd5b810190808051906020019092919050505090507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611a5357600080fd5b505af1158015611a67573d6000803e3d6000fd5b505050506040513d6020811015611a7d57600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611af457600080fd5b505af1158015611b08573d6000803e3d6000fd5b505050506040513d6020811015611b1e57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611bf1578082015181840152602081019050611bd6565b50505050905090810190601f168015611c1e5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015611cfe57600080fd5b505af1158015611d12573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611dd6578082015181840152602081019050611dbb565b50505050905090810190601f168015611e035780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611ef6578082015181840152602081019050611edb565b50505050905090810190601f168015611f235780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611f4357600080fd5b505af1158015611f57573d6000803e3d6000fd5b505050506040513d6020811015611f6d57600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1809450505050509392505050565b60008061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b1580156120df57600080fd5b505af11580156120f3573d6000803e3d6000fd5b505050506040513d602081101561210957600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a150505600a165627a7a723058204a7dfc54315e9181f8a525c4747391179b0e12584ce4ef5deebc31d79404e8f20029"; - - public static final String FUNC_UPDATE = "update"; - - public static final String FUNC_READ = "read"; - - public static final String FUNC_REMOVE = "remove"; - - public static final String FUNC_INSERT = "insert"; - - public static final String FUNC_CREATE = "create"; - - public static final Event CREATERESULT_EVENT = - new Event("createResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event INSERTRESULT_EVENT = - new Event("insertResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event UPDATERESULT_EVENT = - new Event("updateResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event REMOVERESULT_EVENT = - new Event("removeResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event READRESULT_EVENT = - new Event( - "readResult", - Arrays.>asList( - new TypeReference() {}, - new TypeReference() {}, - new TypeReference() {}));; - - @Deprecated - protected DBTest( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected DBTest( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected DBTest( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected DBTest( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall update(String name, BigInteger item_id, String item_name) { - final Function function = - new Function( - FUNC_UPDATE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall, List, List>> read(String name) { - final Function function = - new Function( - FUNC_READ, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), - Arrays.>asList( - new TypeReference>() {}, - new TypeReference>() {}, - new TypeReference>() {})); - return new RemoteCall, List, List>>( - new Callable, List, List>>() { - @Override - public Tuple3, List, List> call() throws Exception { - List results = executeCallMultipleValueReturn(function); - return new Tuple3, List, List>( - convertToNative((List) results.get(0).getValue()), - convertToNative((List) results.get(1).getValue()), - convertToNative((List) results.get(2).getValue())); - } - }); - } - - public RemoteCall remove(String name, BigInteger item_id) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall insert(String name, BigInteger item_id, String item_name) { - final Function function = - new Function( - FUNC_INSERT, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall create() { - final Function function = - new Function(FUNC_CREATE, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public List getCreateResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - CreateResultEventResponse typedResponse = new CreateResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable createResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public CreateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(CREATERESULT_EVENT, log); - CreateResultEventResponse typedResponse = new CreateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable createResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(CREATERESULT_EVENT)); - return createResultEventFlowable(filter); - } - - public List getInsertResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable insertResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public InsertResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(INSERTRESULT_EVENT, log); - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable insertResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); - return insertResultEventFlowable(filter); - } - - public List getUpdateResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable updateResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public UpdateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(UPDATERESULT_EVENT, log); - UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable updateResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(UPDATERESULT_EVENT)); - return updateResultEventFlowable(filter); - } - - public List getRemoveResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable removeResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public RemoveResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(REMOVERESULT_EVENT, log); - RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable removeResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(REMOVERESULT_EVENT)); - return removeResultEventFlowable(filter); - } - - public List getReadResultEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(READRESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - ReadResultEventResponse typedResponse = new ReadResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable readResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public ReadResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(READRESULT_EVENT, log); - ReadResultEventResponse typedResponse = new ReadResultEventResponse(); - typedResponse.log = log; - typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = + private static final String BINARY = + "608060405234801561001057600080fd5b50612183806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a1014610072578063616ffe831461013f578063c4f41ab31461028d578063ebf3b24f14610314578063efc81a8c146103e1575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506103f8565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101a6600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610aee565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156101f15780820151818401526020810190506101d6565b50505050905001848103835286818151815260200191508051906020019060200280838360005b83811015610233578082015181840152602081019050610218565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561027557808201518184015260208101905061025a565b50505050905001965050505050505060405180910390f35b34801561029957600080fd5b506102fe600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506114ad565b6040518082815260200191505060405180910390f35b34801561032057600080fd5b506103cb600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506119a6565b6040518082815260200191505060405180910390f35b3480156103ed57600080fd5b506103f6611fc5565b005b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104a657600080fd5b505af11580156104ba573d6000803e3d6000fd5b505050506040513d60208110156104d057600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561054757600080fd5b505af115801561055b573d6000803e3d6000fd5b505050506040513d602081101561057157600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610644578082015181840152602081019050610629565b50505050905090810190601f1680156106715780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561070d57600080fd5b505af1158015610721573d6000803e3d6000fd5b505050506040513d602081101561073757600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561080a5780820151818401526020810190506107ef565b50505050905090810190601f1680156108375780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561085757600080fd5b505af115801561086b573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a1d578082015181840152602081019050610a02565b50505050905090810190601f168015610a4a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b505050506040513d6020811015610a9557600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610ba657600080fd5b505af1158015610bba573d6000803e3d6000fd5b505050506040513d6020811015610bd057600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c4757600080fd5b505af1158015610c5b573d6000803e3d6000fd5b505050506040513d6020811015610c7157600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610d3f578082015181840152602081019050610d24565b50505050905090810190601f168015610d6c5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610d8c57600080fd5b505af1158015610da0573d6000803e3d6000fd5b505050506040513d6020811015610db657600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610e2d57600080fd5b505af1158015610e41573d6000803e3d6000fd5b505050506040513d6020811015610e5757600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610e965781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610f665781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610fcd57600080fd5b505af1158015610fe1573d6000803e3d6000fd5b505050506040513d6020811015610ff757600080fd5b81019080805190602001909291905050506040519080825280602002602001820160405280156110365781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156110a257600080fd5b505af11580156110b6573d6000803e3d6000fd5b505050506040513d60208110156110cc57600080fd5b8101908080519060200190929190505050821215611494578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561115357600080fd5b505af1158015611167573d6000803e3d6000fd5b505050506040513d602081101561117d57600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561123057600080fd5b505af1158015611244573d6000803e3d6000fd5b505050506040513d602081101561125a57600080fd5b8101908080519060200190929190505050858381518110151561127957fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561133157600080fd5b505af1158015611345573d6000803e3d6000fd5b505050506040513d602081101561135b57600080fd5b8101908080519060200190929190505050848381518110151561137a57fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561142857600080fd5b505af115801561143c573d6000803e3d6000fd5b505050506040513d602081101561145257600080fd5b8101908080519060200190929190505050838381518110151561147157fe5b90602001906020020190600019169081600019168152505081600101915061103e565b8484849b509b509b505050505050505050509193909250565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561155a57600080fd5b505af115801561156e573d6000803e3d6000fd5b505050506040513d602081101561158457600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156115fb57600080fd5b505af115801561160f573d6000803e3d6000fd5b505050506040513d602081101561162557600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b838110156116f85780820151818401526020810190506116dd565b50505050905090810190601f1680156117255780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561174557600080fd5b505af1158015611759573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156118d85780820151818401526020810190506118bd565b50505050905090810190601f1680156119055780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b505050506040513d602081101561194f57600080fd5b810190808051906020019092919050505090507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611a5357600080fd5b505af1158015611a67573d6000803e3d6000fd5b505050506040513d6020811015611a7d57600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611af457600080fd5b505af1158015611b08573d6000803e3d6000fd5b505050506040513d6020811015611b1e57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611bf1578082015181840152602081019050611bd6565b50505050905090810190601f168015611c1e5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015611cfe57600080fd5b505af1158015611d12573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611dd6578082015181840152602081019050611dbb565b50505050905090810190601f168015611e035780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611ef6578082015181840152602081019050611edb565b50505050905090810190601f168015611f235780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611f4357600080fd5b505af1158015611f57573d6000803e3d6000fd5b505050506040513d6020811015611f6d57600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1809450505050509392505050565b60008061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b1580156120df57600080fd5b505af11580156120f3573d6000803e3d6000fd5b505050506040513d602081101561210957600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a150505600a165627a7a723058204a7dfc54315e9181f8a525c4747391179b0e12584ce4ef5deebc31d79404e8f20029"; + + public static final String FUNC_UPDATE = "update"; + + public static final String FUNC_READ = "read"; + + public static final String FUNC_REMOVE = "remove"; + + public static final String FUNC_INSERT = "insert"; + + public static final String FUNC_CREATE = "create"; + + public static final Event CREATERESULT_EVENT = + new Event( + "createResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event INSERTRESULT_EVENT = + new Event( + "insertResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event UPDATERESULT_EVENT = + new Event( + "updateResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event REMOVERESULT_EVENT = + new Event( + "removeResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event READRESULT_EVENT = + new Event( + "readResult", + Arrays.>asList( + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}));; + + @Deprecated + protected DBTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected DBTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected DBTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected DBTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall update( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall, List, List>> read(String name) { + final Function function = + new Function( + FUNC_READ, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), + Arrays.>asList( + new TypeReference>() {}, + new TypeReference>() {}, + new TypeReference>() {})); + return new RemoteCall, List, List>>( + new Callable, List, List>>() { + @Override + public Tuple3, List, List> call() + throws Exception { + List results = executeCallMultipleValueReturn(function); + return new Tuple3, List, List>( + convertToNative((List) results.get(0).getValue()), + convertToNative((List) results.get(1).getValue()), + convertToNative((List) results.get(2).getValue())); + } + }); + } + + public RemoteCall remove(String name, BigInteger item_id) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall insert( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall create() { + final Function function = + new Function( + FUNC_CREATE, + Arrays.asList(), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public List getCreateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CreateResultEventResponse typedResponse = new CreateResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable createResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public CreateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(CREATERESULT_EVENT, log); + CreateResultEventResponse typedResponse = + new CreateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable createResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CREATERESULT_EVENT)); + return createResultEventFlowable(filter); + } + + public List getInsertResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + InsertResultEventResponse typedResponse = new InsertResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable insertResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public InsertResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(INSERTRESULT_EVENT, log); + InsertResultEventResponse typedResponse = + new InsertResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable insertResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); + return insertResultEventFlowable(filter); + } + + public List getUpdateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable updateResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public UpdateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(UPDATERESULT_EVENT, log); + UpdateResultEventResponse typedResponse = + new UpdateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable updateResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(UPDATERESULT_EVENT)); + return updateResultEventFlowable(filter); + } + + public List getRemoveResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable removeResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public RemoveResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(REMOVERESULT_EVENT, log); + RemoveResultEventResponse typedResponse = + new RemoveResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable removeResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(REMOVERESULT_EVENT)); + return removeResultEventFlowable(filter); + } + + public List getReadResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(READRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + ReadResultEventResponse typedResponse = new ReadResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.item_name = - (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); - return typedResponse; - } - }); - } - - public Flowable readResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(READRESULT_EVENT)); - return readResultEventFlowable(filter); - } - - @Deprecated - public static DBTest load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new DBTest(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static DBTest load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new DBTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static DBTest load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new DBTest(contractAddress, web3j, credentials, contractGasProvider); - } - - public static DBTest load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new DBTest(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(DBTest.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(DBTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - DBTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - DBTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class CreateResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class InsertResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class UpdateResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class RemoveResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class ReadResultEventResponse { - public Log log; - - public byte[] name; - - public BigInteger item_id; - - public byte[] item_name; - } + typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable readResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public ReadResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(READRESULT_EVENT, log); + ReadResultEventResponse typedResponse = + new ReadResultEventResponse(); + typedResponse.log = log; + typedResponse.name = + (byte[]) + eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.item_id = + (BigInteger) + eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.item_name = + (byte[]) + eventValues.getNonIndexedValues().get(2).getValue(); + return typedResponse; + } + }); + } + + public Flowable readResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(READRESULT_EVENT)); + return readResultEventFlowable(filter); + } + + @Deprecated + public static DBTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new DBTest(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static DBTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new DBTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static DBTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new DBTest(contractAddress, web3j, credentials, contractGasProvider); + } + + public static DBTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new DBTest(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(DBTest.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(DBTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + DBTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + DBTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class CreateResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class InsertResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class UpdateResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class RemoveResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class ReadResultEventResponse { + public Log log; + + public byte[] name; + + public BigInteger item_id; + + public byte[] item_name; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/DBTestClient.java b/src/test/java/org/fisco/bcos/channel/test/contract/DBTestClient.java index ddc62e72d..9168c8212 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/DBTestClient.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/DBTestClient.java @@ -27,220 +27,228 @@ import org.springframework.core.io.Resource; public class DBTestClient { - static Logger logger = LoggerFactory.getLogger(DBTestClient.class); - public static Web3j web3j; - // 初始化交易参数 - public static java.math.BigInteger gasPrice = new BigInteger("1"); - public static java.math.BigInteger gasLimit = new BigInteger("30000000"); - public static ECKeyPair keyPair; - public static Credentials credentials; - public static String contractAddress = ""; - - /* deploy the contract,get address from blockchain */ - @SuppressWarnings("deprecation") - public static void deployDBTest() { - - RemoteCall deploy = DBTest.deploy(web3j, credentials, gasPrice, gasLimit); - DBTest dbtest; - try { - dbtest = deploy.send(); - contractAddress = dbtest.getContractAddress(); - System.out.println("deploy contract address: " + contractAddress); - logger.info("deploy contract address: " + contractAddress); - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - prop.setProperty("crud_address", contractAddress); - prop.save(); - - System.out.println("deploy contract successful!"); - } catch (TransactionException e) { - if ("0x19".equals(e.getStatus())) { - System.out.println("non-authorized to deploy contracts!"); - } else { - System.out.println(e.getMessage()); - } - } catch (Exception e) { - System.out.println("deploy failed! " + e.getMessage()); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void testDBTest(String[] args) throws Exception { - - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - Object addressObj = prop.getProperty("crud_address"); - if (addressObj != null) { - contractAddress = (String) addressObj; - } else { - deployDBTest(); - } - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - ; - DBTest dbtest = DBTest.load(contractAddress, web3j, credentials, contractGasProvider); - // create table - if ("create".equals(args[0])) { - TransactionReceipt receipt = dbtest.create().send(); - List createResultEvents = dbtest.getCreateResultEvents(receipt); - if (createResultEvents.size() == 0) { - System.out.println("create t_test table failed."); - return; - } - CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); - int createCount = createResultEventResponse.count.intValue(); - switch (createCount) { - case 255: - System.out.println("non-authorized to create t_test table."); - break; - case 0: - System.out.println("t_test table already exist."); - break; - case 1: - System.out.println("create t_test table completed."); - break; - } + static Logger logger = LoggerFactory.getLogger(DBTestClient.class); + public static Web3j web3j; - } - // insert - else if ("insert".equals(args[0])) { - if (args.length == 4) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - - RemoteCall insert = - dbtest.insert(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt txReceipt = insert.send(); - List insertResultEvents = - dbtest.getInsertResultEvents(txReceipt); - if (insertResultEvents.size() > 0) { - for (int i = 0; i < insertResultEvents.size(); i++) { - InsertResultEventResponse insertResultEventResponse = insertResultEvents.get(i); - logger.info("insertCount = " + insertResultEventResponse.count.intValue()); - System.out.println("insertCount = " + insertResultEventResponse.count.intValue()); - } - } else { - System.out.println("t_test table does not exist."); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 insert fruit 1 apple"); - } - } - // select - else if ("select".equals(args[0])) { - if (args.length == 2) { + public static java.math.BigInteger gasPrice = new BigInteger("1"); + public static java.math.BigInteger gasLimit = new BigInteger("30000000"); + public static ECKeyPair keyPair; + public static Credentials credentials; + public static String contractAddress = ""; + + /* deploy the contract,get address from blockchain */ + @SuppressWarnings("deprecation") + public static void deployDBTest() { + + RemoteCall deploy = DBTest.deploy(web3j, credentials, gasPrice, gasLimit); + DBTest dbtest; try { - String keyName = args[1]; - Tuple3, List, List> lists = dbtest.read(keyName).send(); - List value1 = lists.getValue1(); - List value2 = lists.getValue2(); - List value3 = lists.getValue3(); - logger.info("record numbers = " + value1.size()); - System.out.println("record numbers = " + value1.size()); - for (int i = 0; i < value1.size(); i++) { - String name = new String(value1.get(i)); - logger.info("name = " + name); - System.out.println("name = " + name); - int item_id = value2.get(i).intValue(); - logger.info("item_id = " + item_id); - System.out.println("item_id = " + item_id); - String item_name = new String(value3.get(i)); - logger.info("item_name = " + item_name); - System.out.println("item_name = " + item_name); - } + dbtest = deploy.send(); + contractAddress = dbtest.getContractAddress(); + System.out.println("deploy contract address: " + contractAddress); + logger.info("deploy contract address: " + contractAddress); + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + prop.setProperty("crud_address", contractAddress); + prop.save(); + + System.out.println("deploy contract successful!"); + } catch (TransactionException e) { + if ("0x19".equals(e.getStatus())) { + System.out.println("non-authorized to deploy contracts!"); + } else { + System.out.println(e.getMessage()); + } } catch (Exception e) { - logger.info("record numbers = 0"); - System.out.println("record numbers = 0"); + System.out.println("deploy failed! " + e.getMessage()); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 select fruit"); - } } - // update - else if ("update".equals(args[0])) { - if (args.length == 4) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - RemoteCall update = - dbtest.update(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt transactionReceipt = update.send(); - List updateResultEvents = - dbtest.getUpdateResultEvents(transactionReceipt); - - if (updateResultEvents.size() > 0) { - for (int i = 0; i < updateResultEvents.size(); i++) { - UpdateResultEventResponse updateResultEventResponse = updateResultEvents.get(i); - System.out.println("updateCount = " + updateResultEventResponse.count.intValue()); - logger.info("updateCount = " + updateResultEventResponse.count.intValue()); - } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void testDBTest(String[] args) throws Exception { + + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + Object addressObj = prop.getProperty("crud_address"); + if (addressObj != null) { + contractAddress = (String) addressObj; } else { - System.out.println("t_test table does not exist."); + deployDBTest(); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 update fruit 1 orange"); - } - } - // remove - else if ("remove".equals(args[0])) { - if (args.length == 3) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - RemoteCall remove = dbtest.remove(name, BigInteger.valueOf(item_id)); - TransactionReceipt transactionReceipt = remove.send(); - List removeResultEvents = - dbtest.getRemoveResultEvents(transactionReceipt); - - if (removeResultEvents.size() > 0) { - RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0); - logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); - System.out.println("removeCount = " + reomveResultEventResponse.count.intValue()); + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + ; + DBTest dbtest = DBTest.load(contractAddress, web3j, credentials, contractGasProvider); + // create table + if ("create".equals(args[0])) { + TransactionReceipt receipt = dbtest.create().send(); + List createResultEvents = + dbtest.getCreateResultEvents(receipt); + if (createResultEvents.size() == 0) { + System.out.println("create t_test table failed."); + return; + } + CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); + int createCount = createResultEventResponse.count.intValue(); + switch (createCount) { + case 255: + System.out.println("non-authorized to create t_test table."); + break; + case 0: + System.out.println("t_test table already exist."); + break; + case 1: + System.out.println("create t_test table completed."); + break; + } + + } + // insert + else if ("insert".equals(args[0])) { + if (args.length == 4) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + + RemoteCall insert = + dbtest.insert(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt txReceipt = insert.send(); + List insertResultEvents = + dbtest.getInsertResultEvents(txReceipt); + if (insertResultEvents.size() > 0) { + for (int i = 0; i < insertResultEvents.size(); i++) { + InsertResultEventResponse insertResultEventResponse = + insertResultEvents.get(i); + logger.info("insertCount = " + insertResultEventResponse.count.intValue()); + System.out.println( + "insertCount = " + insertResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_test table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 insert fruit 1 apple"); + } + } + // select + else if ("select".equals(args[0])) { + if (args.length == 2) { + try { + String keyName = args[1]; + Tuple3, List, List> lists = + dbtest.read(keyName).send(); + List value1 = lists.getValue1(); + List value2 = lists.getValue2(); + List value3 = lists.getValue3(); + logger.info("record numbers = " + value1.size()); + System.out.println("record numbers = " + value1.size()); + for (int i = 0; i < value1.size(); i++) { + String name = new String(value1.get(i)); + logger.info("name = " + name); + System.out.println("name = " + name); + int item_id = value2.get(i).intValue(); + logger.info("item_id = " + item_id); + System.out.println("item_id = " + item_id); + String item_name = new String(value3.get(i)); + logger.info("item_name = " + item_name); + System.out.println("item_name = " + item_name); + } + } catch (Exception e) { + logger.info("record numbers = 0"); + System.out.println("record numbers = 0"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 select fruit"); + } + } + // update + else if ("update".equals(args[0])) { + if (args.length == 4) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + RemoteCall update = + dbtest.update(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt transactionReceipt = update.send(); + List updateResultEvents = + dbtest.getUpdateResultEvents(transactionReceipt); + + if (updateResultEvents.size() > 0) { + for (int i = 0; i < updateResultEvents.size(); i++) { + UpdateResultEventResponse updateResultEventResponse = + updateResultEvents.get(i); + System.out.println( + "updateCount = " + updateResultEventResponse.count.intValue()); + logger.info("updateCount = " + updateResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_test table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 update fruit 1 orange"); + } + } + // remove + else if ("remove".equals(args[0])) { + if (args.length == 3) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + RemoteCall remove = + dbtest.remove(name, BigInteger.valueOf(item_id)); + TransactionReceipt transactionReceipt = remove.send(); + List removeResultEvents = + dbtest.getRemoveResultEvents(transactionReceipt); + + if (removeResultEvents.size() > 0) { + RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0); + logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); + System.out.println( + "removeCount = " + reomveResultEventResponse.count.intValue()); + } else { + System.out.println("t_test table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 remove fruit 1"); + } } else { - System.out.println("t_test table does not exist."); + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 remove fruit 1"); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); - } - } - - public static void main(String[] args) throws Exception { - - // init the Service - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); // run the daemon service - // init the client keys - keyPair = Keys.createEcKeyPair(); - credentials = Credentials.create(keyPair); - - logger.info("-----> start test !"); - logger.info("init AOMP ChannelEthereumService"); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - try { - web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); - } catch (Exception e) { - System.out.println("\nPlease provide groupID in the first paramters"); - System.exit(0); } - if (args.length > 1) { - if ("deploy".equals(args[1])) { - deployDBTest(); - } else { - String[] params = new String[args.length - 1]; - for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; - testDBTest(params); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + public static void main(String[] args) throws Exception { + + // init the Service + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); // run the daemon service + // init the client keys + keyPair = Keys.createEcKeyPair(); + credentials = Credentials.create(keyPair); + + logger.info("-----> start test !"); + logger.info("init AOMP ChannelEthereumService"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + try { + web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); + } catch (Exception e) { + System.out.println("\nPlease provide groupID in the first paramters"); + System.exit(0); + } + + if (args.length > 1) { + if ("deploy".equals(args[1])) { + deployDBTest(); + } else { + String[] params = new String[args.length - 1]; + for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; + testDBTest(params); + } + } else { + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + } + System.exit(0); } - System.exit(0); - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/MixContract.java b/src/test/java/org/fisco/bcos/channel/test/contract/MixContract.java index 5295abcdb..17a550902 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/MixContract.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/MixContract.java @@ -40,490 +40,522 @@ *

Generated with web3j version none. */ public class MixContract extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b506121de806100206000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a101461007d578063488bdabc1461014a578063616ffe8314610175578063c4f41ab3146102c3578063ebf3b24f1461034a578063efc81a8c14610417575b600080fd5b34801561008957600080fd5b50610134600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061042e565b6040518082815260200191505060405180910390f35b34801561015657600080fd5b5061015f610b24565b6040518082815260200191505060405180910390f35b34801561018157600080fd5b506101dc600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610b2a565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561022757808201518184015260208101905061020c565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561026957808201518184015260208101905061024e565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156102ab578082015181840152602081019050610290565b50505050905001965050505050505060405180910390f35b3480156102cf57600080fd5b50610334600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506114e9565b6040518082815260200191505060405180910390f35b34801561035657600080fd5b50610401600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506119f2565b6040518082815260200191505060405180910390f35b34801561042357600080fd5b5061042c612020565b005b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104dc57600080fd5b505af11580156104f0573d6000803e3d6000fd5b505050506040513d602081101561050657600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561057d57600080fd5b505af1158015610591573d6000803e3d6000fd5b505050506040513d60208110156105a757600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561067a57808201518184015260208101905061065f565b50505050905090810190601f1680156106a75780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156106c757600080fd5b505af11580156106db573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561074357600080fd5b505af1158015610757573d6000803e3d6000fd5b505050506040513d602081101561076d57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610840578082015181840152602081019050610825565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561088d57600080fd5b505af11580156108a1573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561094d57600080fd5b505af1158015610961573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a53578082015181840152602081019050610a38565b50505050905090810190601f168015610a805780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610aa157600080fd5b505af1158015610ab5573d6000803e3d6000fd5b505050506040513d6020811015610acb57600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b60005481565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610be257600080fd5b505af1158015610bf6573d6000803e3d6000fd5b505050506040513d6020811015610c0c57600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c8357600080fd5b505af1158015610c97573d6000803e3d6000fd5b505050506040513d6020811015610cad57600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610d7b578082015181840152602081019050610d60565b50505050905090810190601f168015610da85780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610dc857600080fd5b505af1158015610ddc573d6000803e3d6000fd5b505050506040513d6020811015610df257600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610e6957600080fd5b505af1158015610e7d573d6000803e3d6000fd5b505050506040513d6020811015610e9357600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610ed25781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610f3957600080fd5b505af1158015610f4d573d6000803e3d6000fd5b505050506040513d6020811015610f6357600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610fa25781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561100957600080fd5b505af115801561101d573d6000803e3d6000fd5b505050506040513d602081101561103357600080fd5b81019080805190602001909291905050506040519080825280602002602001820160405280156110725781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505050506040513d602081101561110857600080fd5b81019080805190602001909291905050508212156114d0578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561118f57600080fd5b505af11580156111a3573d6000803e3d6000fd5b505050506040513d60208110156111b957600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561126c57600080fd5b505af1158015611280573d6000803e3d6000fd5b505050506040513d602081101561129657600080fd5b810190808051906020019092919050505085838151811015156112b557fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561136d57600080fd5b505af1158015611381573d6000803e3d6000fd5b505050506040513d602081101561139757600080fd5b810190808051906020019092919050505084838151811015156113b657fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b505050506040513d602081101561148e57600080fd5b810190808051906020019092919050505083838151811015156114ad57fe5b90602001906020020190600019169081600019168152505081600101915061107a565b8484849b509b509b505050505050505050509193909250565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561159657600080fd5b505af11580156115aa573d6000803e3d6000fd5b505050506040513d60208110156115c057600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561163757600080fd5b505af115801561164b573d6000803e3d6000fd5b505050506040513d602081101561166157600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611734578082015181840152602081019050611719565b50505050905090810190601f1680156117615780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561178157600080fd5b505af1158015611795573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561184157600080fd5b505af1158015611855573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156119145780820151818401526020810190506118f9565b50505050905090810190601f1680156119415780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561196157600080fd5b505af1158015611975573d6000803e3d6000fd5b505050506040513d602081101561198b57600080fd5b81019080805190602001909291905050509050600080815460019003919050819055507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611a9f57600080fd5b505af1158015611ab3573d6000803e3d6000fd5b505050506040513d6020811015611ac957600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611b4057600080fd5b505af1158015611b54573d6000803e3d6000fd5b505050506040513d6020811015611b6a57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611c3d578082015181840152602081019050611c22565b50505050905090810190601f168015611c6a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611c8a57600080fd5b505af1158015611c9e573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015611d4a57600080fd5b505af1158015611d5e573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611e22578082015181840152602081019050611e07565b50505050905090810190601f168015611e4f5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611e6f57600080fd5b505af1158015611e83573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611f42578082015181840152602081019050611f27565b50505050905090810190601f168015611f6f5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611f8f57600080fd5b505af1158015611fa3573d6000803e3d6000fd5b505050506040513d6020811015611fb957600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1600080815460010191905081905550809450505050509392505050565b60008061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b15801561213a57600080fd5b505af115801561214e573d6000803e3d6000fd5b505050506040513d602081101561216457600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a150505600a165627a7a72305820f74c6a35abc1f8fd480188a4b3caee48854d7cff40ded5821661707924b1809c0029"; - - public static final String FUNC_UPDATE = "update"; - - public static final String FUNC_TOTALKEYS = "totalKeys"; - - public static final String FUNC_READ = "read"; - - public static final String FUNC_REMOVE = "remove"; - - public static final String FUNC_INSERT = "insert"; - - public static final String FUNC_CREATE = "create"; - - public static final Event CREATERESULT_EVENT = - new Event("createResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event INSERTRESULT_EVENT = - new Event("insertResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event UPDATERESULT_EVENT = - new Event("updateResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event REMOVERESULT_EVENT = - new Event("removeResult", Arrays.>asList(new TypeReference() {}));; - - public static final Event READRESULT_EVENT = - new Event( - "readResult", - Arrays.>asList( - new TypeReference() {}, - new TypeReference() {}, - new TypeReference() {}));; - - @Deprecated - protected MixContract( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected MixContract( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected MixContract( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected MixContract( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall update(String name, BigInteger item_id, String item_name) { - final Function function = - new Function( - FUNC_UPDATE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void update( - String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_UPDATE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall totalKeys() { - final Function function = - new Function( - FUNC_TOTALKEYS, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall, List, List>> read(String name) { - final Function function = - new Function( - FUNC_READ, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), - Arrays.>asList( - new TypeReference>() {}, - new TypeReference>() {}, - new TypeReference>() {})); - return new RemoteCall, List, List>>( - new Callable, List, List>>() { - @Override - public Tuple3, List, List> call() throws Exception { - List results = executeCallMultipleValueReturn(function); - return new Tuple3, List, List>( - convertToNative((List) results.get(0).getValue()), - convertToNative((List) results.get(1).getValue()), - convertToNative((List) results.get(2).getValue())); - } - }); - } - - public RemoteCall remove(String name, BigInteger item_id) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void remove(String name, BigInteger item_id, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_REMOVE, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall insert(String name, BigInteger item_id, String item_name) { - final Function function = - new Function( - FUNC_INSERT, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void insert( - String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_INSERT, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall create() { - final Function function = - new Function(FUNC_CREATE, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void create(TransactionSucCallback callback) { - final Function function = - new Function(FUNC_CREATE, Arrays.asList(), Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public List getCreateResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - CreateResultEventResponse typedResponse = new CreateResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable createResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public CreateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(CREATERESULT_EVENT, log); - CreateResultEventResponse typedResponse = new CreateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable createResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(CREATERESULT_EVENT)); - return createResultEventFlowable(filter); - } - - public List getInsertResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable insertResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public InsertResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(INSERTRESULT_EVENT, log); - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable insertResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); - return insertResultEventFlowable(filter); - } - - public List getUpdateResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable updateResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public UpdateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(UPDATERESULT_EVENT, log); - UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable updateResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(UPDATERESULT_EVENT)); - return updateResultEventFlowable(filter); - } - - public List getRemoveResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable removeResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public RemoveResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(REMOVERESULT_EVENT, log); - RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable removeResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(REMOVERESULT_EVENT)); - return removeResultEventFlowable(filter); - } - - public List getReadResultEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(READRESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - ReadResultEventResponse typedResponse = new ReadResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable readResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public ReadResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(READRESULT_EVENT, log); - ReadResultEventResponse typedResponse = new ReadResultEventResponse(); - typedResponse.log = log; - typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = + private static final String BINARY = + "608060405234801561001057600080fd5b506121de806100206000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a101461007d578063488bdabc1461014a578063616ffe8314610175578063c4f41ab3146102c3578063ebf3b24f1461034a578063efc81a8c14610417575b600080fd5b34801561008957600080fd5b50610134600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061042e565b6040518082815260200191505060405180910390f35b34801561015657600080fd5b5061015f610b24565b6040518082815260200191505060405180910390f35b34801561018157600080fd5b506101dc600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610b2a565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561022757808201518184015260208101905061020c565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561026957808201518184015260208101905061024e565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156102ab578082015181840152602081019050610290565b50505050905001965050505050505060405180910390f35b3480156102cf57600080fd5b50610334600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506114e9565b6040518082815260200191505060405180910390f35b34801561035657600080fd5b50610401600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506119f2565b6040518082815260200191505060405180910390f35b34801561042357600080fd5b5061042c612020565b005b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104dc57600080fd5b505af11580156104f0573d6000803e3d6000fd5b505050506040513d602081101561050657600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561057d57600080fd5b505af1158015610591573d6000803e3d6000fd5b505050506040513d60208110156105a757600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561067a57808201518184015260208101905061065f565b50505050905090810190601f1680156106a75780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156106c757600080fd5b505af11580156106db573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561074357600080fd5b505af1158015610757573d6000803e3d6000fd5b505050506040513d602081101561076d57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610840578082015181840152602081019050610825565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561088d57600080fd5b505af11580156108a1573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561094d57600080fd5b505af1158015610961573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a53578082015181840152602081019050610a38565b50505050905090810190601f168015610a805780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610aa157600080fd5b505af1158015610ab5573d6000803e3d6000fd5b505050506040513d6020811015610acb57600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b60005481565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610be257600080fd5b505af1158015610bf6573d6000803e3d6000fd5b505050506040513d6020811015610c0c57600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c8357600080fd5b505af1158015610c97573d6000803e3d6000fd5b505050506040513d6020811015610cad57600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610d7b578082015181840152602081019050610d60565b50505050905090810190601f168015610da85780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610dc857600080fd5b505af1158015610ddc573d6000803e3d6000fd5b505050506040513d6020811015610df257600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610e6957600080fd5b505af1158015610e7d573d6000803e3d6000fd5b505050506040513d6020811015610e9357600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610ed25781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610f3957600080fd5b505af1158015610f4d573d6000803e3d6000fd5b505050506040513d6020811015610f6357600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015610fa25781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561100957600080fd5b505af115801561101d573d6000803e3d6000fd5b505050506040513d602081101561103357600080fd5b81019080805190602001909291905050506040519080825280602002602001820160405280156110725781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156110de57600080fd5b505af11580156110f2573d6000803e3d6000fd5b505050506040513d602081101561110857600080fd5b81019080805190602001909291905050508212156114d0578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15801561118f57600080fd5b505af11580156111a3573d6000803e3d6000fd5b505050506040513d60208110156111b957600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561126c57600080fd5b505af1158015611280573d6000803e3d6000fd5b505050506040513d602081101561129657600080fd5b810190808051906020019092919050505085838151811015156112b557fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561136d57600080fd5b505af1158015611381573d6000803e3d6000fd5b505050506040513d602081101561139757600080fd5b810190808051906020019092919050505084838151811015156113b657fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b505050506040513d602081101561148e57600080fd5b810190808051906020019092919050505083838151811015156114ad57fe5b90602001906020020190600019169081600019168152505081600101915061107a565b8484849b509b509b505050505050505050509193909250565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561159657600080fd5b505af11580156115aa573d6000803e3d6000fd5b505050506040513d60208110156115c057600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561163757600080fd5b505af115801561164b573d6000803e3d6000fd5b505050506040513d602081101561166157600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611734578082015181840152602081019050611719565b50505050905090810190601f1680156117615780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561178157600080fd5b505af1158015611795573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561184157600080fd5b505af1158015611855573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156119145780820151818401526020810190506118f9565b50505050905090810190601f1680156119415780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561196157600080fd5b505af1158015611975573d6000803e3d6000fd5b505050506040513d602081101561198b57600080fd5b81019080805190602001909291905050509050600080815460019003919050819055507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611a9f57600080fd5b505af1158015611ab3573d6000803e3d6000fd5b505050506040513d6020811015611ac957600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611b4057600080fd5b505af1158015611b54573d6000803e3d6000fd5b505050506040513d6020811015611b6a57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611c3d578082015181840152602081019050611c22565b50505050905090810190601f168015611c6a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611c8a57600080fd5b505af1158015611c9e573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015611d4a57600080fd5b505af1158015611d5e573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015611e22578082015181840152602081019050611e07565b50505050905090810190601f168015611e4f5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611e6f57600080fd5b505af1158015611e83573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611f42578082015181840152602081019050611f27565b50505050905090810190601f168015611f6f5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611f8f57600080fd5b505af1158015611fa3573d6000803e3d6000fd5b505050506040513d6020811015611fb957600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1600080815460010191905081905550809450505050509392505050565b60008061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f64656d6f0000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b15801561213a57600080fd5b505af115801561214e573d6000803e3d6000fd5b505050506040513d602081101561216457600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a150505600a165627a7a72305820f74c6a35abc1f8fd480188a4b3caee48854d7cff40ded5821661707924b1809c0029"; + + public static final String FUNC_UPDATE = "update"; + + public static final String FUNC_TOTALKEYS = "totalKeys"; + + public static final String FUNC_READ = "read"; + + public static final String FUNC_REMOVE = "remove"; + + public static final String FUNC_INSERT = "insert"; + + public static final String FUNC_CREATE = "create"; + + public static final Event CREATERESULT_EVENT = + new Event( + "createResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event INSERTRESULT_EVENT = + new Event( + "insertResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event UPDATERESULT_EVENT = + new Event( + "updateResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event REMOVERESULT_EVENT = + new Event( + "removeResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event READRESULT_EVENT = + new Event( + "readResult", + Arrays.>asList( + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}));; + + @Deprecated + protected MixContract( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected MixContract( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected MixContract( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected MixContract( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall update( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void update( + String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall totalKeys() { + final Function function = + new Function( + FUNC_TOTALKEYS, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall, List, List>> read(String name) { + final Function function = + new Function( + FUNC_READ, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), + Arrays.>asList( + new TypeReference>() {}, + new TypeReference>() {}, + new TypeReference>() {})); + return new RemoteCall, List, List>>( + new Callable, List, List>>() { + @Override + public Tuple3, List, List> call() + throws Exception { + List results = executeCallMultipleValueReturn(function); + return new Tuple3, List, List>( + convertToNative((List) results.get(0).getValue()), + convertToNative((List) results.get(1).getValue()), + convertToNative((List) results.get(2).getValue())); + } + }); + } + + public RemoteCall remove(String name, BigInteger item_id) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void remove(String name, BigInteger item_id, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall insert( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void insert( + String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall create() { + final Function function = + new Function( + FUNC_CREATE, + Arrays.asList(), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void create(TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_CREATE, + Arrays.asList(), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public List getCreateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CreateResultEventResponse typedResponse = new CreateResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable createResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public CreateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(CREATERESULT_EVENT, log); + CreateResultEventResponse typedResponse = + new CreateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable createResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CREATERESULT_EVENT)); + return createResultEventFlowable(filter); + } + + public List getInsertResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + InsertResultEventResponse typedResponse = new InsertResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable insertResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public InsertResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(INSERTRESULT_EVENT, log); + InsertResultEventResponse typedResponse = + new InsertResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable insertResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); + return insertResultEventFlowable(filter); + } + + public List getUpdateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable updateResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public UpdateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(UPDATERESULT_EVENT, log); + UpdateResultEventResponse typedResponse = + new UpdateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable updateResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(UPDATERESULT_EVENT)); + return updateResultEventFlowable(filter); + } + + public List getRemoveResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable removeResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public RemoveResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(REMOVERESULT_EVENT, log); + RemoveResultEventResponse typedResponse = + new RemoveResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable removeResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(REMOVERESULT_EVENT)); + return removeResultEventFlowable(filter); + } + + public List getReadResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(READRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + ReadResultEventResponse typedResponse = new ReadResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.item_name = - (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); - return typedResponse; - } - }); - } - - public Flowable readResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(READRESULT_EVENT)); - return readResultEventFlowable(filter); - } - - @Deprecated - public static MixContract load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new MixContract(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static MixContract load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new MixContract(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static MixContract load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new MixContract(contractAddress, web3j, credentials, contractGasProvider); - } - - public static MixContract load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new MixContract(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(MixContract.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(MixContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - MixContract.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - MixContract.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class CreateResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class InsertResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class UpdateResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class RemoveResultEventResponse { - public Log log; - - public BigInteger count; - } - - public static class ReadResultEventResponse { - public Log log; - - public byte[] name; - - public BigInteger item_id; - - public byte[] item_name; - } + typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable readResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public ReadResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(READRESULT_EVENT, log); + ReadResultEventResponse typedResponse = + new ReadResultEventResponse(); + typedResponse.log = log; + typedResponse.name = + (byte[]) + eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.item_id = + (BigInteger) + eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.item_name = + (byte[]) + eventValues.getNonIndexedValues().get(2).getValue(); + return typedResponse; + } + }); + } + + public Flowable readResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(READRESULT_EVENT)); + return readResultEventFlowable(filter); + } + + @Deprecated + public static MixContract load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new MixContract(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static MixContract load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new MixContract(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static MixContract load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new MixContract(contractAddress, web3j, credentials, contractGasProvider); + } + + public static MixContract load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new MixContract(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + MixContract.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + MixContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + MixContract.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + MixContract.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class CreateResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class InsertResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class UpdateResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class RemoveResultEventResponse { + public Log log; + + public BigInteger count; + } + + public static class ReadResultEventResponse { + public Log log; + + public byte[] name; + + public BigInteger item_id; + + public byte[] item_name; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/MixContractClient.java b/src/test/java/org/fisco/bcos/channel/test/contract/MixContractClient.java index a0f440bc5..fae86fab3 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/MixContractClient.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/MixContractClient.java @@ -27,227 +27,232 @@ import org.springframework.core.io.Resource; public class MixContractClient { - static Logger logger = LoggerFactory.getLogger(MixContractClient.class); - public static Web3j web3j; - // 初始化交易参数 - public static java.math.BigInteger gasPrice = new BigInteger("1"); - public static java.math.BigInteger gasLimit = new BigInteger("30000000"); - public static ECKeyPair keyPair; - public static Credentials credentials; - public static String contractAddress = ""; - - /* deploy the contract,get address from blockchain */ - @SuppressWarnings("deprecation") - public static void deploymixContract() { - - RemoteCall deploy = MixContract.deploy(web3j, credentials, gasPrice, gasLimit); - MixContract mixContract; - try { - mixContract = deploy.send(); - contractAddress = mixContract.getContractAddress(); - System.out.println("deploy contract address: " + contractAddress); - logger.info("deploy contract address: " + contractAddress); - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - prop.setProperty("mix_address", contractAddress); - prop.save(); - - System.out.println("deploy contract successful!"); - } catch (TransactionException e) { - if ("0x19".equals(e.getStatus())) { - System.out.println("non-authorized to deploy contracts!"); - } else { - System.out.println(e.getMessage()); - } - } catch (Exception e) { - System.out.println("deploy failed! " + e.getMessage()); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void testMixContract(String[] args) throws Exception { - - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - Object addressObj = prop.getProperty("mix_address"); - if (addressObj != null) { - contractAddress = (String) addressObj; - } else { - deploymixContract(); - } - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - ; - MixContract mixContract = - MixContract.load(contractAddress, web3j, credentials, contractGasProvider); - // create table - if ("create".equals(args[0])) { - TransactionReceipt receipt = mixContract.create().send(); - List createResultEvents = - mixContract.getCreateResultEvents(receipt); - if (createResultEvents.size() == 0) { - System.out.println("create t_demo table failed."); - return; - } - CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); - int createCount = createResultEventResponse.count.intValue(); - switch (createCount) { - case 255: - System.out.println("non-authorized to create t_demo table."); - break; - case 0: - System.out.println("t_demo table already exist."); - break; - case 1: - System.out.println("create t_demo table completed."); - break; - } + static Logger logger = LoggerFactory.getLogger(MixContractClient.class); + public static Web3j web3j; + // 初始化交易参数 + public static java.math.BigInteger gasPrice = new BigInteger("1"); + public static java.math.BigInteger gasLimit = new BigInteger("30000000"); + public static ECKeyPair keyPair; + public static Credentials credentials; + public static String contractAddress = ""; - } - // insert - else if ("insert".equals(args[0])) { - if (args.length == 4) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - - RemoteCall insert = - mixContract.insert(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt txReceipt = insert.send(); - List insertResultEvents = - mixContract.getInsertResultEvents(txReceipt); - if (insertResultEvents.size() > 0) { - for (int i = 0; i < insertResultEvents.size(); i++) { - InsertResultEventResponse insertResultEventResponse = insertResultEvents.get(i); - logger.info("insertCount = " + insertResultEventResponse.count.intValue()); - System.out.println("insertCount = " + insertResultEventResponse.count.intValue()); - } - } else { - System.out.println("t_demo table does not exist."); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 insert fruit 1 apple"); - } - } - // select - else if ("select".equals(args[0])) { - if (args.length == 2) { + /* deploy the contract,get address from blockchain */ + @SuppressWarnings("deprecation") + public static void deploymixContract() { + + RemoteCall deploy = MixContract.deploy(web3j, credentials, gasPrice, gasLimit); + MixContract mixContract; try { - String keyName = args[1]; - Tuple3, List, List> lists = - mixContract.read(keyName).send(); - List value1 = lists.getValue1(); - List value2 = lists.getValue2(); - List value3 = lists.getValue3(); - logger.info("record numbers = " + value1.size()); - System.out.println("record numbers = " + value1.size()); - for (int i = 0; i < value1.size(); i++) { - String name = new String(value1.get(i)); - logger.info("name = " + name); - System.out.println("name = " + name); - int item_id = value2.get(i).intValue(); - logger.info("item_id = " + item_id); - System.out.println("item_id = " + item_id); - String item_name = new String(value3.get(i)); - logger.info("item_name = " + item_name); - System.out.println("item_name = " + item_name); - } - System.out.println(); - System.out.println("totalKeys = " + mixContract.totalKeys().send()); + mixContract = deploy.send(); + contractAddress = mixContract.getContractAddress(); + System.out.println("deploy contract address: " + contractAddress); + logger.info("deploy contract address: " + contractAddress); + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + prop.setProperty("mix_address", contractAddress); + prop.save(); + System.out.println("deploy contract successful!"); + } catch (TransactionException e) { + if ("0x19".equals(e.getStatus())) { + System.out.println("non-authorized to deploy contracts!"); + } else { + System.out.println(e.getMessage()); + } } catch (Exception e) { - logger.info("record numbers = 0"); - System.out.println("record numbers = 0"); + System.out.println("deploy failed! " + e.getMessage()); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 select fruit"); - } } - // update - else if ("update".equals(args[0])) { - if (args.length == 4) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - RemoteCall update = - mixContract.update(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt transactionReceipt = update.send(); - List updateResultEvents = - mixContract.getUpdateResultEvents(transactionReceipt); - - if (updateResultEvents.size() > 0) { - for (int i = 0; i < updateResultEvents.size(); i++) { - UpdateResultEventResponse updateResultEventResponse = updateResultEvents.get(i); - System.out.println("updateCount = " + updateResultEventResponse.count.intValue()); - logger.info("updateCount = " + updateResultEventResponse.count.intValue()); - } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void testMixContract(String[] args) throws Exception { + + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + Object addressObj = prop.getProperty("mix_address"); + if (addressObj != null) { + contractAddress = (String) addressObj; } else { - System.out.println("t_demo table does not exist."); + deploymixContract(); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 update fruit 1 orange"); - } - } - // remove - else if ("remove".equals(args[0])) { - if (args.length == 3) { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - RemoteCall remove = - mixContract.remove(name, BigInteger.valueOf(item_id)); - TransactionReceipt transactionReceipt = remove.send(); - List removeResultEvents = - mixContract.getRemoveResultEvents(transactionReceipt); - - if (removeResultEvents.size() > 0) { - RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0); - logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); - System.out.println("removeCount = " + reomveResultEventResponse.count.intValue()); + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + ; + MixContract mixContract = + MixContract.load(contractAddress, web3j, credentials, contractGasProvider); + // create table + if ("create".equals(args[0])) { + TransactionReceipt receipt = mixContract.create().send(); + List createResultEvents = + mixContract.getCreateResultEvents(receipt); + if (createResultEvents.size() == 0) { + System.out.println("create t_demo table failed."); + return; + } + CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); + int createCount = createResultEventResponse.count.intValue(); + switch (createCount) { + case 255: + System.out.println("non-authorized to create t_demo table."); + break; + case 0: + System.out.println("t_demo table already exist."); + break; + case 1: + System.out.println("create t_demo table completed."); + break; + } + + } + // insert + else if ("insert".equals(args[0])) { + if (args.length == 4) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + + RemoteCall insert = + mixContract.insert(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt txReceipt = insert.send(); + List insertResultEvents = + mixContract.getInsertResultEvents(txReceipt); + if (insertResultEvents.size() > 0) { + for (int i = 0; i < insertResultEvents.size(); i++) { + InsertResultEventResponse insertResultEventResponse = + insertResultEvents.get(i); + logger.info("insertCount = " + insertResultEventResponse.count.intValue()); + System.out.println( + "insertCount = " + insertResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_demo table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 insert fruit 1 apple"); + } + } + // select + else if ("select".equals(args[0])) { + if (args.length == 2) { + try { + String keyName = args[1]; + Tuple3, List, List> lists = + mixContract.read(keyName).send(); + List value1 = lists.getValue1(); + List value2 = lists.getValue2(); + List value3 = lists.getValue3(); + logger.info("record numbers = " + value1.size()); + System.out.println("record numbers = " + value1.size()); + for (int i = 0; i < value1.size(); i++) { + String name = new String(value1.get(i)); + logger.info("name = " + name); + System.out.println("name = " + name); + int item_id = value2.get(i).intValue(); + logger.info("item_id = " + item_id); + System.out.println("item_id = " + item_id); + String item_name = new String(value3.get(i)); + logger.info("item_name = " + item_name); + System.out.println("item_name = " + item_name); + } + System.out.println(); + System.out.println("totalKeys = " + mixContract.totalKeys().send()); + + } catch (Exception e) { + logger.info("record numbers = 0"); + System.out.println("record numbers = 0"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 select fruit"); + } + } + // update + else if ("update".equals(args[0])) { + if (args.length == 4) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + RemoteCall update = + mixContract.update(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt transactionReceipt = update.send(); + List updateResultEvents = + mixContract.getUpdateResultEvents(transactionReceipt); + + if (updateResultEvents.size() > 0) { + for (int i = 0; i < updateResultEvents.size(); i++) { + UpdateResultEventResponse updateResultEventResponse = + updateResultEvents.get(i); + System.out.println( + "updateCount = " + updateResultEventResponse.count.intValue()); + logger.info("updateCount = " + updateResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_demo table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 update fruit 1 orange"); + } + } + // remove + else if ("remove".equals(args[0])) { + if (args.length == 3) { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + RemoteCall remove = + mixContract.remove(name, BigInteger.valueOf(item_id)); + TransactionReceipt transactionReceipt = remove.send(); + List removeResultEvents = + mixContract.getRemoveResultEvents(transactionReceipt); + + if (removeResultEvents.size() > 0) { + RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0); + logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); + System.out.println( + "removeCount = " + reomveResultEventResponse.count.intValue()); + } else { + System.out.println("t_demo table does not exist."); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 remove fruit 1"); + } } else { - System.out.println("t_demo table does not exist."); + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); } - } else { - System.out.println("\nPlease enter as follow example:\n 1 remove fruit 1"); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); - } - } - - public static void main(String[] args) throws Exception { - - // init the Service - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); // run the daemon service - // init the client keys - keyPair = Keys.createEcKeyPair(); - credentials = Credentials.create(keyPair); - - logger.info("-----> start test !"); - logger.info("init AOMP ChannelEthereumService"); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - try { - web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); - } catch (Exception e) { - System.out.println("\nPlease provide groupID in the first paramters"); - System.exit(0); } - if (args.length > 1) { - if ("deploy".equals(args[1])) { - deploymixContract(); - } else { - String[] params = new String[args.length - 1]; - for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; - testMixContract(params); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + public static void main(String[] args) throws Exception { + + // init the Service + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); // run the daemon service + // init the client keys + keyPair = Keys.createEcKeyPair(); + credentials = Credentials.create(keyPair); + + logger.info("-----> start test !"); + logger.info("init AOMP ChannelEthereumService"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + try { + web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); + } catch (Exception e) { + System.out.println("\nPlease provide groupID in the first paramters"); + System.exit(0); + } + + if (args.length > 1) { + if ("deploy".equals(args[1])) { + deploymixContract(); + } else { + String[] params = new String[args.length - 1]; + for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; + testMixContract(params); + } + } else { + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + } + System.exit(0); } - System.exit(0); - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/Ok.java b/src/test/java/org/fisco/bcos/channel/test/contract/Ok.java index 069538e44..0df245396 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/Ok.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/Ok.java @@ -36,182 +36,192 @@ *

Generated with web3j version none. */ public class Ok extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b5060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060006002600101819055506103bf806100c26000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806366c99139146100515780636d4ce63c1461007e575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100a9565b005b34801561008a57600080fd5b506100936102e1565b6040518082815260200191505060405180910390f35b8060006001015410806100c757506002600101548160026001015401105b156100d1576102de565b8060006001015403600060010181905550806002600101600082825401925050819055507fc77b710b83d1dc3f3fafeccd08a6c469beb873b2f0975b50d1698e46b3ee5b4c816040518082815260200191505060405180910390a160046080604051908101604052806040805190810160405280600881526020017f323031373034313300000000000000000000000000000000000000000000000081525081526020016000800160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152509080600181540180825580915050906001820390600052602060002090600402016000909192909190915060008201518160000190805190602001906102419291906102ee565b5060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301555050505b50565b6000600260010154905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032f57805160ff191683800117855561035d565b8280016001018555821561035d579182015b8281111561035c578251825591602001919060010190610341565b5b50905061036a919061036e565b5090565b61039091905b8082111561038c576000816000905550600101610374565b5090565b905600a165627a7a72305820fb983c66bee66788f407721b23b10a8aae3dc9ef8f1b09e08ec6a6c0b0ec70100029"; - - public static final String FUNC_TRANS = "trans"; - - public static final String FUNC_GET = "get"; - - public static final Event TRANSEVENT_EVENT = - new Event("TransEvent", Arrays.>asList(new TypeReference() {}));; - - @Deprecated - protected Ok( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected Ok( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected Ok( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected Ok( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall trans(BigInteger num) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void trans(BigInteger num, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public RemoteCall get() { - final Function function = - new Function( - FUNC_GET, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public List getTransEventEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(TRANSEVENT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - TransEventEventResponse typedResponse = new TransEventEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.num = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable transEventEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public TransEventEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(TRANSEVENT_EVENT, log); - TransEventEventResponse typedResponse = new TransEventEventResponse(); - typedResponse.log = log; - typedResponse.num = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable transEventEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(TRANSEVENT_EVENT)); - return transEventEventFlowable(filter); - } - - @Deprecated - public static Ok load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Ok(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static Ok load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Ok(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static Ok load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new Ok(contractAddress, web3j, credentials, contractGasProvider); - } - - public static Ok load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new Ok(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Ok.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Ok.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(Ok.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(Ok.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class TransEventEventResponse { - public Log log; - - public BigInteger num; - } + private static final String BINARY = + "608060405234801561001057600080fd5b5060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060006002600101819055506103bf806100c26000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806366c99139146100515780636d4ce63c1461007e575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100a9565b005b34801561008a57600080fd5b506100936102e1565b6040518082815260200191505060405180910390f35b8060006001015410806100c757506002600101548160026001015401105b156100d1576102de565b8060006001015403600060010181905550806002600101600082825401925050819055507fc77b710b83d1dc3f3fafeccd08a6c469beb873b2f0975b50d1698e46b3ee5b4c816040518082815260200191505060405180910390a160046080604051908101604052806040805190810160405280600881526020017f323031373034313300000000000000000000000000000000000000000000000081525081526020016000800160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152509080600181540180825580915050906001820390600052602060002090600402016000909192909190915060008201518160000190805190602001906102419291906102ee565b5060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301555050505b50565b6000600260010154905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032f57805160ff191683800117855561035d565b8280016001018555821561035d579182015b8281111561035c578251825591602001919060010190610341565b5b50905061036a919061036e565b5090565b61039091905b8082111561038c576000816000905550600101610374565b5090565b905600a165627a7a72305820fb983c66bee66788f407721b23b10a8aae3dc9ef8f1b09e08ec6a6c0b0ec70100029"; + + public static final String FUNC_TRANS = "trans"; + + public static final String FUNC_GET = "get"; + + public static final Event TRANSEVENT_EVENT = + new Event( + "TransEvent", + Arrays.>asList(new TypeReference() {}));; + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall trans(BigInteger num) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void trans(BigInteger num, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public RemoteCall get() { + final Function function = + new Function( + FUNC_GET, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public List getTransEventEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(TRANSEVENT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + TransEventEventResponse typedResponse = new TransEventEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.num = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable transEventEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public TransEventEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(TRANSEVENT_EVENT, log); + TransEventEventResponse typedResponse = + new TransEventEventResponse(); + typedResponse.log = log; + typedResponse.num = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable transEventEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSEVENT_EVENT)); + return transEventEventFlowable(filter); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, credentials, contractGasProvider); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(Ok.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Ok.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(Ok.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + Ok.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class TransEventEventResponse { + public Log log; + + public BigInteger num; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/OkClient.java b/src/test/java/org/fisco/bcos/channel/test/contract/OkClient.java index 089fb9a9c..e444b13db 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/OkClient.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/OkClient.java @@ -21,112 +21,112 @@ import org.springframework.core.io.Resource; public class OkClient { - static Logger logger = LoggerFactory.getLogger(OkClient.class); - public static Web3j web3j; - // 初始化交易参数 - public static java.math.BigInteger gasPrice = new BigInteger("1"); - public static java.math.BigInteger gasLimit = new BigInteger("30000000"); - public static ECKeyPair keyPair; - public static Credentials credentials; - public static String contractAddress = ""; + static Logger logger = LoggerFactory.getLogger(OkClient.class); + public static Web3j web3j; + // 初始化交易参数 + public static java.math.BigInteger gasPrice = new BigInteger("1"); + public static java.math.BigInteger gasLimit = new BigInteger("30000000"); + public static ECKeyPair keyPair; + public static Credentials credentials; + public static String contractAddress = ""; - /* deploy the contract,get address from blockchain */ - @SuppressWarnings("deprecation") - public static void deployOk() { + /* deploy the contract,get address from blockchain */ + @SuppressWarnings("deprecation") + public static void deployOk() { - RemoteCall deploy = Ok.deploy(web3j, credentials, gasPrice, gasLimit); - Ok ok; - try { - ok = deploy.send(); - contractAddress = ok.getContractAddress(); - System.out.println("deploy contract address: " + contractAddress); - logger.info("deploy contract address: " + contractAddress); - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - prop.setProperty("ok_address", contractAddress); - prop.save(); + RemoteCall deploy = Ok.deploy(web3j, credentials, gasPrice, gasLimit); + Ok ok; + try { + ok = deploy.send(); + contractAddress = ok.getContractAddress(); + System.out.println("deploy contract address: " + contractAddress); + logger.info("deploy contract address: " + contractAddress); + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + prop.setProperty("ok_address", contractAddress); + prop.save(); - System.out.println("deploy contract successful!"); - } catch (TransactionException e) { - if ("0x19".equals(e.getStatus())) { - System.out.println("non-authorized to deploy contracts!"); - } else { - System.out.println(e.getMessage()); - } - } catch (Exception e) { - System.out.println("deploy failed! " + e.getMessage()); + System.out.println("deploy contract successful!"); + } catch (TransactionException e) { + if ("0x19".equals(e.getStatus())) { + System.out.println("non-authorized to deploy contracts!"); + } else { + System.out.println(e.getMessage()); + } + } catch (Exception e) { + System.out.println("deploy failed! " + e.getMessage()); + } } - } - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void testOk(String[] args) throws Exception { + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void testOk(String[] args) throws Exception { - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - Object addressObj = prop.getProperty("ok_address"); - if (addressObj != null) { - contractAddress = (String) addressObj; - } else { - deployOk(); - } - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - ; - Ok ok = Ok.load(contractAddress, web3j, credentials, contractGasProvider); - // trans - if ("trans".equals(args[0])) { - if (args.length == 2) { - String num = args[1]; + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + Object addressObj = prop.getProperty("ok_address"); + if (addressObj != null) { + contractAddress = (String) addressObj; + } else { + deployOk(); + } + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + ; + Ok ok = Ok.load(contractAddress, web3j, credentials, contractGasProvider); + // trans + if ("trans".equals(args[0])) { + if (args.length == 2) { + String num = args[1]; - RemoteCall insert = ok.trans(new BigInteger(num)); - TransactionReceipt txReceipt = insert.send(); - System.out.println(txReceipt.getTransactionHash()); - } else { - System.out.println("\nPlease enter as follow example:\n 1 trans 5"); - } - } - // get - else if ("get".equals(args[0])) { - BigInteger num = ok.get().send(); - System.out.println("num = " + num); + RemoteCall insert = ok.trans(new BigInteger(num)); + TransactionReceipt txReceipt = insert.send(); + System.out.println(txReceipt.getTransactionHash()); + } else { + System.out.println("\nPlease enter as follow example:\n 1 trans 5"); + } + } + // get + else if ("get".equals(args[0])) { + BigInteger num = ok.get().send(); + System.out.println("num = " + num); - } else { - System.out.println("\nPlease choose follow commands:\n deploy, trans or get"); + } else { + System.out.println("\nPlease choose follow commands:\n deploy, trans or get"); + } } - } - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Exception { - // init the Service - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); // run the daemon service - // init the client keys - keyPair = Keys.createEcKeyPair(); - credentials = Credentials.create(keyPair); + // init the Service + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); // run the daemon service + // init the client keys + keyPair = Keys.createEcKeyPair(); + credentials = Credentials.create(keyPair); - logger.info("-----> start test !"); - logger.info("init AOMP ChannelEthereumService"); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - try { - web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); - } catch (Exception e) { - System.out.println("\nPlease provide groupID in the first paramters"); - System.exit(0); - } + logger.info("-----> start test !"); + logger.info("init AOMP ChannelEthereumService"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + try { + web3j = Web3j.build(channelEthereumService, Integer.parseInt(args[0])); + } catch (Exception e) { + System.out.println("\nPlease provide groupID in the first paramters"); + System.exit(0); + } - if (args.length > 1) { - if ("deploy".equals(args[1])) { - deployOk(); - } else { - String[] params = new String[args.length - 1]; - for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; - testOk(params); - } - } else { - System.out.println("\nPlease choose follow commands:\n deploy, trans or get"); + if (args.length > 1) { + if ("deploy".equals(args[1])) { + deployOk(); + } else { + String[] params = new String[args.length - 1]; + for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; + testOk(params); + } + } else { + System.out.println("\nPlease choose follow commands:\n deploy, trans or get"); + } + System.exit(0); } - System.exit(0); - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/OkD.java b/src/test/java/org/fisco/bcos/channel/test/contract/OkD.java index 0628d0c86..69f14e2d2 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/OkD.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/OkD.java @@ -36,187 +36,194 @@ *

Generated with web3j version none. */ public class OkD extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b50600080600060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060026001018190555061100192508273ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260048152602001807f745f6f6b000000000000000000000000000000000000000000000000000000008152506020018481038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001848103825260218152602001807f66726f6d5f62616c616e63652c746f5f6163636f75742c746f5f62616c616e6381526020017f65000000000000000000000000000000000000000000000000000000000000008152506040019350505050602060405180830381600087803b1580156101f557600080fd5b505af1158015610209573d6000803e3d6000fd5b505050506040513d602081101561021f57600080fd5b81019080805190602001909291905050505061100192508273ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f745f6f6b00000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050506040513d602081101561030057600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561037757600080fd5b505af115801561038b573d6000803e3d6000fd5b505050506040513d60208110156103a157600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001806020018381038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001838103825260038152602001807f307831000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561048d57600080fd5b505af11580156104a1573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632ef8ba746402540be4006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600c8152602001807f66726f6d5f62616c616e6365000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561055257600080fd5b505af1158015610566573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f746f5f6163636f75740000000000000000000000000000000000000000000000815250602001838103825260038152602001807f307832000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561064357600080fd5b505af1158015610657573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632ef8ba7460006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600a8152602001807f746f5f62616c616e63650000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561070457600080fd5b505af1158015610718573d6000803e3d6000fd5b505050505050506107f98061072e6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14610051578063abe181b51461007c575b600080fd5b34801561005d57600080fd5b506100666100ef565b6040518082815260200191505060405180910390f35b34801561008857600080fd5b506100ed600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506100fc565b005b6000600260010154905090565b60008060008084600060010154036000600101819055508460026001016000828254019250508190555061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f745f6f6b00000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156101cb57600080fd5b505af11580156101df573d6000803e3d6000fd5b505050506040513d60208110156101f557600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561026c57600080fd5b505af1158015610280573d6000803e3d6000fd5b505050506040513d602081101561029657600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001806020018381038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561036957808201518184015260208101905061034e565b50505050905090810190601f1680156103965780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156103b657600080fd5b505af11580156103ca573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba746000600101546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600c8152602001807f66726f6d5f62616c616e6365000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561047b57600080fd5b505af115801561048f573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f746f5f6163636f75740000000000000000000000000000000000000000000000815250602001838103825260038152602001807f307832000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561056c57600080fd5b505af1158015610580573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba746002600101546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600a8152602001807f746f5f62616c616e63650000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561063157600080fd5b505af1158015610645573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3687846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156107045780820151818401526020810190506106e9565b50505050905090810190601f1680156107315780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561075157600080fd5b505af1158015610765573d6000803e3d6000fd5b505050506040513d602081101561077b57600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a15050505050505600a165627a7a72305820766a85ac319262dcc91e61bbc2109bdc2369257905f4ca2b1751835597afff7b0029"; - - public static final String FUNC_GET = "get"; - - public static final String FUNC_TRANS = "trans"; - - public static final Event INSERTRESULT_EVENT = - new Event("insertResult", Arrays.>asList(new TypeReference() {}));; - - @Deprecated - protected OkD( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected OkD( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected OkD( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected OkD( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall get() { - final Function function = - new Function( - FUNC_GET, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall trans(String from_accout, BigInteger num) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from_accout), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(num)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public void trans(String from_accout, BigInteger num, TransactionSucCallback callback) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList( - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from_accout), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(num)), - Collections.>emptyList()); - asyncExecuteTransaction(function, callback); - } - - public List getInsertResultEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable insertResultEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public InsertResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(INSERTRESULT_EVENT, log); - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = log; - typedResponse.count = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable insertResultEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); - return insertResultEventFlowable(filter); - } - - @Deprecated - public static OkD load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new OkD(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static OkD load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new OkD(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static OkD load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new OkD(contractAddress, web3j, credentials, contractGasProvider); - } - - public static OkD load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new OkD(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(OkD.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(OkD.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(OkD.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(OkD.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class InsertResultEventResponse { - public Log log; - - public BigInteger count; - } + private static final String BINARY = + "608060405234801561001057600080fd5b50600080600060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060026001018190555061100192508273ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260048152602001807f745f6f6b000000000000000000000000000000000000000000000000000000008152506020018481038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001848103825260218152602001807f66726f6d5f62616c616e63652c746f5f6163636f75742c746f5f62616c616e6381526020017f65000000000000000000000000000000000000000000000000000000000000008152506040019350505050602060405180830381600087803b1580156101f557600080fd5b505af1158015610209573d6000803e3d6000fd5b505050506040513d602081101561021f57600080fd5b81019080805190602001909291905050505061100192508273ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f745f6f6b00000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050506040513d602081101561030057600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561037757600080fd5b505af115801561038b573d6000803e3d6000fd5b505050506040513d60208110156103a157600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001806020018381038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001838103825260038152602001807f307831000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561048d57600080fd5b505af11580156104a1573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632ef8ba746402540be4006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600c8152602001807f66726f6d5f62616c616e6365000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561055257600080fd5b505af1158015610566573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f746f5f6163636f75740000000000000000000000000000000000000000000000815250602001838103825260038152602001807f307832000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561064357600080fd5b505af1158015610657573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632ef8ba7460006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600a8152602001807f746f5f62616c616e63650000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561070457600080fd5b505af1158015610718573d6000803e3d6000fd5b505050505050506107f98061072e6000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14610051578063abe181b51461007c575b600080fd5b34801561005d57600080fd5b506100666100ef565b6040518082815260200191505060405180910390f35b34801561008857600080fd5b506100ed600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506100fc565b005b6000600260010154905090565b60008060008084600060010154036000600101819055508460026001016000828254019250508190555061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f745f6f6b00000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156101cb57600080fd5b505af11580156101df573d6000803e3d6000fd5b505050506040513d60208110156101f557600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561026c57600080fd5b505af1158015610280573d6000803e3d6000fd5b505050506040513d602081101561029657600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001806020018381038352600b8152602001807f66726f6d5f6163636f7574000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561036957808201518184015260208101905061034e565b50505050905090810190601f1680156103965780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156103b657600080fd5b505af11580156103ca573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba746000600101546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600c8152602001807f66726f6d5f62616c616e6365000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561047b57600080fd5b505af115801561048f573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b5166040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f746f5f6163636f75740000000000000000000000000000000000000000000000815250602001838103825260038152602001807f307832000000000000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561056c57600080fd5b505af1158015610580573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba746002600101546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252600a8152602001807f746f5f62616c616e63650000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561063157600080fd5b505af1158015610645573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3687846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b838110156107045780820151818401526020810190506106e9565b50505050905090810190601f1680156107315780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561075157600080fd5b505af1158015610765573d6000803e3d6000fd5b505050506040513d602081101561077b57600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a15050505050505600a165627a7a72305820766a85ac319262dcc91e61bbc2109bdc2369257905f4ca2b1751835597afff7b0029"; + + public static final String FUNC_GET = "get"; + + public static final String FUNC_TRANS = "trans"; + + public static final Event INSERTRESULT_EVENT = + new Event( + "insertResult", + Arrays.>asList(new TypeReference() {}));; + + @Deprecated + protected OkD( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected OkD( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected OkD( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected OkD( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall get() { + final Function function = + new Function( + FUNC_GET, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall trans(String from_accout, BigInteger num) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from_accout), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(num)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public void trans(String from_accout, BigInteger num, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from_accout), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(num)), + Collections.>emptyList()); + asyncExecuteTransaction(function, callback); + } + + public List getInsertResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + InsertResultEventResponse typedResponse = new InsertResultEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable insertResultEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public InsertResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(INSERTRESULT_EVENT, log); + InsertResultEventResponse typedResponse = + new InsertResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable insertResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); + return insertResultEventFlowable(filter); + } + + @Deprecated + public static OkD load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new OkD(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static OkD load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new OkD(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static OkD load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new OkD(contractAddress, web3j, credentials, contractGasProvider); + } + + public static OkD load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new OkD(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(OkD.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + OkD.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(OkD.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + OkD.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class InsertResultEventResponse { + public Log log; + + public BigInteger count; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/OkTest.java b/src/test/java/org/fisco/bcos/channel/test/contract/OkTest.java deleted file mode 100644 index 1fdd8f700..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/contract/OkTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.fisco.bcos.channel.test.contract; - -import org.fisco.bcos.channel.test.TestBase; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.core.RemoteCall; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.web3j.tx.Contract; -import org.junit.Test; - -import java.lang.reflect.Method; -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class OkTest extends TestBase { - - public static Class contractClass; - public String contractName; - public RemoteCall remoteCall; - public String contractAddress; - public java.math.BigInteger gasPrice = new BigInteger("300000000"); - public java.math.BigInteger gasLimit = new BigInteger("300000000"); - - @Test - public void testOkContract() throws Exception { - - Ok okDemo = Ok.deploy(web3j, credentials, gasPrice, gasLimit).send(); - - if (okDemo != null) { - System.out.println("####contract address is: " + okDemo.getContractAddress()); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - assertTrue(receipt.getBlockNumber().intValue() > 0); - assertTrue(receipt.getTransactionIndex().intValue() >= 0); - assertTrue(receipt.getGasUsed().intValue() > 0); - BigInteger oldBalance = okDemo.get().sendAsync().get(60000, TimeUnit.MILLISECONDS); - okDemo.trans(new BigInteger("4")).sendAsync().get(60000, TimeUnit.MILLISECONDS); - BigInteger newBalance = okDemo.get().sendAsync().get(60000, TimeUnit.MILLISECONDS); - System.out.println("####newBalance is: " + oldBalance.intValue()); - assertTrue(newBalance.intValue() == oldBalance.intValue() + 4); - } - } - - @Test - public void testLoadClass() throws Exception { - - contractName = "org.fisco.bcos.channel.test.contract." + "Ok"; - contractClass = Class.forName(contractName); - Method deploy = - contractClass.getMethod( - "deploy", Web3j.class, Credentials.class, BigInteger.class, BigInteger.class); - remoteCall = (RemoteCall) deploy.invoke(null, web3j, credentials, gasPrice, gasLimit); - Contract contract = (Contract) remoteCall.send(); - contractAddress = contract.getContractAddress(); - System.out.println(contractAddress); - - Method load = - contractClass.getMethod( - "load", - String.class, - Web3j.class, - Credentials.class, - BigInteger.class, - BigInteger.class); - Object contractObject = - load.invoke(null, contractAddress, web3j, credentials, gasPrice, gasLimit); - assertNotNull(contractObject); - System.out.println(contractObject.toString()); - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceCollector.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceCollector.java index d46bc37f2..f2bea5d3f 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceCollector.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceCollector.java @@ -7,247 +7,252 @@ import org.slf4j.LoggerFactory; public class PerfomanceCollector { - static Logger logger = LoggerFactory.getLogger(PerfomanceCollector.class); - - public Integer getTotal() { - return total; - } - - public void setTotal(Integer total) { - this.total = total; - } - - public void onMessage(TransactionReceipt receipt, Long cost) { - try { - if (!receipt.isStatusOK()) { - System.out.println("receipt error"); - error.addAndGet(1); - } else { - if (receipt.getLogs().isEmpty()) { - System.out.println("receipt log error"); - error.addAndGet(1); + static Logger logger = LoggerFactory.getLogger(PerfomanceCollector.class); + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public void onMessage(TransactionReceipt receipt, Long cost) { + try { + if (!receipt.isStatusOK()) { + System.out.println("receipt error"); + error.addAndGet(1); + } else { + if (receipt.getLogs().isEmpty()) { + System.out.println("receipt log error"); + error.addAndGet(1); + } + } + + received.incrementAndGet(); + + if ((received.get() + 1) % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf((received.get() + 1) * 100 / total) + + "%"); + } + + if (cost < 50) { + less50.incrementAndGet(); + } else if (cost < 100) { + less100.incrementAndGet(); + ; + } else if (cost < 200) { + less200.incrementAndGet(); + ; + } else if (cost < 400) { + less400.incrementAndGet(); + ; + } else if (cost < 1000) { + less1000.incrementAndGet(); + ; + } else if (cost < 2000) { + less2000.incrementAndGet(); + ; + } else { + timeout2000.incrementAndGet(); + ; + } + + totalCost.addAndGet(cost); + + if (received.intValue() >= total) { + System.out.println("total"); + + // 总耗时 + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + System.out.println("Total transactions: " + String.valueOf(total)); + System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); + System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println( + "Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); + System.out.println( + "Error rate: " + + String.valueOf((error.get() / received.get()) * 100) + + "%"); + + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50.get() / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100.get() / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200.get() / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400.get() / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000.get() / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000.get() / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000.get() / total * 100) + + "%"); + + System.exit(0); + } + } catch (Exception e) { + logger.error("error:", e); } - } - - received.incrementAndGet(); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println( - " |received:" - + String.valueOf((received.get() + 1) * 100 / total) - + "%"); - } - - if (cost < 50) { - less50.incrementAndGet(); - } else if (cost < 100) { - less100.incrementAndGet(); - ; - } else if (cost < 200) { - less200.incrementAndGet(); - ; - } else if (cost < 400) { - less400.incrementAndGet(); - ; - } else if (cost < 1000) { - less1000.incrementAndGet(); - ; - } else if (cost < 2000) { - less2000.incrementAndGet(); - ; - } else { - timeout2000.incrementAndGet(); - ; - } - - totalCost.addAndGet(cost); - - if (received.intValue() >= total) { - System.out.println("total"); - - // 总耗时 - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - System.out.println("Total transactions: " + String.valueOf(total)); - System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); - System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); - System.out.println( - "Error rate: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - - System.out.println("Time area:"); - System.out.println( - "0 < time < 50ms : " - + String.valueOf(less50) - + " : " - + String.valueOf((double) less50.get() / total * 100) - + "%"); - System.out.println( - "50 < time < 100ms : " - + String.valueOf(less100) - + " : " - + String.valueOf((double) less100.get() / total * 100) - + "%"); - System.out.println( - "100 < time < 200ms : " - + String.valueOf(less200) - + " : " - + String.valueOf((double) less200.get() / total * 100) - + "%"); - System.out.println( - "200 < time < 400ms : " - + String.valueOf(less400) - + " : " - + String.valueOf((double) less400.get() / total * 100) - + "%"); - System.out.println( - "400 < time < 1000ms : " - + String.valueOf(less1000) - + " : " - + String.valueOf((double) less1000.get() / total * 100) - + "%"); - System.out.println( - "1000 < time < 2000ms : " - + String.valueOf(less2000) - + " : " - + String.valueOf((double) less2000.get() / total * 100) - + "%"); - System.out.println( - "2000 < time : " - + String.valueOf(timeout2000) - + " : " - + String.valueOf((double) timeout2000.get() / total * 100) - + "%"); - - System.exit(0); - } - } catch (Exception e) { - logger.error("error:", e); } - } - - - public void onSelectMessage(TransactionReceipt receipt, Long cost) { - try { - if (!receipt.isStatusOK()) { - System.out.println("receipt error"); - error.addAndGet(1); - } - - received.incrementAndGet(); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println( - " |received:" - + String.valueOf((received.get() + 1) * 100 / total) - + "%"); - } - - if (cost < 50) { - less50.incrementAndGet(); - } else if (cost < 100) { - less100.incrementAndGet(); - ; - } else if (cost < 200) { - less200.incrementAndGet(); - ; - } else if (cost < 400) { - less400.incrementAndGet(); - ; - } else if (cost < 1000) { - less1000.incrementAndGet(); - ; - } else if (cost < 2000) { - less2000.incrementAndGet(); - ; - } else { - timeout2000.incrementAndGet(); - ; - } - - totalCost.addAndGet(cost); - - if (received.intValue() >= total) { - System.out.println("total"); - - // 总耗时 - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - System.out.println("Total transactions: " + String.valueOf(total)); - System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); - System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); - System.out.println( - "Error rate: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - - System.out.println("Time area:"); - System.out.println( - "0 < time < 50ms : " - + String.valueOf(less50) - + " : " - + String.valueOf((double) less50.get() / total * 100) - + "%"); - System.out.println( - "50 < time < 100ms : " - + String.valueOf(less100) - + " : " - + String.valueOf((double) less100.get() / total * 100) - + "%"); - System.out.println( - "100 < time < 200ms : " - + String.valueOf(less200) - + " : " - + String.valueOf((double) less200.get() / total * 100) - + "%"); - System.out.println( - "200 < time < 400ms : " - + String.valueOf(less400) - + " : " - + String.valueOf((double) less400.get() / total * 100) - + "%"); - System.out.println( - "400 < time < 1000ms : " - + String.valueOf(less1000) - + " : " - + String.valueOf((double) less1000.get() / total * 100) - + "%"); - System.out.println( - "1000 < time < 2000ms : " - + String.valueOf(less2000) - + " : " - + String.valueOf((double) less2000.get() / total * 100) - + "%"); - System.out.println( - "2000 < time : " - + String.valueOf(timeout2000) - + " : " - + String.valueOf((double) timeout2000.get() / total * 100) - + "%"); - - System.exit(0); - } - } catch (Exception e) { - logger.error("error:", e); - } - } - - - - private AtomicLong less50 = new AtomicLong(0); - private AtomicLong less100 = new AtomicLong(0); - private AtomicLong less200 = new AtomicLong(0); - private AtomicLong less400 = new AtomicLong(0); - private AtomicLong less1000 = new AtomicLong(0); - private AtomicLong less2000 = new AtomicLong(0); - private AtomicLong timeout2000 = new AtomicLong(0); - private AtomicLong totalCost = new AtomicLong(0); - - private Integer total = 0; - private AtomicInteger received = new AtomicInteger(0); - private AtomicInteger error = new AtomicInteger(0); - private Long startTimestamp = System.currentTimeMillis(); + + public void onSelectMessage(TransactionReceipt receipt, Long cost) { + try { + if (!receipt.isStatusOK()) { + System.out.println("receipt error"); + error.addAndGet(1); + } + + received.incrementAndGet(); + + if ((received.get() + 1) % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf((received.get() + 1) * 100 / total) + + "%"); + } + + if (cost < 50) { + less50.incrementAndGet(); + } else if (cost < 100) { + less100.incrementAndGet(); + ; + } else if (cost < 200) { + less200.incrementAndGet(); + ; + } else if (cost < 400) { + less400.incrementAndGet(); + ; + } else if (cost < 1000) { + less1000.incrementAndGet(); + ; + } else if (cost < 2000) { + less2000.incrementAndGet(); + ; + } else { + timeout2000.incrementAndGet(); + ; + } + + totalCost.addAndGet(cost); + + if (received.intValue() >= total) { + System.out.println("total"); + + // 总耗时 + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + System.out.println("Total transactions: " + String.valueOf(total)); + System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); + System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println( + "Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); + System.out.println( + "Error rate: " + + String.valueOf((error.get() / received.get()) * 100) + + "%"); + + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50.get() / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100.get() / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200.get() / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400.get() / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000.get() / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000.get() / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000.get() / total * 100) + + "%"); + + System.exit(0); + } + } catch (Exception e) { + logger.error("error:", e); + } + } + + private AtomicLong less50 = new AtomicLong(0); + private AtomicLong less100 = new AtomicLong(0); + private AtomicLong less200 = new AtomicLong(0); + private AtomicLong less400 = new AtomicLong(0); + private AtomicLong less1000 = new AtomicLong(0); + private AtomicLong less2000 = new AtomicLong(0); + private AtomicLong timeout2000 = new AtomicLong(0); + private AtomicLong totalCost = new AtomicLong(0); + + private Integer total = 0; + private AtomicInteger received = new AtomicInteger(0); + private AtomicInteger error = new AtomicInteger(0); + private Long startTimestamp = System.currentTimeMillis(); } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableInsert.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableInsert.java index ac806c5e4..21bb3f2dd 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableInsert.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableInsert.java @@ -2,15 +2,12 @@ import com.google.common.util.concurrent.RateLimiter; import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Random; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; @@ -23,117 +20,125 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerfomanceTableInsert { - private static Logger logger = LoggerFactory.getLogger(PerfomanceTableInsert.class); - private static AtomicInteger sended = new AtomicInteger(0); - - - private static String getId(){ - UUID uuid = UUID.randomUUID(); - return uuid.toString().replace("-", ""); - } - - - private static AtomicLong uniqeid = new AtomicLong(0); - - public static long getNextID() { - return uniqeid.getAndIncrement(); - } - - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = - Web3j.build( - channelEthereumService, - 15 * 100, - scheduledExecutorService, - Integer.parseInt(groupId)); - - Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerfomanceCollector collector = new PerfomanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - Random random = new Random(System.currentTimeMillis()); - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute( - new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerfomanceTableTestCallback callback = new PerfomanceTableTestCallback(); - callback.setCollector(collector); - try { - long _id = getNextID(); - tabletest.insert("fruit"+_id%TableTestClient.modevalue, - BigInteger.valueOf(_id), - "apple"+getId(),callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.error("Error sending:", e); - } - - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); - } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); + private static Logger logger = LoggerFactory.getLogger(PerfomanceTableInsert.class); + private static AtomicInteger sended = new AtomicInteger(0); + + private static String getId() { + UUID uuid = UUID.randomUUID(); + return uuid.toString().replace("-", ""); + } + + private static AtomicLong uniqeid = new AtomicLong(0); + + public static long getNextID() { + return uniqeid.getAndIncrement(); + } + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); + } + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerfomanceCollector collector = new PerfomanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + Random random = new Random(System.currentTimeMillis()); + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerfomanceTableTestCallback callback = + new PerfomanceTableTestCallback(); + callback.setCollector(collector); + try { + long _id = getNextID(); + tabletest.insert( + "fruit" + _id % TableTestClient.modevalue, + BigInteger.valueOf(_id), + "apple" + getId(), + callback); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.error("Error sending:", e); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableModify.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableModify.java index d5fb8cbe4..fae8fae4f 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableModify.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableModify.java @@ -2,15 +2,12 @@ import com.google.common.util.concurrent.RateLimiter; import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Random; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; @@ -23,120 +20,127 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerfomanceTableModify { - private static Logger logger = LoggerFactory.getLogger(PerfomanceTableModify.class); - private static AtomicInteger sended = new AtomicInteger(0); - - - private static String getId(){ - UUID uuid = UUID.randomUUID(); - return uuid.toString().replace("-", ""); - } - - - private static AtomicLong uniqeid = new AtomicLong(0); - - public static long getNextID() { - return uniqeid.getAndIncrement(); - } - - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = - Web3j.build( - channelEthereumService, - 15 * 100, - scheduledExecutorService, - Integer.parseInt(groupId)); - - Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerfomanceCollector collector = new PerfomanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - Random random = new Random(System.currentTimeMillis()); - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute( - new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerfomanceTableTestCallback callback = new PerfomanceTableTestCallback(); - callback.setCollector(collector); - try { - long _id = getNextID(); - Random r=new Random(); - long l1=r.nextLong(); - tabletest.update("fruit"+l1%TableTestClient.modevalue, - BigInteger.valueOf(_id), - "apple"+getId(), - callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.error("Error sending:", e); - } - - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); - } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); + private static Logger logger = LoggerFactory.getLogger(PerfomanceTableModify.class); + private static AtomicInteger sended = new AtomicInteger(0); + + private static String getId() { + UUID uuid = UUID.randomUUID(); + return uuid.toString().replace("-", ""); + } + + private static AtomicLong uniqeid = new AtomicLong(0); + + public static long getNextID() { + return uniqeid.getAndIncrement(); + } + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); + } + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerfomanceCollector collector = new PerfomanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + Random random = new Random(System.currentTimeMillis()); + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerfomanceTableTestCallback callback = + new PerfomanceTableTestCallback(); + callback.setCollector(collector); + try { + long _id = getNextID(); + Random r = new Random(); + long l1 = r.nextLong(); + tabletest.update( + "fruit" + l1 % TableTestClient.modevalue, + BigInteger.valueOf(_id), + "apple" + getId(), + callback); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.error("Error sending:", e); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableQuery.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableQuery.java index 6098537cf..51e6d0bbe 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableQuery.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableQuery.java @@ -2,8 +2,6 @@ import com.google.common.util.concurrent.RateLimiter; import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; import java.util.Random; import java.util.UUID; @@ -11,7 +9,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; @@ -25,146 +22,158 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerfomanceTableQuery { - private static Logger logger = LoggerFactory.getLogger(PerfomanceTableQuery.class); - private static AtomicInteger sended = new AtomicInteger(0); - - - private static String getId(){ - UUID uuid = UUID.randomUUID(); - return uuid.toString().replace("-", ""); - } - - - private static AtomicLong uniqeid = new AtomicLong(0); - - public static long getNextID() { - return uniqeid.getAndIncrement(); - } - - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = - Web3j.build( - channelEthereumService, - 15 * 100, - scheduledExecutorService, - Integer.parseInt(groupId)); - - Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerfomanceCollector collector = new PerfomanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - Random random = new Random(System.currentTimeMillis()); - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute( - new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerfomanceTableTestCallback callback = new PerfomanceTableTestCallback(); - callback.setCollector(collector); - try { - - Long time_before = System.currentTimeMillis(); - long _id = getNextID(); - Random r=new Random(); - long l1=r.nextLong(); - Tuple3, List, List> lists = - tabletest.select("fruit"+l1%TableTestClient.modevalue).send(); - Long time_after = System.currentTimeMillis(); - - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("0"); - collector.onSelectMessage(receipt, time_after-time_before); - - /* - List value1 = lists.getValue1(); - List value2 = lists.getValue2(); - List value3 = lists.getValue3(); - logger.info("record numbers = " + value1.size()); - System.out.println("record numbers = " + value1.size()); - for (int i = 0; i < value1.size(); i++) { - String name = new String(value1.get(i)); - logger.info("name = " + name); - System.out.println("name = " + name); - int item_id = value2.get(i).intValue(); - logger.info("item_id = " + item_id); - System.out.println("item_id = " + item_id); - String item_name = new String(value3.get(i)); - logger.info("item_name = " + item_name); - System.out.println("item_name = " + item_name); - } - - */ - - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.error("Error sending:", e); - } - - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); - } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); + private static Logger logger = LoggerFactory.getLogger(PerfomanceTableQuery.class); + private static AtomicInteger sended = new AtomicInteger(0); + + private static String getId() { + UUID uuid = UUID.randomUUID(); + return uuid.toString().replace("-", ""); + } + + private static AtomicLong uniqeid = new AtomicLong(0); + + public static long getNextID() { + return uniqeid.getAndIncrement(); + } + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); + } + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerfomanceCollector collector = new PerfomanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + Random random = new Random(System.currentTimeMillis()); + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerfomanceTableTestCallback callback = + new PerfomanceTableTestCallback(); + callback.setCollector(collector); + try { + + Long time_before = System.currentTimeMillis(); + long _id = getNextID(); + Random r = new Random(); + long l1 = r.nextLong(); + Tuple3, List, List> lists = + tabletest + .select( + "fruit" + + l1 + % TableTestClient + .modevalue) + .send(); + Long time_after = System.currentTimeMillis(); + + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("0"); + collector.onSelectMessage(receipt, time_after - time_before); + + /* + List value1 = lists.getValue1(); + List value2 = lists.getValue2(); + List value3 = lists.getValue3(); + logger.info("record numbers = " + value1.size()); + System.out.println("record numbers = " + value1.size()); + for (int i = 0; i < value1.size(); i++) { + String name = new String(value1.get(i)); + logger.info("name = " + name); + System.out.println("name = " + name); + int item_id = value2.get(i).intValue(); + logger.info("item_id = " + item_id); + System.out.println("item_id = " + item_id); + String item_name = new String(value3.get(i)); + logger.info("item_name = " + item_name); + System.out.println("item_name = " + item_name); + } + + */ + + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.error("Error sending:", e); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableRemove.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableRemove.java index 88fe4b067..796fd4018 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableRemove.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableRemove.java @@ -2,15 +2,12 @@ import com.google.common.util.concurrent.RateLimiter; import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Random; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; @@ -23,119 +20,127 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerfomanceTableRemove { - private static Logger logger = LoggerFactory.getLogger(PerfomanceTableRemove.class); - private static AtomicInteger sended = new AtomicInteger(0); - - - private static String getId(){ - UUID uuid = UUID.randomUUID(); - return uuid.toString().replace("-", ""); - } - - - private static AtomicLong uniqeid = new AtomicLong(0); - - public static long getNextID() { - return uniqeid.getAndIncrement(); - } - - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = - Web3j.build( - channelEthereumService, - 15 * 100, - scheduledExecutorService, - Integer.parseInt(groupId)); - - Credentials credentials = - Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerfomanceCollector collector = new PerfomanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - Random random = new Random(System.currentTimeMillis()); - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute( - new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerfomanceTableTestCallback callback = new PerfomanceTableTestCallback(); - callback.setCollector(collector); - try { - long _id = getNextID(); - Random r=new Random(); - long l1=r.nextLong(); - tabletest.remove("fruit"+l1%TableTestClient.modevalue, - BigInteger.valueOf(_id), callback); - - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.error("Error sending:", e); - } - - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); - } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); + private static Logger logger = LoggerFactory.getLogger(PerfomanceTableRemove.class); + private static AtomicInteger sended = new AtomicInteger(0); + + private static String getId() { + UUID uuid = UUID.randomUUID(); + return uuid.toString().replace("-", ""); + } + + private static AtomicLong uniqeid = new AtomicLong(0); + + public static long getNextID() { + return uniqeid.getAndIncrement(); + } + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); + } + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + TableTest tabletest = TableTest.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerfomanceCollector collector = new PerfomanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + Random random = new Random(System.currentTimeMillis()); + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerfomanceTableTestCallback callback = + new PerfomanceTableTestCallback(); + callback.setCollector(collector); + try { + long _id = getNextID(); + Random r = new Random(); + long l1 = r.nextLong(); + tabletest.remove( + "fruit" + l1 % TableTestClient.modevalue, + BigInteger.valueOf(_id), + callback); + + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.error("Error sending:", e); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableTestCallback.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableTestCallback.java index 875bf2ba3..0af09dce4 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableTestCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerfomanceTableTestCallback.java @@ -8,33 +8,33 @@ import org.slf4j.LoggerFactory; public class PerfomanceTableTestCallback extends TransactionSucCallback { - private static ObjectMapper objectMapper = new ObjectMapper(); - private Long startTime = System.currentTimeMillis(); + private static ObjectMapper objectMapper = new ObjectMapper(); + private Long startTime = System.currentTimeMillis(); - private PerfomanceCollector collector; + private PerfomanceCollector collector; - public PerfomanceCollector getCollector() { - return collector; - } + public PerfomanceCollector getCollector() { + return collector; + } - public void setCollector(PerfomanceCollector collector) { - this.collector = collector; - } + public void setCollector(PerfomanceCollector collector) { + this.collector = collector; + } - static Logger logger = LoggerFactory.getLogger(PerfomanceTableTestCallback.class); + static Logger logger = LoggerFactory.getLogger(PerfomanceTableTestCallback.class); - PerfomanceTableTestCallback() { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } + PerfomanceTableTestCallback() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } - @Override - public void onResponse(TransactionReceipt receipt) { - Long cost = System.currentTimeMillis() - startTime; + @Override + public void onResponse(TransactionReceipt receipt) { + Long cost = System.currentTimeMillis() - startTime; - try { - collector.onMessage(receipt, cost); - } catch (Exception e) { - logger.error("onMessage error: ", e); + try { + collector.onMessage(receipt, cost); + } catch (Exception e) { + logger.error("onMessage error: ", e); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceCollector.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceCollector.java index 5bfe45a3e..edae4b8f4 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceCollector.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceCollector.java @@ -7,107 +7,142 @@ import org.slf4j.LoggerFactory; public class PerformanceCollector { - static Logger logger = LoggerFactory.getLogger(PerformanceCollector.class); - - public Integer getTotal() { - return total; - } - - public void setTotal(Integer total) { - this.total = total; - } - - public void onMessage(TransactionReceipt receipt, Long cost) { - try { - if (!receipt.isStatusOK()) { - System.out.println("receipt error"); - error.addAndGet(1); - } else { - if (receipt.getLogs().isEmpty()) { - System.out.println("receipt log error"); - error.addAndGet(1); + static Logger logger = LoggerFactory.getLogger(PerformanceCollector.class); + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public void onMessage(TransactionReceipt receipt, Long cost) { + try { + if (!receipt.isStatusOK()) { + System.out.println("receipt error"); + error.addAndGet(1); + } else { + if (receipt.getLogs().isEmpty()) { + System.out.println("receipt log error"); + error.addAndGet(1); + } + } + + received.incrementAndGet(); + + if ((received.get() + 1) % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf((received.get() + 1) * 100 / total) + + "%"); + } + + if (cost < 50) { + less50.incrementAndGet(); + } else if (cost < 100) { + less100.incrementAndGet(); + ; + } else if (cost < 200) { + less200.incrementAndGet(); + ; + } else if (cost < 400) { + less400.incrementAndGet(); + ; + } else if (cost < 1000) { + less1000.incrementAndGet(); + ; + } else if (cost < 2000) { + less2000.incrementAndGet(); + ; + } else { + timeout2000.incrementAndGet(); + ; + } + + totalCost.addAndGet(cost); + + if (received.intValue() >= total) { + System.out.println("total"); + + // 总耗时 + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + System.out.println("Total transactions: " + String.valueOf(total)); + System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); + System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println( + "Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); + System.out.println( + "Error rate: " + + String.valueOf((error.get() / received.get()) * 100) + + "%"); + + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50.get() / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100.get() / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200.get() / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400.get() / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000.get() / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000.get() / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000.get() / total * 100) + + "%"); + + System.exit(0); + } + } catch (Exception e) { + logger.error("error:", e); } - } - - received.incrementAndGet(); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println(" |received:" - + String.valueOf((received.get() + 1) * 100 / total) + "%"); - } - - if (cost < 50) { - less50.incrementAndGet(); - } else if (cost < 100) { - less100.incrementAndGet(); - ; - } else if (cost < 200) { - less200.incrementAndGet(); - ; - } else if (cost < 400) { - less400.incrementAndGet(); - ; - } else if (cost < 1000) { - less1000.incrementAndGet(); - ; - } else if (cost < 2000) { - less2000.incrementAndGet(); - ; - } else { - timeout2000.incrementAndGet(); - ; - } - - totalCost.addAndGet(cost); - - if (received.intValue() >= total) { - System.out.println("total"); - - // 总耗时 - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - System.out.println("Total transactions: " + String.valueOf(total)); - System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); - System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); - System.out.println("Error rate: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - - System.out.println("Time area:"); - System.out.println("0 < time < 50ms : " + String.valueOf(less50) + " : " - + String.valueOf((double) less50.get() / total * 100) + "%"); - System.out.println("50 < time < 100ms : " + String.valueOf(less100) + " : " - + String.valueOf((double) less100.get() / total * 100) + "%"); - System.out.println("100 < time < 200ms : " + String.valueOf(less200) + " : " - + String.valueOf((double) less200.get() / total * 100) + "%"); - System.out.println("200 < time < 400ms : " + String.valueOf(less400) + " : " - + String.valueOf((double) less400.get() / total * 100) + "%"); - System.out.println("400 < time < 1000ms : " + String.valueOf(less1000) + " : " - + String.valueOf((double) less1000.get() / total * 100) + "%"); - System.out.println("1000 < time < 2000ms : " + String.valueOf(less2000) + " : " - + String.valueOf((double) less2000.get() / total * 100) + "%"); - System.out.println("2000 < time : " + String.valueOf(timeout2000) + " : " - + String.valueOf((double) timeout2000.get() / total * 100) + "%"); - - System.exit(0); - } - } catch (Exception e) { - logger.error("error:", e); } - } - - private AtomicLong less50 = new AtomicLong(0); - private AtomicLong less100 = new AtomicLong(0); - private AtomicLong less200 = new AtomicLong(0); - private AtomicLong less400 = new AtomicLong(0); - private AtomicLong less1000 = new AtomicLong(0); - private AtomicLong less2000 = new AtomicLong(0); - private AtomicLong timeout2000 = new AtomicLong(0); - private AtomicLong totalCost = new AtomicLong(0); - - private Integer total = 0; - private AtomicInteger received = new AtomicInteger(0); - private AtomicInteger error = new AtomicInteger(0); - private Long startTimestamp = System.currentTimeMillis(); + + private AtomicLong less50 = new AtomicLong(0); + private AtomicLong less100 = new AtomicLong(0); + private AtomicLong less200 = new AtomicLong(0); + private AtomicLong less400 = new AtomicLong(0); + private AtomicLong less1000 = new AtomicLong(0); + private AtomicLong less2000 = new AtomicLong(0); + private AtomicLong timeout2000 = new AtomicLong(0); + private AtomicLong totalCost = new AtomicLong(0); + + private Integer total = 0; + private AtomicInteger received = new AtomicInteger(0); + private AtomicInteger error = new AtomicInteger(0); + private Long startTimestamp = System.currentTimeMillis(); } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOk.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOk.java index 5c036f4d9..f7a9b1fb0 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOk.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOk.java @@ -18,94 +18,110 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerformanceOk { - private static Logger logger = LoggerFactory.getLogger(PerformanceOk.class); - private static AtomicInteger sended = new AtomicInteger(0); - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; - Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = Web3j.build(channelEthereumService, 15 * 100, scheduledExecutorService, Integer.parseInt(groupId)); - - Credentials credentials = Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - Ok ok = Ok.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerformanceCollector collector = new PerformanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute(new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerformanceOkCallback callback = new PerformanceOkCallback(); - callback.setCollector(collector); - try { - ok.trans(new BigInteger("4"), callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.info(e.getMessage()); + private static Logger logger = LoggerFactory.getLogger(PerformanceOk.class); + private static AtomicInteger sended = new AtomicInteger(0); + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; + Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); } - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + Ok ok = Ok.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerformanceCollector collector = new PerformanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerformanceOkCallback callback = new PerformanceOkCallback(); + callback.setCollector(collector); + try { + ok.trans(new BigInteger("4"), callback); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.info(e.getMessage()); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); - ; + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + ; + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkCallback.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkCallback.java index 0f172edb6..2d352ea47 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkCallback.java @@ -8,32 +8,33 @@ import org.slf4j.LoggerFactory; public class PerformanceOkCallback extends TransactionSucCallback { - private static ObjectMapper objectMapper = new ObjectMapper(); - private Long startTime = System.currentTimeMillis(); + private static ObjectMapper objectMapper = new ObjectMapper(); + private Long startTime = System.currentTimeMillis(); - private PerformanceCollector collector; + private PerformanceCollector collector; - public PerformanceCollector getCollector() { return collector; } + public PerformanceCollector getCollector() { + return collector; + } - public void setCollector(PerformanceCollector collector) { - this.collector = collector; - } + public void setCollector(PerformanceCollector collector) { + this.collector = collector; + } - static Logger logger = LoggerFactory.getLogger(PerformanceOkCallback.class); + static Logger logger = LoggerFactory.getLogger(PerformanceOkCallback.class); - PerformanceOkCallback() { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, - false); - } + PerformanceOkCallback() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } - @Override - public void onResponse(TransactionReceipt receipt) { - Long cost = System.currentTimeMillis() - startTime; + @Override + public void onResponse(TransactionReceipt receipt) { + Long cost = System.currentTimeMillis() - startTime; - try { - collector.onMessage(receipt, cost); - } catch (Exception e) { - logger.error("onMessage error: ", e); + try { + collector.onMessage(receipt, cost); + } catch (Exception e) { + logger.error("onMessage error: ", e); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkD.java b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkD.java index 330aeb3df..dd16c91c8 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkD.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/PerformanceOkD.java @@ -18,92 +18,111 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class PerformanceOkD { - private static Logger logger = LoggerFactory.getLogger(PerformanceOkD.class); - private static AtomicInteger sended = new AtomicInteger(0); - - public static void main(String[] args) throws Exception { - try { - String groupId = args[3]; - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - System.out.println("Start test..."); - System.out.println("==================================================================="); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = Web3j.build(channelEthereumService, 15 * 100, scheduledExecutorService, Integer.parseInt(groupId)); - - Credentials credentials = Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - BigInteger gasPrice = new BigInteger("30000000"); - BigInteger gasLimit = new BigInteger("30000000"); - - String command = args[0]; - Integer count = 0; - Integer qps = 0; - - switch (command) { - case "trans": - count = Integer.parseInt(args[1]); - qps = Integer.parseInt(args[2]); - break; - default: - System.out.println("Args: "); - } - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count); - - threadPool.initialize(); - - System.out.println("Deploying contract..."); - OkD ok = OkD.deploy(web3, credentials, gasPrice, gasLimit).send(); - - PerformanceCollector collector = new PerformanceCollector(); - collector.setTotal(count); - - RateLimiter limiter = RateLimiter.create(qps); - Integer area = count / 10; - final Integer total = count; - - Random random = new Random(System.currentTimeMillis()); - - System.out.println("Start test,total:" + count); - for (Integer i = 0; i < count; ++i) { - threadPool.execute(new Runnable() { - @Override - public void run() { - limiter.acquire(); - PerformanceOkCallback callback = new PerformanceOkCallback(); - callback.setCollector(collector); - try { - ok.trans(String.valueOf(random.nextLong()), new BigInteger("1"), callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.error("Error sending:", e); + private static Logger logger = LoggerFactory.getLogger(PerformanceOkD.class); + private static AtomicInteger sended = new AtomicInteger(0); + + public static void main(String[] args) throws Exception { + try { + String groupId = args[3]; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + System.out.println("Start test..."); + System.out.println( + "==================================================================="); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + ScheduledExecutorService scheduledExecutorService = + Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + BigInteger gasPrice = new BigInteger("30000000"); + BigInteger gasLimit = new BigInteger("30000000"); + + String command = args[0]; + Integer count = 0; + Integer qps = 0; + + switch (command) { + case "trans": + count = Integer.parseInt(args[1]); + qps = Integer.parseInt(args[2]); + break; + default: + System.out.println("Args: "); } - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + total + " transactions"); + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count); + + threadPool.initialize(); + + System.out.println("Deploying contract..."); + OkD ok = OkD.deploy(web3, credentials, gasPrice, gasLimit).send(); + + PerformanceCollector collector = new PerformanceCollector(); + collector.setTotal(count); + + RateLimiter limiter = RateLimiter.create(qps); + Integer area = count / 10; + final Integer total = count; + + Random random = new Random(System.currentTimeMillis()); + + System.out.println("Start test,total:" + count); + for (Integer i = 0; i < count; ++i) { + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + PerformanceOkCallback callback = new PerformanceOkCallback(); + callback.setCollector(collector); + try { + ok.trans( + String.valueOf(random.nextLong()), + new BigInteger("1"), + callback); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.error("Error sending:", e); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + total + + " transactions"); + } + } + }); } - } - }); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); + } catch (Exception e) { + e.printStackTrace(); + System.exit(-1); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/PressureTest.java b/src/test/java/org/fisco/bcos/channel/test/contract/PressureTest.java deleted file mode 100644 index d69fdbb97..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/contract/PressureTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.fisco.bcos.channel.test.contract; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -import org.fisco.bcos.channel.test.TestBase; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Ignore; -import org.junit.Test; - -public class PressureTest extends TestBase { - - @Ignore - @Test - public void pressureTest() throws InterruptedException, ExecutionException { - int threadNum = 500; - System.out.println("####create credential succ, begin deploy contract"); - java.math.BigInteger gasPrice = new BigInteger("300000000"); - java.math.BigInteger gasLimit = new BigInteger("300000000"); - final Ok okDemo = Ok.deploy(web3j, credentials, gasPrice, gasLimit).sendAsync().get(); - if (okDemo != null) { - ArrayList threadArray = new ArrayList(); - for (int threadIndex = 0; threadIndex < threadNum; threadIndex++) { - threadArray.add( - new Thread("" + threadIndex) { - public void run() { - - try { - // System.out.println("####contract address is: " + okDemo.getContractAddress()); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).sendAsync().get(); - System.out.println("###callback trans success"); - BigInteger toBalance = okDemo.get().sendAsync().get(); - System.out.println("============to balance:" + toBalance.intValue()); - Thread.sleep(1000); // sleep 1s - } catch (Exception e) { - System.out.println("callback trans failed, error message:" + e.getMessage()); - } - } - }); - threadArray.get(threadIndex).start(); - } - // join all theads - for (int threadIndex = 0; threadIndex < threadNum; threadIndex++) - threadArray.get(threadIndex).join(); - } - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/TableTest.java b/src/test/java/org/fisco/bcos/channel/test/contract/TableTest.java index 6ed7e28ab..6206f2a66 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/TableTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/TableTest.java @@ -1,6 +1,5 @@ package org.fisco.bcos.channel.test.contract; - import io.reactivex.Flowable; import java.math.BigInteger; import java.util.ArrayList; @@ -30,17 +29,20 @@ import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; /** - *

Auto generated code. + * Auto generated code. + * *

Do not modify! + * *

Please use the web3j command line tools, - * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. * *

Generated with web3j version none. */ @SuppressWarnings("unchecked") public class TableTest extends Contract { - private static final String BINARY = "608060405234801561001057600080fd5b50612239806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a1014610072578063c4f41ab31461013f578063ebf3b24f146101c6578063efc81a8c14610293578063fcd7e3c1146102be575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061040c565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101b0600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610b02565b6040518082815260200191505060405180910390f35b3480156101d257600080fd5b5061027d600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610ffb565b6040518082815260200191505060405180910390f35b34801561029f57600080fd5b506102a861161a565b6040518082815260200191505060405180910390f35b3480156102ca57600080fd5b50610325600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506117b2565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015610370578082015181840152602081019050610355565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156103b2578082015181840152602081019050610397565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156103f45780820151818401526020810190506103d9565b50505050905001965050505050505060405180910390f35b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104ba57600080fd5b505af11580156104ce573d6000803e3d6000fd5b505050506040513d60208110156104e457600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561055b57600080fd5b505af115801561056f573d6000803e3d6000fd5b505050506040513d602081101561058557600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561065857808201518184015260208101905061063d565b50505050905090810190601f1680156106855780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156106a557600080fd5b505af11580156106b9573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561072157600080fd5b505af1158015610735573d6000803e3d6000fd5b505050506040513d602081101561074b57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561092b57600080fd5b505af115801561093f573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a31578082015181840152602081019050610a16565b50505050905090810190601f168015610a5e5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610a7f57600080fd5b505af1158015610a93573d6000803e3d6000fd5b505050506040513d6020811015610aa957600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610baf57600080fd5b505af1158015610bc3573d6000803e3d6000fd5b505050506040513d6020811015610bd957600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c5057600080fd5b505af1158015610c64573d6000803e3d6000fd5b505050506040513d6020811015610c7a57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610d4d578082015181840152602081019050610d32565b50505050905090810190601f168015610d7a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015610d9a57600080fd5b505af1158015610dae573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015610e5a57600080fd5b505af1158015610e6e573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610f2d578082015181840152602081019050610f12565b50505050905090810190601f168015610f5a5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d6020811015610fa457600080fd5b810190808051906020019092919050505090507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156110a857600080fd5b505af11580156110bc573d6000803e3d6000fd5b505050506040513d60208110156110d257600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561114957600080fd5b505af115801561115d573d6000803e3d6000fd5b505050506040513d602081101561117357600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561124657808201518184015260208101905061122b565b50505050905090810190601f1680156112735780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561129357600080fd5b505af11580156112a7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561135357600080fd5b505af1158015611367573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561142b578082015181840152602081019050611410565b50505050905090810190601f1680156114585780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561147857600080fd5b505af115801561148c573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561154b578082015181840152602081019050611530565b50505050905090810190601f1680156115785780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561159857600080fd5b505af11580156115ac573d6000803e3d6000fd5b505050506040513d60208110156115c257600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1809450505050509392505050565b600080600061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b15801561173657600080fd5b505af115801561174a573d6000803e3d6000fd5b505050506040513d602081101561176057600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a1809250505090565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561186a57600080fd5b505af115801561187e573d6000803e3d6000fd5b505050506040513d602081101561189457600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561190b57600080fd5b505af115801561191f573d6000803e3d6000fd5b505050506040513d602081101561193557600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611a035780820151818401526020810190506119e8565b50505050905090810190601f168015611a305780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611a5057600080fd5b505af1158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611af157600080fd5b505af1158015611b05573d6000803e3d6000fd5b505050506040513d6020811015611b1b57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611b5a5781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d6020811015611beb57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611c2a5781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611c9157600080fd5b505af1158015611ca5573d6000803e3d6000fd5b505050506040513d6020811015611cbb57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611cfa5781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611d6657600080fd5b505af1158015611d7a573d6000803e3d6000fd5b505050506040513d6020811015611d9057600080fd5b81019080805190602001909291905050508212156121f4578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b158015611e1757600080fd5b505af1158015611e2b573d6000803e3d6000fd5b505050506040513d6020811015611e4157600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b505050506040513d6020811015611f1e57600080fd5b81019080805190602001909291905050508583815181101515611f3d57fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611ff557600080fd5b505af1158015612009573d6000803e3d6000fd5b505050506040513d602081101561201f57600080fd5b8101908080519060200190929190505050848381518110151561203e57fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156120ec57600080fd5b505af1158015612100573d6000803e3d6000fd5b505050506040513d602081101561211657600080fd5b8101908080519060200190929190505050838381518110151561213557fe5b9060200190602002019060001916908160001916815250507fc65cd2adf133adee2ddcfab8b165c2f1f7b185c4389b0789a11112483efb1c84858381518110151561217c57fe5b90602001906020020151858481518110151561219457fe5b9060200190602002015185858151811015156121ac57fe5b906020019060200201516040518084600019166000191681526020018381526020018260001916600019168152602001935050505060405180910390a1816001019150611d02565b8484849b509b509b5050505050505050505091939092505600a165627a7a723058201ab472e3141e7db3e2203297190547ca2e10b6b55a96dc8278b4a88a2ff72a700029"; + private static final String BINARY = + "608060405234801561001057600080fd5b50612239806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063487a5a1014610072578063c4f41ab31461013f578063ebf3b24f146101c6578063efc81a8c14610293578063fcd7e3c1146102be575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061040c565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101b0600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610b02565b6040518082815260200191505060405180910390f35b3480156101d257600080fd5b5061027d600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610ffb565b6040518082815260200191505060405180910390f35b34801561029f57600080fd5b506102a861161a565b6040518082815260200191505060405180910390f35b3480156102ca57600080fd5b50610325600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506117b2565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015610370578082015181840152602081019050610355565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156103b2578082015181840152602081019050610397565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156103f45780820151818401526020810190506103d9565b50505050905001965050505050505060405180910390f35b60008060008060008061100194508473ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156104ba57600080fd5b505af11580156104ce573d6000803e3d6000fd5b505050506040513d60208110156104e457600080fd5b810190808051906020019092919050505093508373ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561055b57600080fd5b505af115801561056f573d6000803e3d6000fd5b505050506040513d602081101561058557600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff1663e942b516886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561065857808201518184015260208101905061063d565b50505050905090810190601f1680156106855780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156106a557600080fd5b505af11580156106b9573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561072157600080fd5b505af1158015610735573d6000803e3d6000fd5b505050506040513d602081101561074b57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d18a6040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561092b57600080fd5b505af115801561093f573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663bf2b70a18a85856040518463ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825285818151815260200191508051906020019080838360005b83811015610a31578082015181840152602081019050610a16565b50505050905090810190601f168015610a5e5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610a7f57600080fd5b505af1158015610a93573d6000803e3d6000fd5b505050506040513d6020811015610aa957600080fd5b810190808051906020019092919050505090507f0bdcb3b747cf033ae78b4b6e1576d2725709d03f68ad3d641b12cb72de614354816040518082815260200191505060405180910390a180955050505050509392505050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015610baf57600080fd5b505af1158015610bc3573d6000803e3d6000fd5b505050506040513d6020811015610bd957600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015610c5057600080fd5b505af1158015610c64573d6000803e3d6000fd5b505050506040513d6020811015610c7a57600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663cd30a1d1886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b83811015610d4d578082015181840152602081019050610d32565b50505050905090810190601f168015610d7a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015610d9a57600080fd5b505af1158015610dae573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e44594b9876040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b158015610e5a57600080fd5b505af1158015610e6e573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166328bb211788846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015610f2d578082015181840152602081019050610f12565b50505050905090810190601f168015610f5a5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d6020811015610fa457600080fd5b810190808051906020019092919050505090507f896358cb98e9e8e891ae04efd1bc177efbe5cffd7eca2e784b16ed7468553e08816040518082815260200191505060405180910390a18094505050505092915050565b600080600080600061100193508373ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156110a857600080fd5b505af11580156110bc573d6000803e3d6000fd5b505050506040513d60208110156110d257600080fd5b810190808051906020019092919050505092508273ffffffffffffffffffffffffffffffffffffffff166313db93466040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561114957600080fd5b505af115801561115d573d6000803e3d6000fd5b505050506040513d602081101561117357600080fd5b810190808051906020019092919050505091508173ffffffffffffffffffffffffffffffffffffffff1663e942b516896040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561124657808201518184015260208101905061122b565b50505050905090810190601f1680156112735780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561129357600080fd5b505af11580156112a7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16632ef8ba74886040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001838152602001828103825260078152602001807f6974656d5f69640000000000000000000000000000000000000000000000000081525060200192505050600060405180830381600087803b15801561135357600080fd5b505af1158015611367573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663e942b516876040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808060200180602001838103835260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001838103825284818151815260200191508051906020019080838360005b8381101561142b578082015181840152602081019050611410565b50505050905090810190601f1680156114585780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561147857600080fd5b505af115801561148c573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166331afac3689846040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561154b578082015181840152602081019050611530565b50505050905090810190601f1680156115785780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561159857600080fd5b505af11580156115ac573d6000803e3d6000fd5b505050506040513d60208110156115c257600080fd5b810190808051906020019092919050505090507f66f7705280112a4d1145399e0414adc43a2d6974b487710f417edcf7d4a39d71816040518082815260200191505060405180910390a1809450505050509392505050565b600080600061100191508173ffffffffffffffffffffffffffffffffffffffff166356004b6a6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018060200180602001848103845260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001848103835260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001848103825260118152602001807f6974656d5f69642c6974656d5f6e616d650000000000000000000000000000008152506020019350505050602060405180830381600087803b15801561173657600080fd5b505af115801561174a573d6000803e3d6000fd5b505050506040513d602081101561176057600080fd5b810190808051906020019092919050505090507fcd4779437d9d027acc605a96427bfbd3787a1402cb53a5e64cd813d5391fbc2b816040518082815260200191505060405180910390a1809250505090565b6060806060600080600080606080606060008061100198508873ffffffffffffffffffffffffffffffffffffffff1663f23f63c96040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260068152602001807f745f746573740000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b15801561186a57600080fd5b505af115801561187e573d6000803e3d6000fd5b505050506040513d602081101561189457600080fd5b810190808051906020019092919050505097508773ffffffffffffffffffffffffffffffffffffffff16637857d7c96040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561190b57600080fd5b505af115801561191f573d6000803e3d6000fd5b505050506040513d602081101561193557600080fd5b810190808051906020019092919050505096508773ffffffffffffffffffffffffffffffffffffffff1663e8434e398e896040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611a035780820151818401526020810190506119e8565b50505050905090810190601f168015611a305780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b158015611a5057600080fd5b505af1158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b810190808051906020019092919050505095508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611af157600080fd5b505af1158015611b05573d6000803e3d6000fd5b505050506040513d6020811015611b1b57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611b5a5781602001602082028038833980820191505090505b5094508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d6020811015611beb57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611c2a5781602001602082028038833980820191505090505b5093508573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611c9157600080fd5b505af1158015611ca5573d6000803e3d6000fd5b505050506040513d6020811015611cbb57600080fd5b8101908080519060200190929190505050604051908082528060200260200182016040528015611cfa5781602001602082028038833980820191505090505b509250600091505b8573ffffffffffffffffffffffffffffffffffffffff1663949d225d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611d6657600080fd5b505af1158015611d7a573d6000803e3d6000fd5b505050506040513d6020811015611d9057600080fd5b81019080805190602001909291905050508212156121f4578573ffffffffffffffffffffffffffffffffffffffff1663846719e0836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b158015611e1757600080fd5b505af1158015611e2b573d6000803e3d6000fd5b505050506040513d6020811015611e4157600080fd5b810190808051906020019092919050505090508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260048152602001807f6e616d6500000000000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b505050506040513d6020811015611f1e57600080fd5b81019080805190602001909291905050508583815181101515611f3d57fe5b9060200190602002019060001916908160001916815250508073ffffffffffffffffffffffffffffffffffffffff1663fda69fae6040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260078152602001807f6974656d5f696400000000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b158015611ff557600080fd5b505af1158015612009573d6000803e3d6000fd5b505050506040513d602081101561201f57600080fd5b8101908080519060200190929190505050848381518110151561203e57fe5b90602001906020020181815250508073ffffffffffffffffffffffffffffffffffffffff166327314f796040518163ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018080602001828103825260098152602001807f6974656d5f6e616d650000000000000000000000000000000000000000000000815250602001915050602060405180830381600087803b1580156120ec57600080fd5b505af1158015612100573d6000803e3d6000fd5b505050506040513d602081101561211657600080fd5b8101908080519060200190929190505050838381518110151561213557fe5b9060200190602002019060001916908160001916815250507fc65cd2adf133adee2ddcfab8b165c2f1f7b185c4389b0789a11112483efb1c84858381518110151561217c57fe5b90602001906020020151858481518110151561219457fe5b9060200190602002015185858151811015156121ac57fe5b906020019060200201516040518084600019166000191681526020018381526020018260001916600019168152602001935050505060405180910390a1816001019150611d02565b8484849b509b509b5050505050505050505091939092505600a165627a7a723058201ab472e3141e7db3e2203297190547ca2e10b6b55a96dc8278b4a88a2ff72a700029"; public static final String FUNC_UPDATE = "update"; @@ -52,138 +54,192 @@ public class TableTest extends Contract { public static final String FUNC_SELECT = "select"; - public static final Event CREATERESULT_EVENT = new Event("createResult", - Arrays.>asList(new TypeReference() {})); - ; - - public static final Event SELECTRESULT_EVENT = new Event("selectResult", - Arrays.>asList(new TypeReference() {}, new TypeReference() {}, new TypeReference() {})); - ; - - public static final Event INSERTRESULT_EVENT = new Event("insertResult", - Arrays.>asList(new TypeReference() {})); - ; - - public static final Event UPDATERESULT_EVENT = new Event("updateResult", - Arrays.>asList(new TypeReference() {})); - ; - - public static final Event REMOVERESULT_EVENT = new Event("removeResult", - Arrays.>asList(new TypeReference() {})); - ; + public static final Event CREATERESULT_EVENT = + new Event( + "createResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event SELECTRESULT_EVENT = + new Event( + "selectResult", + Arrays.>asList( + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}));; + + public static final Event INSERTRESULT_EVENT = + new Event( + "insertResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event UPDATERESULT_EVENT = + new Event( + "updateResult", + Arrays.>asList(new TypeReference() {}));; + + public static final Event REMOVERESULT_EVENT = + new Event( + "removeResult", + Arrays.>asList(new TypeReference() {}));; @Deprecated - protected TableTest(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected TableTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected TableTest(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected TableTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected TableTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected TableTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected TableTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected TableTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public RemoteCall update(String name, BigInteger item_id, String item_name) { - final Function function = new Function( - FUNC_UPDATE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); + public RemoteCall update( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void update(String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_UPDATE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); + public void update( + String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_UPDATE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall remove(String name, BigInteger item_id) { - final Function function = new Function( - FUNC_REMOVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void remove(String name, BigInteger item_id, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_REMOVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_REMOVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } - public RemoteCall insert(String name, BigInteger item_id, String item_name) { - final Function function = new Function( - FUNC_INSERT, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); + public RemoteCall insert( + String name, BigInteger item_id, String item_name) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void insert(String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_INSERT, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), - Collections.>emptyList()); + public void insert( + String name, BigInteger item_id, String item_name, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_INSERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Int256(item_id), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(item_name)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall create() { - final Function function = new Function( - FUNC_CREATE, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_CREATE, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void create(TransactionSucCallback callback) { - final Function function = new Function( - FUNC_CREATE, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_CREATE, + Arrays.asList(), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall, List, List>> select(String name) { - final Function function = new Function(FUNC_SELECT, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), - Arrays.>asList(new TypeReference>() {}, new TypeReference>() {}, new TypeReference>() {})); + final Function function = + new Function( + FUNC_SELECT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), + Arrays.>asList( + new TypeReference>() {}, + new TypeReference>() {}, + new TypeReference>() {})); return new RemoteCall, List, List>>( new Callable, List, List>>() { @Override - public Tuple3, List, List> call() throws Exception { + public Tuple3, List, List> call() + throws Exception { List results = executeCallMultipleValueReturn(function); return new Tuple3, List, List>( - convertToNative((List) results.get(0).getValue()), - convertToNative((List) results.get(1).getValue()), + convertToNative((List) results.get(0).getValue()), + convertToNative((List) results.get(1).getValue()), convertToNative((List) results.get(2).getValue())); } }); } - public List getCreateResultEvents(TransactionReceipt transactionReceipt) { - List valueList = extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); + public List getCreateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(CREATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { CreateResultEventResponse typedResponse = new CreateResultEventResponse(); typedResponse.log = eventValues.getLog(); @@ -194,32 +250,43 @@ public List getCreateResultEvents(TransactionReceipt } public Flowable createResultEventFlowable(BcosFilter filter) { - return web3j.logFlowable(filter).map(new io.reactivex.functions.Function() { - @Override - public CreateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(CREATERESULT_EVENT, log); - CreateResultEventResponse typedResponse = new CreateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable createResultEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public CreateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(CREATERESULT_EVENT, log); + CreateResultEventResponse typedResponse = + new CreateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable createResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(CREATERESULT_EVENT)); return createResultEventFlowable(filter); } - public List getSelectResultEvents(TransactionReceipt transactionReceipt) { - List valueList = extractEventParametersWithLog(SELECTRESULT_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); + public List getSelectResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(SELECTRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { SelectResultEventResponse typedResponse = new SelectResultEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.item_id = + (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); responses.add(typedResponse); } @@ -227,29 +294,43 @@ public List getSelectResultEvents(TransactionReceipt } public Flowable selectResultEventFlowable(BcosFilter filter) { - return web3j.logFlowable(filter).map(new io.reactivex.functions.Function() { - @Override - public SelectResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(SELECTRESULT_EVENT, log); - SelectResultEventResponse typedResponse = new SelectResultEventResponse(); - typedResponse.log = log; - typedResponse.name = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.item_id = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.item_name = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); - return typedResponse; - } - }); - } - - public Flowable selectResultEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public SelectResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(SELECTRESULT_EVENT, log); + SelectResultEventResponse typedResponse = + new SelectResultEventResponse(); + typedResponse.log = log; + typedResponse.name = + (byte[]) + eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.item_id = + (BigInteger) + eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.item_name = + (byte[]) + eventValues.getNonIndexedValues().get(2).getValue(); + return typedResponse; + } + }); + } + + public Flowable selectResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(SELECTRESULT_EVENT)); return selectResultEventFlowable(filter); } - public List getInsertResultEvents(TransactionReceipt transactionReceipt) { - List valueList = extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); + public List getInsertResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(INSERTRESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { InsertResultEventResponse typedResponse = new InsertResultEventResponse(); typedResponse.log = eventValues.getLog(); @@ -260,27 +341,37 @@ public List getInsertResultEvents(TransactionReceipt } public Flowable insertResultEventFlowable(BcosFilter filter) { - return web3j.logFlowable(filter).map(new io.reactivex.functions.Function() { - @Override - public InsertResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(INSERTRESULT_EVENT, log); - InsertResultEventResponse typedResponse = new InsertResultEventResponse(); - typedResponse.log = log; - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable insertResultEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public InsertResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(INSERTRESULT_EVENT, log); + InsertResultEventResponse typedResponse = + new InsertResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable insertResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(INSERTRESULT_EVENT)); return insertResultEventFlowable(filter); } - public List getUpdateResultEvents(TransactionReceipt transactionReceipt) { - List valueList = extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); + public List getUpdateResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(UPDATERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); typedResponse.log = eventValues.getLog(); @@ -291,27 +382,37 @@ public List getUpdateResultEvents(TransactionReceipt } public Flowable updateResultEventFlowable(BcosFilter filter) { - return web3j.logFlowable(filter).map(new io.reactivex.functions.Function() { - @Override - public UpdateResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(UPDATERESULT_EVENT, log); - UpdateResultEventResponse typedResponse = new UpdateResultEventResponse(); - typedResponse.log = log; - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable updateResultEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public UpdateResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(UPDATERESULT_EVENT, log); + UpdateResultEventResponse typedResponse = + new UpdateResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable updateResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(UPDATERESULT_EVENT)); return updateResultEventFlowable(filter); } - public List getRemoveResultEvents(TransactionReceipt transactionReceipt) { - List valueList = extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); + public List getRemoveResultEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(REMOVERESULT_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); typedResponse.log = eventValues.getLog(); @@ -322,58 +423,96 @@ public List getRemoveResultEvents(TransactionReceipt } public Flowable removeResultEventFlowable(BcosFilter filter) { - return web3j.logFlowable(filter).map(new io.reactivex.functions.Function() { - @Override - public RemoveResultEventResponse apply(Log log) { - Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(REMOVERESULT_EVENT, log); - RemoveResultEventResponse typedResponse = new RemoveResultEventResponse(); - typedResponse.log = log; - typedResponse.count = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable removeResultEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public RemoveResultEventResponse apply(Log log) { + Contract.EventValuesWithLog eventValues = + extractEventParametersWithLog(REMOVERESULT_EVENT, log); + RemoveResultEventResponse typedResponse = + new RemoveResultEventResponse(); + typedResponse.log = log; + typedResponse.count = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable removeResultEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(REMOVERESULT_EVENT)); return removeResultEventFlowable(filter); } @Deprecated - public static TableTest load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + public static TableTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { return new TableTest(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Deprecated - public static TableTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + public static TableTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { return new TableTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - public static TableTest load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + public static TableTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { return new TableTest(contractAddress, web3j, credentials, contractGasProvider); } - public static TableTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + public static TableTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { return new TableTest(contractAddress, web3j, transactionManager, contractGasProvider); } - public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(TableTest.class, web3j, credentials, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + TableTest.class, web3j, credentials, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(TableTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + TableTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); } - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(TableTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + TableTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(TableTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + TableTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); } public static class CreateResultEventResponse { diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/TableTestClient.java b/src/test/java/org/fisco/bcos/channel/test/contract/TableTestClient.java index 26aa8f446..01a6ef064 100644 --- a/src/test/java/org/fisco/bcos/channel/test/contract/TableTestClient.java +++ b/src/test/java/org/fisco/bcos/channel/test/contract/TableTestClient.java @@ -1,276 +1,286 @@ -package org.fisco.bcos.channel.test.contract; - -import java.math.BigInteger; -import java.util.List; -import org.apache.commons.configuration.PropertiesConfiguration; -import org.fisco.bcos.channel.client.Service; -import org.fisco.bcos.channel.test.contract.TableTest.CreateResultEventResponse; -import org.fisco.bcos.channel.test.contract.TableTest.InsertResultEventResponse; -import org.fisco.bcos.channel.test.contract.TableTest.RemoveResultEventResponse; -import org.fisco.bcos.channel.test.contract.TableTest.UpdateResultEventResponse; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.crypto.ECKeyPair; -import org.fisco.bcos.web3j.crypto.Keys; -import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; -import org.fisco.bcos.web3j.protocol.core.RemoteCall; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.web3j.protocol.exceptions.TransactionException; -import org.fisco.bcos.web3j.tuples.generated.Tuple3; -import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; -import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -public class TableTestClient { - - public static int modevalue = 100; - static Logger logger = LoggerFactory.getLogger(TableTestClient.class); - public static Web3j web3j; - - public static java.math.BigInteger gasPrice = new BigInteger("1"); - public static java.math.BigInteger gasLimit = new BigInteger("30000000"); - public static ECKeyPair keyPair; - public static Credentials credentials; - public static String contractAddress = ""; - - /* deploy the contract,get address from blockchain */ - @SuppressWarnings("deprecation") - public static void deployTableTest() { - - RemoteCall deploy = TableTest.deploy(web3j, credentials, gasPrice, gasLimit); - TableTest tabletest; - try { - tabletest = deploy.send(); - contractAddress = tabletest.getContractAddress(); - System.out.println("deploy contract address: " + contractAddress); - logger.info("deploy contract address: " + contractAddress); - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - prop.setProperty("crud_address", contractAddress); - prop.save(); - - System.out.println("deploy contract successful!"); - } catch (TransactionException e) { - if ("0x19".equals(e.getStatus())) { - System.out.println("non-authorized to deploy contracts!"); - } else { - System.out.println(e.getMessage()); - } - } catch (Exception e) { - System.out.println("deploy failed! " + e.getMessage()); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void testTableTest(String[] args) throws Exception { - - final Resource contractResource = new ClassPathResource("contract.properties"); - PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); - Object addressObj = prop.getProperty("crud_address"); - if (addressObj != null) { - contractAddress = (String) addressObj; - } else { - deployTableTest(); - } - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - ; - TableTest tabletest = TableTest.load(contractAddress, web3j, credentials, contractGasProvider); - // create table - if ("create".equals(args[0])) { - TransactionReceipt receipt = tabletest.create().send(); - List createResultEvents = tabletest.getCreateResultEvents(receipt); - if (createResultEvents.size() == 0) { - System.out.println("create t_test table failed."); - return; - } - CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); - int createCount = createResultEventResponse.count.intValue(); - switch (createCount) { - case PrecompiledCommon.PermissionDenied: - System.out.println("non-authorized to create t_test table."); - break; - case 50001: - System.out.println("t_test table already exist."); - break; - case PrecompiledCommon.Success: - System.out.println("create t_test table completed."); - break; - } - - } - // insert - else if ("insert".equals(args[0])) { - if (args.length == 4) { - try - { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - - RemoteCall insert = - tabletest.insert(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt txReceipt = insert.send(); - List insertResultEvents = - tabletest.getInsertResultEvents(txReceipt); - if (insertResultEvents.size() > 0) { - for (int i = 0; i < insertResultEvents.size(); i++) { - InsertResultEventResponse insertResultEventResponse = insertResultEvents.get(i); - logger.info("insertCount = " + insertResultEventResponse.count.intValue()); - System.out.println("insertCount = " + insertResultEventResponse.count.intValue()); - } - } - else - { - System.out.println("t_test table does not exist."); - } - } - catch(Exception e) - { - System.out.println("insert transaction is abnormal, please check the environment"); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 insert fruit 1 apple"); - } - } - // select - else if ("select".equals(args[0])) { - if (args.length == 2) { - try { - String keyName = args[1]; - Tuple3, List, List> lists = tabletest.select(keyName).send(); - List value1 = lists.getValue1(); - List value2 = lists.getValue2(); - List value3 = lists.getValue3(); - logger.info("record numbers = " + value1.size()); - System.out.println("record numbers = " + value1.size()); - for (int i = 0; i < value1.size(); i++) { - String name = new String(value1.get(i)); - logger.info("name = " + name); - System.out.println("name = " + name); - int item_id = value2.get(i).intValue(); - logger.info("item_id = " + item_id); - System.out.println("item_id = " + item_id); - String item_name = new String(value3.get(i)); - logger.info("item_name = " + item_name); - System.out.println("item_name = " + item_name); - } - } catch (Exception e) { - logger.info("record numbers = 0"); - System.out.println("record numbers = 0"); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 select fruit"); - } - } - // update - else if ("update".equals(args[0])) { - if (args.length == 4) { - try { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - String item_name = args[3]; - RemoteCall update = - tabletest.update(name, BigInteger.valueOf(item_id), item_name); - TransactionReceipt transactionReceipt = update.send(); - List updateResultEvents = - tabletest.getUpdateResultEvents(transactionReceipt); - - if (updateResultEvents.size() > 0) { - for (int i = 0; i < updateResultEvents.size(); i++) { - UpdateResultEventResponse updateResultEventResponse = updateResultEvents.get(i); - System.out.println("updateCount = " + updateResultEventResponse.count.intValue()); - logger.info("updateCount = " + updateResultEventResponse.count.intValue()); - } - } - else - { - System.out.println("t_test table does not exist."); - } - } - catch(Exception e) - { - System.out.println("update transaction is abnormal, please check the environment"); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 update fruit 1 orange"); - } - } - // remove - else if ("remove".equals(args[0])) { - if (args.length == 3) { - try - { - String name = args[1]; - int item_id = Integer.parseInt(args[2]); - RemoteCall remove = tabletest.remove(name, BigInteger.valueOf(item_id)); - TransactionReceipt transactionReceipt = remove.send(); - List removeResultEvents = - tabletest.getRemoveResultEvents(transactionReceipt); - - if (removeResultEvents.size() > 0) { - RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0); - logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); - System.out.println("removeCount = " + reomveResultEventResponse.count.intValue()); - } else { - System.out.println("t_test table does not exist."); - } - } - catch(Exception e) - { - System.out.println("remove transaction is abnormal, please check the environment"); - } - } else { - System.out.println("\nPlease enter as follow example:\n 1 1 remove fruit 1"); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); - } - } - - public static void main(String[] args) throws Exception { - - // init the Service - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); // run the daemon service - // init the client keys - keyPair = Keys.createEcKeyPair(); - credentials = Credentials.create(keyPair); - - logger.info("-----> start test !"); - logger.info("init AOMP ChannelEthereumService"); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - channelEthereumService.setTimeout(5*1000); - service.setGroupId(Integer.parseInt(args[0])); - try { - web3j = Web3j.build(channelEthereumService,service.getGroupId()); - } - catch (Exception e) { - System.out.println("\nPlease provide groupID in the first paramters"); - System.exit(0); - } - - if (args.length > 1) { - if ("deploy".equals(args[1])) { - deployTableTest(); - } else { - String[] params = new String[args.length - 1]; - for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; - testTableTest(params); - } - } else { - System.out.println( - "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); - } - System.exit(0); - } -} +package org.fisco.bcos.channel.test.contract; + +import java.math.BigInteger; +import java.util.List; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.fisco.bcos.channel.client.Service; +import org.fisco.bcos.channel.test.contract.TableTest.CreateResultEventResponse; +import org.fisco.bcos.channel.test.contract.TableTest.InsertResultEventResponse; +import org.fisco.bcos.channel.test.contract.TableTest.RemoveResultEventResponse; +import org.fisco.bcos.channel.test.contract.TableTest.UpdateResultEventResponse; +import org.fisco.bcos.web3j.crypto.Credentials; +import org.fisco.bcos.web3j.crypto.ECKeyPair; +import org.fisco.bcos.web3j.crypto.Keys; +import org.fisco.bcos.web3j.precompile.common.PrecompiledCommon; +import org.fisco.bcos.web3j.protocol.Web3j; +import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; +import org.fisco.bcos.web3j.protocol.core.RemoteCall; +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; +import org.fisco.bcos.web3j.protocol.exceptions.TransactionException; +import org.fisco.bcos.web3j.tuples.generated.Tuple3; +import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; +import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class TableTestClient { + + public static int modevalue = 100; + static Logger logger = LoggerFactory.getLogger(TableTestClient.class); + public static Web3j web3j; + + public static java.math.BigInteger gasPrice = new BigInteger("1"); + public static java.math.BigInteger gasLimit = new BigInteger("30000000"); + public static ECKeyPair keyPair; + public static Credentials credentials; + public static String contractAddress = ""; + + /* deploy the contract,get address from blockchain */ + @SuppressWarnings("deprecation") + public static void deployTableTest() { + + RemoteCall deploy = TableTest.deploy(web3j, credentials, gasPrice, gasLimit); + TableTest tabletest; + try { + tabletest = deploy.send(); + contractAddress = tabletest.getContractAddress(); + System.out.println("deploy contract address: " + contractAddress); + logger.info("deploy contract address: " + contractAddress); + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + prop.setProperty("crud_address", contractAddress); + prop.save(); + + System.out.println("deploy contract successful!"); + } catch (TransactionException e) { + if ("0x19".equals(e.getStatus())) { + System.out.println("non-authorized to deploy contracts!"); + } else { + System.out.println( + "deploy transaction is abnormal, please check the environment msg:" + + e.getMessage()); + } + } catch (Exception e) { + System.out.println("deploy transaction is abnormal, please check the environment"); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void testTableTest(String[] args) throws Exception { + + final Resource contractResource = new ClassPathResource("contract.properties"); + PropertiesConfiguration prop = new PropertiesConfiguration(contractResource.getFile()); + Object addressObj = prop.getProperty("crud_address"); + if (addressObj != null) { + contractAddress = (String) addressObj; + } else { + deployTableTest(); + } + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + ; + TableTest tabletest = + TableTest.load(contractAddress, web3j, credentials, contractGasProvider); + // create table + if ("create".equals(args[0])) { + TransactionReceipt receipt = tabletest.create().send(); + List createResultEvents = + tabletest.getCreateResultEvents(receipt); + if (createResultEvents.size() == 0) { + System.out.println("create t_test table failed."); + return; + } + CreateResultEventResponse createResultEventResponse = createResultEvents.get(0); + int createCount = createResultEventResponse.count.intValue(); + System.out.println("create table ret:" + createCount); + switch (createCount) { + case PrecompiledCommon.PermissionDenied: + System.out.println("non-authorized to create t_test table."); + break; + case PrecompiledCommon.PermissionDenied_RC3: + System.out.println("non-authorized to create t_test table."); + break; + case PrecompiledCommon.TableExist: + System.out.println("t_test table already exist."); + break; + case PrecompiledCommon.Success: + System.out.println("create t_test table success."); + break; + default: + System.out.println("unknown return value:" + createCount); + } + + } + // insert + else if ("insert".equals(args[0])) { + if (args.length == 4) { + try { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + + RemoteCall insert = + tabletest.insert(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt txReceipt = insert.send(); + List insertResultEvents = + tabletest.getInsertResultEvents(txReceipt); + if (insertResultEvents.size() > 0) { + for (int i = 0; i < insertResultEvents.size(); i++) { + InsertResultEventResponse insertResultEventResponse = + insertResultEvents.get(i); + logger.info( + "insertCount = " + insertResultEventResponse.count.intValue()); + System.out.println( + "insertCount = " + insertResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_test table does not exist."); + } + } catch (Exception e) { + System.out.println( + "insert transaction is abnormal, please check the environment"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 insert fruit 1 apple"); + } + } + // select + else if ("select".equals(args[0])) { + if (args.length == 2) { + try { + String keyName = args[1]; + Tuple3, List, List> lists = + tabletest.select(keyName).send(); + List value1 = lists.getValue1(); + List value2 = lists.getValue2(); + List value3 = lists.getValue3(); + logger.info("record numbers = " + value1.size()); + System.out.println("record numbers = " + value1.size()); + for (int i = 0; i < value1.size(); i++) { + String name = new String(value1.get(i)); + logger.info("name = " + name); + System.out.println("name = " + name); + int item_id = value2.get(i).intValue(); + logger.info("item_id = " + item_id); + System.out.println("item_id = " + item_id); + String item_name = new String(value3.get(i)); + logger.info("item_name = " + item_name); + System.out.println("item_name = " + item_name); + } + } catch (Exception e) { + logger.info("record numbers = 0"); + System.out.println("record numbers = 0"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 select fruit"); + } + } + // update + else if ("update".equals(args[0])) { + if (args.length == 4) { + try { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + String item_name = args[3]; + RemoteCall update = + tabletest.update(name, BigInteger.valueOf(item_id), item_name); + TransactionReceipt transactionReceipt = update.send(); + List updateResultEvents = + tabletest.getUpdateResultEvents(transactionReceipt); + + if (updateResultEvents.size() > 0) { + for (int i = 0; i < updateResultEvents.size(); i++) { + UpdateResultEventResponse updateResultEventResponse = + updateResultEvents.get(i); + System.out.println( + "updateCount = " + updateResultEventResponse.count.intValue()); + logger.info( + "updateCount = " + updateResultEventResponse.count.intValue()); + } + } else { + System.out.println("t_test table does not exist."); + } + } catch (Exception e) { + System.out.println( + "update transaction is abnormal, please check the environment"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 update fruit 1 orange"); + } + } + // remove + else if ("remove".equals(args[0])) { + if (args.length == 3) { + try { + String name = args[1]; + int item_id = Integer.parseInt(args[2]); + RemoteCall remove = + tabletest.remove(name, BigInteger.valueOf(item_id)); + TransactionReceipt transactionReceipt = remove.send(); + List removeResultEvents = + tabletest.getRemoveResultEvents(transactionReceipt); + + if (removeResultEvents.size() > 0) { + RemoveResultEventResponse reomveResultEventResponse = + removeResultEvents.get(0); + logger.info("removeCount = " + reomveResultEventResponse.count.intValue()); + System.out.println( + "removeCount = " + reomveResultEventResponse.count.intValue()); + } else { + System.out.println("t_test table does not exist."); + } + } catch (Exception e) { + System.out.println( + "remove transaction is abnormal, please check the environment"); + } + } else { + System.out.println("\nPlease enter as follow example:\n 1 1 remove fruit 1"); + } + } else { + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + } + } + + public static void main(String[] args) throws Exception { + + // init the Service + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); // run the daemon service + // init the client keys + keyPair = Keys.createEcKeyPair(); + credentials = Credentials.create(keyPair); + + logger.info("-----> start test !"); + logger.info("init AOMP ChannelEthereumService"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + channelEthereumService.setTimeout(5 * 1000); + service.setGroupId(Integer.parseInt(args[0])); + try { + web3j = Web3j.build(channelEthereumService, service.getGroupId()); + } catch (Exception e) { + System.out.println("\nPlease provide groupID in the first paramters"); + System.exit(0); + } + + if (args.length > 1) { + if ("deploy".equals(args[1])) { + deployTableTest(); + } else { + String[] params = new String[args.length - 1]; + for (int i = 0; i < params.length; i++) params[i] = args[i + 1]; + testTableTest(params); + } + } else { + System.out.println( + "\nPlease choose follow commands:\n deploy, create, insert, select, update or remove"); + } + System.exit(0); + } +} diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/Trans.java b/src/test/java/org/fisco/bcos/channel/test/contract/Trans.java deleted file mode 100644 index 2013bcbd3..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/contract/Trans.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.fisco.bcos.channel.test.contract; - -import io.reactivex.Flowable; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.fisco.bcos.web3j.abi.EventEncoder; -import org.fisco.bcos.web3j.abi.TypeReference; -import org.fisco.bcos.web3j.abi.datatypes.Event; -import org.fisco.bcos.web3j.abi.datatypes.Function; -import org.fisco.bcos.web3j.abi.datatypes.Type; -import org.fisco.bcos.web3j.abi.datatypes.generated.Uint256; -import org.fisco.bcos.web3j.crypto.Credentials; -import org.fisco.bcos.web3j.protocol.Web3j; -import org.fisco.bcos.web3j.protocol.core.DefaultBlockParameter; -import org.fisco.bcos.web3j.protocol.core.RemoteCall; -import org.fisco.bcos.web3j.protocol.core.methods.request.BcosFilter; -import org.fisco.bcos.web3j.protocol.core.methods.response.Log; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.web3j.tx.Contract; -import org.fisco.bcos.web3j.tx.TransactionManager; -import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; - -/** - * Auto generated code. - * - *

Do not modify! - * - *

Please use the web3j command line tools, - * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. - * - *

Generated with web3j version none. - */ -public class Trans extends Contract { - private static final String BINARY = - "606060405234610000575b6001600060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c010000000000000000000000009081020402179055506402540be4006000600101819055506002600260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c0100000000000000000000000090810204021790555060006002600101819055505b5b61011d806100b66000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806366c99139146100435780636d4ce63c14610060575b610000565b346100005761005e6004808035906020019091905050610083565b005b346100005761006d61010f565b6040518082815260200191505060405180910390f35b8060006001015410806100a157506002600101548160026001015401105b156100ab5761010c565b8060006001015403600060010181905550806002600101600082825401925050819055507f708194b465f22e1d7b3d3abcea9aa099715f27b82909295cc402b17dd6bd92796002600101546040518082815260200191505060405180910390a15b50565b600060026001015490505b9056"; - - public static final String FUNC_TRANS = "trans"; - - public static final String FUNC_GET = "get"; - - public static final Event LOGADD_EVENT = - new Event("LogAdd", Arrays.>asList(new TypeReference() {}));; - - @Deprecated - protected Trans( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected Trans( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected Trans( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected Trans( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall trans(BigInteger num) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList(new Uint256(num)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall get() { - final Function function = - new Function( - FUNC_GET, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public List getLogAddEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(LOGADD_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - LogAddEventResponse typedResponse = new LogAddEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.index = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable logAddEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public LogAddEventResponse apply(Log log) { - EventValuesWithLog eventValues = extractEventParametersWithLog(LOGADD_EVENT, log); - LogAddEventResponse typedResponse = new LogAddEventResponse(); - typedResponse.log = log; - typedResponse.index = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable logAddEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(LOGADD_EVENT)); - return logAddEventFlowable(filter); - } - - @Deprecated - public static Trans load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Trans(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static Trans load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Trans(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static Trans load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new Trans(contractAddress, web3j, credentials, contractGasProvider); - } - - public static Trans load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new Trans(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Trans.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - Trans.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(Trans.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(Trans.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class LogAddEventResponse { - public Log log; - - public BigInteger index; - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/contract/TransTest.java b/src/test/java/org/fisco/bcos/channel/test/contract/TransTest.java deleted file mode 100644 index 2d379ec69..000000000 --- a/src/test/java/org/fisco/bcos/channel/test/contract/TransTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.fisco.bcos.channel.test.contract; - -import static org.junit.Assert.assertTrue; - -import java.math.BigInteger; -import java.util.List; -import java.util.stream.Collectors; -import org.fisco.bcos.channel.test.TestBase; -import org.fisco.bcos.web3j.protocol.core.methods.response.Log; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.junit.Test; - -public class TransTest extends TestBase { - @Test - public void testOkContract() throws Exception { - - BigInteger gasPrice = new BigInteger("300000000"); - BigInteger gasLimit = new BigInteger("300000000"); - - Trans okDemo = Trans.deploy(web3j, credentials, gasPrice, gasLimit).send(); - - if (okDemo != null) { - System.out.println("####contract address is: " + okDemo.getContractAddress()); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - - List ilist = okDemo.getLogAddEvents(receipt); - List log = ilist.stream().map(x -> x.log).collect(Collectors.toList()); - System.out.println("event log data is " + log.get(0).getData()); - BigInteger oldBalance = okDemo.get().send(); - - System.out.println("####oldBalance is: " + oldBalance.intValue()); - - okDemo.trans(new BigInteger("4")).send(); - - BigInteger newBalance = okDemo.get().send(); - System.out.println("####newBalance is: " + newBalance.intValue()); - assertTrue(newBalance.intValue() == oldBalance.intValue() + 4); - } - } -} diff --git a/src/test/java/org/fisco/bcos/channel/test/guomi/GMErc20Transaction.java b/src/test/java/org/fisco/bcos/channel/test/guomi/GMErc20Transaction.java index cd4589648..58cbf5c6a 100644 --- a/src/test/java/org/fisco/bcos/channel/test/guomi/GMErc20Transaction.java +++ b/src/test/java/org/fisco/bcos/channel/test/guomi/GMErc20Transaction.java @@ -13,37 +13,40 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class GMErc20Transaction { - public static void main(String[] args) throws Exception { - EncryptType encryptType = new EncryptType(1); - System.out.println(encryptType.getEncryptType()); - String groupId = "1"; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); - System.out.println("==================================================================="); + public static void main(String[] args) throws Exception { + EncryptType encryptType = new EncryptType(1); + System.out.println(encryptType.getEncryptType()); + String groupId = "1"; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); + System.out.println("==================================================================="); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - channelEthereumService.setTimeout(10000); - Web3j web3 = Web3j.build(channelEthereumService, Integer.parseInt(groupId)); - BigInteger gasPrice = new BigInteger("300000000"); - BigInteger gasLimit = new BigInteger("300000000"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + channelEthereumService.setTimeout(10000); + Web3j web3 = Web3j.build(channelEthereumService, Integer.parseInt(groupId)); + BigInteger gasPrice = new BigInteger("300000000"); + BigInteger gasLimit = new BigInteger("300000000"); - Credentials credentials1 = - GenCredential.create("a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); + Credentials credentials1 = + GenCredential.create( + "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - NewSolTest erc20 = NewSolTest.deploy(web3, credentials1, contractGasProvider).send(); + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + NewSolTest erc20 = NewSolTest.deploy(web3, credentials1, contractGasProvider).send(); - for (int i = 0; i < 1; i++) { - System.out.println("####contract address is: " + erc20.getContractAddress()); - erc20.transfer("0x0f49a17d17f82da2a7d92ecf19268274150eaf5e", new BigInteger("100")).send(); + for (int i = 0; i < 1; i++) { + System.out.println("####contract address is: " + erc20.getContractAddress()); + erc20.transfer("0x0f49a17d17f82da2a7d92ecf19268274150eaf5e", new BigInteger("100")) + .send(); - BigInteger oldBalance = erc20.balanceOf("0x0f49a17d17f82da2a7d92ecf19268274150eaf5e").send(); - System.out.println( - "0x0f49a17d17f82da2a7d92ecf19268274150eaf5e balance" + oldBalance.intValue()); + BigInteger oldBalance = + erc20.balanceOf("0x0f49a17d17f82da2a7d92ecf19268274150eaf5e").send(); + System.out.println( + "0x0f49a17d17f82da2a7d92ecf19268274150eaf5e balance" + oldBalance.intValue()); + } + System.exit(0); } - System.exit(0); - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/guomi/GMOkTransaction.java b/src/test/java/org/fisco/bcos/channel/test/guomi/GMOkTransaction.java index 429106b56..e2249ed44 100644 --- a/src/test/java/org/fisco/bcos/channel/test/guomi/GMOkTransaction.java +++ b/src/test/java/org/fisco/bcos/channel/test/guomi/GMOkTransaction.java @@ -14,34 +14,35 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class GMOkTransaction { - public static void main(String[] args) throws Exception { - EncryptType encryptType = new EncryptType(1); - String groupId = "1"; - ApplicationContext context = - new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.run(); - System.out.println("==================================================================="); + public static void main(String[] args) throws Exception { + EncryptType encryptType = new EncryptType(1); + String groupId = "1"; + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.run(); + System.out.println("==================================================================="); - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - channelEthereumService.setTimeout(10000); - Web3j web3 = Web3j.build(channelEthereumService, Integer.parseInt(groupId)); - BigInteger gasPrice = new BigInteger("300000000"); - BigInteger gasLimit = new BigInteger("3000000000"); + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + channelEthereumService.setTimeout(10000); + Web3j web3 = Web3j.build(channelEthereumService, Integer.parseInt(groupId)); + BigInteger gasPrice = new BigInteger("300000000"); + BigInteger gasLimit = new BigInteger("3000000000"); - Credentials credentials1 = - GenCredential.create("a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); + Credentials credentials1 = + GenCredential.create( + "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); - ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); - final Ok okDemo = Ok.deploy(web3, credentials1, contractGasProvider).send(); + ContractGasProvider contractGasProvider = new StaticGasProvider(gasPrice, gasLimit); + final Ok okDemo = Ok.deploy(web3, credentials1, contractGasProvider).send(); - for (int i = 0; i < 1; i++) { - System.out.println("####contract address is: " + okDemo.getContractAddress()); - TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); + for (int i = 0; i < 1; i++) { + System.out.println("####contract address is: " + okDemo.getContractAddress()); + TransactionReceipt receipt = okDemo.trans(new BigInteger("4")).send(); - System.out.println(" balance = " + okDemo.get().send().intValue()); + System.out.println(" balance = " + okDemo.get().send().intValue()); + } + System.exit(0); } - System.exit(0); - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/guomi/NewSolTest.java b/src/test/java/org/fisco/bcos/channel/test/guomi/NewSolTest.java index 3ac416443..e908b0d30 100644 --- a/src/test/java/org/fisco/bcos/channel/test/guomi/NewSolTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/guomi/NewSolTest.java @@ -34,447 +34,464 @@ *

Generated with web3j version none. */ public class NewSolTest extends Contract { - private static final String BINARY = - "60806040523480156200001157600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040805190810160405280600381526020017f4142430000000000000000000000000000000000000000000000000000000000815250600290805190602001906200009f92919062000222565b506040805190810160405280600e81526020017f41424320546f6b656e207465737400000000000000000000000000000000000081525060039080519060200190620000ed92919062000222565b506012600460006101000a81548160ff021916908360ff160217905550600460009054906101000a900460ff1660ff16600a0a6305f5e10002600581905550600554600660008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff16005546040518082815260200191505060405180910390a3620002d1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200026557805160ff191683800117855562000296565b8280016001018555821562000296579182015b828111156200029557825182559160200191906001019062000278565b5b509050620002a59190620002a9565b5090565b620002ce91905b80821115620002ca576000816000905550600101620002b0565b5090565b90565b61129680620002e16000396000f3fe608060405260043610610105576000357c0100000000000000000000000000000000000000000000000000000000900480635bfa2796116100a7578063ad8a973111610076578063ad8a9731146104a2578063b11b688314610535578063c938e561146105c5578063cc8be70e1461063857610105565b80635bfa2796146103035780636904e9651461039357806384052a5e14610406578063852d92131461041d57610105565b80631f2d4860116100e35780631f2d4860146101b157806328bfaecd1461022457806346b136151461027b5780635089e2c8146102ac57610105565b80630256e2781461010a578063029855d21461013557806316cad12a14610160575b600080fd5b34801561011657600080fd5b5061011f61069d565b6040518082815260200191505060405180910390f35b34801561014157600080fd5b5061014a6106e8565b6040518082815260200191505060405180910390f35b34801561016c57600080fd5b506101af6004803603602081101561018357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106ee565b005b3480156101bd57600080fd5b5061020a600480360360408110156101d457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061078d565b604051808215151515815260200191505060405180910390f35b34801561023057600080fd5b5061023961087f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028757600080fd5b506102906108a5565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102b857600080fd5b506102c16108b8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561030f57600080fd5b506103186108dd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035857808201518184015260208101905061033d565b50505050905090810190601f1680156103855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561039f57600080fd5b506103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061097b565b604051808215151515815260200191505060405180910390f35b34801561041257600080fd5b5061041b610b16565b005b34801561042957600080fd5b5061048c6004803603604081101561044057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb5565b6040518082815260200191505060405180910390f35b3480156104ae57600080fd5b5061051b600480360360608110156104c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610d3c565b604051808215151515815260200191505060405180910390f35b34801561054157600080fd5b5061054a610fe7565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561058a57808201518184015260208101905061056f565b50505050905090810190601f1680156105b75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105d157600080fd5b5061061e600480360360408110156105e857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611085565b604051808215151515815260200191505060405180910390f35b34801561064457600080fd5b506106876004803603602081101561065b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506111e9565b6040518082815260200191505060405180910390f35b6000600660008073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460055403905090565b60055481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561074957600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600081600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fd1e45707b3f71c77903b61f04c900f772db264b9bf618f1cc3308fb516eb6169846040518082815260200191505060405180910390a36001905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109735780601f1061094857610100808354040283529160200191610973565b820191906000526020600020905b81548152906001019060200180831161095657829003601f168201915b505050505081565b60006109cf82600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a6482600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461124e90919063ffffffff16565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff1846040518082815260200191505060405180910390a36001905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b7257600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5c7c30d4a0f08950cb23be4132957b357fa5dfdb0fcf218f81b86a1c036e47d060405160405180910390a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000610d9082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610e6282600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f3482600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461124e90919063ffffffff16565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff1846040518082815260200191505060405180910390a3600190509392505050565b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561107d5780601f106110525761010080835404028352916020019161107d565b820191906000526020600020905b81548152906001019060200180831161106057829003601f168201915b505050505081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110e257600080fd5b8273ffffffffffffffffffffffffffffffffffffffff16636904e9656000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156111a657600080fd5b505af11580156111ba573d6000803e3d6000fd5b505050506040513d60208110156111d057600080fd5b8101908080519060200190929190505050905092915050565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600082821115151561124357600080fd5b818303905092915050565b6000818301905082811015151561126457600080fd5b9291505056fea165627a7a723058208d4f5f612b6dd9a6324eee8f76d9c4328546720472182cd9b678e52be8fa71960029"; - - public static final String FUNC_NAME = "name"; - - public static final String FUNC_APPROVE = "approve"; - - public static final String FUNC_TOTALSUPPLY = "totalSupply"; - - public static final String FUNC_TRANSFERFROM = "transferFrom"; - - public static final String FUNC_DECIMALS = "decimals"; - - public static final String FUNC__TOTALSUPPLY = "_totalSupply"; - - public static final String FUNC_BALANCEOF = "balanceOf"; - - public static final String FUNC_ACCEPTOWNERSHIP = "acceptOwnership"; - - public static final String FUNC_OWNER = "owner"; - - public static final String FUNC_SYMBOL = "symbol"; - - public static final String FUNC_TRANSFER = "transfer"; - - public static final String FUNC_NEWOWNER = "newOwner"; - - public static final String FUNC_TRANSFERANYERC20TOKEN = "transferAnyERC20Token"; - - public static final String FUNC_ALLOWANCE = "allowance"; - - public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership"; - - public static final Event OWNERSHIPTRANSFERRED_EVENT = - new Event( - "OwnershipTransferred", - Arrays.>asList( - new TypeReference

(true) {}, new TypeReference
(true) {}));; - - public static final Event TRANSFER_EVENT = - new Event( - "Transfer", - Arrays.>asList( - new TypeReference
(true) {}, - new TypeReference
(true) {}, - new TypeReference() {}));; - - public static final Event APPROVAL_EVENT = - new Event( - "Approval", - Arrays.>asList( - new TypeReference
(true) {}, - new TypeReference
(true) {}, - new TypeReference() {}));; - - @Deprecated - protected NewSolTest( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected NewSolTest( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected NewSolTest( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected NewSolTest( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall name() { - final Function function = - new Function( - FUNC_NAME, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall approve(String spender, BigInteger tokens) { - final Function function = - new Function( - FUNC_APPROVE, - Arrays.asList(new Address(spender), new Uint256(tokens)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall totalSupply() { - final Function function = - new Function( - FUNC_TOTALSUPPLY, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall transferFrom(String from, String to, BigInteger tokens) { - final Function function = - new Function( - FUNC_TRANSFERFROM, - Arrays.asList(new Address(from), new Address(to), new Uint256(tokens)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall decimals() { - final Function function = - new Function( - FUNC_DECIMALS, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall _totalSupply() { - final Function function = - new Function( - FUNC__TOTALSUPPLY, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall balanceOf(String tokenOwner) { - final Function function = - new Function( - FUNC_BALANCEOF, - Arrays.asList(new Address(tokenOwner)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall acceptOwnership() { - final Function function = - new Function( - FUNC_ACCEPTOWNERSHIP, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall owner() { - final Function function = - new Function( - FUNC_OWNER, - Arrays.asList(), - Arrays.>asList(new TypeReference
() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall symbol() { - final Function function = - new Function( - FUNC_SYMBOL, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall transfer(String to, BigInteger tokens) { - final Function function = - new Function( - FUNC_TRANSFER, - Arrays.asList(new Address(to), new Uint256(tokens)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall newOwner() { - final Function function = - new Function( - FUNC_NEWOWNER, - Arrays.asList(), - Arrays.>asList(new TypeReference
() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public RemoteCall transferAnyERC20Token( - String tokenAddress, BigInteger tokens) { - final Function function = - new Function( - FUNC_TRANSFERANYERC20TOKEN, - Arrays.asList(new Address(tokenAddress), new Uint256(tokens)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall allowance(String tokenOwner, String spender) { - final Function function = - new Function( - FUNC_ALLOWANCE, - Arrays.asList(new Address(tokenOwner), new Address(spender)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall transferOwnership(String _newOwner) { - final Function function = - new Function( - FUNC_TRANSFEROWNERSHIP, - Arrays.asList(new Address(_newOwner)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public List getOwnershipTransferredEvents( - TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse._from = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse._to = (String) eventValues.getIndexedValues().get(1).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable ownershipTransferredEventFlowable( - BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public OwnershipTransferredEventResponse apply(Log log) { - EventValuesWithLog eventValues = - extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, log); - OwnershipTransferredEventResponse typedResponse = + private static final String BINARY = + "60806040523480156200001157600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040805190810160405280600381526020017f4142430000000000000000000000000000000000000000000000000000000000815250600290805190602001906200009f92919062000222565b506040805190810160405280600e81526020017f41424320546f6b656e207465737400000000000000000000000000000000000081525060039080519060200190620000ed92919062000222565b506012600460006101000a81548160ff021916908360ff160217905550600460009054906101000a900460ff1660ff16600a0a6305f5e10002600581905550600554600660008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff16005546040518082815260200191505060405180910390a3620002d1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200026557805160ff191683800117855562000296565b8280016001018555821562000296579182015b828111156200029557825182559160200191906001019062000278565b5b509050620002a59190620002a9565b5090565b620002ce91905b80821115620002ca576000816000905550600101620002b0565b5090565b90565b61129680620002e16000396000f3fe608060405260043610610105576000357c0100000000000000000000000000000000000000000000000000000000900480635bfa2796116100a7578063ad8a973111610076578063ad8a9731146104a2578063b11b688314610535578063c938e561146105c5578063cc8be70e1461063857610105565b80635bfa2796146103035780636904e9651461039357806384052a5e14610406578063852d92131461041d57610105565b80631f2d4860116100e35780631f2d4860146101b157806328bfaecd1461022457806346b136151461027b5780635089e2c8146102ac57610105565b80630256e2781461010a578063029855d21461013557806316cad12a14610160575b600080fd5b34801561011657600080fd5b5061011f61069d565b6040518082815260200191505060405180910390f35b34801561014157600080fd5b5061014a6106e8565b6040518082815260200191505060405180910390f35b34801561016c57600080fd5b506101af6004803603602081101561018357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106ee565b005b3480156101bd57600080fd5b5061020a600480360360408110156101d457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061078d565b604051808215151515815260200191505060405180910390f35b34801561023057600080fd5b5061023961087f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561028757600080fd5b506102906108a5565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102b857600080fd5b506102c16108b8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561030f57600080fd5b506103186108dd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035857808201518184015260208101905061033d565b50505050905090810190601f1680156103855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561039f57600080fd5b506103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061097b565b604051808215151515815260200191505060405180910390f35b34801561041257600080fd5b5061041b610b16565b005b34801561042957600080fd5b5061048c6004803603604081101561044057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb5565b6040518082815260200191505060405180910390f35b3480156104ae57600080fd5b5061051b600480360360608110156104c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610d3c565b604051808215151515815260200191505060405180910390f35b34801561054157600080fd5b5061054a610fe7565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561058a57808201518184015260208101905061056f565b50505050905090810190601f1680156105b75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105d157600080fd5b5061061e600480360360408110156105e857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611085565b604051808215151515815260200191505060405180910390f35b34801561064457600080fd5b506106876004803603602081101561065b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506111e9565b6040518082815260200191505060405180910390f35b6000600660008073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460055403905090565b60055481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561074957600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600081600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fd1e45707b3f71c77903b61f04c900f772db264b9bf618f1cc3308fb516eb6169846040518082815260200191505060405180910390a36001905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109735780601f1061094857610100808354040283529160200191610973565b820191906000526020600020905b81548152906001019060200180831161095657829003601f168201915b505050505081565b60006109cf82600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a6482600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461124e90919063ffffffff16565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff1846040518082815260200191505060405180910390a36001905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b7257600080fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5c7c30d4a0f08950cb23be4132957b357fa5dfdb0fcf218f81b86a1c036e47d060405160405180910390a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000610d9082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610e6282600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123290919063ffffffff16565b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f3482600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461124e90919063ffffffff16565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f18f84334255a242551aa98c68047b5da8063eab9fbeaec1eddeea280044b9ff1846040518082815260200191505060405180910390a3600190509392505050565b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561107d5780601f106110525761010080835404028352916020019161107d565b820191906000526020600020905b81548152906001019060200180831161106057829003601f168201915b505050505081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110e257600080fd5b8273ffffffffffffffffffffffffffffffffffffffff16636904e9656000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156111a657600080fd5b505af11580156111ba573d6000803e3d6000fd5b505050506040513d60208110156111d057600080fd5b8101908080519060200190929190505050905092915050565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600082821115151561124357600080fd5b818303905092915050565b6000818301905082811015151561126457600080fd5b9291505056fea165627a7a723058208d4f5f612b6dd9a6324eee8f76d9c4328546720472182cd9b678e52be8fa71960029"; + + public static final String FUNC_NAME = "name"; + + public static final String FUNC_APPROVE = "approve"; + + public static final String FUNC_TOTALSUPPLY = "totalSupply"; + + public static final String FUNC_TRANSFERFROM = "transferFrom"; + + public static final String FUNC_DECIMALS = "decimals"; + + public static final String FUNC__TOTALSUPPLY = "_totalSupply"; + + public static final String FUNC_BALANCEOF = "balanceOf"; + + public static final String FUNC_ACCEPTOWNERSHIP = "acceptOwnership"; + + public static final String FUNC_OWNER = "owner"; + + public static final String FUNC_SYMBOL = "symbol"; + + public static final String FUNC_TRANSFER = "transfer"; + + public static final String FUNC_NEWOWNER = "newOwner"; + + public static final String FUNC_TRANSFERANYERC20TOKEN = "transferAnyERC20Token"; + + public static final String FUNC_ALLOWANCE = "allowance"; + + public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership"; + + public static final Event OWNERSHIPTRANSFERRED_EVENT = + new Event( + "OwnershipTransferred", + Arrays.>asList( + new TypeReference
(true) {}, + new TypeReference
(true) {}));; + + public static final Event TRANSFER_EVENT = + new Event( + "Transfer", + Arrays.>asList( + new TypeReference
(true) {}, + new TypeReference
(true) {}, + new TypeReference() {}));; + + public static final Event APPROVAL_EVENT = + new Event( + "Approval", + Arrays.>asList( + new TypeReference
(true) {}, + new TypeReference
(true) {}, + new TypeReference() {}));; + + @Deprecated + protected NewSolTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected NewSolTest( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected NewSolTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected NewSolTest( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall name() { + final Function function = + new Function( + FUNC_NAME, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall approve(String spender, BigInteger tokens) { + final Function function = + new Function( + FUNC_APPROVE, + Arrays.asList(new Address(spender), new Uint256(tokens)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall totalSupply() { + final Function function = + new Function( + FUNC_TOTALSUPPLY, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall transferFrom(String from, String to, BigInteger tokens) { + final Function function = + new Function( + FUNC_TRANSFERFROM, + Arrays.asList( + new Address(from), new Address(to), new Uint256(tokens)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall decimals() { + final Function function = + new Function( + FUNC_DECIMALS, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall _totalSupply() { + final Function function = + new Function( + FUNC__TOTALSUPPLY, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall balanceOf(String tokenOwner) { + final Function function = + new Function( + FUNC_BALANCEOF, + Arrays.asList(new Address(tokenOwner)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall acceptOwnership() { + final Function function = + new Function( + FUNC_ACCEPTOWNERSHIP, + Arrays.asList(), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall owner() { + final Function function = + new Function( + FUNC_OWNER, + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall symbol() { + final Function function = + new Function( + FUNC_SYMBOL, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall transfer(String to, BigInteger tokens) { + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList(new Address(to), new Uint256(tokens)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall newOwner() { + final Function function = + new Function( + FUNC_NEWOWNER, + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteCall transferAnyERC20Token( + String tokenAddress, BigInteger tokens) { + final Function function = + new Function( + FUNC_TRANSFERANYERC20TOKEN, + Arrays.asList(new Address(tokenAddress), new Uint256(tokens)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteCall allowance(String tokenOwner, String spender) { + final Function function = + new Function( + FUNC_ALLOWANCE, + Arrays.asList(new Address(tokenOwner), new Address(spender)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall transferOwnership(String _newOwner) { + final Function function = + new Function( + FUNC_TRANSFEROWNERSHIP, + Arrays.asList(new Address(_newOwner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public List getOwnershipTransferredEvents( + TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse(); - typedResponse.log = log; - typedResponse._from = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse._to = (String) eventValues.getIndexedValues().get(1).getValue(); - return typedResponse; - } - }); - } - - public Flowable ownershipTransferredEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT)); - return ownershipTransferredEventFlowable(filter); - } - - public List getTransferEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - TransferEventResponse typedResponse = new TransferEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.to = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable transferEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public TransferEventResponse apply(Log log) { - EventValuesWithLog eventValues = extractEventParametersWithLog(TRANSFER_EVENT, log); - TransferEventResponse typedResponse = new TransferEventResponse(); - typedResponse.log = log; - typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.to = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.tokens = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable transferEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(TRANSFER_EVENT)); - return transferEventFlowable(filter); - } - - public List getApprovalEvents(TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - ApprovalEventResponse typedResponse = new ApprovalEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.tokenOwner = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.spender = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable approvalEventFlowable(BcosFilter filter) { - return web3j - .logFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public ApprovalEventResponse apply(Log log) { - EventValuesWithLog eventValues = extractEventParametersWithLog(APPROVAL_EVENT, log); - ApprovalEventResponse typedResponse = new ApprovalEventResponse(); - typedResponse.log = log; - typedResponse.tokenOwner = - (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.spender = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.tokens = - (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable approvalEventFlowable( - DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT)); - return approvalEventFlowable(filter); - } - - @Deprecated - public static NewSolTest load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new NewSolTest(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static NewSolTest load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new NewSolTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static NewSolTest load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new NewSolTest(contractAddress, web3j, credentials, contractGasProvider); - } - - public static NewSolTest load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new NewSolTest(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(NewSolTest.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall( - NewSolTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(NewSolTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall( - NewSolTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class OwnershipTransferredEventResponse { - public Log log; - - public String _from; - - public String _to; - } - - public static class TransferEventResponse { - public Log log; - - public String from; - - public String to; - - public BigInteger tokens; - } - - public static class ApprovalEventResponse { - public Log log; - - public String tokenOwner; - - public String spender; - - public BigInteger tokens; - } + typedResponse.log = eventValues.getLog(); + typedResponse._from = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse._to = (String) eventValues.getIndexedValues().get(1).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable ownershipTransferredEventFlowable( + BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function< + Log, OwnershipTransferredEventResponse>() { + @Override + public OwnershipTransferredEventResponse apply(Log log) { + EventValuesWithLog eventValues = + extractEventParametersWithLog( + OWNERSHIPTRANSFERRED_EVENT, log); + OwnershipTransferredEventResponse typedResponse = + new OwnershipTransferredEventResponse(); + typedResponse.log = log; + typedResponse._from = + (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse._to = + (String) eventValues.getIndexedValues().get(1).getValue(); + return typedResponse; + } + }); + } + + public Flowable ownershipTransferredEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT)); + return ownershipTransferredEventFlowable(filter); + } + + public List getTransferEvents(TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + TransferEventResponse typedResponse = new TransferEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.to = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable transferEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public TransferEventResponse apply(Log log) { + EventValuesWithLog eventValues = + extractEventParametersWithLog(TRANSFER_EVENT, log); + TransferEventResponse typedResponse = new TransferEventResponse(); + typedResponse.log = log; + typedResponse.from = + (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.to = + (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokens = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable transferEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSFER_EVENT)); + return transferEventFlowable(filter); + } + + public List getApprovalEvents(TransactionReceipt transactionReceipt) { + List valueList = + extractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); + ArrayList responses = + new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + ApprovalEventResponse typedResponse = new ApprovalEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.tokenOwner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.spender = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable approvalEventFlowable(BcosFilter filter) { + return web3j.logFlowable(filter) + .map( + new io.reactivex.functions.Function() { + @Override + public ApprovalEventResponse apply(Log log) { + EventValuesWithLog eventValues = + extractEventParametersWithLog(APPROVAL_EVENT, log); + ApprovalEventResponse typedResponse = new ApprovalEventResponse(); + typedResponse.log = log; + typedResponse.tokenOwner = + (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.spender = + (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokens = + (BigInteger) + eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable approvalEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + BcosFilter filter = new BcosFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT)); + return approvalEventFlowable(filter); + } + + @Deprecated + public static NewSolTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new NewSolTest(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static NewSolTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new NewSolTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static NewSolTest load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new NewSolTest(contractAddress, web3j, credentials, contractGasProvider); + } + + public static NewSolTest load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new NewSolTest(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + NewSolTest.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + NewSolTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + NewSolTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + NewSolTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + public static class OwnershipTransferredEventResponse { + public Log log; + + public String _from; + + public String _to; + } + + public static class TransferEventResponse { + public Log log; + + public String from; + + public String to; + + public BigInteger tokens; + } + + public static class ApprovalEventResponse { + public Log log; + + public String tokenOwner; + + public String spender; + + public BigInteger tokens; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/guomi/Ok.java b/src/test/java/org/fisco/bcos/channel/test/guomi/Ok.java index 74afdae46..5485af0cf 100644 --- a/src/test/java/org/fisco/bcos/channel/test/guomi/Ok.java +++ b/src/test/java/org/fisco/bcos/channel/test/guomi/Ok.java @@ -27,126 +27,130 @@ *

Generated with web3j version none. */ public class Ok extends Contract { - // guomi - private static final String BINARY = - "608060405234801561001057600080fd5b5060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260010181905550610388806100c26000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063299f7f9d146100515780638fff0fc41461007c575b600080fd5b34801561005d57600080fd5b506100666100a9565b6040518082815260200191505060405180910390f35b34801561008857600080fd5b506100a7600480360381019080803590602001909291905050506100b6565b005b6000600260010154905090565b8060006001015410806100d457506002600101548160026001015401105b156100de576102b4565b80600060010154036000600101819055508060026001016000828254019250508190555060046080604051908101604052806040805190810160405280600881526020017f323031373034313300000000000000000000000000000000000000000000000081525081526020016000800160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152509080600181540180825580915050906001820390600052602060002090600402016000909192909190915060008201518160000190805190602001906102179291906102b7565b5060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301555050505b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102f857805160ff1916838001178555610326565b82800160010185558215610326579182015b8281111561032557825182559160200191906001019061030a565b5b5090506103339190610337565b5090565b61035991905b8082111561035557600081600090555060010161033d565b5090565b905600a165627a7a72305820655d41c12843377b8b971cde92c0ed68d054c621a2d6d489822839b694a541640029"; - - public static final String FUNC_GET = "get"; - - public static final String FUNC_TRANS = "trans"; - - @Deprecated - protected Ok( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected Ok( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected Ok( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected Ok( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall get() { - final Function function = - new Function( - FUNC_GET, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteCall trans(BigInteger num) { - final Function function = - new Function( - FUNC_TRANS, - Arrays.asList(new Uint256(num)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - @Deprecated - public static Ok load( - String contractAddress, - Web3j web3j, - Credentials credentials, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Ok(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static Ok load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return new Ok(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static Ok load( - String contractAddress, - Web3j web3j, - Credentials credentials, - ContractGasProvider contractGasProvider) { - return new Ok(contractAddress, web3j, credentials, contractGasProvider); - } - - public static Ok load( - String contractAddress, - Web3j web3j, - TransactionManager transactionManager, - ContractGasProvider contractGasProvider) { - return new Ok(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Ok.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(Ok.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(Ok.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - Web3j web3j, - TransactionManager transactionManager, - BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(Ok.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } + // guomi + private static final String BINARY = + "608060405234801561001057600080fd5b5060016000800160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506402540be40060006001018190555060028060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260010181905550610388806100c26000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063299f7f9d146100515780638fff0fc41461007c575b600080fd5b34801561005d57600080fd5b506100666100a9565b6040518082815260200191505060405180910390f35b34801561008857600080fd5b506100a7600480360381019080803590602001909291905050506100b6565b005b6000600260010154905090565b8060006001015410806100d457506002600101548160026001015401105b156100de576102b4565b80600060010154036000600101819055508060026001016000828254019250508190555060046080604051908101604052806040805190810160405280600881526020017f323031373034313300000000000000000000000000000000000000000000000081525081526020016000800160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152509080600181540180825580915050906001820390600052602060002090600402016000909192909190915060008201518160000190805190602001906102179291906102b7565b5060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301555050505b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102f857805160ff1916838001178555610326565b82800160010185558215610326579182015b8281111561032557825182559160200191906001019061030a565b5b5090506103339190610337565b5090565b61035991905b8082111561035557600081600090555060010161033d565b5090565b905600a165627a7a72305820655d41c12843377b8b971cde92c0ed68d054c621a2d6d489822839b694a541640029"; + + public static final String FUNC_GET = "get"; + + public static final String FUNC_TRANS = "trans"; + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected Ok( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public RemoteCall get() { + final Function function = + new Function( + FUNC_GET, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteCall trans(BigInteger num) { + final Function function = + new Function( + FUNC_TRANS, + Arrays.asList(new Uint256(num)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return new Ok(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, credentials, contractGasProvider); + } + + public static Ok load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return new Ok(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(Ok.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + Ok.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(Ok.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + Ok.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagTransferUser.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagTransferUser.java index 7c5138276..d1567a335 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagTransferUser.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagTransferUser.java @@ -1,41 +1,44 @@ package org.fisco.bcos.channel.test.parallel.parallelok; import java.math.BigInteger; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DagTransferUser { - private static Logger logger = LoggerFactory.getLogger(DagTransferUser.class); - private String user; - private BigInteger amount; - - @Override - public String toString() { - return "DagTransferUser [user=" + user + ", amount=" + amount + "]"; - } - public String getUser() { - return user; - } - public void setUser(String user) { - this.user = user; - } - synchronized public BigInteger getAmount() { - return amount; - } - synchronized public void setAmount(BigInteger amount) { - this.amount = amount; - } - - synchronized public void increase(BigInteger amount) { - logger.debug("increase before amount is " + this.amount); - this.amount = this.amount.add(amount); - logger.debug("increase after amount is " + this.amount); - } - - synchronized public void decrease(BigInteger amount) { - logger.debug("decrease before amount is " + this.amount); - this.amount = this.amount.subtract(amount); - logger.debug("decrease after amount is " + this.amount); - } -} \ No newline at end of file + private static Logger logger = LoggerFactory.getLogger(DagTransferUser.class); + private String user; + private BigInteger amount; + + @Override + public String toString() { + return "DagTransferUser [user=" + user + ", amount=" + amount + "]"; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public synchronized BigInteger getAmount() { + return amount; + } + + public synchronized void setAmount(BigInteger amount) { + this.amount = amount; + } + + public synchronized void increase(BigInteger amount) { + logger.debug("increase before amount is " + this.amount); + this.amount = this.amount.add(amount); + logger.debug("increase after amount is " + this.amount); + } + + public synchronized void decrease(BigInteger amount) { + logger.debug("decrease before amount is " + this.amount); + this.amount = this.amount.subtract(amount); + logger.debug("decrease after amount is " + this.amount); + } +} diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagUserMgr.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagUserMgr.java index eb49899b8..1c2890dc2 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagUserMgr.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/DagUserMgr.java @@ -1,149 +1,143 @@ package org.fisco.bcos.channel.test.parallel.parallelok; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DagUserMgr { - private static Logger logger = LoggerFactory.getLogger(DagUserMgr.class); + private static Logger logger = LoggerFactory.getLogger(DagUserMgr.class); - private List userList = new ArrayList(); + private List userList = new ArrayList(); - private String file = null; + private String file = null; - private String testType = "transfer"; + private String testType = "transfer"; - private String parallelokAddr = ""; + private String parallelokAddr = ""; - public void setContractAddr(String addr) { - this.parallelokAddr = addr; - } - - public String getContractAddr() { - return this.parallelokAddr; - } - - public List getUserList() { - return userList; - } - - public void setUserList(List userList) { - this.userList = userList; - } + public void setContractAddr(String addr) { + this.parallelokAddr = addr; + } + + public String getContractAddr() { + return this.parallelokAddr; + } + + public List getUserList() { + return userList; + } + + public void setUserList(List userList) { + this.userList = userList; + } - public String getFile() { - return file; - } + public String getFile() { + return file; + } - public void setFile(String file) { - this.file = file; - } - - synchronized public void addUser(DagTransferUser user) { - userList.add(user); - } - - public boolean isEmpty() { - return userList.isEmpty(); - } - - public DagTransferUser getFrom(int idx) { - assert !isEmpty() : "Has no user."; - return userList.get(idx % userList.size()); - } - - public DagTransferUser getTo(int idx) { - assert !isEmpty() : "Has no user."; - int mid = userList.size() / 2; - return userList.get((idx + mid) % userList.size()); - } - - public DagTransferUser getNext(int idx) { - return userList.get((idx + 1) % userList.size()); - } - - public void writeDagTransferUser() throws IOException { - if (file == null) { - return; - } - logger.info("file {}, begin load.", file); - - BufferedWriter bw = null; - try { - bw = new BufferedWriter(new FileWriter(new File(file))); - - // Write contract address first - bw.write(parallelokAddr + "\n"); - - // And write user - for (int i = 0; i < userList.size(); i++) { - bw.write(userList.get(i).getUser() + "\n"); - logger.trace(" write user , user is {}", userList.get(i).getUser()); - } - - bw.flush(); - - } finally { - if (bw != null) { - bw.close(); - } - } - - logger.info("file {}, load end, count is {}.", file, userList.size()); - - System.out.println(" # write DagTransferUser end, count is " + userList.size()); - } - - public void loadDagTransferUser() throws IOException { - if (file == null) { - return; - } - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(new File(file))); - - String line = null; - - // Get contract addr first - if ((line = br.readLine()) != null) { - parallelokAddr = line; - } - - // And get user - while ((line = br.readLine()) != null) { - line = line.trim(); - if (!line.isEmpty()) { - DagTransferUser user = new DagTransferUser(); - user.setUser(line); - addUser(user); - // System.out.println("load DagTransferUser ==>> " + line); - } - } - - } finally { - if (br != null) { - br.close(); - } - } - - logger.info("file {}, load end, count is {}.", file, userList.size()); - - System.out.println(" # load DagTransferUser end, count is " + userList.size()); - } - - public String getTestType() { - return testType; - } - - public void setTestType(String testType) { - this.testType = testType; - } + public void setFile(String file) { + this.file = file; + } + + public synchronized void addUser(DagTransferUser user) { + userList.add(user); + } + + public boolean isEmpty() { + return userList.isEmpty(); + } + + public DagTransferUser getFrom(int idx) { + assert !isEmpty() : "Has no user."; + return userList.get(idx % userList.size()); + } + + public DagTransferUser getTo(int idx) { + assert !isEmpty() : "Has no user."; + int mid = userList.size() / 2; + return userList.get((idx + mid) % userList.size()); + } + + public DagTransferUser getNext(int idx) { + return userList.get((idx + 1) % userList.size()); + } + + public void writeDagTransferUser() throws IOException { + if (file == null) { + return; + } + logger.info("file {}, begin load.", file); + + BufferedWriter bw = null; + try { + bw = new BufferedWriter(new FileWriter(new File(file))); + + // Write contract address first + bw.write(parallelokAddr + "\n"); + + // And write user + for (int i = 0; i < userList.size(); i++) { + bw.write(userList.get(i).getUser() + "\n"); + logger.trace(" write user , user is {}", userList.get(i).getUser()); + } + + bw.flush(); + + } finally { + if (bw != null) { + bw.close(); + } + } + + logger.info("file {}, load end, count is {}.", file, userList.size()); + + System.out.println(" Write DagTransferUser end, count is " + userList.size()); + } + + public void loadDagTransferUser() throws IOException { + if (file == null) { + return; + } + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(new File(file))); + + String line = null; + + // Get contract addr first + if ((line = br.readLine()) != null) { + parallelokAddr = line; + } + + // And get user + while ((line = br.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty()) { + DagTransferUser user = new DagTransferUser(); + user.setUser(line); + addUser(user); + // System.out.println("load DagTransferUser ==>> " + line); + } + } + + } finally { + if (br != null) { + br.close(); + } + } + + logger.info("file {}, load end, count is {}.", file, userList.size()); + + System.out.println("Load DagTransferUser end, count is " + userList.size()); + } + + public String getTestType() { + return testType; + } + + public void setTestType(String testType) { + this.testType = testType; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelOk.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelOk.java index 8862e7d7a..5b633466d 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelOk.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelOk.java @@ -17,23 +17,20 @@ import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; /** - *

* Auto generated code. - *

- * Do not modify! - *

- * Please use the web3j - * command line tools, or the - * org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen - * module to update. * - *

- * Generated with web3j version none. + *

Do not modify! + * + *

Please use the web3j command line tools, + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. + * + *

Generated with web3j version none. */ @SuppressWarnings("unchecked") public class ParallelOk extends Contract { - private static final String BINARY = "60806040526110066000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610bb7806100626000396000f30060806040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334a18dda1461009357806335ee5f871461010657806379fa913f146101835780638a42ebe9146101ec5780639b80b0501461025f578063bca926af14610318578063d39f70bc1461032f578063fad42f8714610346575b600080fd5b34801561009f57600080fd5b50610104600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506103ff565b005b34801561011257600080fd5b5061016d600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610570565b6040518082815260200191505060405180910390f35b34801561018f57600080fd5b506101ea600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105e5565b005b3480156101f857600080fd5b5061025d600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061074d565b005b34801561026b57600080fd5b50610316600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506107c1565b005b34801561032457600080fd5b5061032d6108b8565b005b34801561033b57600080fd5b506103446109a1565b005b34801561035257600080fd5b506103fd600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610a84565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630553904e3084846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156104e25780820151818401526020810190506104c7565b50505050905090810190601f16801561050f5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561053057600080fd5b505af1158015610544573d6000803e3d6000fd5b505050506040513d602081101561055a57600080fd5b8101908080519060200190929190505050505050565b60006001826040518082805190602001908083835b6020831015156105aa5780518252602082019150602081019050602083039250610585565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166311e3f2af30836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156106c15780820151818401526020810190506106a6565b50505050905090810190601f1680156106ee5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561070e57600080fd5b505af1158015610722573d6000803e3d6000fd5b505050506040513d602081101561073857600080fd5b81019080805190602001909291905050505050565b806001836040518082805190602001908083835b6020831015156107865780518252602082019150602081019050602083039250610761565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020819055505050565b806001846040518082805190602001908083835b6020831015156107fa57805182526020820191506020810190506020830392506107d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b602083101515610873578051825260208201915060208101905060208303925061084e565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540192505081905550505050565b6108f86040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e74323536290081525060026103ff565b6109386040805190810160405280601381526020017f73657428737472696e672c75696e74323536290000000000000000000000000081525060016103ff565b61099f606060405190810160405280602981526020017f7472616e736665725769746852657665727428737472696e672c737472696e6781526020017f2c75696e7432353629000000000000000000000000000000000000000000000081525060026103ff565b565b6109df6040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e7432353629008152506105e5565b610a1d6040805190810160405280601381526020017f73657428737472696e672c75696e7432353629000000000000000000000000008152506105e5565b610a82606060405190810160405280602981526020017f7472616e736665725769746852657665727428737472696e672c737472696e6781526020017f2c75696e743235362900000000000000000000000000000000000000000000008152506105e5565b565b806001846040518082805190602001908083835b602083101515610abd5780518252602082019150602081019050602083039250610a98565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b602083101515610b365780518252602082019150602081019050602083039250610b11565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390206000828254019250508190555060648111151515610b8657600080fd5b5050505600a165627a7a723058206c64dc79155185b3154a84b9b328acf23858657ed29a9cf028fb8166b86b5a200029"; + private static final String BINARY = + "60806040526110066000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610aeb806100626000396000f30060806040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334a18dda1461009357806335ee5f871461010657806379fa913f146101835780638a42ebe9146101ec5780639b80b0501461025f578063bca926af14610318578063d39f70bc1461032f578063fad42f8714610346575b600080fd5b34801561009f57600080fd5b50610104600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506103ff565b005b34801561011257600080fd5b5061016d600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610570565b6040518082815260200191505060405180910390f35b34801561018f57600080fd5b506101ea600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105e5565b005b3480156101f857600080fd5b5061025d600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061074d565b005b34801561026b57600080fd5b50610316600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506107c1565b005b34801561032457600080fd5b5061032d6108b8565b005b34801561033b57600080fd5b5061034461093a565b005b34801561035257600080fd5b506103fd600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506109b8565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630553904e3084846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156104e25780820151818401526020810190506104c7565b50505050905090810190601f16801561050f5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561053057600080fd5b505af1158015610544573d6000803e3d6000fd5b505050506040513d602081101561055a57600080fd5b8101908080519060200190929190505050505050565b60006001826040518082805190602001908083835b6020831015156105aa5780518252602082019150602081019050602083039250610585565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166311e3f2af30836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156106c15780820151818401526020810190506106a6565b50505050905090810190601f1680156106ee5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561070e57600080fd5b505af1158015610722573d6000803e3d6000fd5b505050506040513d602081101561073857600080fd5b81019080805190602001909291905050505050565b806001836040518082805190602001908083835b6020831015156107865780518252602082019150602081019050602083039250610761565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020819055505050565b806001846040518082805190602001908083835b6020831015156107fa57805182526020820191506020810190506020830392506107d5565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b602083101515610873578051825260208201915060208101905060208303925061084e565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540192505081905550505050565b6108f86040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e74323536290081525060026103ff565b6109386040805190810160405280601381526020017f73657428737472696e672c75696e74323536290000000000000000000000000081525060016103ff565b565b6109786040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e7432353629008152506105e5565b6109b66040805190810160405280601381526020017f73657428737472696e672c75696e7432353629000000000000000000000000008152506105e5565b565b806001846040518082805190602001908083835b6020831015156109f157805182526020820191506020810190506020830392506109cc565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b602083101515610a6a5780518252602082019150602081019050602083039250610a45565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390206000828254019250508190555060648111151515610aba57600080fd5b5050505600a165627a7a72305820df737a0d19f72bf33d291d99c82bf0c9d46af962f3cfcdaeca3f04e82d20f01c0029"; public static final String FUNC_REGISTERPARALLELFUNCTION = "registerParallelFunction"; @@ -52,183 +49,344 @@ public class ParallelOk extends Contract { public static final String FUNC_TRANSFERWITHREVERT = "transferWithRevert"; @Deprecated - protected ParallelOk(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, + protected ParallelOk( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected ParallelOk(String contractAddress, Web3j web3j, Credentials credentials, + protected ParallelOk( + String contractAddress, + Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected ParallelOk(String contractAddress, Web3j web3j, TransactionManager transactionManager, - BigInteger gasPrice, BigInteger gasLimit) { + protected ParallelOk( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected ParallelOk(String contractAddress, Web3j web3j, TransactionManager transactionManager, + protected ParallelOk( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public RemoteCall registerParallelFunction(String functionName, BigInteger criticalSize) { - final Function function = new Function(FUNC_REGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(criticalSize)), - Collections.>emptyList()); + public RemoteCall registerParallelFunction( + String functionName, BigInteger criticalSize) { + final Function function = + new Function( + FUNC_REGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256( + criticalSize)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void registerParallelFunction(String functionName, BigInteger criticalSize, - TransactionSucCallback callback) { - final Function function = new Function(FUNC_REGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(criticalSize)), - Collections.>emptyList()); + public void registerParallelFunction( + String functionName, BigInteger criticalSize, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_REGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256( + criticalSize)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String registerParallelFunctionSeq(String functionName, BigInteger criticalSize) { + final Function function = + new Function( + FUNC_REGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256( + criticalSize)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall balanceOf(String name) { - final Function function = new Function(FUNC_BALANCEOF, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), - Arrays.>asList(new TypeReference() { - })); + final Function function = + new Function( + FUNC_BALANCEOF, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteCall unregisterParallelFunction(String functionName) { - final Function function = new Function(FUNC_UNREGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_UNREGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void unregisterParallelFunction(String functionName, TransactionSucCallback callback) { - final Function function = new Function(FUNC_UNREGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_UNREGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String unregisterParallelFunctionSeq(String functionName) { + final Function function = + new Function( + FUNC_UNREGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall set(String name, BigInteger num) { - final Function function = new Function(FUNC_SET, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_SET, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void set(String name, BigInteger num, TransactionSucCallback callback) { - final Function function = new Function(FUNC_SET, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_SET, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String setSeq(String name, BigInteger num) { + final Function function = + new Function( + FUNC_SET, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall transfer(String from, String to, BigInteger num) { - final Function function = new Function(FUNC_TRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void transfer(String from, String to, BigInteger num, TransactionSucCallback callback) { - final Function function = new Function(FUNC_TRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String transferSeq(String from, String to, BigInteger num) { + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall enableParallel() { - final Function function = new Function(FUNC_ENABLEPARALLEL, Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_ENABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void enableParallel(TransactionSucCallback callback) { - final Function function = new Function(FUNC_ENABLEPARALLEL, Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_ENABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String enableParallelSeq() { + final Function function = + new Function( + FUNC_ENABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall disableParallel() { - final Function function = new Function(FUNC_DISABLEPARALLEL, Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_DISABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void disableParallel(TransactionSucCallback callback) { - final Function function = new Function(FUNC_DISABLEPARALLEL, Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_DISABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } - public RemoteCall transferWithRevert(String from, String to, BigInteger num) { - final Function function = new Function(FUNC_TRANSFERWITHREVERT, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + public String disableParallelSeq() { + final Function function = + new Function( + FUNC_DISABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); + return createTransactionSeq(function); + } + + public RemoteCall transferWithRevert( + String from, String to, BigInteger num) { + final Function function = + new Function( + FUNC_TRANSFERWITHREVERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void transferWithRevert(String from, String to, BigInteger num, TransactionSucCallback callback) { - final Function function = new Function(FUNC_TRANSFERWITHREVERT, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + public void transferWithRevert( + String from, String to, BigInteger num, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_TRANSFERWITHREVERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String transferWithRevertSeq(String from, String to, BigInteger num) { + final Function function = + new Function( + FUNC_TRANSFERWITHREVERT, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + @Deprecated - public static ParallelOk load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, + public static ParallelOk load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { return new ParallelOk(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Deprecated - public static ParallelOk load(String contractAddress, Web3j web3j, TransactionManager transactionManager, - BigInteger gasPrice, BigInteger gasLimit) { + public static ParallelOk load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { return new ParallelOk(contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - public static ParallelOk load(String contractAddress, Web3j web3j, Credentials credentials, + public static ParallelOk load( + String contractAddress, + Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { return new ParallelOk(contractAddress, web3j, credentials, contractGasProvider); } - public static ParallelOk load(String contractAddress, Web3j web3j, TransactionManager transactionManager, + public static ParallelOk load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { return new ParallelOk(contractAddress, web3j, transactionManager, contractGasProvider); } - public static RemoteCall deploy(Web3j web3j, Credentials credentials, - ContractGasProvider contractGasProvider) { - return deployRemoteCall(ParallelOk.class, web3j, credentials, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + ParallelOk.class, web3j, credentials, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(ParallelOk.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + ParallelOk.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); } - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(ParallelOk.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + return deployRemoteCall( + ParallelOk.class, web3j, transactionManager, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(ParallelOk.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + return deployRemoteCall( + ParallelOk.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelRevert.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelRevert.java index d3903ba89..9d207ec57 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelRevert.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/ParallelRevert.java @@ -17,17 +17,20 @@ import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; /** - *

Auto generated code. + * Auto generated code. + * *

Do not modify! + * *

Please use the web3j command line tools, - * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. * *

Generated with web3j version none. */ @SuppressWarnings("unchecked") public class ParallelRevert extends Contract { - private static final String BINARY = "60806040526110076000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610930806100626000396000f300608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334a18dda1461008857806335ee5f87146100fb57806379fa913f146101785780638a42ebe9146101e15780639b80b05014610254578063bca926af1461030d578063d39f70bc14610324575b600080fd5b34801561009457600080fd5b506100f9600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061033b565b005b34801561010757600080fd5b50610162600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ac565b6040518082815260200191505060405180910390f35b34801561018457600080fd5b506101df600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610521565b005b3480156101ed57600080fd5b50610252600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610689565b005b34801561026057600080fd5b5061030b600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506106fd565b005b34801561031957600080fd5b50610322610804565b005b34801561033057600080fd5b50610339610886565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630553904e3084846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561041e578082015181840152602081019050610403565b50505050905090810190601f16801561044b5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561046c57600080fd5b505af1158015610480573d6000803e3d6000fd5b505050506040513d602081101561049657600080fd5b8101908080519060200190929190505050505050565b60006001826040518082805190602001908083835b6020831015156104e657805182526020820191506020810190506020830392506104c1565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166311e3f2af30836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156105fd5780820151818401526020810190506105e2565b50505050905090810190601f16801561062a5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561064a57600080fd5b505af115801561065e573d6000803e3d6000fd5b505050506040513d602081101561067457600080fd5b81019080805190602001909291905050505050565b806001836040518082805190602001908083835b6020831015156106c2578051825260208201915060208101905060208303925061069d565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020819055505050565b806001846040518082805190602001908083835b6020831015156107365780518252602082019150602081019050602083039250610711565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b6020831015156107af578051825260208201915060208101905060208303925061078a565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540192505081905550606481111515156107ff57600080fd5b505050565b6108446040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e743235362900815250600261033b565b6108846040805190810160405280601381526020017f73657428737472696e672c75696e743235362900000000000000000000000000815250600161033b565b565b6108c46040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e743235362900815250610521565b6109026040805190810160405280601381526020017f73657428737472696e672c75696e743235362900000000000000000000000000815250610521565b5600a165627a7a7230582098a8175f9228fd5e6de012a15166541c53bff8d97397ba470d9257fdbb5b3ca90029"; + private static final String BINARY = + "60806040526110076000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610930806100626000396000f300608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806334a18dda1461008857806335ee5f87146100fb57806379fa913f146101785780638a42ebe9146101e15780639b80b05014610254578063bca926af1461030d578063d39f70bc14610324575b600080fd5b34801561009457600080fd5b506100f9600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061033b565b005b34801561010757600080fd5b50610162600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104ac565b6040518082815260200191505060405180910390f35b34801561018457600080fd5b506101df600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610521565b005b3480156101ed57600080fd5b50610252600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610689565b005b34801561026057600080fd5b5061030b600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001909291905050506106fd565b005b34801561031957600080fd5b50610322610804565b005b34801561033057600080fd5b50610339610886565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630553904e3084846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561041e578082015181840152602081019050610403565b50505050905090810190601f16801561044b5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561046c57600080fd5b505af1158015610480573d6000803e3d6000fd5b505050506040513d602081101561049657600080fd5b8101908080519060200190929190505050505050565b60006001826040518082805190602001908083835b6020831015156104e657805182526020820191506020810190506020830392506104c1565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166311e3f2af30836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156105fd5780820151818401526020810190506105e2565b50505050905090810190601f16801561062a5780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b15801561064a57600080fd5b505af115801561065e573d6000803e3d6000fd5b505050506040513d602081101561067457600080fd5b81019080805190602001909291905050505050565b806001836040518082805190602001908083835b6020831015156106c2578051825260208201915060208101905060208303925061069d565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020819055505050565b806001846040518082805190602001908083835b6020831015156107365780518252602082019150602081019050602083039250610711565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540392505081905550806001836040518082805190602001908083835b6020831015156107af578051825260208201915060208101905060208303925061078a565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008282540192505081905550606481111515156107ff57600080fd5b505050565b6108446040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e743235362900815250600261033b565b6108846040805190810160405280601381526020017f73657428737472696e672c75696e743235362900000000000000000000000000815250600161033b565b565b6108c46040805190810160405280601f81526020017f7472616e7366657228737472696e672c737472696e672c75696e743235362900815250610521565b6109026040805190810160405280601381526020017f73657428737472696e672c75696e743235362900000000000000000000000000815250610521565b5600a165627a7a7230582098a8175f9228fd5e6de012a15166541c53bff8d97397ba470d9257fdbb5b3ca90029"; public static final String FUNC_REGISTERPARALLELFUNCTION = "registerParallelFunction"; @@ -44,167 +47,243 @@ public class ParallelRevert extends Contract { public static final String FUNC_DISABLEPARALLEL = "disableParallel"; @Deprecated - protected ParallelRevert(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected ParallelRevert( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected ParallelRevert(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected ParallelRevert( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected ParallelRevert(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected ParallelRevert( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected ParallelRevert(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected ParallelRevert( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public RemoteCall registerParallelFunction(String functionName, BigInteger criticalSize) { - final Function function = new Function( - FUNC_REGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(criticalSize)), - Collections.>emptyList()); + public RemoteCall registerParallelFunction( + String functionName, BigInteger criticalSize) { + final Function function = + new Function( + FUNC_REGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256( + criticalSize)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void registerParallelFunction(String functionName, BigInteger criticalSize, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_REGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(criticalSize)), - Collections.>emptyList()); + public void registerParallelFunction( + String functionName, BigInteger criticalSize, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_REGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256( + criticalSize)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall balanceOf(String name) { - final Function function = new Function(FUNC_BALANCEOF, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), - Arrays.>asList(new TypeReference() {})); + final Function function = + new Function( + FUNC_BALANCEOF, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteCall unregisterParallelFunction(String functionName) { - final Function function = new Function( - FUNC_UNREGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_UNREGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void unregisterParallelFunction(String functionName, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_UNREGISTERPARALLELFUNCTION, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_UNREGISTERPARALLELFUNCTION, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(functionName)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall set(String name, BigInteger num) { - final Function function = new Function( - FUNC_SET, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_SET, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void set(String name, BigInteger num, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_SET, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_SET, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(name), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall transfer(String from, String to, BigInteger num) { - final Function function = new Function( - FUNC_TRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void transfer(String from, String to, BigInteger num, TransactionSucCallback callback) { - final Function function = new Function( - FUNC_TRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_TRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(from), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(to), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(num)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall enableParallel() { - final Function function = new Function( - FUNC_ENABLEPARALLEL, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_ENABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void enableParallel(TransactionSucCallback callback) { - final Function function = new Function( - FUNC_ENABLEPARALLEL, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_ENABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } public RemoteCall disableParallel() { - final Function function = new Function( - FUNC_DISABLEPARALLEL, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_DISABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void disableParallel(TransactionSucCallback callback) { - final Function function = new Function( - FUNC_DISABLEPARALLEL, - Arrays.asList(), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_DISABLEPARALLEL, + Arrays.asList(), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } @Deprecated - public static ParallelRevert load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + public static ParallelRevert load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, + BigInteger gasLimit) { return new ParallelRevert(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Deprecated - public static ParallelRevert load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + public static ParallelRevert load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { return new ParallelRevert(contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - public static ParallelRevert load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + public static ParallelRevert load( + String contractAddress, + Web3j web3j, + Credentials credentials, + ContractGasProvider contractGasProvider) { return new ParallelRevert(contractAddress, web3j, credentials, contractGasProvider); } - public static ParallelRevert load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + public static ParallelRevert load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { return new ParallelRevert(contractAddress, web3j, transactionManager, contractGasProvider); } - public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return deployRemoteCall(ParallelRevert.class, web3j, credentials, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + ParallelRevert.class, web3j, credentials, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(ParallelRevert.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + ParallelRevert.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); } - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(ParallelRevert.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { + return deployRemoteCall( + ParallelRevert.class, web3j, transactionManager, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(ParallelRevert.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + ParallelRevert.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDT.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDT.java index d25811414..4f7cc8a50 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDT.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDT.java @@ -1,81 +1,82 @@ package org.fisco.bcos.channel.test.parallel.parallelok; +import java.math.BigInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigInteger; - -import org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDTTest; -import org.fisco.bcos.channel.test.parallel.parallelok.DagUserMgr; - public class PerformanceDT { - private static Logger logger = LoggerFactory.getLogger(PerformanceDT.class); + private static Logger logger = LoggerFactory.getLogger(PerformanceDT.class); - public static void Usage() { - System.out.println(" Usage:"); - System.out.println( - " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID add count tps file."); - System.out.println( - " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID transfer count tps file strategy."); - System.out.println( - " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID transferRevert count tps file strategy."); - System.exit(0); - } + public static void Usage() { + System.out.println(" Usage:"); + System.out.println( + " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID add count tps file."); + System.out.println( + " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID transfer count tps file strategy."); + System.out.println( + " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.parallelok.PerformanceDT groupID transferRevert count tps file strategy."); + System.exit(0); + } - public static void main(String[] args) throws Exception { - if (args.length < 4) { - Usage(); - } + public static void main(String[] args) throws Exception { + if (args.length < 4) { + Usage(); + } - String groupID = args[0]; - String command = args[1]; - BigInteger count = new BigInteger(args[2]); - BigInteger tps = new BigInteger(args[3]); - String file = null; - BigInteger deci = new BigInteger("0"); - if (args.length > 4) { - file = args[4]; - if (args.length > 5) { - deci = new BigInteger(args[5]); - } - } + String groupID = args[0]; + String command = args[1]; + BigInteger count = new BigInteger(args[2]); + BigInteger tps = new BigInteger(args[3]); + String file = null; + BigInteger deci = new BigInteger("0"); + if (args.length > 4) { + file = args[4]; + if (args.length > 5) { + deci = new BigInteger(args[5]); + } + } - // deci can not bigger than 10. - if (deci.compareTo(new BigInteger("10")) > 0) { - deci = new BigInteger("10"); - } + // deci can not bigger than 10. + if (deci.compareTo(new BigInteger("10")) > 0) { + deci = new BigInteger("10"); + } - logger.info(" dag transfer test begin, command is {}, count is {}, tps is {}, file is {}, deci is {}", command, - count, tps, file, deci); + logger.info( + " dag transfer test begin, command is {}, count is {}, tps is {}, file is {}, deci is {}", + command, + count, + tps, + file, + deci); - DagUserMgr d = new DagUserMgr(); - d.setFile(file); + DagUserMgr d = new DagUserMgr(); + d.setFile(file); - PerformanceDTCollector collector = new PerformanceDTCollector(); - collector.setTotal(count.intValue()); - collector.setDagUserMrg(d); + PerformanceDTCollector collector = new PerformanceDTCollector(); + collector.setTotal(count.intValue()); + collector.setDagUserMrg(d); - PerformanceDTTest PerformanceDTTest = new PerformanceDTTest(groupID); - PerformanceDTTest.setCollector(collector); - PerformanceDTTest.setDagUserMgr(d); - collector.setPerformanceDTTest(PerformanceDTTest); + PerformanceDTTest PerformanceDTTest = new PerformanceDTTest(groupID); + PerformanceDTTest.setCollector(collector); + PerformanceDTTest.setDagUserMgr(d); + collector.setPerformanceDTTest(PerformanceDTTest); - switch (command) { - case "add": - d.setTestType("add"); - PerformanceDTTest.userAddTest(count, tps); - break; - case "transfer": - d.setTestType("transfer"); - d.loadDagTransferUser(); - PerformanceDTTest.userTransferTest(count, tps, deci); - break; - case "transferRevert": - d.setTestType("transferRevert"); - d.loadDagTransferUser(); - PerformanceDTTest.userTransferRevertTest(count, tps, deci); - default: - Usage(); - } - } + switch (command) { + case "add": + d.setTestType("add"); + PerformanceDTTest.userAddTest(count, tps); + break; + case "transfer": + d.setTestType("transfer"); + d.loadDagTransferUser(); + PerformanceDTTest.userTransferTest(count, tps, deci); + break; + case "transferRevert": + d.setTestType("transferRevert"); + d.loadDagTransferUser(); + PerformanceDTTest.userTransferRevertTest(count, tps, deci); + default: + Usage(); + } + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCallback.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCallback.java index 068e38cd5..0bc512b25 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCallback.java @@ -1,119 +1,128 @@ package org.fisco.bcos.channel.test.parallel.parallelok; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import java.math.BigInteger; - import org.fisco.bcos.channel.client.TransactionSucCallback; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - public class PerformanceDTCallback extends TransactionSucCallback { - static private ObjectMapper objectMapper = new ObjectMapper(); - private Long startTime = System.currentTimeMillis(); - - private PerformanceDTCollector collector = null; - private DagUserMgr dagUserMgr = null; - - private DagTransferUser user = null; - private DagTransferUser fromUser = null; - private DagTransferUser toUser = null; - private BigInteger amount = null; - - private String callBackType = "transfer"; - - public String getCallBackType() { - return callBackType; - } - - public void setCallBackType(String callBackType) { - this.callBackType = callBackType; - } - - public DagUserMgr getDagUserMgr() { - return dagUserMgr; - } - - public void setDagUserMgr(DagUserMgr dagUserMgr) { - this.dagUserMgr = dagUserMgr; - } - - public DagTransferUser getDagTransferUser() { - return user; - } - - public void setDagTransferUser(DagTransferUser dagTransferUser) { - this.user = dagTransferUser; - } - - public PerformanceDTCollector getCollector() { - return collector; - } - - public void setCollector(PerformanceDTCollector collector) { - this.collector = collector; - } - - static Logger logger = LoggerFactory.getLogger(PerformanceDTCallback.class); - - public PerformanceDTCallback() { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - - @Override - public void onResponse(TransactionReceipt receipt) { - Long cost = System.currentTimeMillis() - startTime; - - try { - if (receipt.isStatusOK()) { - - if (callBackType.compareTo("set") == 0) { // add test - dagUserMgr.addUser(user); - } else if (callBackType.compareTo("transfer") == 0) { // transfer test - fromUser.decrease(amount); - toUser.increase(amount); - } else if (callBackType.compareTo("transferRevert") == 0) { // tranfer revert test - fromUser.decrease(amount); - toUser.increase(amount); - } - } - - if (callBackType.compareTo("transferRevert") == 0) { - String info = "[RevertTest-TxSent]" + "\t[TxHash]=" + receipt.getTransactionHash() + "\t[From]=" - + fromUser.getUser() + "\t[FromBalance]=" + fromUser.getAmount() + "\t[To]=" + toUser.getUser() - + "\t[ToBalance]=" + toUser.getAmount() + "\t[Status]=" + receipt.getStatus(); - System.out.println(info); - } - - collector.onMessage(receipt, cost); - } catch (Exception e) { - logger.error("onMessage error: ", e); - } - } - - public DagTransferUser getFromUser() { - return fromUser; - } - - public void setFromUser(DagTransferUser fromUser) { - this.fromUser = fromUser; - } - - public DagTransferUser getToUser() { - return toUser; - } - - public void setToUser(DagTransferUser toUser) { - this.toUser = toUser; - } - - public BigInteger getAmount() { - return amount; - } - - public void setAmount(BigInteger amount) { - this.amount = amount; - } + private static ObjectMapper objectMapper = new ObjectMapper(); + private Long startTime = System.currentTimeMillis(); + + private PerformanceDTCollector collector = null; + private DagUserMgr dagUserMgr = null; + + private DagTransferUser user = null; + private DagTransferUser fromUser = null; + private DagTransferUser toUser = null; + private BigInteger amount = null; + + private String callBackType = "transfer"; + + public String getCallBackType() { + return callBackType; + } + + public void setCallBackType(String callBackType) { + this.callBackType = callBackType; + } + + public DagUserMgr getDagUserMgr() { + return dagUserMgr; + } + + public void setDagUserMgr(DagUserMgr dagUserMgr) { + this.dagUserMgr = dagUserMgr; + } + + public DagTransferUser getDagTransferUser() { + return user; + } + + public void setDagTransferUser(DagTransferUser dagTransferUser) { + this.user = dagTransferUser; + } + + public PerformanceDTCollector getCollector() { + return collector; + } + + public void setCollector(PerformanceDTCollector collector) { + this.collector = collector; + } + + static Logger logger = LoggerFactory.getLogger(PerformanceDTCallback.class); + + public PerformanceDTCallback() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + @Override + public void onResponse(TransactionReceipt receipt) { + Long cost = System.currentTimeMillis() - startTime; + + try { + if (receipt.isStatusOK()) { + + if (callBackType.compareTo("set") == 0) { // add test + dagUserMgr.addUser(user); + } else if (callBackType.compareTo("transfer") == 0) { // transfer test + fromUser.decrease(amount); + toUser.increase(amount); + } else if (callBackType.compareTo("transferRevert") == 0) { // tranfer revert test + fromUser.decrease(amount); + toUser.increase(amount); + } + } + + if (callBackType.compareTo("transferRevert") == 0) { + String info = + "[RevertTest-TxSent]" + + "\t[TxHash]=" + + receipt.getTransactionHash() + + "\t[From]=" + + fromUser.getUser() + + "\t[FromBalance]=" + + fromUser.getAmount() + + "\t[To]=" + + toUser.getUser() + + "\t[ToBalance]=" + + toUser.getAmount() + + "\t[Status]=" + + receipt.getStatus(); + System.out.println(info); + } + + collector.onMessage(receipt, cost); + } catch (Exception e) { + logger.error("onMessage error: ", e); + } + } + + public DagTransferUser getFromUser() { + return fromUser; + } + + public void setFromUser(DagTransferUser fromUser) { + this.fromUser = fromUser; + } + + public DagTransferUser getToUser() { + return toUser; + } + + public void setToUser(DagTransferUser toUser) { + this.toUser = toUser; + } + + public BigInteger getAmount() { + return amount; + } + + public void setAmount(BigInteger amount) { + this.amount = amount; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCollector.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCollector.java index 0d0eb8ee2..59aab15d9 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCollector.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTCollector.java @@ -1,156 +1,225 @@ package org.fisco.bcos.channel.test.parallel.parallelok; -import java.math.BigInteger; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.channel.test.parallel.parallelok.DagUserMgr; - public class PerformanceDTCollector { - static Logger logger = LoggerFactory.getLogger(PerformanceDTCollector.class); - - private Integer total = 0; - private DagUserMgr dagUserMrg; - private PerformanceDTTest PerformanceDTTest; - - public PerformanceDTTest getPerformanceDTTest() { - return PerformanceDTTest; - } - - public void setPerformanceDTTest(PerformanceDTTest PerformanceDTTest) { - this.PerformanceDTTest = PerformanceDTTest; - } - - public Integer getTotal() { - return total; - } - - public void setTotal(Integer total) { - this.total = total; - } - - public DagUserMgr getDagUserMrg() { - return dagUserMrg; - } - - public void setDagUserMrg(DagUserMgr dagUserMrg) { - this.dagUserMrg = dagUserMrg; - } - - public boolean isEnd() { - return received.intValue() >= total; - } - - public void onMessage(TransactionReceipt receipt, Long cost) { - try { - if (!receipt.isStatusOK()) { - System.out.println("receipt error! status: " + receipt.getStatus()); - error.addAndGet(1); - } - - received.incrementAndGet(); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println(" |received:" - + String.valueOf((received.get() + 1) * 100 / total) + "%"); - } - - if (cost < 50) { - less50.incrementAndGet(); - } else if (cost < 100) { - less100.incrementAndGet(); - ; - } else if (cost < 200) { - less200.incrementAndGet(); - ; - } else if (cost < 400) { - less400.incrementAndGet(); - ; - } else if (cost < 1000) { - less1000.incrementAndGet(); - ; - } else if (cost < 2000) { - less2000.incrementAndGet(); - ; - } else { - timeout2000.incrementAndGet(); - ; - } - - totalCost.addAndGet(cost); - - if (isEnd()) { - System.out.println("total"); - - // - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - System.out.println("Total transactions: " + String.valueOf(total)); - System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); - System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); - System.out.println("Error rate: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - System.out.println( - "Return Error rate: " + String.valueOf((ret_error.get() / received.get()) * 100) + "%"); - - System.out.println("Time area:"); - System.out.println("0 < time < 50ms : " + String.valueOf(less50) + " : " - + String.valueOf((double) less50.get() / total * 100) + "%"); - System.out.println("50 < time < 100ms : " + String.valueOf(less100) + " : " - + String.valueOf((double) less100.get() / total * 100) + "%"); - System.out.println("100 < time < 200ms : " + String.valueOf(less200) + " : " - + String.valueOf((double) less200.get() / total * 100) + "%"); - System.out.println("200 < time < 400ms : " + String.valueOf(less400) + " : " - + String.valueOf((double) less400.get() / total * 100) + "%"); - System.out.println("400 < time < 1000ms : " + String.valueOf(less1000) + " : " - + String.valueOf((double) less1000.get() / total * 100) + "%"); - System.out.println("1000 < time < 2000ms : " + String.valueOf(less2000) + " : " - + String.valueOf((double) less2000.get() / total * 100) + "%"); - System.out.println("2000 < time : " + String.valueOf(timeout2000) + " : " - + String.valueOf((double) timeout2000.get() / total * 100) + "%"); - } - - } catch (Exception e) { - logger.error("error:", e); - System.exit(0); - } - } - - private AtomicLong less50 = new AtomicLong(0); - private AtomicLong less100 = new AtomicLong(0); - private AtomicLong less200 = new AtomicLong(0); - private AtomicLong less400 = new AtomicLong(0); - private AtomicLong less1000 = new AtomicLong(0); - private AtomicLong less2000 = new AtomicLong(0); - private AtomicLong timeout2000 = new AtomicLong(0); - private AtomicLong totalCost = new AtomicLong(0); - - private AtomicInteger received = new AtomicInteger(0); - - public AtomicInteger getReceived() { - return received; - } - - public void setReceived(AtomicInteger received) { - this.received = received; - } - - private AtomicInteger error = new AtomicInteger(0); - private AtomicInteger ret_error = new AtomicInteger(0); - private Long startTimestamp = System.currentTimeMillis(); - - public Long getStartTimestamp() { - return startTimestamp; - } - - public void setStartTimestamp(Long startTimestamp) { - this.startTimestamp = startTimestamp; - } + static Logger logger = LoggerFactory.getLogger(PerformanceDTCollector.class); + static HashMap errorInfos = new HashMap(); + + private Integer total = 0; + private DagUserMgr dagUserMrg; + private PerformanceDTTest PerformanceDTTest; + + public PerformanceDTCollector() { + errorInfos.put("0x0", "None"); + errorInfos.put("0x1", "Unknown"); + errorInfos.put("0x2", "BadRLP"); + errorInfos.put("0x3", "InvalidFormat"); + errorInfos.put("0x4", "OutOfGasIntrinsic"); + errorInfos.put("0x5", "InvalidSignature"); + errorInfos.put("0x6", "InvalidNonce"); + errorInfos.put("0x7", "NotEnoughCash"); + errorInfos.put("0x8", "OutOfGasBase"); + errorInfos.put("0x9", "BlockGasLimitReached"); + errorInfos.put("0xa", "BadInstruction"); + errorInfos.put("0xb", "BadJumpDestination"); + errorInfos.put("0xc", "OutOfGas"); + errorInfos.put("0xd", "OutOfStack"); + errorInfos.put("0xe", "StackUnderflow"); + errorInfos.put("0xf", "NonceCheckFail"); + errorInfos.put("0x10", "BlockLimitCheckFail"); + errorInfos.put("0x11", "FilterCheckFail"); + errorInfos.put("0x12", "NoDeployPermission"); + errorInfos.put("0x13", "NoCallPermission"); + errorInfos.put("0x14", "NoTxPermission"); + errorInfos.put("0x15", "PrecompiledError"); + errorInfos.put("0x16", "RevertInstruction"); + errorInfos.put("0x17", "InvalidZeroSignatureFormat"); + errorInfos.put("0x18", "AddressAlreadyUsed"); + errorInfos.put("0x19", "PermissionDenied"); + errorInfos.put("0x1a", "CallAddressError"); + errorInfos.put("0x1b", "GasOverflow"); + errorInfos.put("0x1c", "TxPoolIsFull"); + } + + public PerformanceDTTest getPerformanceDTTest() { + return PerformanceDTTest; + } + + public void setPerformanceDTTest(PerformanceDTTest PerformanceDTTest) { + this.PerformanceDTTest = PerformanceDTTest; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public DagUserMgr getDagUserMrg() { + return dagUserMrg; + } + + public void setDagUserMrg(DagUserMgr dagUserMrg) { + this.dagUserMrg = dagUserMrg; + } + + public boolean isEnd() { + return received.intValue() >= total; + } + + public void onMessage(TransactionReceipt receipt, Long cost) { + try { + if (!receipt.isStatusOK()) { + System.out.println("receipt error! status: " + errorInfos.get(receipt.getStatus())); + error.addAndGet(1); + } + + received.incrementAndGet(); + + if ((received.get() + 1) % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf((received.get() + 1) * 100 / total) + + "%"); + } + + if (cost < 50) { + less50.incrementAndGet(); + } else if (cost < 100) { + less100.incrementAndGet(); + ; + } else if (cost < 200) { + less200.incrementAndGet(); + ; + } else if (cost < 400) { + less400.incrementAndGet(); + ; + } else if (cost < 1000) { + less1000.incrementAndGet(); + ; + } else if (cost < 2000) { + less2000.incrementAndGet(); + ; + } else { + timeout2000.incrementAndGet(); + ; + } + + totalCost.addAndGet(cost); + + if (isEnd()) { + System.out.println("total"); + + // + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + System.out.println("Total transactions: " + String.valueOf(total)); + System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); + System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println( + "Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); + System.out.println( + "Error rate: " + + String.valueOf( + ((double) error.get() / (double) received.get()) * 100) + + "%"); + System.out.println( + "Return Error rate: " + + String.valueOf( + ((double) ret_error.get() / (double) received.get()) * 100) + + "%"); + + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50.get() / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100.get() / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200.get() / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400.get() / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000.get() / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000.get() / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000.get() / total * 100) + + "%"); + } + + } catch (Exception e) { + logger.error("error:", e); + System.exit(0); + } + } + + private AtomicLong less50 = new AtomicLong(0); + private AtomicLong less100 = new AtomicLong(0); + private AtomicLong less200 = new AtomicLong(0); + private AtomicLong less400 = new AtomicLong(0); + private AtomicLong less1000 = new AtomicLong(0); + private AtomicLong less2000 = new AtomicLong(0); + private AtomicLong timeout2000 = new AtomicLong(0); + private AtomicLong totalCost = new AtomicLong(0); + + private AtomicInteger received = new AtomicInteger(0); + + public AtomicInteger getReceived() { + return received; + } + + public void setReceived(AtomicInteger received) { + this.received = received; + } + + private AtomicInteger error = new AtomicInteger(0); + private AtomicInteger ret_error = new AtomicInteger(0); + private Long startTimestamp = System.currentTimeMillis(); + + public Long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(Long startTimestamp) { + this.startTimestamp = startTimestamp; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTTest.java b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTTest.java index 64be46f9e..1edf5814e 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/parallelok/PerformanceDTTest.java @@ -1,414 +1,720 @@ package org.fisco.bcos.channel.test.parallel.parallelok; import com.google.common.util.concurrent.RateLimiter; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.*; import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.web3j.tuples.generated.Tuple2; +import org.fisco.bcos.web3j.tx.Contract; +import org.fisco.bcos.web3j.tx.TransactionManager; import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; import org.fisco.bcos.web3j.utils.Web3AsyncThreadPoolSize; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.math.BigInteger; -import java.util.List; -import java.util.Random; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - public class PerformanceDTTest { - private static Logger logger = LoggerFactory.getLogger(PerformanceDTTest.class); - private static AtomicInteger sended = new AtomicInteger(0); - private static String groupId = "1"; - - private Web3j web3; - private ParallelOk parallelok; - - private Credentials credentials; - private DagUserMgr dagUserMgr; - private PerformanceDTCollector collector; - private String parallelokAddr = ""; - - public PerformanceDTTest(String groupID) throws Exception { - groupId = groupID; - initialize(groupId); - } - - public DagUserMgr getDagUserMgr() { - return dagUserMgr; - } - - public void setDagUserMgr(DagUserMgr dagUserMgr) { - this.dagUserMgr = dagUserMgr; - } - - public Web3j getWeb3() { - return web3; - } - - public void setWeb3(Web3j web3) { - this.web3 = web3; - } - - public Credentials getCredentials() { - return credentials; - } - - public void setCredentials(Credentials credentials) { - this.credentials = credentials; - } - - public PerformanceDTCollector getCollector() { - return collector; - } - - public void setCollector(PerformanceDTCollector collector) { - this.collector = collector; - } - - public void veryTransferData() { - // System.out.println(" data validation => "); - List allUser = dagUserMgr.getUserList(); - int total_user = allUser.size(); - - int verify_success = 0; - - int verify_failed = 0; - - allUser = dagUserMgr.getUserList(); - - try { - for (int i = 0; i < allUser.size(); ++i) { - BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); - - String user = allUser.get(i).getUser(); - BigInteger local = allUser.get(i).getAmount(); - BigInteger remote = result; - - logger.debug(" user " + user + " local amount " + local + " remote amount " + remote); - if (local.compareTo(remote) != 0) { - verify_failed++; - logger.error(" local amount is not same as remote, user " + user + " local " + local + " remote " - + remote); - } else { - verify_success++; - } - } - - System.out.println("validation:"); - System.out.println(" \tuser count is " + total_user); - System.out.println(" \tverify_success count is " + verify_success); - System.out.println(" \tverify_failed count is " + verify_failed); - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); - } - } - - public void initialize(String groupId) throws Exception { - - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - - Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; - Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - web3 = Web3j.build(channelEthereumService, 15 * 100, scheduledExecutorService, Integer.parseInt(groupId)); - - credentials = Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - } - - public void userAddTest(BigInteger count, BigInteger qps) { - - try { - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count.intValue()); - - threadPool.initialize(); - - System.out.println("Deploying contract "); - System.out.println("==================================================================="); - credentials = Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - parallelok = ParallelOk.deploy(web3, credentials, new BigInteger("30000000"), new BigInteger("30000000")) - .send(); - - // enable parallel transaction - parallelok.enableParallel().send(); - - parallelokAddr = parallelok.getContractAddress(); - - System.out.println("ParallelOk address: " + parallelokAddr); - - RateLimiter limiter = RateLimiter.create(qps.intValue()); - Integer area = count.intValue() / 10; - - long seconds = System.currentTimeMillis() / 1000l; - - this.collector.setStartTimestamp(System.currentTimeMillis()); - - System.out.println("==================================================================="); - System.out.println("Start UserAdd test, count " + count); - - for (Integer i = 0; i < count.intValue(); ++i) { - final int index = i; - threadPool.execute(new Runnable() { - @Override - public void run() { - boolean success = false; - while (!success) { - limiter.acquire(); - String user = Long.toHexString(seconds) + Integer.toHexString(index); - BigInteger amount = new BigInteger("1000000000"); - DagTransferUser dtu = new DagTransferUser(); - dtu.setUser(user); - dtu.setAmount(amount); - - PerformanceDTCallback callback = new PerformanceDTCallback(); - callback.setCollector(collector); - callback.setDagTransferUser(dtu); - callback.setDagUserMgr(getDagUserMgr()); - callback.setCallBackType("set"); - - try { - parallelok.set(user, amount, callback); - success = true; - } catch (Exception e) { - success = false; - continue; - } - } - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + count + " transactions"); - } - } - }); - } - - // end or not - while (!collector.isEnd()) { - Thread.sleep(3000); - } - - dagUserMgr.setContractAddr(parallelokAddr); - dagUserMgr.writeDagTransferUser(); - System.exit(0); - - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); - } - } - - public void userTransferRevertTest(BigInteger count, BigInteger qps, BigInteger deci) { - - try { - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count.intValue()); - - threadPool.initialize(); - - RateLimiter limiter = RateLimiter.create(qps.intValue()); - Integer area = count.intValue() / 10; - - parallelokAddr = dagUserMgr.getContractAddr(); - parallelok = ParallelOk.load(parallelokAddr, web3, credentials, - new StaticGasProvider(new BigInteger("30000000"), new BigInteger("30000000"))); - - System.out.println("ParallelOk address: " + parallelokAddr); - - // query all account balance info - List allUser = dagUserMgr.getUserList(); - for (int i = 0; i < allUser.size(); ++i) { - BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); - - allUser.get(i).setAmount(result); - - logger.debug(" query user " + allUser.get(i).getUser() + " amount " + result); - } - - System.out.println("Start UserTransferRevert test..."); - System.out.println("==================================================================="); - - this.collector.setStartTimestamp(System.currentTimeMillis()); - - for (Integer i = 0; i < 2 * count.intValue(); i += 2) { - final int index = i; - threadPool.execute(new Runnable() { - @Override - public void run() { - boolean success = false; - while (!success) { - limiter.acquire(); - DagTransferUser from = dagUserMgr.getFrom(index); - DagTransferUser to = dagUserMgr.getNext(index); - - Random random = new Random(); - int value = random.nextInt(101); - int prob = random.nextInt(10); - if (prob < deci.intValue()) { - value += 101; - } - BigInteger amount = BigInteger.valueOf(value); - - PerformanceDTCallback callback = new PerformanceDTCallback(); - callback.setCallBackType("transferRevert"); - callback.setCollector(collector); - callback.setDagUserMgr(getDagUserMgr()); - callback.setFromUser(from); - callback.setToUser(to); - callback.setAmount(amount); - - String info = "[RevertTest-SendTx]" + "\t[From]=" + from.getUser() + "\t[FromBalance]=" - + from.getAmount() + "\t[To]=" + to.getUser() + "\t[ToBalance]=" + to.getAmount() - + "\t[Amount]=" + amount; - System.out.println(info); - - try { - parallelok.transferWithRevert(from.getUser(), to.getUser(), amount, callback); - success = true; - } catch (Exception e) { - success = false; - continue; - } - } - } - }); - } - - // end or not - while (!collector.isEnd()) { - Thread.sleep(3000); - } - - veryTransferData(); - System.exit(0); - - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); - } - } - - public void userTransferTest(BigInteger count, BigInteger qps, BigInteger deci) { - - try { - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count.intValue()); - - threadPool.initialize(); - - RateLimiter limiter = RateLimiter.create(qps.intValue()); - Integer area = count.intValue() / 10; - - parallelokAddr = dagUserMgr.getContractAddr(); - parallelok = ParallelOk.load(parallelokAddr, web3, credentials, - new StaticGasProvider(new BigInteger("30000000"), new BigInteger("30000000"))); - - System.out.println("ParallelOk address: " + parallelokAddr); - - // query all account balance info - List allUser = dagUserMgr.getUserList(); - for (int i = 0; i < allUser.size(); ++i) { - BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); - - allUser.get(i).setAmount(result); - - logger.debug(" query user " + allUser.get(i).getUser() + " amount " + result); - } - - System.out.println("Start UserTransfer test..."); - System.out.println("==================================================================="); - - this.collector.setStartTimestamp(System.currentTimeMillis()); - - for (Integer i = 0; i < count.intValue(); ++i) { - final int index = i; - threadPool.execute(new Runnable() { - @Override - public void run() { - boolean success = false; - while (!success) { - limiter.acquire(); - DagTransferUser from = dagUserMgr.getFrom(index); - DagTransferUser to = dagUserMgr.getTo(index); - - if ((deci.intValue() > 0) && (deci.intValue() >= (index % 10 + 1))) { - to = dagUserMgr.getNext(index); - } - - Random random = new Random(); - int r = random.nextInt(100); - BigInteger amount = BigInteger.valueOf(r); - - PerformanceDTCallback callback = new PerformanceDTCallback(); - callback.setCallBackType("transfer"); - callback.setCollector(collector); - callback.setDagUserMgr(getDagUserMgr()); - callback.setFromUser(from); - callback.setToUser(to); - callback.setAmount(amount); - - try { - logger.debug(" transfer from is " + from + " to is " + to + " amount is " + amount); - parallelok.transfer(from.getUser(), to.getUser(), amount, callback); - success = true; - } catch (Exception e) { - success = false; - continue; - } - } - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + count + " transactions"); - } - } - }); - } - - // end or not - while (!collector.isEnd()) { - Thread.sleep(3000); - } - - veryTransferData(); - System.exit(0); - - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); - } - } - - public ParallelOk getDagTransfer() { - return parallelok; - } - - public void setDagTransfer(ParallelOk parallelok) { - this.parallelok = parallelok; - } + private static Logger logger = LoggerFactory.getLogger(PerformanceDTTest.class); + + private static String groupId = "1"; + + private Web3j web3; + private ParallelOk parallelok; + private TransactionManager transactionManager; + + private Credentials credentials; + private DagUserMgr dagUserMgr; + private PerformanceDTCollector collector; + private String parallelokAddr = ""; + + private static AtomicInteger sended = new AtomicInteger(0); + private static CountDownLatch latch; + + public PerformanceDTTest(String groupID) throws Exception { + groupId = groupID; + initialize(groupId); + } + + public DagUserMgr getDagUserMgr() { + return dagUserMgr; + } + + public void setDagUserMgr(DagUserMgr dagUserMgr) { + this.dagUserMgr = dagUserMgr; + } + + public Web3j getWeb3() { + return web3; + } + + public void setWeb3(Web3j web3) { + this.web3 = web3; + } + + public Credentials getCredentials() { + return credentials; + } + + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } + + public PerformanceDTCollector getCollector() { + return collector; + } + + public void setCollector(PerformanceDTCollector collector) { + this.collector = collector; + } + + public void veryTransferData(ThreadPoolTaskExecutor threadPool) { + // System.out.println(" data validation => "); + List allUser = dagUserMgr.getUserList(); + int total_user = allUser.size(); + + AtomicInteger verify_success = new AtomicInteger(0); + + AtomicInteger verify_failed = new AtomicInteger(0); + + allUser = dagUserMgr.getUserList(); + + try { + final ParallelOk _parallelok = parallelok; + final List _allUser = allUser; + + for (int i = 0; i < allUser.size(); ++i) { + final Integer _i = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + try { + BigInteger result = + parallelok.balanceOf(_allUser.get(_i).getUser()).send(); + + String user = _allUser.get(_i).getUser(); + BigInteger local = _allUser.get(_i).getAmount(); + BigInteger remote = result; + + logger.debug( + " user " + + user + + " local amount " + + local + + " remote amount " + + remote); + if (local.compareTo(remote) != 0) { + verify_failed.incrementAndGet(); + logger.error( + " local amount is not same as remote, user " + + user + + " local " + + local + + " remote " + + remote); + } else { + verify_success.incrementAndGet(); + } + } catch (Exception e) { + logger.error("getAmount error: ", e); + } + } + }); + } + + while (verify_success.get() + verify_failed.get() < total_user) { + Thread.sleep(40); + ; + } + + System.out.println("validation:"); + System.out.println(" \tuser count is " + total_user); + System.out.println(" \tverify_success count is " + verify_success); + System.out.println(" \tverify_failed count is " + verify_failed); + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + } + + public void initialize(String groupId) throws Exception { + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; + Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; + + ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); + + web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + transactionManager = Contract.getTheTransactionManager(web3, credentials); + } + + public void userAddTest(BigInteger count, BigInteger qps) { + + try { + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count.intValue()); + + threadPool.initialize(); + + System.out.println("Deploying contract "); + System.out.println( + "==================================================================="); + credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + parallelok = + ParallelOk.deploy( + web3, + credentials, + new BigInteger("30000000"), + new BigInteger("30000000")) + .send(); + + // enable parallel transaction + parallelok.enableParallel().send(); + + parallelokAddr = parallelok.getContractAddress(); + + System.out.println("ParallelOk address: " + parallelokAddr); + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + Integer area = count.intValue() / 10; + + long seconds = System.currentTimeMillis() / 1000l; + + System.out.println( + "==================================================================="); + System.out.println("Start UserAdd test, count " + count); + + long startTime = System.currentTimeMillis(); + this.collector.setStartTimestamp(startTime); + + for (Integer i = 0; i < count.intValue(); ++i) { + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + boolean success = false; + while (!success) { + limiter.acquire(); + String user = + Long.toHexString(seconds) + Integer.toHexString(index); + BigInteger amount = new BigInteger("1000000000"); + DagTransferUser dtu = new DagTransferUser(); + dtu.setUser(user); + dtu.setAmount(amount); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCollector(collector); + callback.setDagTransferUser(dtu); + callback.setDagUserMgr(getDagUserMgr()); + callback.setCallBackType("set"); + + try { + parallelok.set(user, amount, callback); + success = true; + } catch (Exception e) { + success = false; + continue; + } + } + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + long elapsed = System.currentTimeMillis() - startTime; + double sendSpeed = current / ((double) elapsed / 1000); + System.out.println( + "Already sended: " + + current + + "/" + + count + + " transactions" + + ",QPS=" + + sendSpeed); + } + } + }); + } + + // end or not + while (!collector.isEnd()) { + Thread.sleep(3000); + } + + dagUserMgr.setContractAddr(parallelokAddr); + dagUserMgr.writeDagTransferUser(); + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + } + + public void userTransferRevertTest(BigInteger count, BigInteger qps, BigInteger deci) { + + try { + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count.intValue()); + + threadPool.initialize(); + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + Integer area = count.intValue() / 10; + + parallelokAddr = dagUserMgr.getContractAddr(); + parallelok = + ParallelOk.load( + parallelokAddr, + web3, + credentials, + new StaticGasProvider( + new BigInteger("30000000"), new BigInteger("30000000"))); + + System.out.println("ParallelOk address: " + parallelokAddr); + + // query all account balance info + List allUser = dagUserMgr.getUserList(); + for (int i = 0; i < allUser.size(); ++i) { + BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); + + allUser.get(i).setAmount(result); + + logger.debug(" query user " + allUser.get(i).getUser() + " amount " + result); + } + + System.out.println("Start UserTransferRevert test..."); + System.out.println( + "==================================================================="); + + long startTime = System.currentTimeMillis(); + this.collector.setStartTimestamp(startTime); + + for (Integer i = 0; i < 2 * count.intValue(); i += 2) { + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + boolean success = false; + while (!success) { + limiter.acquire(); + DagTransferUser from = dagUserMgr.getFrom(index); + DagTransferUser to = dagUserMgr.getNext(index); + + Random random = new Random(); + int value = random.nextInt(101); + int prob = random.nextInt(10); + if (prob < deci.intValue()) { + value += 101; + } + BigInteger amount = BigInteger.valueOf(value); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCallBackType("transferRevert"); + callback.setCollector(collector); + callback.setDagUserMgr(getDagUserMgr()); + callback.setFromUser(from); + callback.setToUser(to); + callback.setAmount(amount); + + String info = + "[RevertTest-SendTx]" + + "\t[From]=" + + from.getUser() + + "\t[FromBalance]=" + + from.getAmount() + + "\t[To]=" + + to.getUser() + + "\t[ToBalance]=" + + to.getAmount() + + "\t[Amount]=" + + amount; + System.out.println(info); + + try { + parallelok.transferWithRevert( + from.getUser(), to.getUser(), amount, callback); + success = true; + } catch (Exception e) { + success = false; + continue; + } + } + } + }); + } + + // end or not + while (!collector.isEnd()) { + Thread.sleep(3000); + } + + veryTransferData(threadPool); + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + } + + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public void userTransferTest(BigInteger count, BigInteger qps, BigInteger deci) { + List signedTransactions = new ArrayList(); + List callbacks = new ArrayList(); + + try { + parallelokAddr = dagUserMgr.getContractAddr(); + parallelok = + ParallelOk.load( + parallelokAddr, + web3, + credentials, + new StaticGasProvider( + new BigInteger("30000000"), new BigInteger("30000000"))); + + /* + System.out.println("Reading account state..."); + List allUser = dagUserMgr.getUserList(); + for (int i = 0; i < allUser.size(); ++i) { + BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); + allUser.get(i).setAmount(result); + } + */ + + List allUser = dagUserMgr.getUserList(); + + int coreNum = Runtime.getRuntime().availableProcessors(); + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(Math.max(count.intValue(), allUser.size()) + 1000); + threadPool.initialize(); + + Lock lock = new ReentrantLock(); + + final ParallelOk _parallelok = parallelok; + AtomicInteger geted = new AtomicInteger(0); + for (int i = 0; i < allUser.size(); ++i) { + final Integer _i = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + try { + BigInteger result = + _parallelok.balanceOf(allUser.get(_i).getUser()).send(); + + allUser.get(_i).setAmount(result); + int all = geted.incrementAndGet(); + if (all >= allUser.size()) { + System.out.println( + dateFormat.format(new Date()) + + " Query account finished"); + } + } catch (Exception e) { + System.out.println( + " Query failed, user is " + allUser.get(_i).getUser()); + System.exit(0); + } + } + }); + } + + while (geted.get() < allUser.size()) { + Thread.sleep(50); + } + + latch = new CountDownLatch(count.intValue()); + + AtomicLong signed = new AtomicLong(0); + // create signed transactions + System.out.println("Creating signed transactions..."); + for (int i = 0; i < count.intValue(); ++i) { + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + while (true) { + DagTransferUser from = dagUserMgr.getFrom(index); + DagTransferUser to = dagUserMgr.getTo(index); + + if ((deci.intValue() > 0) + && (deci.intValue() >= (index % 10 + 1))) { + to = dagUserMgr.getNext(index); + } + + Random random = new Random(); + int r = random.nextInt(100); + BigInteger amount = BigInteger.valueOf(r); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCallBackType("transfer"); + callback.setCollector(collector); + callback.setDagUserMgr(getDagUserMgr()); + callback.setFromUser(from); + callback.setToUser(to); + callback.setAmount(amount); + + try { + String signedTransaction = + parallelok.transferSeq( + from.getUser(), to.getUser(), amount); + lock.lock(); + signedTransactions.add(signedTransaction); + callbacks.add(callback); + + long totalSigned = signed.incrementAndGet(); + if (totalSigned % (count.longValue() / 10) == 0) { + System.out.println( + "Signed transaction: " + + String.valueOf( + totalSigned + * 100 + / count.longValue()) + + "%"); + } + + break; + } catch (Exception e) { + e.printStackTrace(); + continue; + } finally { + lock.unlock(); + } + } + latch.countDown(); + } + }); + } + + latch.await(); + + latch = new CountDownLatch(count.intValue()); + + long startTime = System.currentTimeMillis(); + collector.setStartTimestamp(startTime); + AtomicInteger sent = new AtomicInteger(0); + int division = count.intValue() / 10; + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + System.out.println("Sending signed transactions..."); + for (int i = 0; i < count.intValue(); ++i) { + limiter.acquire(); + + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + while (true) { + try { + transactionManager.sendTransaction( + signedTransactions.get(index), + callbacks.get(index)); + break; + } catch (Exception e) { + continue; + } + } + + int current = sent.incrementAndGet(); + + if (current >= division && ((current % division) == 0)) { + long elapsed = System.currentTimeMillis() - startTime; + double sendSpeed = current / ((double) elapsed / 1000); + System.out.println( + "Already sent: " + + current + + "/" + + count + + " transactions" + + ",QPS=" + + sendSpeed); + } + + latch.countDown(); + } + }); + } + + latch.await(); + + while (!collector.isEnd()) { + Thread.sleep(3000); + } + + veryTransferData(threadPool); + + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + /* + try { + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count.intValue()); + + threadPool.initialize(); + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + Integer area = count.intValue() / 10; + + parallelokAddr = dagUserMgr.getContractAddr(); + parallelok = + ParallelOk.load( + parallelokAddr, + web3, + credentials, + new StaticGasProvider( + new BigInteger("30000000"), new BigInteger("30000000"))); + + System.out.println("ParallelOk address: " + parallelokAddr); + + // query all account balance info + List allUser = dagUserMgr.getUserList(); + for (int i = 0; i < allUser.size(); ++i) { + BigInteger result = parallelok.balanceOf(allUser.get(i).getUser()).send(); + + allUser.get(i).setAmount(result); + + logger.debug(" query user " + allUser.get(i).getUser() + " amount " + result); + } + + System.out.println("Start UserTransfer test..."); + System.out.println( + "==================================================================="); + + long startTime = System.currentTimeMillis(); + this.collector.setStartTimestamp(startTime); + + for (Integer i = 0; i < count.intValue(); ++i) { + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + boolean success = false; + while (!success) { + limiter.acquire(); + DagTransferUser from = dagUserMgr.getFrom(index); + DagTransferUser to = dagUserMgr.getTo(index); + + if ((deci.intValue() > 0) + && (deci.intValue() >= (index % 10 + 1))) { + to = dagUserMgr.getNext(index); + } + + Random random = new Random(); + int r = random.nextInt(100); + BigInteger amount = BigInteger.valueOf(r); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCallBackType("transfer"); + callback.setCollector(collector); + callback.setDagUserMgr(getDagUserMgr()); + callback.setFromUser(from); + callback.setToUser(to); + callback.setAmount(amount); + + try { + logger.debug( + " transfer from is " + + from + + " to is " + + to + + " amount is " + + amount); + parallelok.transfer( + from.getUser(), to.getUser(), amount, callback); + success = true; + } catch (Exception e) { + success = false; + continue; + } + } + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + long elapsed = System.currentTimeMillis() - startTime; + double sendSpeed = current / ((double)elapsed / 1000); + System.out.println( + "Already sended: " + + current + + "/" + + count + + " transactions" + + ",QPS=" + + sendSpeed); + } + } + }); + } + + // end or not + while (!collector.isEnd()) { + Thread.sleep(3000); + } + + veryTransferData(); + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + */ + } + + public ParallelOk getDagTransfer() { + return parallelok; + } + + public void setDagTransfer(ParallelOk parallelok) { + this.parallelok = parallelok; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransfer.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransfer.java index 85f73c7aa..50a0100ef 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransfer.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransfer.java @@ -20,22 +20,20 @@ import org.fisco.bcos.web3j.tx.gas.ContractGasProvider; /** - *

* Auto generated code. - *

- * Do not modify! - *

- * Please use the web3j - * command line tools, or the - * org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen - * module to update. * - *

- * Generated with web3j version none. + *

Do not modify! + * + *

Please use the web3j command line tools, + * or the org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. + * + *

Generated with web3j version none. */ +@SuppressWarnings("unchecked") public class DagTransfer extends Contract { - private static final String BINARY = "608060405234801561001057600080fd5b506103c6806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630b37617b146100725780631536aedd1461013f5780633fe8e3f5146101c3578063e555f3d91461024a578063ff2b0127146102d1575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610358565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101a6600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610364565b604051808381526020018281526020019250505060405180910390f35b3480156101cf57600080fd5b50610234600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610379565b6040518082815260200191505060405180910390f35b34801561025657600080fd5b506102bb600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610384565b6040518082815260200191505060405180910390f35b3480156102dd57600080fd5b50610342600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061038f565b6040518082815260200191505060405180910390f35b60008090509392505050565b60008060008081915080905091509150915091565b600080905092915050565b600080905092915050565b6000809050929150505600a165627a7a72305820bde537b6eff20e760fa77d91f856463f97ff39d9725e79f31079d5da9ba0cc8a0029"; + private static final String BINARY = + "608060405234801561001057600080fd5b506103c6806100206000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630b37617b146100725780631536aedd1461013f5780633fe8e3f5146101c3578063e555f3d91461024a578063ff2b0127146102d1575b600080fd5b34801561007e57600080fd5b50610129600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610358565b6040518082815260200191505060405180910390f35b34801561014b57600080fd5b506101a6600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610364565b604051808381526020018281526020019250505060405180910390f35b3480156101cf57600080fd5b50610234600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610379565b6040518082815260200191505060405180910390f35b34801561025657600080fd5b506102bb600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610384565b6040518082815260200191505060405180910390f35b3480156102dd57600080fd5b50610342600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061038f565b6040518082815260200191505060405180910390f35b60008090509392505050565b60008060008081915080905091509150915091565b600080905092915050565b600080905092915050565b6000809050929150505600a165627a7a723058207ff2a508f6093d5b125faa8cb120d0157aa5384ad0b65abc9c8d9b9b7d1eaaca0029"; public static final String FUNC_USERTRANSFER = "userTransfer"; @@ -48,150 +46,262 @@ public class DagTransfer extends Contract { public static final String FUNC_USERDRAW = "userDraw"; @Deprecated - protected DagTransfer(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, + protected DagTransfer( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected DagTransfer(String contractAddress, Web3j web3j, Credentials credentials, + protected DagTransfer( + String contractAddress, + Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected DagTransfer(String contractAddress, Web3j web3j, TransactionManager transactionManager, - BigInteger gasPrice, BigInteger gasLimit) { + protected DagTransfer( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected DagTransfer(String contractAddress, Web3j web3j, TransactionManager transactionManager, + protected DagTransfer( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public RemoteCall userTransfer(String user_a, String user_b, BigInteger amount) { - final Function function = new Function(FUNC_USERTRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_a), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_b), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(amount)), - Collections.>emptyList()); + public RemoteCall userTransfer( + String user_a, String user_b, BigInteger amount) { + final Function function = + new Function( + FUNC_USERTRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_a), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_b), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public void userTransfer(String user_a, String user_b, BigInteger amount, TransactionSucCallback callback) { - final Function function = new Function(FUNC_USERTRANSFER, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_a), - new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_b), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(amount)), - Collections.>emptyList()); + public void userTransfer( + String user_a, String user_b, BigInteger amount, TransactionSucCallback callback) { + final Function function = + new Function( + FUNC_USERTRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_a), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_b), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String userTransferSeq(String user_a, String user_b, BigInteger amount) { + final Function function = + new Function( + FUNC_USERTRANSFER, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_a), + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user_b), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall> userBalance(String user) { - final Function function = new Function(FUNC_USERBALANCE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user)), - Arrays.>asList(new TypeReference() { - }, new TypeReference() { - })); - return new RemoteCall>(new Callable>() { - @Override - public Tuple2 call() throws Exception { - List results = executeCallMultipleValueReturn(function); - return new Tuple2((BigInteger) results.get(0).getValue(), - (BigInteger) results.get(1).getValue()); - } - }); + final Function function = + new Function( + FUNC_USERBALANCE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user)), + Arrays.>asList( + new TypeReference() {}, new TypeReference() {})); + return new RemoteCall>( + new Callable>() { + @Override + public Tuple2 call() throws Exception { + List results = executeCallMultipleValueReturn(function); + return new Tuple2( + (BigInteger) results.get(0).getValue(), + (BigInteger) results.get(1).getValue()); + } + }); } public RemoteCall userAdd(String user, BigInteger balance) { - final Function function = new Function(FUNC_USERADD, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERADD, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void userAdd(String user, BigInteger balance, TransactionSucCallback callback) { - final Function function = new Function(FUNC_USERADD, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERADD, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String userAddSeq(String user, BigInteger balance) { + final Function function = + new Function( + FUNC_USERADD, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall userSave(String user, BigInteger balance) { - final Function function = new Function(FUNC_USERSAVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERSAVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void userSave(String user, BigInteger balance, TransactionSucCallback callback) { - final Function function = new Function(FUNC_USERSAVE, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERSAVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String userSaveSeq(String user, BigInteger balance) { + final Function function = + new Function( + FUNC_USERSAVE, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + public RemoteCall userDraw(String user, BigInteger balance) { - final Function function = new Function(FUNC_USERDRAW, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERDRAW, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public void userDraw(String user, BigInteger balance, TransactionSucCallback callback) { - final Function function = new Function(FUNC_USERDRAW, - Arrays.asList(new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), - new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), - Collections.>emptyList()); + final Function function = + new Function( + FUNC_USERDRAW, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); asyncExecuteTransaction(function, callback); } + public String userDrawSeq(String user, BigInteger balance) { + final Function function = + new Function( + FUNC_USERDRAW, + Arrays.asList( + new org.fisco.bcos.web3j.abi.datatypes.Utf8String(user), + new org.fisco.bcos.web3j.abi.datatypes.generated.Uint256(balance)), + Collections.>emptyList()); + return createTransactionSeq(function); + } + @Deprecated - public static DagTransfer load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, + public static DagTransfer load( + String contractAddress, + Web3j web3j, + Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { return new DagTransfer(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Deprecated - public static DagTransfer load(String contractAddress, Web3j web3j, TransactionManager transactionManager, - BigInteger gasPrice, BigInteger gasLimit) { + public static DagTransfer load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { return new DagTransfer(contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - public static DagTransfer load(String contractAddress, Web3j web3j, Credentials credentials, + public static DagTransfer load( + String contractAddress, + Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { return new DagTransfer(contractAddress, web3j, credentials, contractGasProvider); } - public static DagTransfer load(String contractAddress, Web3j web3j, TransactionManager transactionManager, + public static DagTransfer load( + String contractAddress, + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { return new DagTransfer(contractAddress, web3j, transactionManager, contractGasProvider); } - public static RemoteCall deploy(Web3j web3j, Credentials credentials, - ContractGasProvider contractGasProvider) { - return deployRemoteCall(DagTransfer.class, web3j, credentials, contractGasProvider, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall( + DagTransfer.class, web3j, credentials, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, - BigInteger gasLimit) { - return deployRemoteCall(DagTransfer.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall( + DagTransfer.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); } - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return deployRemoteCall(DagTransfer.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + return deployRemoteCall( + DagTransfer.class, web3j, transactionManager, contractGasProvider, BINARY, ""); } @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, - BigInteger gasPrice, BigInteger gasLimit) { - return deployRemoteCall(DagTransfer.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + public static RemoteCall deploy( + Web3j web3j, + TransactionManager transactionManager, + BigInteger gasPrice, + BigInteger gasLimit) { + return deployRemoteCall( + DagTransfer.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransferUser.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransferUser.java index 7a891e642..26d918212 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransferUser.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagTransferUser.java @@ -1,45 +1,44 @@ package org.fisco.bcos.channel.test.parallel.precompile; import java.math.BigInteger; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DagTransferUser { - private static Logger logger = LoggerFactory.getLogger(DagTransferUser.class); - private String user; - private BigInteger amount; - - @Override - public String toString() { - return "DagTransferUser [user=" + user + ", amount=" + amount + "]"; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - synchronized public BigInteger getAmount() { - return amount; - } - - synchronized public void setAmount(BigInteger amount) { - this.amount = amount; - } - - synchronized public void increase(BigInteger amount) { - logger.debug("increase before amount is " + this.amount); - this.amount = this.amount.add(amount); - logger.debug("increase after amount is " + this.amount); - } - - synchronized public void decrease(BigInteger amount) { - logger.debug("decrease before amount is " + this.amount); - this.amount = this.amount.subtract(amount); - logger.debug("decrease after amount is " + this.amount); - } -} \ No newline at end of file + private static Logger logger = LoggerFactory.getLogger(DagTransferUser.class); + private String user; + private BigInteger amount; + + @Override + public String toString() { + return "DagTransferUser [user=" + user + ", amount=" + amount + "]"; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public synchronized BigInteger getAmount() { + return amount; + } + + public synchronized void setAmount(BigInteger amount) { + this.amount = amount; + } + + public synchronized void increase(BigInteger amount) { + logger.debug("increase before amount is " + this.amount); + this.amount = this.amount.add(amount); + logger.debug("increase after amount is " + this.amount); + } + + public synchronized void decrease(BigInteger amount) { + logger.debug("decrease before amount is " + this.amount); + this.amount = this.amount.subtract(amount); + logger.debug("decrease after amount is " + this.amount); + } +} diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagUserMgr.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagUserMgr.java index c5c952e25..7e468d80e 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagUserMgr.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/DagUserMgr.java @@ -1,127 +1,121 @@ package org.fisco.bcos.channel.test.parallel.precompile; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DagUserMgr { - private static Logger logger = LoggerFactory.getLogger(DagUserMgr.class); - - private List userList = new ArrayList(); - - private String file = null; - - private String testType = "transfer"; - - public List getUserList() { - return userList; - } - - public void setUserList(List userList) { - this.userList = userList; - } - - public String getFile() { - return file; - } - - public void setFile(String file) { - this.file = file; - } - - synchronized public void addUser(DagTransferUser user) { - userList.add(user); - } - - public boolean isEmpty() { - return userList.isEmpty(); - } - - public DagTransferUser getFrom(int idx) { - assert !isEmpty() : "Has no user."; - return userList.get(idx % userList.size()); - } - - public DagTransferUser getTo(int idx) { - assert !isEmpty() : "Has no user."; - int mid = userList.size() / 2; - return userList.get((idx + mid) % userList.size()); - } - - public DagTransferUser getNext(int idx) { - return userList.get((idx + 1) % userList.size()); - } - - public void writeDagTransferUser() throws IOException { - if (file == null) { - return; - } - logger.info("file {}, begin load.", file); - - BufferedWriter bw = null; - try { - bw = new BufferedWriter(new FileWriter(new File(file))); - for (int i = 0; i < userList.size(); i++) { - bw.write(userList.get(i).getUser() + "\n"); - logger.trace(" write user , user is {}", userList.get(i).getUser()); - } - - bw.flush(); - - } finally { - if (bw != null) { - bw.close(); - } - } - - logger.info("file {}, load end, count is {}.", file, userList.size()); - - System.out.println(" # write DagTransferUser end, count is " + userList.size()); - } - - public void loadDagTransferUser() throws IOException { - if (file == null) { - return; - } - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(new File(file))); - - String line = null; - while ((line = br.readLine()) != null) { - line = line.trim(); - if (!line.isEmpty()) { - DagTransferUser user = new DagTransferUser(); - user.setUser(line); - addUser(user); - // System.out.println("load DagTransferUser ==>> " + line); - } - } - - } finally { - if (br != null) { - br.close(); - } - } - - logger.info("file {}, load end, count is {}.", file, userList.size()); - - System.out.println(" # load DagTransferUser end, count is " + userList.size()); - } - - public String getTestType() { - return testType; - } - - public void setTestType(String testType) { - this.testType = testType; - } + private static Logger logger = LoggerFactory.getLogger(DagUserMgr.class); + + private List userList = new ArrayList(); + + private String file = null; + + private String testType = "transfer"; + + public List getUserList() { + return userList; + } + + public void setUserList(List userList) { + this.userList = userList; + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } + + public synchronized void addUser(DagTransferUser user) { + userList.add(user); + } + + public boolean isEmpty() { + return userList.isEmpty(); + } + + public DagTransferUser getFrom(int idx) { + assert !isEmpty() : "Has no user."; + return userList.get(idx % userList.size()); + } + + public DagTransferUser getTo(int idx) { + assert !isEmpty() : "Has no user."; + int mid = userList.size() / 2; + return userList.get((idx + mid) % userList.size()); + } + + public DagTransferUser getNext(int idx) { + return userList.get((idx + 1) % userList.size()); + } + + public void writeDagTransferUser() throws IOException { + if (file == null) { + return; + } + logger.info("file {}, begin load.", file); + + BufferedWriter bw = null; + try { + bw = new BufferedWriter(new FileWriter(new File(file))); + for (int i = 0; i < userList.size(); i++) { + bw.write(userList.get(i).getUser() + "\n"); + logger.trace(" write user , user is {}", userList.get(i).getUser()); + } + + bw.flush(); + + } finally { + if (bw != null) { + bw.close(); + } + } + + logger.info("file {}, load end, count is {}.", file, userList.size()); + + System.out.println("Write DagTransferUser end, count is " + userList.size()); + } + + public void loadDagTransferUser() throws IOException { + if (file == null) { + return; + } + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(new File(file))); + + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty()) { + DagTransferUser user = new DagTransferUser(); + user.setUser(line); + addUser(user); + // System.out.println("load DagTransferUser ==>> " + line); + } + } + + } finally { + if (br != null) { + br.close(); + } + } + + logger.info("file {}, load end, count is {}.", file, userList.size()); + + System.out.println("Load DagTransferUser end, count is " + userList.size()); + } + + public String getTestType() { + return testType; + } + + public void setTestType(String testType) { + this.testType = testType; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDT.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDT.java index ea6533a96..a5dd84d4f 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDT.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDT.java @@ -1,75 +1,76 @@ package org.fisco.bcos.channel.test.parallel.precompile; +import java.math.BigInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigInteger; - -import org.fisco.bcos.channel.test.parallel.precompile.PerformanceDTTest; -import org.fisco.bcos.channel.test.parallel.precompile.DagUserMgr; - public class PerformanceDT { - private static Logger logger = LoggerFactory.getLogger(PerformanceDT.class); + private static Logger logger = LoggerFactory.getLogger(PerformanceDT.class); - public static void Usage() { - System.out.println(" Usage:"); - System.out.println( - " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.precompile.PerformanceDT groupID add count tps file."); - System.out.println( - " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.precompile.PerformanceDT groupID transfer count tps file strategy."); - System.exit(0); - } - - public static void main(String[] args) throws Exception { - if (args.length < 4) { - Usage(); + public static void Usage() { + System.out.println(" Usage:"); + System.out.println( + " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.precompile.PerformanceDT groupID add count tps file."); + System.out.println( + " \t java -cp conf/:lib/*:apps/* org.fisco.bcos.channel.test.parallel.precompile.PerformanceDT groupID transfer count tps file strategy."); + System.exit(0); } - String groupID = args[0]; - String command = args[1]; - BigInteger count = new BigInteger(args[2]); - BigInteger tps = new BigInteger(args[3]); - String file = null; - BigInteger deci = new BigInteger("0"); - if (args.length > 4) { - file = args[4]; - if (args.length > 5) { - deci = new BigInteger(args[5]); - } - } + public static void main(String[] args) throws Exception { + if (args.length < 4) { + Usage(); + } - // deci can not bigger than 10. - if (deci.compareTo(new BigInteger("10")) > 0) { - deci = new BigInteger("10"); - } + String groupID = args[0]; + String command = args[1]; + BigInteger count = new BigInteger(args[2]); + BigInteger tps = new BigInteger(args[3]); + String file = null; + BigInteger deci = new BigInteger("0"); + if (args.length > 4) { + file = args[4]; + if (args.length > 5) { + deci = new BigInteger(args[5]); + } + } + + // deci can not bigger than 10. + if (deci.compareTo(new BigInteger("10")) > 0) { + deci = new BigInteger("10"); + } - logger.info(" dag transfer test begin, command is {}, count is {}, tps is {}, file is {}, deci is {}", command, - count, tps, file, deci); + logger.info( + " dag transfer test begin, command is {}, count is {}, tps is {}, file is {}, deci is {}", + command, + count, + tps, + file, + deci); - DagUserMgr d = new DagUserMgr(); - d.setFile(file); + DagUserMgr d = new DagUserMgr(); + d.setFile(file); - PerformanceDTCollector collector = new PerformanceDTCollector(); - collector.setTotal(count.intValue()); - collector.setDagUserMrg(d); + PerformanceDTCollector collector = new PerformanceDTCollector(); + collector.setTotal(count.intValue()); + collector.setDagUserMrg(d); - PerformanceDTTest PerformanceDTTest = new PerformanceDTTest(groupID); - PerformanceDTTest.setCollector(collector); - PerformanceDTTest.setDagUserMgr(d); - collector.setPerformanceDTTest(PerformanceDTTest); + PerformanceDTTest PerformanceDTTest = new PerformanceDTTest(groupID); + PerformanceDTTest.setCollector(collector); + PerformanceDTTest.setDagUserMgr(d); + collector.setPerformanceDTTest(PerformanceDTTest); - switch (command) { - case "add": - d.setTestType("add"); - PerformanceDTTest.userAddTest(count, tps); - break; - case "transfer": - d.setTestType("transfer"); - d.loadDagTransferUser(); - PerformanceDTTest.userTransferTest(count, tps, deci); - break; - default: - Usage(); + switch (command) { + case "add": + d.setTestType("add"); + PerformanceDTTest.userAddTest(count, tps); + break; + case "transfer": + d.setTestType("transfer"); + d.loadDagTransferUser(); + PerformanceDTTest.userTransferTest(count, tps, deci); + break; + default: + Usage(); + } } - } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCallback.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCallback.java index dbfcc7b46..8275607b0 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCallback.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCallback.java @@ -1,118 +1,116 @@ package org.fisco.bcos.channel.test.parallel.precompile; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import java.math.BigInteger; - import org.fisco.bcos.channel.client.TransactionSucCallback; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - public class PerformanceDTCallback extends TransactionSucCallback { - static private ObjectMapper objectMapper = new ObjectMapper(); - private Long startTime = System.currentTimeMillis(); - - private PerformanceDTCollector collector = null; - private DagUserMgr dagUserMgr = null; - - private DagTransferUser user = null; - private DagTransferUser fromUser = null; - private DagTransferUser toUser = null; - private BigInteger amount = null; - - private String callBackType = "transfer"; - - public String getCallBackType() { - return callBackType; - } - - public void setCallBackType(String callBackType) { - this.callBackType = callBackType; - } - - public DagUserMgr getDagUserMgr() { - return dagUserMgr; - } - - public void setDagUserMgr(DagUserMgr dagUserMgr) { - this.dagUserMgr = dagUserMgr; - } - - public DagTransferUser getDagTransferUser() { - return user; - } - - public void setDagTransferUser(DagTransferUser dagTransferUser) { - this.user = dagTransferUser; - } - - public PerformanceDTCollector getCollector() { - return collector; - } - - public void setCollector(PerformanceDTCollector collector) { - this.collector = collector; - } - - static Logger logger = LoggerFactory.getLogger(PerformanceDTCallback.class); - - public PerformanceDTCallback() { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - - @Override - public void onResponse(TransactionReceipt receipt) { - Long cost = System.currentTimeMillis() - startTime; - - try { - if (receipt.isStatusOK()) { - String output = receipt.getOutput(); - if (!output.isEmpty()) { - int code = new BigInteger(output.substring(2, output.length()), 16).intValue(); - logger.debug(" output is {}, code is {} ", output, code); - if (0 == code) { - if (callBackType.compareTo("add") == 0) { // add test - dagUserMgr.addUser(user); - } else if (callBackType.compareTo("transfer") == 0) { // transfer test - fromUser.decrease(amount); - toUser.increase(amount); - } - } else { - logger.error(" invalid return: code is " + code); - } - } else { - logger.error(" empty return "); - } - } - collector.onMessage(receipt, cost); - } catch (Exception e) { - logger.error("onMessage error: ", e); - } - } - - public DagTransferUser getFromUser() { - return fromUser; - } - - public void setFromUser(DagTransferUser fromUser) { - this.fromUser = fromUser; - } - - public DagTransferUser getToUser() { - return toUser; - } - - public void setToUser(DagTransferUser toUser) { - this.toUser = toUser; - } - - public BigInteger getAmount() { - return amount; - } - - public void setAmount(BigInteger amount) { - this.amount = amount; - } + private static ObjectMapper objectMapper = new ObjectMapper(); + private Long startTime = System.currentTimeMillis(); + + private PerformanceDTCollector collector = null; + private DagUserMgr dagUserMgr = null; + + private DagTransferUser user = null; + private DagTransferUser fromUser = null; + private DagTransferUser toUser = null; + private BigInteger amount = null; + + private String callBackType = "transfer"; + + public String getCallBackType() { + return callBackType; + } + + public void setCallBackType(String callBackType) { + this.callBackType = callBackType; + } + + public DagUserMgr getDagUserMgr() { + return dagUserMgr; + } + + public void setDagUserMgr(DagUserMgr dagUserMgr) { + this.dagUserMgr = dagUserMgr; + } + + public DagTransferUser getDagTransferUser() { + return user; + } + + public void setDagTransferUser(DagTransferUser dagTransferUser) { + this.user = dagTransferUser; + } + + public PerformanceDTCollector getCollector() { + return collector; + } + + public void setCollector(PerformanceDTCollector collector) { + this.collector = collector; + } + + static Logger logger = LoggerFactory.getLogger(PerformanceDTCallback.class); + + public PerformanceDTCallback() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + @Override + public void onResponse(TransactionReceipt receipt) { + Long cost = System.currentTimeMillis() - startTime; + + try { + if (receipt.isStatusOK()) { + String output = receipt.getOutput(); + if (!output.isEmpty()) { + int code = new BigInteger(output.substring(2, output.length()), 16).intValue(); + logger.debug(" output is {}, code is {} ", output, code); + if (0 == code) { + if (callBackType.compareTo("add") == 0) { // add test + dagUserMgr.addUser(user); + } else if (callBackType.compareTo("transfer") == 0) { // transfer test + fromUser.decrease(amount); + toUser.increase(amount); + } + } else { + logger.error(" invalid return: code is " + code); + } + } else { + logger.error(" empty return "); + } + } + collector.onMessage(receipt, cost); + } catch (Exception e) { + logger.error("onMessage error: ", e); + } + } + + public DagTransferUser getFromUser() { + return fromUser; + } + + public void setFromUser(DagTransferUser fromUser) { + this.fromUser = fromUser; + } + + public DagTransferUser getToUser() { + return toUser; + } + + public void setToUser(DagTransferUser toUser) { + this.toUser = toUser; + } + + public BigInteger getAmount() { + return amount; + } + + public void setAmount(BigInteger amount) { + this.amount = amount; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCollector.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCollector.java index 75e7169a2..29804cfda 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCollector.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTCollector.java @@ -1,166 +1,239 @@ package org.fisco.bcos.channel.test.parallel.precompile; import java.math.BigInteger; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - +import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; -import org.fisco.bcos.channel.test.parallel.precompile.DagUserMgr; - public class PerformanceDTCollector { - static Logger logger = LoggerFactory.getLogger(PerformanceDTCollector.class); - - private Integer total = 0; - private DagUserMgr dagUserMrg; - private PerformanceDTTest PerformanceDTTest; - - public PerformanceDTTest getPerformanceDTTest() { - return PerformanceDTTest; - } - - public void setPerformanceDTTest(PerformanceDTTest PerformanceDTTest) { - this.PerformanceDTTest = PerformanceDTTest; - } - - public Integer getTotal() { - return total; - } - - public void setTotal(Integer total) { - this.total = total; - } - - public DagUserMgr getDagUserMrg() { - return dagUserMrg; - } - - public void setDagUserMrg(DagUserMgr dagUserMrg) { - this.dagUserMrg = dagUserMrg; - } - - public boolean isEnd() { - return received.intValue() >= total; - } - - public void onMessage(TransactionReceipt receipt, Long cost) { - try { - if (receipt.isStatusOK()) { - String output = receipt.getOutput(); - if (!output.isEmpty()) { - int code = new BigInteger(output.substring(2, output.length()), 16).intValue(); - if (0 != code) { - error.addAndGet(1); - ret_error.addAndGet(1); - } - } else { - error.addAndGet(1); - } - } else { - error.addAndGet(1); - } - - received.incrementAndGet(); - - if ((received.get() + 1) % (total / 10) == 0) { - System.out.println(" |received:" - + String.valueOf((received.get() + 1) * 100 / total) + "%"); - } - - if (cost < 50) { - less50.incrementAndGet(); - } else if (cost < 100) { - less100.incrementAndGet(); - ; - } else if (cost < 200) { - less200.incrementAndGet(); - ; - } else if (cost < 400) { - less400.incrementAndGet(); - ; - } else if (cost < 1000) { - less1000.incrementAndGet(); - ; - } else if (cost < 2000) { - less2000.incrementAndGet(); - ; - } else { - timeout2000.incrementAndGet(); - ; - } - - totalCost.addAndGet(cost); - - if (isEnd()) { - System.out.println("total"); - - // - Long totalTime = System.currentTimeMillis() - startTimestamp; - - System.out.println("==================================================================="); - - System.out.println("Total transactions: " + String.valueOf(total)); - System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); - System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); - System.out.println("Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); - System.out.println("Error rate: " + String.valueOf((error.get() / received.get()) * 100) + "%"); - System.out.println( - "Return Error rate: " + String.valueOf((ret_error.get() / received.get()) * 100) + "%"); - - System.out.println("Time area:"); - System.out.println("0 < time < 50ms : " + String.valueOf(less50) + " : " - + String.valueOf((double) less50.get() / total * 100) + "%"); - System.out.println("50 < time < 100ms : " + String.valueOf(less100) + " : " - + String.valueOf((double) less100.get() / total * 100) + "%"); - System.out.println("100 < time < 200ms : " + String.valueOf(less200) + " : " - + String.valueOf((double) less200.get() / total * 100) + "%"); - System.out.println("200 < time < 400ms : " + String.valueOf(less400) + " : " - + String.valueOf((double) less400.get() / total * 100) + "%"); - System.out.println("400 < time < 1000ms : " + String.valueOf(less1000) + " : " - + String.valueOf((double) less1000.get() / total * 100) + "%"); - System.out.println("1000 < time < 2000ms : " + String.valueOf(less2000) + " : " - + String.valueOf((double) less2000.get() / total * 100) + "%"); - System.out.println("2000 < time : " + String.valueOf(timeout2000) + " : " - + String.valueOf((double) timeout2000.get() / total * 100) + "%"); - } - - } catch (Exception e) { - logger.error("error:", e); - System.exit(0); - } - } - - private AtomicLong less50 = new AtomicLong(0); - private AtomicLong less100 = new AtomicLong(0); - private AtomicLong less200 = new AtomicLong(0); - private AtomicLong less400 = new AtomicLong(0); - private AtomicLong less1000 = new AtomicLong(0); - private AtomicLong less2000 = new AtomicLong(0); - private AtomicLong timeout2000 = new AtomicLong(0); - private AtomicLong totalCost = new AtomicLong(0); - - private AtomicInteger received = new AtomicInteger(0); - - public AtomicInteger getReceived() { - return received; - } - - public void setReceived(AtomicInteger received) { - this.received = received; - } - - private AtomicInteger error = new AtomicInteger(0); - private AtomicInteger ret_error = new AtomicInteger(0); - private Long startTimestamp = System.currentTimeMillis(); - - public Long getStartTimestamp() { - return startTimestamp; - } - - public void setStartTimestamp(Long startTimestamp) { - this.startTimestamp = startTimestamp; - } + static Logger logger = LoggerFactory.getLogger(PerformanceDTCollector.class); + static HashMap errorInfos = new HashMap(); + + private Integer total = 0; + private DagUserMgr dagUserMrg; + private PerformanceDTTest PerformanceDTTest; + + public PerformanceDTCollector() { + errorInfos.put("0x0", "None"); + errorInfos.put("0x1", "Unknown"); + errorInfos.put("0x2", "BadRLP"); + errorInfos.put("0x3", "InvalidFormat"); + errorInfos.put("0x4", "OutOfGasIntrinsic"); + errorInfos.put("0x5", "InvalidSignature"); + errorInfos.put("0x6", "InvalidNonce"); + errorInfos.put("0x7", "NotEnoughCash"); + errorInfos.put("0x8", "OutOfGasBase"); + errorInfos.put("0x9", "BlockGasLimitReached"); + errorInfos.put("0xa", "BadInstruction"); + errorInfos.put("0xb", "BadJumpDestination"); + errorInfos.put("0xc", "OutOfGas"); + errorInfos.put("0xd", "OutOfStack"); + errorInfos.put("0xe", "StackUnderflow"); + errorInfos.put("0xf", "NonceCheckFail"); + errorInfos.put("0x10", "BlockLimitCheckFail"); + errorInfos.put("0x11", "FilterCheckFail"); + errorInfos.put("0x12", "NoDeployPermission"); + errorInfos.put("0x13", "NoCallPermission"); + errorInfos.put("0x14", "NoTxPermission"); + errorInfos.put("0x15", "PrecompiledError"); + errorInfos.put("0x16", "RevertInstruction"); + errorInfos.put("0x17", "InvalidZeroSignatureFormat"); + errorInfos.put("0x18", "AddressAlreadyUsed"); + errorInfos.put("0x19", "PermissionDenied"); + errorInfos.put("0x1a", "CallAddressError"); + errorInfos.put("0x1b", "GasOverflow"); + errorInfos.put("0x1c", "TxPoolIsFull"); + } + + public PerformanceDTTest getPerformanceDTTest() { + return PerformanceDTTest; + } + + public void setPerformanceDTTest(PerformanceDTTest PerformanceDTTest) { + this.PerformanceDTTest = PerformanceDTTest; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public DagUserMgr getDagUserMrg() { + return dagUserMrg; + } + + public void setDagUserMrg(DagUserMgr dagUserMrg) { + this.dagUserMrg = dagUserMrg; + } + + public boolean isEnd() { + return received.intValue() >= total; + } + + public void onMessage(TransactionReceipt receipt, Long cost) { + + try { + if (receipt.isStatusOK()) { + String output = receipt.getOutput(); + if (!output.isEmpty()) { + int code = new BigInteger(output.substring(2, output.length()), 16).intValue(); + if (0 != code) { + error.addAndGet(1); + ret_error.addAndGet(1); + } + } else { + logger.error("Received error"); + error.addAndGet(1); + } + } else { + System.out.println("receipt error! status: " + errorInfos.get(receipt.getStatus())); + error.addAndGet(1); + } + + int count = received.incrementAndGet(); + + if (count % (total / 10) == 0) { + System.out.println( + " |received:" + + String.valueOf(count * 100 / total) + + "%"); + } + + if (cost < 50) { + less50.incrementAndGet(); + } else if (cost < 100) { + less100.incrementAndGet(); + ; + } else if (cost < 200) { + less200.incrementAndGet(); + ; + } else if (cost < 400) { + less400.incrementAndGet(); + ; + } else if (cost < 1000) { + less1000.incrementAndGet(); + ; + } else if (cost < 2000) { + less2000.incrementAndGet(); + ; + } else { + timeout2000.incrementAndGet(); + ; + } + + totalCost.addAndGet(cost); + + if (isEnd()) { + System.out.println("total"); + + // + Long totalTime = System.currentTimeMillis() - startTimestamp; + + System.out.println( + "==================================================================="); + + System.out.println("Total transactions: " + String.valueOf(total)); + System.out.println("Total time: " + String.valueOf(totalTime) + "ms"); + System.out.println("TPS: " + String.valueOf(total / ((double) totalTime / 1000))); + System.out.println( + "Avg time cost: " + String.valueOf(totalCost.get() / total) + "ms"); + System.out.println( + "Error rate: " + + String.valueOf( + ((double) error.get() / (double) received.get()) * 100) + + "%"); + System.out.println( + "Return Error rate: " + + String.valueOf( + ((double) ret_error.get() / (double) received.get()) * 100) + + "%"); + + System.out.println("Time area:"); + System.out.println( + "0 < time < 50ms : " + + String.valueOf(less50) + + " : " + + String.valueOf((double) less50.get() / total * 100) + + "%"); + System.out.println( + "50 < time < 100ms : " + + String.valueOf(less100) + + " : " + + String.valueOf((double) less100.get() / total * 100) + + "%"); + System.out.println( + "100 < time < 200ms : " + + String.valueOf(less200) + + " : " + + String.valueOf((double) less200.get() / total * 100) + + "%"); + System.out.println( + "200 < time < 400ms : " + + String.valueOf(less400) + + " : " + + String.valueOf((double) less400.get() / total * 100) + + "%"); + System.out.println( + "400 < time < 1000ms : " + + String.valueOf(less1000) + + " : " + + String.valueOf((double) less1000.get() / total * 100) + + "%"); + System.out.println( + "1000 < time < 2000ms : " + + String.valueOf(less2000) + + " : " + + String.valueOf((double) less2000.get() / total * 100) + + "%"); + System.out.println( + "2000 < time : " + + String.valueOf(timeout2000) + + " : " + + String.valueOf((double) timeout2000.get() / total * 100) + + "%"); + } + + } catch (Exception e) { + logger.error("error:", e); + System.exit(0); + } + } + + private AtomicLong less50 = new AtomicLong(0); + private AtomicLong less100 = new AtomicLong(0); + private AtomicLong less200 = new AtomicLong(0); + private AtomicLong less400 = new AtomicLong(0); + private AtomicLong less1000 = new AtomicLong(0); + private AtomicLong less2000 = new AtomicLong(0); + private AtomicLong timeout2000 = new AtomicLong(0); + private AtomicLong totalCost = new AtomicLong(0); + + private AtomicInteger received = new AtomicInteger(0); + + public AtomicInteger getReceived() { + return received; + } + + public void setReceived(AtomicInteger received) { + this.received = received; + } + + private AtomicInteger error = new AtomicInteger(0); + private AtomicInteger ret_error = new AtomicInteger(0); + private Long startTimestamp = System.currentTimeMillis(); + + public Long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(Long startTimestamp) { + this.startTimestamp = startTimestamp; + } } diff --git a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTTest.java b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTTest.java index 0d8640585..733807781 100644 --- a/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTTest.java +++ b/src/test/java/org/fisco/bcos/channel/test/parallel/precompile/PerformanceDTTest.java @@ -1,312 +1,552 @@ package org.fisco.bcos.channel.test.parallel.precompile; import com.google.common.util.concurrent.RateLimiter; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.*; import org.fisco.bcos.channel.client.Service; import org.fisco.bcos.web3j.crypto.Credentials; import org.fisco.bcos.web3j.protocol.Web3j; import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService; import org.fisco.bcos.web3j.protocol.core.methods.response.TransactionReceipt; import org.fisco.bcos.web3j.tuples.generated.Tuple2; +import org.fisco.bcos.web3j.tx.Contract; +import org.fisco.bcos.web3j.tx.TransactionManager; import org.fisco.bcos.web3j.tx.gas.StaticGasProvider; import org.fisco.bcos.web3j.utils.Web3AsyncThreadPoolSize; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.math.BigInteger; -import java.util.List; -import java.util.Random; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - public class PerformanceDTTest { - private static Logger logger = LoggerFactory.getLogger(PerformanceDTTest.class); - private static AtomicInteger sended = new AtomicInteger(0); - private static final String dagTransferAddr = "0x0000000000000000000000000000000000005002"; - private static String groupId = "1"; - - private Web3j web3; - private DagTransfer dagTransfer; - - private Credentials credentials; - private DagUserMgr dagUserMgr; - private PerformanceDTCollector collector; - - public PerformanceDTTest(String groupID) throws Exception { - groupId = groupID; - initialize(groupId); - } + private static Logger logger = LoggerFactory.getLogger(PerformanceDTTest.class); + private static AtomicInteger sended = new AtomicInteger(0); + private static final String dagTransferAddr = "0x0000000000000000000000000000000000005002"; + private static String groupId = "1"; - public DagUserMgr getDagUserMgr() { - return dagUserMgr; - } + private Web3j web3; + private DagTransfer dagTransfer; - public void setDagUserMgr(DagUserMgr dagUserMgr) { - this.dagUserMgr = dagUserMgr; - } + private Credentials credentials; + private DagUserMgr dagUserMgr; + private PerformanceDTCollector collector; - public Web3j getWeb3() { - return web3; - } + private static CountDownLatch latch; + private TransactionManager transactionManager; - public void setWeb3(Web3j web3) { - this.web3 = web3; - } + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - public Credentials getCredentials() { - return credentials; - } + public PerformanceDTTest(String groupID) throws Exception { + groupId = groupID; + initialize(groupId); + } - public void setCredentials(Credentials credentials) { - this.credentials = credentials; - } + public DagUserMgr getDagUserMgr() { + return dagUserMgr; + } - public PerformanceDTCollector getCollector() { - return collector; - } + public void setDagUserMgr(DagUserMgr dagUserMgr) { + this.dagUserMgr = dagUserMgr; + } - public void setCollector(PerformanceDTCollector collector) { - this.collector = collector; - } + public Web3j getWeb3() { + return web3; + } - public void veryTransferData() { - // System.out.println(" data validation => "); - List allUser = dagUserMgr.getUserList(); - int total_user = allUser.size(); + public void setWeb3(Web3j web3) { + this.web3 = web3; + } - int verify_success = 0; + public Credentials getCredentials() { + return credentials; + } - int verify_failed = 0; + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } - allUser = dagUserMgr.getUserList(); + public PerformanceDTCollector getCollector() { + return collector; + } - try { - for (int i = 0; i < allUser.size(); ++i) { - Tuple2 result = dagTransfer.userBalance(allUser.get(i).getUser()).send(); + public void setCollector(PerformanceDTCollector collector) { + this.collector = collector; + } - String user = allUser.get(i).getUser(); - BigInteger local = allUser.get(i).getAmount(); - BigInteger remote = result.getValue2(); + public void veryTransferData(ThreadPoolTaskExecutor threadPool) { + List allUser = dagUserMgr.getUserList(); + Integer total_user = allUser.size(); + + AtomicInteger verify_success = new AtomicInteger(0); + AtomicInteger verify_failed = new AtomicInteger(0); + + allUser = dagUserMgr.getUserList(); + + try { + final DagTransfer _dagTransfer = dagTransfer; + final List _allUser = allUser; + for (int i = 0; i < allUser.size(); ++i) { + final Integer _i = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + try { + Tuple2 result = + _dagTransfer + .userBalance(_allUser.get(_i).getUser()) + .send(); + + String user = _allUser.get(_i).getUser(); + BigInteger local = _allUser.get(_i).getAmount(); + BigInteger remote = result.getValue2(); + + if (result.getValue1().compareTo(new BigInteger("0")) != 0) { + logger.error( + " query failed, user " + + user + + " ret code " + + result.getValue1()); + verify_failed.incrementAndGet(); + return; + } + + logger.debug( + " user " + + user + + " local amount " + + local + + " remote amount " + + remote); + if (local.compareTo(remote) != 0) { + verify_failed.incrementAndGet(); + logger.error( + " local amount is not same as remote, user " + + user + + " local " + + local + + " remote " + + remote); + } else { + verify_success.incrementAndGet(); + } + } catch (Exception e) { + logger.error("getAmount error: ", e); + } + } + }); + } - if (result.getValue1().compareTo(new BigInteger("0")) != 0) { - logger.error(" query failed, user " + user + " ret code " + result.getValue1()); - verify_failed++; - continue; - } + while (verify_success.get() + verify_failed.get() < total_user) { + Thread.sleep(40); + ; + } - logger.debug(" user " + user + " local amount " + local + " remote amount " + remote); - if (local.compareTo(remote) != 0) { - verify_failed++; - logger.error(" local amount is not same as remote, user " + user + " local " + local + " remote " + remote); - } else { - verify_success++; + System.out.println("validation:"); + System.out.println(" \tuser count is " + total_user); + System.out.println(" \tverify_success count is " + verify_success); + System.out.println(" \tverify_failed count is " + verify_failed); + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); } - } - - System.out.println("validation:"); - System.out.println(" \tuser count is " + total_user); - System.out.println(" \tverify_success count is " + verify_success); - System.out.println(" \tverify_failed count is " + verify_failed); - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); } - } - - public void initialize(String groupId) throws Exception { - - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - Service service = context.getBean(Service.class); - service.setGroupId(Integer.parseInt(groupId)); - service.run(); - - ChannelEthereumService channelEthereumService = new ChannelEthereumService(); - channelEthereumService.setChannelService(service); - Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; - Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; - - ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); - Web3j web3 = Web3j.build(channelEthereumService, 15 * 100, scheduledExecutorService, Integer.parseInt(groupId)); - - Credentials credentials = Credentials.create("b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); - - dagTransfer = DagTransfer.load(dagTransferAddr, web3, credentials, - new StaticGasProvider(new BigInteger("30000000"), new BigInteger("30000000"))); - } - - public void userAddTest(BigInteger count, BigInteger qps) { - - try { - - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count.intValue()); - - threadPool.initialize(); - - System.out.println("Start UserAdd test, count " + count); - System.out.println("==================================================================="); - - RateLimiter limiter = RateLimiter.create(qps.intValue()); - Integer area = count.intValue() / 10; - - long seconds = System.currentTimeMillis() / 1000l; - - this.collector.setStartTimestamp(System.currentTimeMillis()); - - for (Integer i = 0; i < count.intValue(); ++i) { - final int index = i; - threadPool.execute(new Runnable() { - @Override - public void run() { - limiter.acquire(); - String user = Long.toHexString(seconds) + Integer.toHexString(index); - BigInteger amount = new BigInteger("1000000000"); - DagTransferUser dtu = new DagTransferUser(); - dtu.setUser(user); - dtu.setAmount(amount); - - PerformanceDTCallback callback = new PerformanceDTCallback(); - callback.setCollector(collector); - callback.setDagTransferUser(dtu); - callback.setDagUserMgr(getDagUserMgr()); - callback.setCallBackType("add"); - - try { - dagTransfer.userAdd(user, amount, callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); + public void initialize(String groupId) throws Exception { + + ApplicationContext context = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + Service service = context.getBean(Service.class); + service.setGroupId(Integer.parseInt(groupId)); + service.run(); + + ChannelEthereumService channelEthereumService = new ChannelEthereumService(); + channelEthereumService.setChannelService(service); + + Web3AsyncThreadPoolSize.web3AsyncCorePoolSize = 3000; + Web3AsyncThreadPoolSize.web3AsyncPoolSize = 2000; + + ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(500); + Web3j web3 = + Web3j.build( + channelEthereumService, + 15 * 100, + scheduledExecutorService, + Integer.parseInt(groupId)); + + Credentials credentials = + Credentials.create( + "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6"); + + dagTransfer = + DagTransfer.load( + dagTransferAddr, + web3, + credentials, + new StaticGasProvider( + new BigInteger("30000000"), new BigInteger("30000000"))); + transactionManager = Contract.getTheTransactionManager(web3, credentials); + } - callback.onResponse(receipt); - logger.info(e.getMessage()); + public void userAddTest(BigInteger count, BigInteger qps) { + + try { + + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(count.intValue()); + threadPool.initialize(); + + System.out.println("Start UserAdd test, count " + count); + System.out.println( + "==================================================================="); + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + Integer area = count.intValue() / 10; + + long seconds = System.currentTimeMillis() / 1000l; + + this.collector.setStartTimestamp(System.currentTimeMillis()); + + for (Integer i = 0; i < count.intValue(); ++i) { + final int index = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + limiter.acquire(); + String user = + Long.toHexString(seconds) + Integer.toHexString(index); + BigInteger amount = new BigInteger("1000000000"); + DagTransferUser dtu = new DagTransferUser(); + dtu.setUser(user); + dtu.setAmount(amount); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCollector(collector); + callback.setDagTransferUser(dtu); + callback.setDagUserMgr(getDagUserMgr()); + callback.setCallBackType("add"); + + try { + dagTransfer.userAdd(user, amount, callback); + } catch (Exception e) { + TransactionReceipt receipt = new TransactionReceipt(); + receipt.setStatus("-1"); + + callback.onResponse(receipt); + logger.info(e.getMessage()); + } + + int current = sended.incrementAndGet(); + + if (current >= area && ((current % area) == 0)) { + System.out.println( + "Already sended: " + + current + + "/" + + count + + " transactions"); + } + } + }); } - int current = sended.incrementAndGet(); - - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + count + " transactions"); + // end or not + while (!collector.isEnd()) { + Thread.sleep(100); } - } - }); - } - - // end or not - while (!collector.isEnd()) { - Thread.sleep(3000); - } - dagUserMgr.writeDagTransferUser(); - System.exit(0); + dagUserMgr.writeDagTransferUser(); + System.exit(0); - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } } - } - - public void userTransferTest(BigInteger count, BigInteger qps, BigInteger deci) { - try { + public void userTransferTest(BigInteger count, BigInteger qps, BigInteger deci) { + System.out.println("Start UserTransfer test..."); + System.out.println("==================================================================="); + + String dirName = "./.signed_transactions"; + File dir = new File(dirName); + if (dir.exists()) { + File[] fileList = dir.listFiles(); + for (File file : fileList) { + if (!file.delete()) { + System.out.printf("Can't clean %s%n", dirName); + System.exit(0); + } + } + } else { + if (!dir.mkdir()) { + System.out.printf("Can't create directory %s%n", dirName); + System.exit(0); + } + } - ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); - threadPool.setCorePoolSize(200); - threadPool.setMaxPoolSize(500); - threadPool.setQueueCapacity(count.intValue()); + try { + System.out.println(dateFormat.format(new Date()) + " Querying account state..."); + + List allUser = dagUserMgr.getUserList(); + + int coreNum = Runtime.getRuntime().availableProcessors(); + ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); + threadPool.setCorePoolSize(200); + threadPool.setMaxPoolSize(500); + threadPool.setQueueCapacity(Math.max(count.intValue(), allUser.size())); + threadPool.initialize(); + + Lock lock = new ReentrantLock(); + final DagTransfer _dagTransfer = dagTransfer; + AtomicInteger geted = new AtomicInteger(0); + for (int i = 0; i < allUser.size(); ++i) { + final Integer _i = i; + threadPool.execute( + new Runnable() { + @Override + public void run() { + try { + Tuple2 result = + _dagTransfer + .userBalance(allUser.get(_i).getUser()) + .send(); + + if (result.getValue1().compareTo(new BigInteger("0")) == 0) { + allUser.get(_i).setAmount(result.getValue2()); + } else { + System.out.println( + " Query failed, user is " + + allUser.get(_i).getUser()); + System.exit(0); + } + int all = geted.incrementAndGet(); + if (all >= allUser.size()) { + System.out.println( + dateFormat.format(new Date()) + + " Query account finished"); + } + } catch (Exception e) { + System.out.println( + " Query failed, user is " + allUser.get(_i).getUser()); + System.exit(0); + } + } + }); + } - threadPool.initialize(); + while (geted.get() < allUser.size()) { + Thread.sleep(50); + } - System.out.println("Start UserTransfer test..."); - System.out.println("==================================================================="); + System.out.println(""); - RateLimiter limiter = RateLimiter.create(qps.intValue()); - Integer area = count.intValue() / 10; + AtomicLong signed = new AtomicLong(0); + int segmentSize = 200000; + int segmentCount = count.intValue() / segmentSize; + if (count.intValue() % segmentSize != 0) { + segmentCount++; + } - // query all account balance info - List allUser = dagUserMgr.getUserList(); - for (int i = 0; i < allUser.size(); ++i) { - Tuple2 result = dagTransfer.userBalance(allUser.get(i).getUser()).send(); - if (result.getValue1().compareTo(new BigInteger("0")) == 0) { - allUser.get(i).setAmount(result.getValue2()); - } else { - // account not exist?? - System.out.println(" Query failed, user is " + allUser.get(i).getUser()); - } - logger.debug( - " query user " + allUser.get(i).getUser() + " ret " + result.getValue1() + " amount " + result.getValue2()); - } - - this.collector.setStartTimestamp(System.currentTimeMillis()); - - for (Integer i = 0; i < count.intValue(); ++i) { - final int index = i; - threadPool.execute(new Runnable() { - @Override - public void run() { - limiter.acquire(); - DagTransferUser from = dagUserMgr.getFrom(index); - DagTransferUser to = dagUserMgr.getTo(index); - if ((deci.intValue() > 0) && (deci.intValue() >= (index % 10 + 1))) { - to = dagUserMgr.getNext(index); + AtomicLong totalWrited = new AtomicLong(0); + for (int i = 0; i < segmentCount; ++i) { + int start = i * segmentSize; + int end = start + segmentSize; + if (end > count.intValue()) { + end = count.intValue(); + } + + String fileName = dirName + "/signed_transactions_" + i; + + Lock fileLock = new ReentrantLock(); + BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); + + AtomicLong writed = new AtomicLong(0); + for (int j = start; j < end; ++j) { + final int index = j; + final int totalWrite = end - start; + threadPool.execute( + new Runnable() { + @Override + public void run() { + while (true) { + DagTransferUser from = dagUserMgr.getFrom(index); + DagTransferUser to = dagUserMgr.getTo(index); + if ((deci.intValue() > 0) + && (deci.intValue() >= (index % 10 + 1))) { + to = dagUserMgr.getNext(index); + } + + Random random = new Random(); + int r = random.nextInt(100) + 1; + BigInteger amount = BigInteger.valueOf(r); + + try { + String signedTransaction = + dagTransfer.userTransferSeq( + from.getUser(), to.getUser(), amount); + String content = + String.format( + "%s %d %d%n", + signedTransaction, index, r); + fileLock.lock(); + writer.write(content); + + long totalSigned = signed.incrementAndGet(); + if (totalSigned % (count.longValue() / 10) == 0) { + System.out.println( + "Signed transaction: " + + String.valueOf( + totalSigned + * 100 + / count.longValue()) + + "%"); + } + + long writedCount = writed.incrementAndGet(); + totalWrited.incrementAndGet(); + if (writedCount >= totalWrite) { + writer.close(); + } + + break; + } catch (Exception e) { + e.printStackTrace(); + continue; + } finally { + fileLock.unlock(); + } + } + } + }); + } } - Random random = new Random(); - int r = random.nextInt(100) + 1; - BigInteger amount = BigInteger.valueOf(r); - - PerformanceDTCallback callback = new PerformanceDTCallback(); - callback.setCallBackType("transfer"); - callback.setCollector(collector); - callback.setDagUserMgr(getDagUserMgr()); - callback.setFromUser(from); - callback.setToUser(to); - callback.setAmount(amount); - - try { - logger.debug(" transfer from is " + from + " to is " + to + " amount is " + amount); - dagTransfer.userTransfer(from.getUser(), to.getUser(), amount, callback); - } catch (Exception e) { - TransactionReceipt receipt = new TransactionReceipt(); - receipt.setStatus("-1"); - - callback.onResponse(receipt); - logger.info(e.getMessage()); + while (totalWrited.get() < count.intValue()) { + Thread.sleep(50); } - int current = sended.incrementAndGet(); + System.out.print(dateFormat.format(new Date()) + " Prepare transactions finished"); + System.out.println(""); + + long sent = 0; + File[] fileList = dir.listFiles(); + + System.out.println(dateFormat.format(new Date()) + " Sending signed transactions..."); + + long startTime = System.currentTimeMillis(); + collector.setStartTimestamp(startTime); + + RateLimiter limiter = RateLimiter.create(qps.intValue()); + for (int i = 0; i < fileList.length; ++i) { + BufferedReader reader = new BufferedReader(new FileReader(fileList[i])); + + List signedTransactions = new ArrayList(); + List callbacks = new ArrayList(); + String line = null; + + while ((line = reader.readLine()) != null) { + String[] fields = line.split(" "); + signedTransactions.add(fields[0]); + + int index = Integer.parseInt(fields[1]); + BigInteger amount = new BigInteger(fields[2]); + + DagTransferUser from = dagUserMgr.getFrom(index); + DagTransferUser to = dagUserMgr.getTo(index); + + PerformanceDTCallback callback = new PerformanceDTCallback(); + callback.setCallBackType("transfer"); + callback.setCollector(collector); + callback.setDagUserMgr(getDagUserMgr()); + callback.setFromUser(from); + callback.setToUser(to); + callback.setAmount(amount); + callbacks.add(callback); + } + + latch = new CountDownLatch(signedTransactions.size()); + + for (int j = 0; j < signedTransactions.size(); ++j) { + limiter.acquire(); + + final int index = j; + threadPool.execute( + new Runnable() { + @Override + public void run() { + while (true) { + try { + transactionManager.sendTransaction( + signedTransactions.get(index), + callbacks.get(index)); + break; + } catch (Exception e) { + logger.error("Send transaction error: ", e); + continue; + } + } + + latch.countDown(); + } + }); + } + + latch.await(); + long elapsed = System.currentTimeMillis() - startTime; + sent += signedTransactions.size(); + double sendSpeed = sent / ((double) elapsed / 1000); + System.out.println( + "Already sent: " + + sent + + "/" + + count + + " transactions" + + ",QPS=" + + sendSpeed); + } - if (current >= area && ((current % area) == 0)) { - System.out.println("Already sended: " + current + "/" + count + " transactions"); + while (!collector.isEnd()) { + Thread.sleep(1000); } - } - }); - } - // end or not - while (!collector.isEnd()) { - Thread.sleep(3000); - } + logger.info("End to send"); - veryTransferData(); - System.exit(0); + System.out.println(dateFormat.format(new Date()) + " Verifying result..."); + veryTransferData(threadPool); - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } } - } - public DagTransfer getDagTransfer() { - return dagTransfer; - } + public DagTransfer getDagTransfer() { + return dagTransfer; + } - public void setDagTransfer(DagTransfer dagTransfer) { - this.dagTransfer = dagTransfer; - } + public void setDagTransfer(DagTransfer dagTransfer) { + this.dagTransfer = dagTransfer; + } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/EventEncoderTest.java b/src/test/java/org/fisco/bcos/web3j/abi/EventEncoderTest.java index b2659b49d..bae9d678f 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/EventEncoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/EventEncoderTest.java @@ -1,18 +1,20 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import org.junit.Test; + public class EventEncoderTest { @Test public void testBuildEventSignature() { - assertThat(EventEncoder.buildEventSignature("Deposit(address,hash256,uint256)"), + assertThat( + EventEncoder.buildEventSignature("Deposit(address,hash256,uint256)"), is("0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20")); - assertThat(EventEncoder.buildEventSignature("Notify(uint256,uint256)"), + assertThat( + EventEncoder.buildEventSignature("Notify(uint256,uint256)"), is("0x71e71a8458267085d5ab16980fd5f114d2d37f232479c245d523ce8d23ca40ed")); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/FunctionEncoderTest.java b/src/test/java/org/fisco/bcos/web3j/abi/FunctionEncoderTest.java index 7fd6f56ad..eda1c5dac 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/FunctionEncoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/FunctionEncoderTest.java @@ -1,16 +1,15 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; -import org.fisco.bcos.web3j.abi.datatypes.*; -import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes10; -import org.fisco.bcos.web3j.abi.datatypes.generated.Uint32; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; import java.math.BigInteger; import java.util.Arrays; import java.util.Collections; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import org.fisco.bcos.web3j.abi.datatypes.*; +import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes10; +import org.fisco.bcos.web3j.abi.datatypes.generated.Uint32; +import org.junit.Test; public class FunctionEncoderTest { @@ -23,11 +22,7 @@ public void testBuildMethodId() { public void testBuildMessageSignature() { assertThat( FunctionEncoder.buildMethodSignature( - "baz", - Arrays.asList( - new Uint32(BigInteger.valueOf(69)), - new Bool(true)) - ), + "baz", Arrays.asList(new Uint32(BigInteger.valueOf(69)), new Bool(true))), is("baz(uint32,bool)")); } @@ -45,89 +40,97 @@ public void testEncodeConstructorEmpty() { @Test public void testEncodeConstructorString() { - assertThat(FunctionEncoder.encodeConstructor( - Collections.singletonList(new Utf8String("Greetings!"))), - is("0000000000000000000000000000000000000000000000000000000000000020" - + "000000000000000000000000000000000000000000000000000000000000000a" - + "4772656574696e67732100000000000000000000000000000000000000000000")); + assertThat( + FunctionEncoder.encodeConstructor( + Collections.singletonList(new Utf8String("Greetings!"))), + is( + "0000000000000000000000000000000000000000000000000000000000000020" + + "000000000000000000000000000000000000000000000000000000000000000a" + + "4772656574696e67732100000000000000000000000000000000000000000000")); } @Test public void testEncodeConstructorUint() { - assertThat(FunctionEncoder.encodeConstructor( - Arrays.asList(new Uint(BigInteger.ONE), new Uint(BigInteger.valueOf(0x20)))), - is("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000020")); + assertThat( + FunctionEncoder.encodeConstructor( + Arrays.asList( + new Uint(BigInteger.ONE), new Uint(BigInteger.valueOf(0x20)))), + is( + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000020")); } @Test public void testFunctionSimpleEncode() { - Function function = new Function( - "baz", - Arrays.asList(new Uint32(BigInteger.valueOf(69)), new Bool(true)), - Collections.>emptyList() - ); + Function function = + new Function( + "baz", + Arrays.asList(new Uint32(BigInteger.valueOf(69)), new Bool(true)), + Collections.>emptyList()); - assertThat(FunctionEncoder.encode(function), - is("0xcdcd77c0" - + "0000000000000000000000000000000000000000000000000000000000000045" - + "0000000000000000000000000000000000000000000000000000000000000001" - )); + assertThat( + FunctionEncoder.encode(function), + is( + "0xcdcd77c0" + + "0000000000000000000000000000000000000000000000000000000000000045" + + "0000000000000000000000000000000000000000000000000000000000000001")); } @Test public void testFunctionMDynamicArrayEncode1() { - Function function = new Function( - "sam", - Arrays.asList( - new DynamicBytes("dave".getBytes()), - new Bool(true), - new DynamicArray<>( - new Uint(BigInteger.ONE), - new Uint(BigInteger.valueOf(2)), - new Uint(BigInteger.valueOf(3)))), - Collections.>emptyList() - ); + Function function = + new Function( + "sam", + Arrays.asList( + new DynamicBytes("dave".getBytes()), + new Bool(true), + new DynamicArray<>( + new Uint(BigInteger.ONE), + new Uint(BigInteger.valueOf(2)), + new Uint(BigInteger.valueOf(3)))), + Collections.>emptyList()); - assertThat(FunctionEncoder.encode(function), - is("0xa5643bf2" - + "0000000000000000000000000000000000000000000000000000000000000060" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "00000000000000000000000000000000000000000000000000000000000000a0" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "6461766500000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003")); + assertThat( + FunctionEncoder.encode(function), + is( + "0xa5643bf2" + + "0000000000000000000000000000000000000000000000000000000000000060" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "00000000000000000000000000000000000000000000000000000000000000a0" + + "0000000000000000000000000000000000000000000000000000000000000004" + + "6461766500000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000003" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000003")); } @Test public void testFunctionMDynamicArrayEncode2() { - Function function = new Function( - "f", - Arrays.asList( - new Uint(BigInteger.valueOf(0x123)), - new DynamicArray<>( - new Uint32(BigInteger.valueOf(0x456)), - new Uint32(BigInteger.valueOf(0x789)) - ), - new Bytes10("1234567890".getBytes()), - new DynamicBytes("Hello, world!".getBytes())), - Collections.>emptyList() - ); + Function function = + new Function( + "f", + Arrays.asList( + new Uint(BigInteger.valueOf(0x123)), + new DynamicArray<>( + new Uint32(BigInteger.valueOf(0x456)), + new Uint32(BigInteger.valueOf(0x789))), + new Bytes10("1234567890".getBytes()), + new DynamicBytes("Hello, world!".getBytes())), + Collections.>emptyList()); - assertThat(FunctionEncoder.encode(function), - is("0x8be65246" - + "0000000000000000000000000000000000000000000000000000000000000123" - + "0000000000000000000000000000000000000000000000000000000000000080" - + "3132333435363738393000000000000000000000000000000000000000000000" - + "00000000000000000000000000000000000000000000000000000000000000e0" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000456" - + "0000000000000000000000000000000000000000000000000000000000000789" - + "000000000000000000000000000000000000000000000000000000000000000d" - + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" - )); + assertThat( + FunctionEncoder.encode(function), + is( + "0x8be65246" + + "0000000000000000000000000000000000000000000000000000000000000123" + + "0000000000000000000000000000000000000000000000000000000000000080" + + "3132333435363738393000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000e0" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000456" + + "0000000000000000000000000000000000000000000000000000000000000789" + + "000000000000000000000000000000000000000000000000000000000000000d" + + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000")); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoderTest.java b/src/test/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoderTest.java index 8ac861b52..a96b6a72b 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/FunctionReturnDecoderTest.java @@ -1,155 +1,169 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; -import org.fisco.bcos.web3j.abi.datatypes.*; -import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes16; -import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes32; -import org.fisco.bcos.web3j.abi.datatypes.generated.Uint256; -import org.fisco.bcos.web3j.crypto.Hash; -import org.fisco.bcos.web3j.utils.Numeric; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; +import org.fisco.bcos.web3j.abi.datatypes.*; +import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes16; +import org.fisco.bcos.web3j.abi.datatypes.generated.Bytes32; +import org.fisco.bcos.web3j.abi.datatypes.generated.Uint256; +import org.fisco.bcos.web3j.crypto.Hash; +import org.fisco.bcos.web3j.utils.Numeric; +import org.junit.Test; public class FunctionReturnDecoderTest { @Test public void testSimpleFunctionDecode() { - Function function = new Function( - "test", - Collections.emptyList(), - Collections.singletonList(new TypeReference(){}) - ); - - assertThat(FunctionReturnDecoder.decode( - "0x0000000000000000000000000000000000000000000000000000000000000037", - function.getOutputParameters()), + Function function = + new Function( + "test", + Collections.emptyList(), + Collections.singletonList(new TypeReference() {})); + + assertThat( + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000037", + function.getOutputParameters()), equalTo(Collections.singletonList(new Uint(BigInteger.valueOf(55))))); } @Test public void testSimpleFunctionStringResultDecode() { - Function function = new Function("simple", - Arrays.asList(), - Collections.singletonList(new TypeReference() { - })); - - List utf8Strings = FunctionReturnDecoder.decode( - - "0x0000000000000000000000000000000000000000000000000000000000000020" - + "000000000000000000000000000000000000000000000000000000000000000d" - + "6f6e65206d6f72652074696d6500000000000000000000000000000000000000", - function.getOutputParameters()); + Function function = + new Function( + "simple", + Arrays.asList(), + Collections.singletonList(new TypeReference() {})); + + List utf8Strings = + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000020" + + "000000000000000000000000000000000000000000000000000000000000000d" + + "6f6e65206d6f72652074696d6500000000000000000000000000000000000000", + function.getOutputParameters()); assertThat(utf8Strings.get(0).getValue(), is("one more time")); } @Test public void testFunctionEmptyStringResultDecode() { - Function function = new Function("test", - Collections.emptyList(), - Collections.singletonList(new TypeReference() { - })); - - List utf8Strings = FunctionReturnDecoder.decode( - "0x0000000000000000000000000000000000000000000000000000000000000020" - + "0000000000000000000000000000000000000000000000000000000000000000", - function.getOutputParameters()); + Function function = + new Function( + "test", + Collections.emptyList(), + Collections.singletonList(new TypeReference() {})); + + List utf8Strings = + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000000", + function.getOutputParameters()); assertThat(utf8Strings.get(0).getValue(), is("")); } @Test public void testMultipleResultFunctionDecode() { - Function function = new Function( - "test", - Collections.emptyList(), - Arrays.asList(new TypeReference() { }, new TypeReference() { }) - ); - - assertThat(FunctionReturnDecoder.decode( - "0x0000000000000000000000000000000000000000000000000000000000000037" - + "0000000000000000000000000000000000000000000000000000000000000007", - function.getOutputParameters()), - equalTo(Arrays.asList(new Uint(BigInteger.valueOf(55)), - new Uint(BigInteger.valueOf(7))))); + Function function = + new Function( + "test", + Collections.emptyList(), + Arrays.asList(new TypeReference() {}, new TypeReference() {})); + + assertThat( + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000037" + + "0000000000000000000000000000000000000000000000000000000000000007", + function.getOutputParameters()), + equalTo( + Arrays.asList( + new Uint(BigInteger.valueOf(55)), + new Uint(BigInteger.valueOf(7))))); } @Test public void testDecodeMultipleStringValues() { - Function function = new Function("function", - Collections.emptyList(), - Arrays.asList( - new TypeReference() { }, new TypeReference() { }, - new TypeReference() { }, new TypeReference() { })); - - assertThat(FunctionReturnDecoder.decode( - "0x0000000000000000000000000000000000000000000000000000000000000080" - + "00000000000000000000000000000000000000000000000000000000000000c0" - + "0000000000000000000000000000000000000000000000000000000000000100" - + "0000000000000000000000000000000000000000000000000000000000000140" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "6465663100000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "6768693100000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "6a6b6c3100000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000004" - + "6d6e6f3200000000000000000000000000000000000000000000000000000000", - function.getOutputParameters()), - equalTo(Arrays.asList( - new Utf8String("def1"), new Utf8String("ghi1"), - new Utf8String("jkl1"), new Utf8String("mno2")))); + Function function = + new Function( + "function", + Collections.emptyList(), + Arrays.asList( + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {})); + + assertThat( + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000080" + + "00000000000000000000000000000000000000000000000000000000000000c0" + + "0000000000000000000000000000000000000000000000000000000000000100" + + "0000000000000000000000000000000000000000000000000000000000000140" + + "0000000000000000000000000000000000000000000000000000000000000004" + + "6465663100000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000004" + + "6768693100000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000004" + + "6a6b6c3100000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000004" + + "6d6e6f3200000000000000000000000000000000000000000000000000000000", + function.getOutputParameters()), + equalTo( + Arrays.asList( + new Utf8String("def1"), new Utf8String("ghi1"), + new Utf8String("jkl1"), new Utf8String("mno2")))); } - @Test @SuppressWarnings("unchecked") public void testDecodeStaticArrayValue() { List> outputParameters = new ArrayList<>(1); - outputParameters.add((TypeReference) - new TypeReference.StaticArrayTypeReference>(2) {}); + outputParameters.add( + (TypeReference) + new TypeReference.StaticArrayTypeReference>(2) {}); outputParameters.add((TypeReference) new TypeReference() {}); + List decoded = + FunctionReturnDecoder.decode( + "0x0000000000000000000000000000000000000000000000000000000000000037" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "000000000000000000000000000000000000000000000000000000000000000a", + outputParameters); - List decoded = FunctionReturnDecoder.decode( - "0x0000000000000000000000000000000000000000000000000000000000000037" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "000000000000000000000000000000000000000000000000000000000000000a", - outputParameters); - - List expected = Arrays.asList( - new StaticArray<>(new Uint256(BigInteger.valueOf(55)), new Uint256(BigInteger.ONE)), - new Uint256(BigInteger.TEN)); + List expected = + Arrays.asList( + new StaticArray<>( + new Uint256(BigInteger.valueOf(55)), new Uint256(BigInteger.ONE)), + new Uint256(BigInteger.TEN)); assertThat(decoded, equalTo(expected)); } @Test public void testVoidResultFunctionDecode() { - Function function = new Function( - "test", - Collections.emptyList(), - Collections.emptyList()); + Function function = new Function("test", Collections.emptyList(), Collections.emptyList()); - assertThat(FunctionReturnDecoder.decode("0x", function.getOutputParameters()), + assertThat( + FunctionReturnDecoder.decode("0x", function.getOutputParameters()), is(Collections.emptyList())); } @Test public void testEmptyResultFunctionDecode() { - Function function = new Function( - "test", - Collections.emptyList(), - Collections.singletonList(new TypeReference() { })); - - assertThat(FunctionReturnDecoder.decode("0x", function.getOutputParameters()), + Function function = + new Function( + "test", + Collections.emptyList(), + Collections.singletonList(new TypeReference() {})); + + assertThat( + FunctionReturnDecoder.decode("0x", function.getOutputParameters()), is(Collections.emptyList())); } @@ -158,9 +172,8 @@ public void testDecodeIndexedUint256Value() { Uint256 value = new Uint256(BigInteger.TEN); String encoded = TypeEncoder.encodeNumeric(value); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - encoded, - new TypeReference() {}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue(encoded, new TypeReference() {}), equalTo(value)); } @@ -170,9 +183,8 @@ public void testDecodeIndexedStringValue() { String encoded = TypeEncoder.encodeString(string); String hash = Hash.sha3(encoded); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - hash, - new TypeReference() {}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue(hash, new TypeReference() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } @@ -181,9 +193,8 @@ public void testDecodeIndexedBytes32Value() { String rawInput = "0x1234567890123456789012345678901234567890123456789012345678901234"; byte[] rawInputBytes = Numeric.hexStringToByteArray(rawInput); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - rawInput, - new TypeReference(){}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue(rawInput, new TypeReference() {}), equalTo(new Bytes32(rawInputBytes))); } @@ -192,21 +203,20 @@ public void testDecodeIndexedBytes16Value() { String rawInput = "0x1234567890123456789012345678901200000000000000000000000000000000"; byte[] rawInputBytes = Numeric.hexStringToByteArray(rawInput.substring(0, 34)); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - rawInput, - new TypeReference(){}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue(rawInput, new TypeReference() {}), equalTo(new Bytes16(rawInputBytes))); } @Test public void testDecodeIndexedDynamicBytesValue() { - DynamicBytes bytes = new DynamicBytes(new byte[]{ 1, 2, 3, 4, 5}); + DynamicBytes bytes = new DynamicBytes(new byte[] {1, 2, 3, 4, 5}); String encoded = TypeEncoder.encodeDynamicBytes(bytes); String hash = Hash.sha3(encoded); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - hash, - new TypeReference() {}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue( + hash, new TypeReference() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } @@ -216,9 +226,9 @@ public void testDecodeIndexedDynamicArrayValue() { String encoded = TypeEncoder.encodeDynamicArray(array); String hash = Hash.sha3(encoded); - assertThat(FunctionReturnDecoder.decodeIndexedValue( - hash, - new TypeReference() {}), + assertThat( + FunctionReturnDecoder.decodeIndexedValue( + hash, new TypeReference() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/TypeDecoderTest.java b/src/test/java/org/fisco/bcos/web3j/abi/TypeDecoderTest.java index 87d966ebc..f2d6b9615 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/TypeDecoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/TypeDecoderTest.java @@ -1,99 +1,103 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; -import org.fisco.bcos.web3j.abi.datatypes.*; -import org.fisco.bcos.web3j.abi.datatypes.generated.*; - -import java.math.BigInteger; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; +import java.math.BigInteger; +import org.fisco.bcos.web3j.abi.datatypes.*; +import org.fisco.bcos.web3j.abi.datatypes.generated.*; +import org.junit.Test; + public class TypeDecoderTest { @Test public void testBoolDecode() { - assertThat(TypeDecoder.decodeBool( - "0000000000000000000000000000000000000000000000000000000000000000", 0), + assertThat( + TypeDecoder.decodeBool( + "0000000000000000000000000000000000000000000000000000000000000000", 0), is(new Bool(false))); - assertThat(TypeDecoder.decodeBool( - "0000000000000000000000000000000000000000000000000000000000000001", 0), + assertThat( + TypeDecoder.decodeBool( + "0000000000000000000000000000000000000000000000000000000000000001", 0), is(new Bool(true))); } @Test public void testBoolDecodeGivenOffset() { // Decode second parameter as Bool - assertThat(TypeDecoder.decode( - "0000000000000000000000000000000000000000000000007fffffffffffffff" - + "0000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000007fffffffffffffff", - 64, Bool.class), + assertThat( + TypeDecoder.decode( + "0000000000000000000000000000000000000000000000007fffffffffffffff" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000007fffffffffffffff", + 64, + Bool.class), is(new Bool(false))); - assertThat(TypeDecoder.decode( - "0000000000000000000000000000000000000000000000007fffffffffffffff" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000007fffffffffffffff", - 64, Bool.class), + assertThat( + TypeDecoder.decode( + "0000000000000000000000000000000000000000000000007fffffffffffffff" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000007fffffffffffffff", + 64, + Bool.class), is(new Bool(true))); } @Test public void testUintDecode() { - assertThat(TypeDecoder.decodeNumeric( - "0000000000000000000000000000000000000000000000000000000000000000", - Uint64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "0000000000000000000000000000000000000000000000000000000000000000", + Uint64.class), is(new Uint64(BigInteger.ZERO))); - assertThat(TypeDecoder.decodeNumeric( - "0000000000000000000000000000000000000000000000007fffffffffffffff", - Uint64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "0000000000000000000000000000000000000000000000007fffffffffffffff", + Uint64.class), is(new Uint64(BigInteger.valueOf(Long.MAX_VALUE)))); - assertThat(TypeDecoder.decodeNumeric( - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - Uint64.class - ), - is(new Uint64(new BigInteger( - "0ffffffffffffffff", 16)))); + assertThat( + TypeDecoder.decodeNumeric( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + Uint64.class), + is(new Uint64(new BigInteger("0ffffffffffffffff", 16)))); } @Test public void testIntDecode() { - assertThat(TypeDecoder.decodeNumeric( - "0000000000000000000000000000000000000000000000000000000000000000", - Int64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "0000000000000000000000000000000000000000000000000000000000000000", + Int64.class), is(new Int64(BigInteger.ZERO))); - assertThat(TypeDecoder.decodeNumeric( - "0000000000000000000000000000000000000000000000007fffffffffffffff", - Int64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "0000000000000000000000000000000000000000000000007fffffffffffffff", + Int64.class), is(new Int64(BigInteger.valueOf(Long.MAX_VALUE)))); - assertThat(TypeDecoder.decodeNumeric( - "fffffffffffffffffffffffffffffffffffffffffffffff88000000000000000", - Int64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "fffffffffffffffffffffffffffffffffffffffffffffff88000000000000000", + Int64.class), is(new Int64(BigInteger.valueOf(Long.MIN_VALUE)))); - assertThat(TypeDecoder.decodeNumeric( - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - Int64.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + Int64.class), is(new Int64(BigInteger.valueOf(-1)))); - assertThat(TypeDecoder.decodeNumeric( - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - Int256.class - ), + assertThat( + TypeDecoder.decodeNumeric( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + Int256.class), is(new Int256(BigInteger.valueOf(-1)))); } @@ -149,153 +153,176 @@ public void testFixedDecode() { @Test public void testStaticBytes() { - Bytes6 staticBytes = new Bytes6(new byte[] { 0, 1, 2, 3, 4, 5 }); - assertThat(TypeDecoder.decodeBytes( - "0001020304050000000000000000000000000000000000000000000000000000", Bytes6.class), + Bytes6 staticBytes = new Bytes6(new byte[] {0, 1, 2, 3, 4, 5}); + assertThat( + TypeDecoder.decodeBytes( + "0001020304050000000000000000000000000000000000000000000000000000", + Bytes6.class), is(staticBytes)); - Bytes empty = new Bytes1(new byte[] { 0 }); - assertThat(TypeDecoder.decodeBytes( - "0000000000000000000000000000000000000000000000000000000000000000", Bytes1.class), + Bytes empty = new Bytes1(new byte[] {0}); + assertThat( + TypeDecoder.decodeBytes( + "0000000000000000000000000000000000000000000000000000000000000000", + Bytes1.class), is(empty)); Bytes dave = new Bytes4("dave".getBytes()); - assertThat(TypeDecoder.decodeBytes( - "6461766500000000000000000000000000000000000000000000000000000000", Bytes4.class), + assertThat( + TypeDecoder.decodeBytes( + "6461766500000000000000000000000000000000000000000000000000000000", + Bytes4.class), is(dave)); } @Test public void testDynamicBytes() { - DynamicBytes dynamicBytes = new DynamicBytes(new byte[] { 0, 1, 2, 3, 4, 5 }); - assertThat(TypeDecoder.decodeDynamicBytes( - "0000000000000000000000000000000000000000000000000000000000000006" // length - + "0001020304050000000000000000000000000000000000000000000000000000", 0), + DynamicBytes dynamicBytes = new DynamicBytes(new byte[] {0, 1, 2, 3, 4, 5}); + assertThat( + TypeDecoder.decodeDynamicBytes( + "0000000000000000000000000000000000000000000000000000000000000006" // length + + "0001020304050000000000000000000000000000000000000000000000000000", + 0), is(dynamicBytes)); - DynamicBytes empty = new DynamicBytes(new byte[] { 0 }); - assertThat(TypeDecoder.decodeDynamicBytes( - "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000000", 0), + DynamicBytes empty = new DynamicBytes(new byte[] {0}); + assertThat( + TypeDecoder.decodeDynamicBytes( + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000000", + 0), is(empty)); DynamicBytes dave = new DynamicBytes("dave".getBytes()); - assertThat(TypeDecoder.decodeDynamicBytes( + assertThat( + TypeDecoder.decodeDynamicBytes( "0000000000000000000000000000000000000000000000000000000000000004" - + "6461766500000000000000000000000000000000000000000000000000000000", 0), + + "6461766500000000000000000000000000000000000000000000000000000000", + 0), is(dave)); - DynamicBytes loremIpsum = new DynamicBytes( - ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " - + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " - + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex " - + "ea commodo consequat. Duis aute irure dolor in reprehenderit in " - + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur " - + "sint occaecat cupidatat non proident, sunt in culpa qui officia " - + "deserunt mollit anim id est laborum.").getBytes()); - - assertThat(TypeDecoder.decodeDynamicBytes( - "00000000000000000000000000000000000000000000000000000000000001bd" - + "4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73" - + "656374657475722061646970697363696e6720656c69742c2073656420646f20" - + "656975736d6f642074656d706f7220696e6369646964756e74207574206c6162" - + "6f726520657420646f6c6f7265206d61676e6120616c697175612e2055742065" - + "6e696d206164206d696e696d2076656e69616d2c2071756973206e6f73747275" - + "6420657865726369746174696f6e20756c6c616d636f206c61626f726973206e" - + "69736920757420616c697175697020657820656120636f6d6d6f646f20636f6e" - + "7365717561742e2044756973206175746520697275726520646f6c6f7220696e" - + "20726570726568656e646572697420696e20766f6c7570746174652076656c69" - + "7420657373652063696c6c756d20646f6c6f726520657520667567696174206e" - + "756c6c612070617269617475722e204578636570746575722073696e74206f63" - + "63616563617420637570696461746174206e6f6e2070726f6964656e742c2073" - + "756e7420696e2063756c706120717569206f666669636961206465736572756e" - + "74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e000000", - 0), + DynamicBytes loremIpsum = + new DynamicBytes( + ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " + + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " + + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex " + + "ea commodo consequat. Duis aute irure dolor in reprehenderit in " + + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur " + + "sint occaecat cupidatat non proident, sunt in culpa qui officia " + + "deserunt mollit anim id est laborum.") + .getBytes()); + + assertThat( + TypeDecoder.decodeDynamicBytes( + "00000000000000000000000000000000000000000000000000000000000001bd" + + "4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73" + + "656374657475722061646970697363696e6720656c69742c2073656420646f20" + + "656975736d6f642074656d706f7220696e6369646964756e74207574206c6162" + + "6f726520657420646f6c6f7265206d61676e6120616c697175612e2055742065" + + "6e696d206164206d696e696d2076656e69616d2c2071756973206e6f73747275" + + "6420657865726369746174696f6e20756c6c616d636f206c61626f726973206e" + + "69736920757420616c697175697020657820656120636f6d6d6f646f20636f6e" + + "7365717561742e2044756973206175746520697275726520646f6c6f7220696e" + + "20726570726568656e646572697420696e20766f6c7570746174652076656c69" + + "7420657373652063696c6c756d20646f6c6f726520657520667567696174206e" + + "756c6c612070617269617475722e204578636570746575722073696e74206f63" + + "63616563617420637570696461746174206e6f6e2070726f6964656e742c2073" + + "756e7420696e2063756c706120717569206f666669636961206465736572756e" + + "74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e000000", + 0), is(loremIpsum)); } @Test public void testAddress() { - assertThat(TypeDecoder.decodeAddress( - "000000000000000000000000be5422d15f39373eb0a97ff8c10fbd0e40e29338"), + assertThat( + TypeDecoder.decodeAddress( + "000000000000000000000000be5422d15f39373eb0a97ff8c10fbd0e40e29338"), is(new Address("0xbe5422d15f39373eb0a97ff8c10fbd0e40e29338"))); } @Test public void testUtf8String() { - assertThat(TypeDecoder.decodeUtf8String( - "000000000000000000000000000000000000000000000000000000000000000d" // length - + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000", 0), + assertThat( + TypeDecoder.decodeUtf8String( + "000000000000000000000000000000000000000000000000000000000000000d" // length + + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000", + 0), is(new Utf8String("Hello, world!"))); } @Test public void testStaticArray() { - assertThat(TypeDecoder.decodeStaticArray( - "000000000000000000000000000000000000000000000000000000000000000a" - + "0000000000000000000000000000000000000000000000007fffffffffffffff", - 0, - new TypeReference.StaticArrayTypeReference>(2) {}, - 2), - is(new StaticArray( - new Uint256(BigInteger.TEN), - new Uint256(BigInteger.valueOf(Long.MAX_VALUE))))); - - assertThat(TypeDecoder.decodeStaticArray( + assertThat( + TypeDecoder.decodeStaticArray( + "000000000000000000000000000000000000000000000000000000000000000a" + + "0000000000000000000000000000000000000000000000007fffffffffffffff", + 0, + new TypeReference.StaticArrayTypeReference>(2) {}, + 2), + is( + new StaticArray( + new Uint256(BigInteger.TEN), + new Uint256(BigInteger.valueOf(Long.MAX_VALUE))))); + + assertThat( + TypeDecoder.decodeStaticArray( "000000000000000000000000000000000000000000000000000000000000000d" - + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000d" - + "776f726c64212048656c6c6f2c00000000000000000000000000000000000000", - 0, - new TypeReference.StaticArrayTypeReference>(2){}, - 2 - ), - equalTo(new StaticArray( - new Utf8String("Hello, world!"), - new Utf8String("world! Hello,")))); + + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000d" + + "776f726c64212048656c6c6f2c00000000000000000000000000000000000000", + 0, + new TypeReference.StaticArrayTypeReference>(2) {}, + 2), + equalTo( + new StaticArray( + new Utf8String("Hello, world!"), new Utf8String("world! Hello,")))); } @Test(expected = UnsupportedOperationException.class) public void testEmptyStaticArray() { - assertThat(TypeDecoder.decodeStaticArray( - "0000000000000000000000000000000000000000000000000000000000000000", - 0, - new TypeReference.StaticArrayTypeReference>(0) {}, - 0), is("invalid")); + assertThat( + TypeDecoder.decodeStaticArray( + "0000000000000000000000000000000000000000000000000000000000000000", + 0, + new TypeReference.StaticArrayTypeReference>(0) {}, + 0), + is("invalid")); } @Test public void testDynamicArray() { - assertThat(TypeDecoder.decodeDynamicArray( - "0000000000000000000000000000000000000000000000000000000000000000", // length - 0, - new TypeReference>() { } - ), + assertThat( + TypeDecoder.decodeDynamicArray( + "0000000000000000000000000000000000000000000000000000000000000000", // length + 0, + new TypeReference>() {}), equalTo(DynamicArray.empty("uint256"))); - assertThat(TypeDecoder.decodeDynamicArray( - "0000000000000000000000000000000000000000000000000000000000000002" // length - + "000000000000000000000000000000000000000000000000000000000000000a" - + "0000000000000000000000000000000000000000000000007fffffffffffffff", - 0, - new TypeReference>() { } - ), - equalTo(new DynamicArray( - new Uint256(BigInteger.TEN), - new Uint256(BigInteger.valueOf(Long.MAX_VALUE))))); - - assertThat(TypeDecoder.decodeDynamicArray( - "0000000000000000000000000000000000000000000000000000000000000002" // length - + "000000000000000000000000000000000000000000000000000000000000000d" - + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000d" - + "776f726c64212048656c6c6f2c00000000000000000000000000000000000000", - 0, - new TypeReference>() { } - ), - equalTo(new DynamicArray( - new Utf8String("Hello, world!"), - new Utf8String("world! Hello,")))); + assertThat( + TypeDecoder.decodeDynamicArray( + "0000000000000000000000000000000000000000000000000000000000000002" // length + + "000000000000000000000000000000000000000000000000000000000000000a" + + "0000000000000000000000000000000000000000000000007fffffffffffffff", + 0, + new TypeReference>() {}), + equalTo( + new DynamicArray( + new Uint256(BigInteger.TEN), + new Uint256(BigInteger.valueOf(Long.MAX_VALUE))))); + + assertThat( + TypeDecoder.decodeDynamicArray( + "0000000000000000000000000000000000000000000000000000000000000002" // length + + "000000000000000000000000000000000000000000000000000000000000000d" + + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000d" + + "776f726c64212048656c6c6f2c00000000000000000000000000000000000000", + 0, + new TypeReference>() {}), + equalTo( + new DynamicArray( + new Utf8String("Hello, world!"), new Utf8String("world! Hello,")))); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/TypeEncoderTest.java b/src/test/java/org/fisco/bcos/web3j/abi/TypeEncoderTest.java index d6f3507e7..1ed184e76 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/TypeEncoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/TypeEncoderTest.java @@ -1,45 +1,53 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; -import org.fisco.bcos.web3j.abi.datatypes.*; -import org.fisco.bcos.web3j.abi.datatypes.generated.*; - -import java.math.BigInteger; - import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.math.BigInteger; +import org.fisco.bcos.web3j.abi.datatypes.*; +import org.fisco.bcos.web3j.abi.datatypes.generated.*; +import org.junit.Test; public class TypeEncoderTest { @Test public void testBoolEncode() { - assertThat(TypeEncoder.encodeBool(new Bool(false)), + assertThat( + TypeEncoder.encodeBool(new Bool(false)), is("0000000000000000000000000000000000000000000000000000000000000000")); - assertThat(TypeEncoder.encodeBool(new Bool(true)), + assertThat( + TypeEncoder.encodeBool(new Bool(true)), is("0000000000000000000000000000000000000000000000000000000000000001")); } @Test public void testUintEncode() { Uint zero = new Uint64(BigInteger.ZERO); - assertThat(TypeEncoder.encodeNumeric(zero), + assertThat( + TypeEncoder.encodeNumeric(zero), is("0000000000000000000000000000000000000000000000000000000000000000")); Uint maxLong = new Uint64(BigInteger.valueOf(Long.MAX_VALUE)); - assertThat(TypeEncoder.encodeNumeric(maxLong), + assertThat( + TypeEncoder.encodeNumeric(maxLong), is("0000000000000000000000000000000000000000000000007fffffffffffffff")); - Uint maxValue = new Uint( - new BigInteger("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - 16)); - assertThat(TypeEncoder.encodeNumeric(maxValue), + Uint maxValue = + new Uint( + new BigInteger( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + 16)); + assertThat( + TypeEncoder.encodeNumeric(maxValue), is("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - Uint largeValue = new Uint( - new BigInteger("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - 16)); - assertThat(TypeEncoder.encodeNumeric(largeValue), + Uint largeValue = + new Uint( + new BigInteger( + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", + 16)); + assertThat( + TypeEncoder.encodeNumeric(largeValue), is("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")); } @@ -51,27 +59,31 @@ public void testInvalidUintEncode() { @Test(expected = UnsupportedOperationException.class) public void testTooLargeUintEncode() { // 1 more than "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - new Uint(new BigInteger("10000000000000000000000000000000000000000000000000000000000000000", - 16)); - + new Uint( + new BigInteger( + "10000000000000000000000000000000000000000000000000000000000000000", 16)); } @Test public void testIntEncode() { Int zero = new Int64(BigInteger.ZERO); - assertThat(TypeEncoder.encodeNumeric(zero), + assertThat( + TypeEncoder.encodeNumeric(zero), is("0000000000000000000000000000000000000000000000000000000000000000")); Int maxLong = new Int64(BigInteger.valueOf(Long.MAX_VALUE)); - assertThat(TypeEncoder.encodeNumeric(maxLong), + assertThat( + TypeEncoder.encodeNumeric(maxLong), is("0000000000000000000000000000000000000000000000007fffffffffffffff")); Int minLong = new Int64(BigInteger.valueOf(Long.MIN_VALUE)); - assertThat(TypeEncoder.encodeNumeric(minLong), + assertThat( + TypeEncoder.encodeNumeric(minLong), is("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")); Int minusOne = new Int(BigInteger.valueOf(-1)); - assertThat(TypeEncoder.encodeNumeric(minusOne), + assertThat( + TypeEncoder.encodeNumeric(minusOne), is("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); } @@ -118,105 +130,123 @@ public void testFixedEncode() { @Test public void testStaticBytes() { - Bytes staticBytes = new Bytes6(new byte[] { 0, 1, 2, 3, 4, 5 }); - assertThat(TypeEncoder.encodeBytes(staticBytes), + Bytes staticBytes = new Bytes6(new byte[] {0, 1, 2, 3, 4, 5}); + assertThat( + TypeEncoder.encodeBytes(staticBytes), is("0001020304050000000000000000000000000000000000000000000000000000")); - Bytes empty = new Bytes1(new byte[] { 0 }); - assertThat(TypeEncoder.encodeBytes(empty), + Bytes empty = new Bytes1(new byte[] {0}); + assertThat( + TypeEncoder.encodeBytes(empty), is("0000000000000000000000000000000000000000000000000000000000000000")); Bytes dave = new Bytes4("dave".getBytes()); - assertThat(TypeEncoder.encodeBytes(dave), + assertThat( + TypeEncoder.encodeBytes(dave), is("6461766500000000000000000000000000000000000000000000000000000000")); } @Test public void testDynamicBytes() { - DynamicBytes dynamicBytes = new DynamicBytes(new byte[] { 0, 1, 2, 3, 4, 5 }); - assertThat(TypeEncoder.encodeDynamicBytes(dynamicBytes), - is("0000000000000000000000000000000000000000000000000000000000000006" - + "0001020304050000000000000000000000000000000000000000000000000000")); + DynamicBytes dynamicBytes = new DynamicBytes(new byte[] {0, 1, 2, 3, 4, 5}); + assertThat( + TypeEncoder.encodeDynamicBytes(dynamicBytes), + is( + "0000000000000000000000000000000000000000000000000000000000000006" + + "0001020304050000000000000000000000000000000000000000000000000000")); - DynamicBytes empty = new DynamicBytes(new byte[] { 0 }); - assertThat(TypeEncoder.encodeDynamicBytes(empty), - is("0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000000")); + DynamicBytes empty = new DynamicBytes(new byte[] {0}); + assertThat( + TypeEncoder.encodeDynamicBytes(empty), + is( + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000000")); DynamicBytes dave = new DynamicBytes("dave".getBytes()); - assertThat(TypeEncoder.encodeDynamicBytes(dave), - is("0000000000000000000000000000000000000000000000000000000000000004" - + "6461766500000000000000000000000000000000000000000000000000000000")); - - DynamicBytes loremIpsum = new DynamicBytes( - ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " - + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " - + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex " - + "ea commodo consequat. Duis aute irure dolor in reprehenderit in " - + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur " - + "sint occaecat cupidatat non proident, sunt in culpa qui officia " - + "deserunt mollit anim id est laborum.").getBytes()); - assertThat(TypeEncoder.encodeDynamicBytes(loremIpsum), - is("00000000000000000000000000000000000000000000000000000000000001bd" - + "4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73" - + "656374657475722061646970697363696e6720656c69742c2073656420646f20" - + "656975736d6f642074656d706f7220696e6369646964756e74207574206c6162" - + "6f726520657420646f6c6f7265206d61676e6120616c697175612e2055742065" - + "6e696d206164206d696e696d2076656e69616d2c2071756973206e6f73747275" - + "6420657865726369746174696f6e20756c6c616d636f206c61626f726973206e" - + "69736920757420616c697175697020657820656120636f6d6d6f646f20636f6e" - + "7365717561742e2044756973206175746520697275726520646f6c6f7220696e" - + "20726570726568656e646572697420696e20766f6c7570746174652076656c69" - + "7420657373652063696c6c756d20646f6c6f726520657520667567696174206e" - + "756c6c612070617269617475722e204578636570746575722073696e74206f63" - + "63616563617420637570696461746174206e6f6e2070726f6964656e742c2073" - + "756e7420696e2063756c706120717569206f666669636961206465736572756e" - + "74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e000000")); + assertThat( + TypeEncoder.encodeDynamicBytes(dave), + is( + "0000000000000000000000000000000000000000000000000000000000000004" + + "6461766500000000000000000000000000000000000000000000000000000000")); + + DynamicBytes loremIpsum = + new DynamicBytes( + ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " + + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " + + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex " + + "ea commodo consequat. Duis aute irure dolor in reprehenderit in " + + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur " + + "sint occaecat cupidatat non proident, sunt in culpa qui officia " + + "deserunt mollit anim id est laborum.") + .getBytes()); + assertThat( + TypeEncoder.encodeDynamicBytes(loremIpsum), + is( + "00000000000000000000000000000000000000000000000000000000000001bd" + + "4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73" + + "656374657475722061646970697363696e6720656c69742c2073656420646f20" + + "656975736d6f642074656d706f7220696e6369646964756e74207574206c6162" + + "6f726520657420646f6c6f7265206d61676e6120616c697175612e2055742065" + + "6e696d206164206d696e696d2076656e69616d2c2071756973206e6f73747275" + + "6420657865726369746174696f6e20756c6c616d636f206c61626f726973206e" + + "69736920757420616c697175697020657820656120636f6d6d6f646f20636f6e" + + "7365717561742e2044756973206175746520697275726520646f6c6f7220696e" + + "20726570726568656e646572697420696e20766f6c7570746174652076656c69" + + "7420657373652063696c6c756d20646f6c6f726520657520667567696174206e" + + "756c6c612070617269617475722e204578636570746575722073696e74206f63" + + "63616563617420637570696461746174206e6f6e2070726f6964656e742c2073" + + "756e7420696e2063756c706120717569206f666669636961206465736572756e" + + "74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e000000")); } @Test public void testAddress() { Address address = new Address("0xbe5422d15f39373eb0a97ff8c10fbd0e40e29338"); assertThat(address.getTypeAsString(), is("address")); - assertThat(TypeEncoder.encodeAddress(address), + assertThat( + TypeEncoder.encodeAddress(address), is("000000000000000000000000be5422d15f39373eb0a97ff8c10fbd0e40e29338")); } @Test public void testUtf8String() { Utf8String string = new Utf8String("Hello, world!"); - assertThat(TypeEncoder.encodeString(string), - is("000000000000000000000000000000000000000000000000000000000000000d" - + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000")); + assertThat( + TypeEncoder.encodeString(string), + is( + "000000000000000000000000000000000000000000000000000000000000000d" + + "48656c6c6f2c20776f726c642100000000000000000000000000000000000000")); } @Test public void testFixedArray() { - StaticArray array = new StaticArray<>( - new Ufixed(BigInteger.valueOf(0x2), BigInteger.valueOf(0x2)), - new Ufixed(BigInteger.valueOf(0x8), BigInteger.valueOf(0x8)) - ); - - assertThat(TypeEncoder.encodeArrayValues(array), - is("0000000000000000000000000000000220000000000000000000000000000000" - + "0000000000000000000000000000000880000000000000000000000000000000")); + StaticArray array = + new StaticArray<>( + new Ufixed(BigInteger.valueOf(0x2), BigInteger.valueOf(0x2)), + new Ufixed(BigInteger.valueOf(0x8), BigInteger.valueOf(0x8))); + + assertThat( + TypeEncoder.encodeArrayValues(array), + is( + "0000000000000000000000000000000220000000000000000000000000000000" + + "0000000000000000000000000000000880000000000000000000000000000000")); } @Test public void testDynamicArray() { - DynamicArray array = new DynamicArray<>( - new Uint(BigInteger.ONE), - new Uint(BigInteger.valueOf(2)), - new Uint(BigInteger.valueOf(3)) - ); + DynamicArray array = + new DynamicArray<>( + new Uint(BigInteger.ONE), + new Uint(BigInteger.valueOf(2)), + new Uint(BigInteger.valueOf(3))); assertThat( TypeEncoder.encodeDynamicArray(array), - is("0000000000000000000000000000000000000000000000000000000000000003" - + "0000000000000000000000000000000000000000000000000000000000000001" - + "0000000000000000000000000000000000000000000000000000000000000002" - + "0000000000000000000000000000000000000000000000000000000000000003" - )); + is( + "0000000000000000000000000000000000000000000000000000000000000003" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000003")); } @Test @@ -225,7 +255,6 @@ public void testEmptyArray() { DynamicArray array = DynamicArray.empty("uint"); assertThat( TypeEncoder.encodeDynamicArray(array), - is("0000000000000000000000000000000000000000000000000000000000000000") - ); + is("0000000000000000000000000000000000000000000000000000000000000000")); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/UtilsTest.java b/src/test/java/org/fisco/bcos/web3j/abi/UtilsTest.java index 4ec4dc7bf..ce80515ee 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/UtilsTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/UtilsTest.java @@ -1,54 +1,55 @@ package org.fisco.bcos.web3j.abi; -import org.junit.Test; +import static org.fisco.bcos.web3j.abi.Utils.typeMap; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.fisco.bcos.web3j.abi.datatypes.*; import org.fisco.bcos.web3j.abi.datatypes.generated.Int64; import org.fisco.bcos.web3j.abi.datatypes.generated.StaticArray2; import org.fisco.bcos.web3j.abi.datatypes.generated.Uint256; import org.fisco.bcos.web3j.abi.datatypes.generated.Uint64; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.fisco.bcos.web3j.abi.Utils.typeMap; +import org.junit.Test; public class UtilsTest { @Test public void testGetTypeName() throws ClassNotFoundException { - assertThat(Utils.getTypeName(new TypeReference(){}), is("uint256")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("int256")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("ufixed256")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("fixed256")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("uint256")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("int256")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("ufixed256")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("fixed256")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("uint64")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("int64")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("bool")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("string")); - assertThat(Utils.getTypeName(new TypeReference(){}), is("bytes")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("uint64")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("int64")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("bool")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("string")); + assertThat(Utils.getTypeName(new TypeReference() {}), is("bytes")); - assertThat(Utils.getTypeName( - new TypeReference.StaticArrayTypeReference>(5){}), + assertThat( + Utils.getTypeName( + new TypeReference.StaticArrayTypeReference>(5) {}), is("uint256[5]")); - assertThat(Utils.getTypeName( - new TypeReference>(){}), - is("uint256[]")); + assertThat(Utils.getTypeName(new TypeReference>() {}), is("uint256[]")); } @Test public void testTypeMap() throws Exception { - final List input = Arrays.asList( - BigInteger.ZERO, BigInteger.ONE, BigInteger.TEN); + final List input = + Arrays.asList(BigInteger.ZERO, BigInteger.ONE, BigInteger.TEN); - assertThat(typeMap(input, Uint256.class), - equalTo(Arrays.asList( - new Uint256(BigInteger.ZERO), - new Uint256(BigInteger.ONE), - new Uint256(BigInteger.TEN)))); + assertThat( + typeMap(input, Uint256.class), + equalTo( + Arrays.asList( + new Uint256(BigInteger.ZERO), + new Uint256(BigInteger.ONE), + new Uint256(BigInteger.TEN)))); } @Test @@ -60,13 +61,13 @@ public void testTypeMapNested() { StaticArray2 staticArray1 = new StaticArray2<>(new Uint256(1), new Uint256(2)); StaticArray2 staticArray2 = new StaticArray2<>(new Uint256(3), new Uint256(4)); List> expectedList = Arrays.asList(staticArray1, staticArray2); - assertThat(typeMap(input, StaticArray2.class, Uint256.class), - equalTo(expectedList)); + assertThat(typeMap(input, StaticArray2.class, Uint256.class), equalTo(expectedList)); } @Test public void testTypeMapEmpty() { - assertThat(typeMap(new ArrayList(), Uint256.class), + assertThat( + typeMap(new ArrayList(), Uint256.class), equalTo(new ArrayList())); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/AddressTest.java b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/AddressTest.java index 86bfaf2ca..72d662d5e 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/AddressTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/AddressTest.java @@ -1,17 +1,19 @@ package org.fisco.bcos.web3j.abi.datatypes; -import org.junit.Test; - import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; +import org.junit.Test; + public class AddressTest { @Test public void testToString() { - assertThat(new Address("00052b08330e05d731e38c856c1043288f7d9744").toString(), + assertThat( + new Address("00052b08330e05d731e38c856c1043288f7d9744").toString(), is("0x00052b08330e05d731e38c856c1043288f7d9744")); - assertThat(new Address("0x00052b08330e05d731e38c856c1043288f7d9744").toString(), + assertThat( + new Address("0x00052b08330e05d731e38c856c1043288f7d9744").toString(), is("0x00052b08330e05d731e38c856c1043288f7d9744")); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointTypeTest.java b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointTypeTest.java index 34117e8fc..bc5094597 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointTypeTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/FixedPointTypeTest.java @@ -1,29 +1,25 @@ package org.fisco.bcos.web3j.abi.datatypes; -import org.junit.Test; - -import java.math.BigInteger; - import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.math.BigInteger; +import org.junit.Test; + public class FixedPointTypeTest { @Test public void testConvert() { assertThat( FixedPointType.convert(BigInteger.valueOf(0x2), BigInteger.valueOf(0x2)), - is(new BigInteger("220000000000000000000000000000000", 16)) - ); + is(new BigInteger("220000000000000000000000000000000", 16))); assertThat( FixedPointType.convert(BigInteger.valueOf(0x8), BigInteger.valueOf(0x8)), - is(new BigInteger("880000000000000000000000000000000", 16)) - ); + is(new BigInteger("880000000000000000000000000000000", 16))); assertThat( FixedPointType.convert(BigInteger.valueOf(0xAAFF), BigInteger.valueOf(0x1111)), - is(new BigInteger("AAFF11110000000000000000000000000000", 16)) - ); + is(new BigInteger("AAFF11110000000000000000000000000000", 16))); } } diff --git a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/StaticArrayTest.java b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/StaticArrayTest.java index 2aee627ce..6fe0e50fa 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/StaticArrayTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/StaticArrayTest.java @@ -1,15 +1,14 @@ package org.fisco.bcos.web3j.abi.datatypes; -import org.junit.Test; -import org.fisco.bcos.web3j.abi.datatypes.generated.StaticArray3; -import org.fisco.bcos.web3j.abi.datatypes.generated.Uint8; - -import java.util.stream.IntStream; - import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; +import java.util.stream.IntStream; +import org.fisco.bcos.web3j.abi.datatypes.generated.StaticArray3; +import org.fisco.bcos.web3j.abi.datatypes.generated.Uint8; +import org.junit.Test; + public class StaticArrayTest { @Test @@ -32,23 +31,24 @@ public void throwsIfSizeDoesntMatchType() { new StaticArray3<>(arrayOfUints(4)); fail(); } catch (UnsupportedOperationException e) { - assertThat(e.getMessage(), equalTo( - "Expected array of type [StaticArray3] to have [3] elements.")); + assertThat( + e.getMessage(), + equalTo("Expected array of type [StaticArray3] to have [3] elements.")); } } @Test public void throwsIfSizeIsAboveMaxOf32() { try { - new StaticArray<>(arrayOfUints(33)); - fail(); + new StaticArray<>(arrayOfUints(1025)); } catch (UnsupportedOperationException e) { - assertThat(e.getMessage(), equalTo( - "Static arrays with a length greater than 32 are not supported.")); + assertThat( + e.getMessage(), + equalTo("Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256")); } } private Uint[] arrayOfUints(int length) { return IntStream.rangeClosed(1, length).mapToObj(Uint8::new).toArray(Uint[]::new); } -} \ No newline at end of file +} diff --git a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/Utf8StringTest.java b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/Utf8StringTest.java index daf061a65..41c8993fa 100644 --- a/src/test/java/org/fisco/bcos/web3j/abi/datatypes/Utf8StringTest.java +++ b/src/test/java/org/fisco/bcos/web3j/abi/datatypes/Utf8StringTest.java @@ -1,10 +1,10 @@ package org.fisco.bcos.web3j.abi.datatypes; -import org.junit.Test; - import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; +import org.junit.Test; + public class Utf8StringTest { @Test diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/ECKeyTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/ECKeyTest.java index 49398e558..8ccc2b751 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/ECKeyTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/ECKeyTest.java @@ -7,26 +7,26 @@ /** Created by mingzhenliu on 2017/7/12. */ public class ECKeyTest { - @Test - public void eckeyTest() throws Exception { + @Test + public void eckeyTest() throws Exception { - ECKeyPair keyPair = Keys.createEcKeyPair(); - System.out.println("public key " + keyPair.getPublicKey()); - System.out.println("private key " + keyPair.getPrivateKey()); - System.out.println("serialize key " + Hex.toHexString(Keys.serialize(keyPair))); - // public key - // 6005884739482598907019672016029935954035758996027051146272921018865015941269698926222431345309233458526942087465818124661687956402067203118790805113144306 - // private key 11695290896330592173013668505941497555094145434653626165899956696676058923570 - // serialize key - keyPair = - Keys.deserialize( - Hex.decode( - "19db4cd14479981c3d7e785ec2412619885b5a7ffc438e6801474b962996023272ac27315da55056067973a3b58b27385bb9c919331df1751771016efcbe61a969458d6f7286b7a7107e4cd6e17b348c9df6c2b3fe9bf239555f90a78f8603f2")); - System.out.println("public key " + keyPair.getPublicKey()); - System.out.println("private key " + Hex.toHexString(keyPair.getPrivateKey().toByteArray())); - String str = "hello world"; - Sign.SignatureData sigData = Sign.getSignInterface().signMessage(str.getBytes(), keyPair); - BigInteger publicKey = Sign.signedMessageToKey(str.getBytes(), sigData); - System.out.println("publicKey " + publicKey); - } + ECKeyPair keyPair = Keys.createEcKeyPair(); + System.out.println("public key " + keyPair.getPublicKey()); + System.out.println("private key " + keyPair.getPrivateKey()); + System.out.println("serialize key " + Hex.toHexString(Keys.serialize(keyPair))); + // public key + // 6005884739482598907019672016029935954035758996027051146272921018865015941269698926222431345309233458526942087465818124661687956402067203118790805113144306 + // private key 11695290896330592173013668505941497555094145434653626165899956696676058923570 + // serialize key + keyPair = + Keys.deserialize( + Hex.decode( + "19db4cd14479981c3d7e785ec2412619885b5a7ffc438e6801474b962996023272ac27315da55056067973a3b58b27385bb9c919331df1751771016efcbe61a969458d6f7286b7a7107e4cd6e17b348c9df6c2b3fe9bf239555f90a78f8603f2")); + System.out.println("public key " + keyPair.getPublicKey()); + System.out.println("private key " + Hex.toHexString(keyPair.getPrivateKey().toByteArray())); + String str = "hello world"; + Sign.SignatureData sigData = Sign.getSignInterface().signMessage(str.getBytes(), keyPair); + BigInteger publicKey = Sign.signedMessageToKey(str.getBytes(), sigData); + System.out.println("publicKey " + publicKey); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/ECRecoverTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/ECRecoverTest.java index d4201ca04..98592bca0 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/ECRecoverTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/ECRecoverTest.java @@ -12,54 +12,55 @@ public class ECRecoverTest { - public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; + public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; - @Test - public void testRecoverAddressFromSignature() { - // CHECKSTYLE:OFF - String signature = - "0x2c6401216c9031b9a6fb8cbfccab4fcec6c951cdf40e2320108d1856eb532250576865fbcd452bcdc4c57321b619ed7a9cfd38bd973c3e1e0243ac2777fe9d5b1b"; - // CHECKSTYLE:ON - String address = "0x31b26e43651e9371c88af3d36c14cfd938baf4fd"; - String message = "v0G9u7huK4mJb2K1"; + @Test + public void testRecoverAddressFromSignature() { + // CHECKSTYLE:OFF + String signature = + "0x2c6401216c9031b9a6fb8cbfccab4fcec6c951cdf40e2320108d1856eb532250576865fbcd452bcdc4c57321b619ed7a9cfd38bd973c3e1e0243ac2777fe9d5b1b"; + // CHECKSTYLE:ON + String address = "0x31b26e43651e9371c88af3d36c14cfd938baf4fd"; + String message = "v0G9u7huK4mJb2K1"; - String prefix = PERSONAL_MESSAGE_PREFIX + message.length(); - byte[] msgHash = Hash.sha3((prefix + message).getBytes()); + String prefix = PERSONAL_MESSAGE_PREFIX + message.length(); + byte[] msgHash = Hash.sha3((prefix + message).getBytes()); - byte[] signatureBytes = Numeric.hexStringToByteArray(signature); - byte v = signatureBytes[64]; - if (v < 27) { - v += 27; - } + byte[] signatureBytes = Numeric.hexStringToByteArray(signature); + byte v = signatureBytes[64]; + if (v < 27) { + v += 27; + } - SignatureData sd = - new SignatureData( - v, - (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32), - (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64)); + SignatureData sd = + new SignatureData( + v, + (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32), + (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64)); - String addressRecovered = null; - boolean match = false; + String addressRecovered = null; + boolean match = false; - // Iterate for each possible key to recover - for (int i = 0; i < 4; i++) { - BigInteger publicKey = - Sign.recoverFromSignature( - (byte) i, - new ECDSASignature(new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())), - msgHash); + // Iterate for each possible key to recover + for (int i = 0; i < 4; i++) { + BigInteger publicKey = + Sign.recoverFromSignature( + (byte) i, + new ECDSASignature( + new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())), + msgHash); - if (publicKey != null) { - addressRecovered = "0x" + Keys.getAddress(publicKey); + if (publicKey != null) { + addressRecovered = "0x" + Keys.getAddress(publicKey); - if (addressRecovered.equals(address)) { - match = true; - break; + if (addressRecovered.equals(address)) { + match = true; + break; + } + } } - } - } - assertThat(addressRecovered, is(address)); - assertTrue(match); - } + assertThat(addressRecovered, is(address)); + assertTrue(match); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/KeysTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/KeysTest.java index 976ffa74a..79706edd5 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/KeysTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/KeysTest.java @@ -16,126 +16,130 @@ public class KeysTest { - private static final byte[] ENCODED; - - static { - byte[] privateKey = Numeric.hexStringToByteArray(SampleKeys.PRIVATE_KEY_STRING); - byte[] publicKey = Numeric.hexStringToByteArray(SampleKeys.PUBLIC_KEY_STRING); - ENCODED = Arrays.copyOf(privateKey, privateKey.length + publicKey.length); - System.arraycopy(publicKey, 0, ENCODED, privateKey.length, publicKey.length); - } - - @Test - public void testCreateSecp256k1KeyPair() throws Exception { - KeyPair keyPair = Keys.createSecp256k1KeyPair(); - PrivateKey privateKey = keyPair.getPrivate(); - PublicKey publicKey = keyPair.getPublic(); - - assertNotNull(privateKey); - assertNotNull(publicKey); - - assertThat(privateKey.getEncoded().length, is(144)); - assertThat(publicKey.getEncoded().length, is(88)); - } - - @Test - public void testCreateEcKeyPair() throws Exception { - ECKeyPair ecKeyPair = Keys.createEcKeyPair(); - assertThat(ecKeyPair.getPublicKey().signum(), is(1)); - assertThat(ecKeyPair.getPrivateKey().signum(), is(1)); - } - - @Test - public void testGetAddressString() { - assertThat(Keys.getAddress(SampleKeys.PUBLIC_KEY_STRING), is(SampleKeys.ADDRESS_NO_PREFIX)); - } - - @Test - public void testGetAddressZeroPaddedAddress() { - String publicKey = - "0xa1b31be4d58a7ddd24b135db0da56a90fb5382077ae26b250e1dc9cd6232ce22" - + "70f4c995428bc76aa78e522316e95d7834d725efc9ca754d043233af6ca90113"; - assertThat(Keys.getAddress(publicKey), is("01c52b08330e05d731e38c856c1043288f7d9744")); - } - - @Test - public void testGetAddressBigInteger() { - assertThat(Keys.getAddress(SampleKeys.PUBLIC_KEY), is(SampleKeys.ADDRESS_NO_PREFIX)); - } - - @Test - public void testGetAddressSmallPublicKey() { - byte[] address = - Keys.getAddress(Numeric.toBytesPadded(BigInteger.valueOf(0x1234), Keys.PUBLIC_KEY_SIZE)); - String expected = Numeric.toHexStringNoPrefix(address); - - assertThat(Keys.getAddress("0x1234"), equalTo(expected)); - } - - @Test - public void testGetAddressZeroPadded() { - byte[] address = - Keys.getAddress(Numeric.toBytesPadded(BigInteger.valueOf(0x1234), Keys.PUBLIC_KEY_SIZE)); - String expected = Numeric.toHexStringNoPrefix(address); - - String value = "1234"; - assertThat( - Keys.getAddress( - "0x" + Strings.zeros(Keys.PUBLIC_KEY_LENGTH_IN_HEX - value.length()) + value), - equalTo(expected)); - } - - @Test - public void testToChecksumAddress() { - // Test cases as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#test-cases - - assertThat( - Keys.toChecksumAddress("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359"), - is("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")); - - // All uppercase - assertThat( - Keys.toChecksumAddress("0x52908400098527886E0F7030069857D2E4169EE7"), - is("0x52908400098527886E0F7030069857D2E4169EE7")); - assertThat( - Keys.toChecksumAddress("0x8617E340B3D01FA5F11F306F4090FD50E238070D"), - is("0x8617E340B3D01FA5F11F306F4090FD50E238070D")); - - // All lowercase - assertThat( - Keys.toChecksumAddress("0xde709f2102306220921060314715629080e2fb77"), - is("0xde709f2102306220921060314715629080e2fb77")); - assertThat( - Keys.toChecksumAddress("0x27b1fdb04752bbc536007a920d24acb045561c26"), - is("0x27b1fdb04752bbc536007a920d24acb045561c26")); - - // Normal - assertThat( - Keys.toChecksumAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), - is("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")); - assertThat( - Keys.toChecksumAddress("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"), - is("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")); - assertThat( - Keys.toChecksumAddress("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"), - is("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB")); - assertThat( - Keys.toChecksumAddress("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"), - is("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb")); - } - - @Test - public void testSerializeECKey() { - assertThat(Keys.serialize(SampleKeys.KEY_PAIR), is(ENCODED)); - } - - @Test - public void testDeserializeECKey() { - assertThat(Keys.deserialize(ENCODED), is(SampleKeys.KEY_PAIR)); - } - - @Test(expected = RuntimeException.class) - public void testDeserializeInvalidKey() { - Keys.deserialize(new byte[0]); - } + private static final byte[] ENCODED; + + static { + byte[] privateKey = Numeric.hexStringToByteArray(SampleKeys.PRIVATE_KEY_STRING); + byte[] publicKey = Numeric.hexStringToByteArray(SampleKeys.PUBLIC_KEY_STRING); + ENCODED = Arrays.copyOf(privateKey, privateKey.length + publicKey.length); + System.arraycopy(publicKey, 0, ENCODED, privateKey.length, publicKey.length); + } + + @Test + public void testCreateSecp256k1KeyPair() throws Exception { + KeyPair keyPair = Keys.createSecp256k1KeyPair(); + PrivateKey privateKey = keyPair.getPrivate(); + PublicKey publicKey = keyPair.getPublic(); + + assertNotNull(privateKey); + assertNotNull(publicKey); + + assertThat(privateKey.getEncoded().length, is(144)); + assertThat(publicKey.getEncoded().length, is(88)); + } + + @Test + public void testCreateEcKeyPair() throws Exception { + ECKeyPair ecKeyPair = Keys.createEcKeyPair(); + assertThat(ecKeyPair.getPublicKey().signum(), is(1)); + assertThat(ecKeyPair.getPrivateKey().signum(), is(1)); + } + + @Test + public void testGetAddressString() { + assertThat(Keys.getAddress(SampleKeys.PUBLIC_KEY_STRING), is(SampleKeys.ADDRESS_NO_PREFIX)); + } + + @Test + public void testGetAddressZeroPaddedAddress() { + String publicKey = + "0xa1b31be4d58a7ddd24b135db0da56a90fb5382077ae26b250e1dc9cd6232ce22" + + "70f4c995428bc76aa78e522316e95d7834d725efc9ca754d043233af6ca90113"; + assertThat(Keys.getAddress(publicKey), is("01c52b08330e05d731e38c856c1043288f7d9744")); + } + + @Test + public void testGetAddressBigInteger() { + assertThat(Keys.getAddress(SampleKeys.PUBLIC_KEY), is(SampleKeys.ADDRESS_NO_PREFIX)); + } + + @Test + public void testGetAddressSmallPublicKey() { + byte[] address = + Keys.getAddress( + Numeric.toBytesPadded(BigInteger.valueOf(0x1234), Keys.PUBLIC_KEY_SIZE)); + String expected = Numeric.toHexStringNoPrefix(address); + + assertThat(Keys.getAddress("0x1234"), equalTo(expected)); + } + + @Test + public void testGetAddressZeroPadded() { + byte[] address = + Keys.getAddress( + Numeric.toBytesPadded(BigInteger.valueOf(0x1234), Keys.PUBLIC_KEY_SIZE)); + String expected = Numeric.toHexStringNoPrefix(address); + + String value = "1234"; + assertThat( + Keys.getAddress( + "0x" + + Strings.zeros(Keys.PUBLIC_KEY_LENGTH_IN_HEX - value.length()) + + value), + equalTo(expected)); + } + + @Test + public void testToChecksumAddress() { + // Test cases as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#test-cases + + assertThat( + Keys.toChecksumAddress("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359"), + is("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")); + + // All uppercase + assertThat( + Keys.toChecksumAddress("0x52908400098527886E0F7030069857D2E4169EE7"), + is("0x52908400098527886E0F7030069857D2E4169EE7")); + assertThat( + Keys.toChecksumAddress("0x8617E340B3D01FA5F11F306F4090FD50E238070D"), + is("0x8617E340B3D01FA5F11F306F4090FD50E238070D")); + + // All lowercase + assertThat( + Keys.toChecksumAddress("0xde709f2102306220921060314715629080e2fb77"), + is("0xde709f2102306220921060314715629080e2fb77")); + assertThat( + Keys.toChecksumAddress("0x27b1fdb04752bbc536007a920d24acb045561c26"), + is("0x27b1fdb04752bbc536007a920d24acb045561c26")); + + // Normal + assertThat( + Keys.toChecksumAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), + is("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")); + assertThat( + Keys.toChecksumAddress("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"), + is("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")); + assertThat( + Keys.toChecksumAddress("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"), + is("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB")); + assertThat( + Keys.toChecksumAddress("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"), + is("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb")); + } + + @Test + public void testSerializeECKey() { + assertThat(Keys.serialize(SampleKeys.KEY_PAIR), is(ENCODED)); + } + + @Test + public void testDeserializeECKey() { + assertThat(Keys.deserialize(ENCODED), is(SampleKeys.KEY_PAIR)); + } + + @Test(expected = RuntimeException.class) + public void testDeserializeInvalidKey() { + Keys.deserialize(new byte[0]); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/SampleKeys.java b/src/test/java/org/fisco/bcos/web3j/crypto/SampleKeys.java index 7fe17c350..69d94eba8 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/SampleKeys.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/SampleKeys.java @@ -6,22 +6,22 @@ /** Keys generated for unit testing purposes. */ public class SampleKeys { - public static final String PRIVATE_KEY_STRING = - "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"; - static final String PUBLIC_KEY_STRING = - "0x506bc1dc099358e5137292f4efdd57e400f29ba5132aa5d12b18dac1c1f6aab" - + "a645c0b7b58158babbfa6c6cd5a48aa7340a8749176b120e8516216787a13dc76"; - public static final String ADDRESS = "0xef678007d18427e6022059dbc264f27507cd1ffc"; - public static final String ADDRESS_NO_PREFIX = Numeric.cleanHexPrefix(ADDRESS); + public static final String PRIVATE_KEY_STRING = + "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"; + static final String PUBLIC_KEY_STRING = + "0x506bc1dc099358e5137292f4efdd57e400f29ba5132aa5d12b18dac1c1f6aab" + + "a645c0b7b58158babbfa6c6cd5a48aa7340a8749176b120e8516216787a13dc76"; + public static final String ADDRESS = "0xef678007d18427e6022059dbc264f27507cd1ffc"; + public static final String ADDRESS_NO_PREFIX = Numeric.cleanHexPrefix(ADDRESS); - public static final String PASSWORD = "Insecure Pa55w0rd"; + public static final String PASSWORD = "Insecure Pa55w0rd"; - static final BigInteger PRIVATE_KEY = Numeric.toBigInt(PRIVATE_KEY_STRING); - static final BigInteger PUBLIC_KEY = Numeric.toBigInt(PUBLIC_KEY_STRING); + static final BigInteger PRIVATE_KEY = Numeric.toBigInt(PRIVATE_KEY_STRING); + static final BigInteger PUBLIC_KEY = Numeric.toBigInt(PUBLIC_KEY_STRING); - static final ECKeyPair KEY_PAIR = new ECKeyPair(PRIVATE_KEY, PUBLIC_KEY); + static final ECKeyPair KEY_PAIR = new ECKeyPair(PRIVATE_KEY, PUBLIC_KEY); - public static final Credentials CREDENTIALS = Credentials.create(KEY_PAIR); + public static final Credentials CREDENTIALS = Credentials.create(KEY_PAIR); - private SampleKeys() {} + private SampleKeys() {} } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/SignTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/SignTest.java index 792a7ddbd..3a96fcc8f 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/SignTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/SignTest.java @@ -9,46 +9,47 @@ public class SignTest { - private static final byte[] TEST_MESSAGE = "A test message".getBytes(); - - // @Test - // public void testSignMessage() { - // Sign.SignatureData signatureData = Sign.signPrefixedMessage(TEST_MESSAGE, - // SampleKeys.KEY_PAIR); - // - // Sign.SignatureData expected = new Sign.SignatureData( - // (byte) 28, - // Numeric.hexStringToByteArray( - // "0x0464eee9e2fe1a10ffe48c78b80de1ed8dcf996f3f60955cb2e03cb21903d930"), - // Numeric.hexStringToByteArray( - // "0x06624da478b3f862582e85b31c6a21c6cae2eee2bd50f55c93c4faad9d9c8d7f") - // ); - // - // assertThat(signatureData, is(expected)); - // } - - // @Test - // public void testSignedMessageToKey() throws SignatureException { - // Sign.SignatureData signatureData = Sign.signPrefixedMessage(TEST_MESSAGE, - // SampleKeys.KEY_PAIR); - // BigInteger key = Sign.signedPrefixedMessageToKey(TEST_MESSAGE, signatureData); - // assertThat(key, equalTo(SampleKeys.PUBLIC_KEY)); - // } - - @Test - public void testPublicKeyFromPrivateKey() { - assertThat(Sign.publicKeyFromPrivate(SampleKeys.PRIVATE_KEY), equalTo(SampleKeys.PUBLIC_KEY)); - } - - @Test(expected = RuntimeException.class) - public void testInvalidSignature() throws SignatureException { - Sign.signedMessageToKey( - TEST_MESSAGE, new Sign.SignatureData((byte) 27, new byte[] {1}, new byte[] {0})); - } - - @Test - public void testPublicKeyFromPrivatePoint() { - ECPoint point = Sign.publicPointFromPrivate(SampleKeys.PRIVATE_KEY); - assertThat(Sign.publicFromPoint(point.getEncoded(false)), equalTo(SampleKeys.PUBLIC_KEY)); - } + private static final byte[] TEST_MESSAGE = "A test message".getBytes(); + + // @Test + // public void testSignMessage() { + // Sign.SignatureData signatureData = Sign.signPrefixedMessage(TEST_MESSAGE, + // SampleKeys.KEY_PAIR); + // + // Sign.SignatureData expected = new Sign.SignatureData( + // (byte) 28, + // Numeric.hexStringToByteArray( + // "0x0464eee9e2fe1a10ffe48c78b80de1ed8dcf996f3f60955cb2e03cb21903d930"), + // Numeric.hexStringToByteArray( + // "0x06624da478b3f862582e85b31c6a21c6cae2eee2bd50f55c93c4faad9d9c8d7f") + // ); + // + // assertThat(signatureData, is(expected)); + // } + + // @Test + // public void testSignedMessageToKey() throws SignatureException { + // Sign.SignatureData signatureData = Sign.signPrefixedMessage(TEST_MESSAGE, + // SampleKeys.KEY_PAIR); + // BigInteger key = Sign.signedPrefixedMessageToKey(TEST_MESSAGE, signatureData); + // assertThat(key, equalTo(SampleKeys.PUBLIC_KEY)); + // } + + @Test + public void testPublicKeyFromPrivateKey() { + assertThat( + Sign.publicKeyFromPrivate(SampleKeys.PRIVATE_KEY), equalTo(SampleKeys.PUBLIC_KEY)); + } + + @Test(expected = RuntimeException.class) + public void testInvalidSignature() throws SignatureException { + Sign.signedMessageToKey( + TEST_MESSAGE, new Sign.SignatureData((byte) 27, new byte[] {1}, new byte[] {0})); + } + + @Test + public void testPublicKeyFromPrivatePoint() { + ECPoint point = Sign.publicPointFromPrivate(SampleKeys.PRIVATE_KEY); + assertThat(Sign.publicFromPoint(point.getEncoded(false)), equalTo(SampleKeys.PUBLIC_KEY)); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionDecoderTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionDecoderTest.java index 0411dcff4..3247d05a1 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionDecoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionDecoderTest.java @@ -9,72 +9,74 @@ public class TransactionDecoderTest { - @Test - public void testDecoding() throws Exception { - BigInteger gasPrice = BigInteger.ONE; - BigInteger gasLimit = BigInteger.TEN; - String to = "0x0add5355"; - BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); - BigInteger randomid = new BigInteger("500"); - BigInteger blockLimit = new BigInteger("501"); - RawTransaction rawTransaction = - RawTransaction.createContractTransaction( - randomid, gasPrice, gasLimit, blockLimit, value, "0x0000000000"); - byte[] encodedMessage = TransactionEncoder.encode(rawTransaction); - String hexMessage = Numeric.toHexString(encodedMessage); + @Test + public void testDecoding() throws Exception { + BigInteger gasPrice = BigInteger.ONE; + BigInteger gasLimit = BigInteger.TEN; + String to = "0x0add5355"; + BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); + BigInteger randomid = new BigInteger("500"); + BigInteger blockLimit = new BigInteger("501"); + RawTransaction rawTransaction = + RawTransaction.createContractTransaction( + randomid, gasPrice, gasLimit, blockLimit, value, "0x0000000000"); + byte[] encodedMessage = TransactionEncoder.encode(rawTransaction); + String hexMessage = Numeric.toHexString(encodedMessage); - RawTransaction result = TransactionDecoder.decode(hexMessage); - assertNotNull(result); - assertEquals(blockLimit, result.getBlockLimit()); - assertEquals(gasPrice, result.getGasPrice()); - assertEquals(gasLimit, result.getGasLimit()); - assertEquals("0x", result.getTo()); - assertEquals(value, result.getValue()); - assertEquals("0000000000", result.getData()); - } + RawTransaction result = TransactionDecoder.decode(hexMessage); + assertNotNull(result); + assertEquals(blockLimit, result.getBlockLimit()); + assertEquals(gasPrice, result.getGasPrice()); + assertEquals(gasLimit, result.getGasLimit()); + assertEquals("0x", result.getTo()); + assertEquals(value, result.getValue()); + assertEquals("0000000000", result.getData()); + } - @Test - public void testDecodingSigned() throws Exception { - BigInteger gasPrice = BigInteger.ONE; - BigInteger gasLimit = BigInteger.TEN; - String to = "0x0add5355"; - BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); - BigInteger randomid = new BigInteger("500"); - BigInteger blockLimit = new BigInteger("501"); - RawTransaction rawTransaction = - RawTransaction.createEtherTransaction(randomid, gasPrice, gasLimit, blockLimit, to, value); - byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, SampleKeys.CREDENTIALS); - String hexMessage = Numeric.toHexString(signedMessage); + @Test + public void testDecodingSigned() throws Exception { + BigInteger gasPrice = BigInteger.ONE; + BigInteger gasLimit = BigInteger.TEN; + String to = "0x0add5355"; + BigInteger value = BigInteger.valueOf(Long.MAX_VALUE); + BigInteger randomid = new BigInteger("500"); + BigInteger blockLimit = new BigInteger("501"); + RawTransaction rawTransaction = + RawTransaction.createEtherTransaction( + randomid, gasPrice, gasLimit, blockLimit, to, value); + byte[] signedMessage = + TransactionEncoder.signMessage(rawTransaction, SampleKeys.CREDENTIALS); + String hexMessage = Numeric.toHexString(signedMessage); - RawTransaction result = TransactionDecoder.decode(hexMessage); - assertNotNull(result); - assertEquals(randomid, result.getRandomid()); - assertEquals(gasPrice, result.getGasPrice()); - assertEquals(gasLimit, result.getGasLimit()); - assertEquals(to, result.getTo()); - assertEquals(value, result.getValue()); - assertEquals("", result.getData()); - assertTrue(result instanceof SignedRawTransaction); - SignedRawTransaction signedResult = (SignedRawTransaction) result; - assertNotNull(signedResult.getSignatureData()); - Sign.SignatureData signatureData = signedResult.getSignatureData(); - byte[] encodedTransaction = TransactionEncoder.encode(rawTransaction); - BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureData); - assertEquals(key, SampleKeys.PUBLIC_KEY); - assertEquals(SampleKeys.ADDRESS, signedResult.getFrom()); - signedResult.verify(SampleKeys.ADDRESS); - assertNull(signedResult.getChainId()); - } + RawTransaction result = TransactionDecoder.decode(hexMessage); + assertNotNull(result); + assertEquals(randomid, result.getRandomid()); + assertEquals(gasPrice, result.getGasPrice()); + assertEquals(gasLimit, result.getGasLimit()); + assertEquals(to, result.getTo()); + assertEquals(value, result.getValue()); + assertEquals("", result.getData()); + assertTrue(result instanceof SignedRawTransaction); + SignedRawTransaction signedResult = (SignedRawTransaction) result; + assertNotNull(signedResult.getSignatureData()); + Sign.SignatureData signatureData = signedResult.getSignatureData(); + byte[] encodedTransaction = TransactionEncoder.encode(rawTransaction); + BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureData); + assertEquals(key, SampleKeys.PUBLIC_KEY); + assertEquals(SampleKeys.ADDRESS, signedResult.getFrom()); + signedResult.verify(SampleKeys.ADDRESS); + assertNull(signedResult.getChainId()); + } - @Ignore - @Test - public void testRSize31() throws Exception { - // CHECKSTYLE:OFF - String hexTransaction = - "0xf883370183419ce09433c98f20dd73d7bb1d533c4aa3371f2b30c6ebde80a45093dc7d00000000000000000000000000000000000000000000000000000000000000351c9fb90996c836fb34b782ee3d6efa9e2c79a75b277c014e353b51b23b00524d2da07435ebebca627a51a863bf590aff911c4746ab8386a0477c8221bb89671a5d58"; - // CHECKSTYLE:ON - RawTransaction result = TransactionDecoder.decode(hexTransaction); - SignedRawTransaction signedResult = (SignedRawTransaction) result; - assertEquals("0x1b609b03e2e9b0275a61fa5c69a8f32550285536", signedResult.getFrom()); - } + @Ignore + @Test + public void testRSize31() throws Exception { + // CHECKSTYLE:OFF + String hexTransaction = + "0xf883370183419ce09433c98f20dd73d7bb1d533c4aa3371f2b30c6ebde80a45093dc7d00000000000000000000000000000000000000000000000000000000000000351c9fb90996c836fb34b782ee3d6efa9e2c79a75b277c014e353b51b23b00524d2da07435ebebca627a51a863bf590aff911c4746ab8386a0477c8221bb89671a5d58"; + // CHECKSTYLE:ON + RawTransaction result = TransactionDecoder.decode(hexTransaction); + SignedRawTransaction signedResult = (SignedRawTransaction) result; + assertEquals("0x1b609b03e2e9b0275a61fa5c69a8f32550285536", signedResult.getFrom()); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionEncoderTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionEncoderTest.java index 7f6234bcc..f09ade1a2 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionEncoderTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionEncoderTest.java @@ -13,99 +13,109 @@ public class TransactionEncoderTest { - static BigInteger gasPrice = BigInteger.ONE; - static BigInteger gasLimit = BigInteger.TEN; - - @Test - public void testSignMessage() { - byte[] signedMessage = - TransactionEncoder.signMessage(createEtherTransaction(), SampleKeys.CREDENTIALS); - String hexMessage = Numeric.toHexString(signedMessage); - assertThat( - hexMessage, - is( - "0xf85a8201f4010a8201f5840add5355887fffffffffffffff801ba01cf44d4680e1ecaf11a9a997b08055ae84c5d417b1fc7c2bdbaffc3fd4a7659aa07a424ef2ad019c599a24309c97f4cd10d0e4293a51d8c1abb095052bf54a7ba7")); - } - - @Ignore - @Test - public void testGMSignMessage() { - EncryptType encryptType = new EncryptType(1); - - Credentials credentials = - GenCredential.create("a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); - System.out.println(credentials.getEcKeyPair().getPublicKey().toString(16)); - - Credentials credentials1 = - Credentials.create("a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); - System.out.println(credentials1.getEcKeyPair().getPublicKey().toString(16)); - - byte[] signedMessage = TransactionEncoder.signMessage(createContractTransaction(), credentials); - String hexMessage = Numeric.toHexString(signedMessage); - assertThat( - hexMessage, - is( - "0xf8948201f4010a8201f5800a850000000000b8408234c544a9f3ce3b401a92cc7175602ce2a1e29b1ec135381c7d2a9e8f78f3edc9c06ee55252857c9a4560cb39e9d70d40f4331cace4d2b3121b967fa7a829f0a03d8627050f6688f27e2b5b89c9c141d3a48603029849e088486d1c7ea079ea7fa037024ed35d2c099d7eb68fb133e57735b03605ec32ded39ab305c3b56e5d99e7")); - } - - @Test - public void testEtherTransactionAsRlpValues() { - List rlpStrings = - TransactionEncoder.asRlpValues( - createEtherTransaction(), new Sign.SignatureData((byte) 0, new byte[32], new byte[32])); - assertThat(rlpStrings.size(), is(10)); - // assertThat(rlpStrings.get(3), equalTo(RlpString.create(new BigInteger("10")))); - } - - @Test - public void testContractAsRlpValues() { - List rlpStrings = TransactionEncoder.asRlpValues(createContractTransaction(), null); - assertThat(rlpStrings.size(), is(7)); - // assertThat(rlpStrings.get(3), is(RlpString.create(""))); - } - - // @Test - // public void testEip155Encode() { - // assertThat(TransactionEncoder.encode(createEip155RawTransaction(), (byte) 1), - // is(Numeric.hexStringToByteArray( - // - // "0xec098504a817c800825208943535353535353535353535353535353535353535880de0" - // + "b6b3a764000080018080"))); - // } - // - // @Test - // public void testEip155Transaction() { - // // https://github.com/ethereum/EIPs/issues/155 - // Credentials credentials = Credentials.create( - // "0x4646464646464646464646464646464646464646464646464646464646464646"); - // - // assertThat(TransactionEncoder.signMessage( - // createEip155RawTransaction(), (byte) 1, credentials), - // is(Numeric.hexStringToByteArray( - // - // "0xf86c098504a817c800825208943535353535353535353535353535353535353535880" - // + - // "de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d" - // + - // "3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf55" - // + "5c9f3dc64214b297fb1966a3b6d83"))); - // } - - private static RawTransaction createEtherTransaction() { - - BigInteger randomid = new BigInteger("500"); - BigInteger blockLimit = new BigInteger("501"); - - return RawTransaction.createEtherTransaction( - randomid, gasPrice, gasLimit, blockLimit, "0xadd5355", BigInteger.valueOf(Long.MAX_VALUE)); - } - - static RawTransaction createContractTransaction() { - - BigInteger randomid = new BigInteger("500"); - BigInteger blockLimit = new BigInteger("501"); - - return RawTransaction.createContractTransaction( - randomid, gasPrice, gasLimit, blockLimit, BigInteger.TEN, "0x0000000000"); - } + static BigInteger gasPrice = BigInteger.ONE; + static BigInteger gasLimit = BigInteger.TEN; + + @Test + public void testSignMessage() { + byte[] signedMessage = + TransactionEncoder.signMessage(createEtherTransaction(), SampleKeys.CREDENTIALS); + String hexMessage = Numeric.toHexString(signedMessage); + assertThat( + hexMessage, + is( + "0xf85a8201f4010a8201f5840add5355887fffffffffffffff801ba01cf44d4680e1ecaf11a9a997b08055ae84c5d417b1fc7c2bdbaffc3fd4a7659aa07a424ef2ad019c599a24309c97f4cd10d0e4293a51d8c1abb095052bf54a7ba7")); + } + + @Ignore + @Test + public void testGMSignMessage() { + EncryptType encryptType = new EncryptType(1); + + Credentials credentials = + GenCredential.create( + "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); + System.out.println(credentials.getEcKeyPair().getPublicKey().toString(16)); + + Credentials credentials1 = + Credentials.create( + "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"); + System.out.println(credentials1.getEcKeyPair().getPublicKey().toString(16)); + + byte[] signedMessage = + TransactionEncoder.signMessage(createContractTransaction(), credentials); + String hexMessage = Numeric.toHexString(signedMessage); + assertThat( + hexMessage, + is( + "0xf8948201f4010a8201f5800a850000000000b8408234c544a9f3ce3b401a92cc7175602ce2a1e29b1ec135381c7d2a9e8f78f3edc9c06ee55252857c9a4560cb39e9d70d40f4331cace4d2b3121b967fa7a829f0a03d8627050f6688f27e2b5b89c9c141d3a48603029849e088486d1c7ea079ea7fa037024ed35d2c099d7eb68fb133e57735b03605ec32ded39ab305c3b56e5d99e7")); + } + + @Test + public void testEtherTransactionAsRlpValues() { + List rlpStrings = + TransactionEncoder.asRlpValues( + createEtherTransaction(), + new Sign.SignatureData((byte) 0, new byte[32], new byte[32])); + assertThat(rlpStrings.size(), is(10)); + // assertThat(rlpStrings.get(3), equalTo(RlpString.create(new BigInteger("10")))); + } + + @Test + public void testContractAsRlpValues() { + List rlpStrings = + TransactionEncoder.asRlpValues(createContractTransaction(), null); + assertThat(rlpStrings.size(), is(7)); + // assertThat(rlpStrings.get(3), is(RlpString.create(""))); + } + + // @Test + // public void testEip155Encode() { + // assertThat(TransactionEncoder.encode(createEip155RawTransaction(), (byte) 1), + // is(Numeric.hexStringToByteArray( + // + // "0xec098504a817c800825208943535353535353535353535353535353535353535880de0" + // + "b6b3a764000080018080"))); + // } + // + // @Test + // public void testEip155Transaction() { + // // https://github.com/ethereum/EIPs/issues/155 + // Credentials credentials = Credentials.create( + // "0x4646464646464646464646464646464646464646464646464646464646464646"); + // + // assertThat(TransactionEncoder.signMessage( + // createEip155RawTransaction(), (byte) 1, credentials), + // is(Numeric.hexStringToByteArray( + // + // "0xf86c098504a817c800825208943535353535353535353535353535353535353535880" + // + + // "de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d" + // + + // "3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf55" + // + "5c9f3dc64214b297fb1966a3b6d83"))); + // } + + private static RawTransaction createEtherTransaction() { + + BigInteger randomid = new BigInteger("500"); + BigInteger blockLimit = new BigInteger("501"); + + return RawTransaction.createEtherTransaction( + randomid, + gasPrice, + gasLimit, + blockLimit, + "0xadd5355", + BigInteger.valueOf(Long.MAX_VALUE)); + } + + static RawTransaction createContractTransaction() { + + BigInteger randomid = new BigInteger("500"); + BigInteger blockLimit = new BigInteger("501"); + + return RawTransaction.createContractTransaction( + randomid, gasPrice, gasLimit, blockLimit, BigInteger.TEN, "0x0000000000"); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionUtilsTest.java b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionUtilsTest.java index 2ca0112a0..7f38c35a6 100644 --- a/src/test/java/org/fisco/bcos/web3j/crypto/TransactionUtilsTest.java +++ b/src/test/java/org/fisco/bcos/web3j/crypto/TransactionUtilsTest.java @@ -4,27 +4,28 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; -import org.fisco.bcos.channel.test.TestBase; import org.junit.Ignore; import org.junit.Test; -public class TransactionUtilsTest extends TestBase { +public class TransactionUtilsTest { - @Ignore - @Test - public void testGenerateTransactionHash() { - assertThat( - generateTransactionHashHexEncoded( - TransactionEncoderTest.createContractTransaction(), SampleKeys.CREDENTIALS), - is("0xc3a0f520404c8cd0cb1c98be6b8e17ee32bf134ac1697d078e90422525c2d902")); - } + @Ignore + @Test + public void testGenerateTransactionHash() { + assertThat( + generateTransactionHashHexEncoded( + TransactionEncoderTest.createContractTransaction(), SampleKeys.CREDENTIALS), + is("0xc3a0f520404c8cd0cb1c98be6b8e17ee32bf134ac1697d078e90422525c2d902")); + } - @Ignore - @Test - public void testGenerateEip155TransactionHash() { - assertThat( - generateTransactionHashHexEncoded( - TransactionEncoderTest.createContractTransaction(), (byte) 1, SampleKeys.CREDENTIALS), - is("0x568c7f6920c1cee8332e245c473657b9c53044eb96ed7532f5550f1139861e9e")); - } + @Ignore + @Test + public void testGenerateEip155TransactionHash() { + assertThat( + generateTransactionHashHexEncoded( + TransactionEncoderTest.createContractTransaction(), + (byte) 1, + SampleKeys.CREDENTIALS), + is("0x568c7f6920c1cee8332e245c473657b9c53044eb96ed7532f5550f1139861e9e")); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/solidity/AbiTest.java b/src/test/java/org/fisco/bcos/web3j/solidity/AbiTest.java index 868869d47..7e45c29df 100644 --- a/src/test/java/org/fisco/bcos/web3j/solidity/AbiTest.java +++ b/src/test/java/org/fisco/bcos/web3j/solidity/AbiTest.java @@ -25,45 +25,45 @@ public class AbiTest { - @Test - public void simpleTest() throws IOException { - String contractAbi = - "[{" - + "\"name\":\"simpleFunction\"," - + "\"constant\":true," - + "\"payable\":true," - + "\"type\":\"function\"," - + "\"inputs\": [{\"name\":\"_in\", \"type\":\"bytes32\"}]," - + "\"outputs\":[{\"name\":\"_out\",\"type\":\"bytes32\"}]}]"; + @Test + public void simpleTest() throws IOException { + String contractAbi = + "[{" + + "\"name\":\"simpleFunction\"," + + "\"constant\":true," + + "\"payable\":true," + + "\"type\":\"function\"," + + "\"inputs\": [{\"name\":\"_in\", \"type\":\"bytes32\"}]," + + "\"outputs\":[{\"name\":\"_out\",\"type\":\"bytes32\"}]}]"; - Abi abi = Abi.fromJson(contractAbi); - assertEquals(abi.size(), 1); + Abi abi = Abi.fromJson(contractAbi); + assertEquals(abi.size(), 1); - Abi.Entry onlyFunc = abi.get(0); - assertEquals(onlyFunc.type, Abi.Entry.Type.function); - assertEquals(onlyFunc.inputs.size(), 1); - assertEquals(onlyFunc.outputs.size(), 1); - assertTrue(onlyFunc.payable); - assertTrue(onlyFunc.constant); - } + Abi.Entry onlyFunc = abi.get(0); + assertEquals(onlyFunc.type, Abi.Entry.Type.function); + assertEquals(onlyFunc.inputs.size(), 1); + assertEquals(onlyFunc.outputs.size(), 1); + assertTrue(onlyFunc.payable); + assertTrue(onlyFunc.constant); + } - @Test - public void simpleLegacyTest() throws IOException { - String contractAbi = - "[{" - + "\"name\":\"simpleFunction\"," - + "\"constant\":true," - + "\"type\":\"function\"," - + "\"inputs\": [{\"name\":\"_in\", \"type\":\"bytes32\"}]," - + "\"outputs\":[{\"name\":\"_out\",\"type\":\"bytes32\"}]}]"; + @Test + public void simpleLegacyTest() throws IOException { + String contractAbi = + "[{" + + "\"name\":\"simpleFunction\"," + + "\"constant\":true," + + "\"type\":\"function\"," + + "\"inputs\": [{\"name\":\"_in\", \"type\":\"bytes32\"}]," + + "\"outputs\":[{\"name\":\"_out\",\"type\":\"bytes32\"}]}]"; - Abi abi = Abi.fromJson(contractAbi); - assertEquals(abi.size(), 1); + Abi abi = Abi.fromJson(contractAbi); + assertEquals(abi.size(), 1); - Abi.Entry onlyFunc = abi.get(0); - assertEquals(onlyFunc.type, Abi.Entry.Type.function); - assertEquals(onlyFunc.inputs.size(), 1); - assertEquals(onlyFunc.outputs.size(), 1); - assertTrue(onlyFunc.constant); - } + Abi.Entry onlyFunc = abi.get(0); + assertEquals(onlyFunc.type, Abi.Entry.Type.function); + assertEquals(onlyFunc.inputs.size(), 1); + assertEquals(onlyFunc.outputs.size(), 1); + assertTrue(onlyFunc.constant); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/solidity/CompilerTest.java b/src/test/java/org/fisco/bcos/web3j/solidity/CompilerTest.java index 58d869491..69503dc19 100644 --- a/src/test/java/org/fisco/bcos/web3j/solidity/CompilerTest.java +++ b/src/test/java/org/fisco/bcos/web3j/solidity/CompilerTest.java @@ -37,180 +37,153 @@ /** Created by Anton Nashatyrev on 03.03.2016. */ public class CompilerTest { - @Test - public void solc_getVersion_shouldWork() throws IOException { - final String version = SolidityCompiler.runGetVersionOutput(); - - // ##### May produce 2 lines: - // solc, the solidity compiler commandline interface - // Version: 0.4.7+commit.822622cf.mod.Darwin.appleclang - System.out.println(version); - - assertThat(version, containsString("Version:")); - } - - @Test - public void simpleTest() throws IOException { - String contract = - "pragma solidity ^0.4.7;\n" - + "\n" - + "contract a {\n" - + "\n" - + " mapping(address => string) private mailbox;\n" - + "\n" - + " event Mailed(address from, string message);\n" - + " event Read(address from, string message);\n" - + "\n" - + "}"; - - SolidityCompiler.Result res = - SolidityCompiler.compile(contract.getBytes(), true, ABI, BIN, INTERFACE, METADATA); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - if (result.getContract("a") != null) System.out.println(result.getContract("a").bin); - else Assert.fail(); - } - - @Test - public void defaultFuncTest() throws IOException { - String contractSrc = - "pragma solidity ^0.4.7;\n" + "contract a {" + " function() {throw;}" + "}"; - - SolidityCompiler.Result res = SolidityCompiler.compile(contractSrc.getBytes(), true, BIN); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - - CompilationResult.ContractMetadata a = result.getContract("a"); - // CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - // System.out.print(contract.functions[0].toString()); - } - - @Test - public void compileFilesTest() throws IOException { - - File solFileList = new File("src/test/resources/contract"); - File[] solFiles = solFileList.listFiles(); - - for (File solFile : solFiles) { - - SolidityCompiler.Result res = - SolidityCompiler.compile(solFile, true, ABI, BIN, INTERFACE, METADATA); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - // Assert.assertEquals(solFile.getName(), result.getContractName()+".sol"); - // Assert.assertEquals(solFile.getAbsolutePath(), result.getContractPath()); - System.out.println("contractname " + solFile.getName()); - Path source = Paths.get(solFile.getPath()); - // todo - String contractname = solFile.getName().split("\\.")[0]; - CompilationResult.ContractMetadata a = - result.getContract(source, solFile.getName().split("\\.")[0]); - System.out.println("abi " + a.abi); - System.out.println("bin " + a.bin); - FileUtils.writeStringToFile( - new File("src/test/resources/solidity/" + contractname + ".abi"), a.abi); - FileUtils.writeStringToFile( - new File("src/test/resources/solidity/" + contractname + ".bin"), a.bin); - String binFile; - String abiFile; - String tempDirPath = new File("src/test/java/").getAbsolutePath(); - String packageName = "org.fisco.bcos.temp"; - String filename = contractname; - abiFile = "src/test/resources/solidity/" + filename + ".abi"; - binFile = "src/test/resources/solidity/" + filename + ".bin"; - SolidityFunctionWrapperGenerator.main( - Arrays.asList( - "-a", abiFile, - "-b", binFile, - "-p", packageName, - "-o", tempDirPath) - .toArray(new String[0])); + @Test + public void solc_getVersion_shouldWork() throws IOException { + final String version = SolidityCompiler.runGetVersionOutput(); + + // ##### May produce 2 lines: + // solc, the solidity compiler commandline interface + // Version: 0.4.7+commit.822622cf.mod.Darwin.appleclang + System.out.println(version); + + assertThat(version, containsString("Version:")); + } + + @Test + public void simpleTest() throws IOException { + String contract = + "pragma solidity ^0.4.7;\n" + + "\n" + + "contract a {\n" + + "\n" + + " mapping(address => string) private mailbox;\n" + + "\n" + + " event Mailed(address from, string message);\n" + + " event Read(address from, string message);\n" + + "\n" + + "}"; + + SolidityCompiler.Result res = + SolidityCompiler.compile(contract.getBytes(), true, ABI, BIN, INTERFACE, METADATA); + CompilationResult result = CompilationResult.parse(res.output); + if (result.getContract("a") != null) System.out.println(result.getContract("a").bin); + else Assert.fail(); + } + + @Test + public void defaultFuncTest() throws IOException { + String contractSrc = + "pragma solidity ^0.4.7;\n" + "contract a {" + " function() {throw;}" + "}"; + + SolidityCompiler.Result res = SolidityCompiler.compile(contractSrc.getBytes(), true, BIN); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract("a"); + } + + @Test + public void compileFilesTest() throws IOException { + + File solFileList = new File("src/test/resources/contract"); + File[] solFiles = solFileList.listFiles(); + + for (File solFile : solFiles) { + if (!solFile.getName().endsWith(".sol") || solFile.getName().contains("Lib")) { + continue; + } + SolidityCompiler.Result res = + SolidityCompiler.compile(solFile, true, ABI, BIN, INTERFACE, METADATA); + CompilationResult result = CompilationResult.parse(res.output); + System.out.println("contractname " + solFile.getName()); + Path source = Paths.get(solFile.getPath()); + String contractname = solFile.getName().split("\\.")[0]; + CompilationResult.ContractMetadata a = + result.getContract(source, solFile.getName().split("\\.")[0]); + FileUtils.writeStringToFile( + new File("src/test/resources/solidity/" + contractname + ".abi"), a.abi); + FileUtils.writeStringToFile( + new File("src/test/resources/solidity/" + contractname + ".bin"), a.bin); + String binFile; + String abiFile; + String tempDirPath = new File("src/test/java/").getAbsolutePath(); + String packageName = "org.fisco.bcos.temp"; + String filename = contractname; + abiFile = "src/test/resources/solidity/" + filename + ".abi"; + binFile = "src/test/resources/solidity/" + filename + ".bin"; + SolidityFunctionWrapperGenerator.main( + Arrays.asList( + "-a", + abiFile, + "-b", + binFile, + "-p", + packageName, + "-o", + tempDirPath) + .toArray(new String[0])); + } + } + + @Test + public void compileFilesWithImportTest() throws IOException { + + Path source = Paths.get("src", "test", "resources", "contract", "test2.sol"); + + SolidityCompiler.Result res = + SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract(source, "test2"); + } + + @Test + public void compileFilesWithImportFromParentFileTest() throws IOException { + + Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); + + SolidityCompiler.Option allowPathsOption = + new AllowPaths(Collections.singletonList(source.getParent().getParent().toFile())); + SolidityCompiler.Result res = + SolidityCompiler.compile( + source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); + CompilationResult result = CompilationResult.parse(res.output); + + Assert.assertEquals(2, result.getContractKeys().size()); + Assert.assertEquals(result.getContract("test3"), result.getContract(source, "test3")); + Assert.assertNotNull(result.getContract("test1")); + + CompilationResult.ContractMetadata a = result.getContract(source, "test3"); + } + + @Test + public void compileFilesWithImportFromParentStringTest() throws IOException { + + Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); + + SolidityCompiler.Option allowPathsOption = + new AllowPaths( + Collections.singletonList( + source.getParent().getParent().toAbsolutePath().toString())); + SolidityCompiler.Result res = + SolidityCompiler.compile( + source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract(source, "test3"); + } + + @Test + public void compileFilesWithImportFromParentPathTest() throws IOException { + + Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); + + SolidityCompiler.Option allowPathsOption = + new AllowPaths(Collections.singletonList(source.getParent().getParent())); + SolidityCompiler.Result res = + SolidityCompiler.compile( + source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); + CompilationResult result = CompilationResult.parse(res.output); + + CompilationResult.ContractMetadata a = result.getContract("test3"); } - System.out.println("generate successfully"); - } - - @Test - public void compileFilesWithImportTest() throws IOException { - - Path source = Paths.get("src", "test", "resources", "contract", "test2.sol"); - - SolidityCompiler.Result res = - SolidityCompiler.compile(source.toFile(), true, ABI, BIN, INTERFACE, METADATA); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - - CompilationResult.ContractMetadata a = result.getContract(source, "test2"); - // CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - // System.out.print(contract.functions[0].toString()); - } - - @Test - public void compileFilesWithImportFromParentFileTest() throws IOException { - - Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); - - SolidityCompiler.Option allowPathsOption = - new AllowPaths(Collections.singletonList(source.getParent().getParent().toFile())); - SolidityCompiler.Result res = - SolidityCompiler.compile( - source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - - Assert.assertEquals(2, result.getContractKeys().size()); - Assert.assertEquals(result.getContract("test3"), result.getContract(source, "test3")); - Assert.assertNotNull(result.getContract("test1")); - - CompilationResult.ContractMetadata a = result.getContract(source, "test3"); - // CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - // System.out.print(contract.functions[0].toString()); - } - - @Test - public void compileFilesWithImportFromParentStringTest() throws IOException { - - Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); - - SolidityCompiler.Option allowPathsOption = - new AllowPaths( - Collections.singletonList(source.getParent().getParent().toAbsolutePath().toString())); - SolidityCompiler.Result res = - SolidityCompiler.compile( - source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - - CompilationResult.ContractMetadata a = result.getContract(source, "test3"); - // CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - // System.out.print(contract.functions[0].toString()); - } - - @Test - public void compileFilesWithImportFromParentPathTest() throws IOException { - - Path source = Paths.get("src", "test", "resources", "contract", "test3.sol"); - - SolidityCompiler.Option allowPathsOption = - new AllowPaths(Collections.singletonList(source.getParent().getParent())); - SolidityCompiler.Result res = - SolidityCompiler.compile( - source.toFile(), true, ABI, BIN, INTERFACE, METADATA, allowPathsOption); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - - CompilationResult.ContractMetadata a = result.getContract("test3"); - // CallTransaction.Contract contract = new CallTransaction.Contract(a.abi); - // System.out.print(contract.functions[0].toString()); - } - - public static void main(String[] args) throws Exception { - new CompilerTest().simpleTest(); - } } diff --git a/src/test/java/org/fisco/bcos/web3j/solidity/SolidityFunctionWrapperGeneratorTest.java b/src/test/java/org/fisco/bcos/web3j/solidity/SolidityFunctionWrapperGeneratorTest.java deleted file mode 100644 index b714be642..000000000 --- a/src/test/java/org/fisco/bcos/web3j/solidity/SolidityFunctionWrapperGeneratorTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.fisco.bcos.web3j.solidity; - -import static org.fisco.bcos.web3j.solidity.compiler.SolidityCompiler.Options.*; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import org.apache.commons.io.FileUtils; -import org.fisco.bcos.web3j.codegen.SolidityFunctionWrapperGenerator; -import org.fisco.bcos.web3j.solidity.compiler.CompilationResult; -import org.fisco.bcos.web3j.solidity.compiler.SolidityCompiler; -import org.junit.Test; - -public class SolidityFunctionWrapperGeneratorTest { - - protected String tempDirPath = new File("src/test/java/").getAbsolutePath(); - protected String packageName = "org.fisco.bcos.temp"; - - @Test - public void generateClassFromABIAndBIN() throws Exception { - File fileList = new File("src/test/resources/solidity"); - File[] files = fileList.listFiles(); - String abiFile = ""; - String binFile = ""; - for (File file : files) { - String filename = file.getName(); - String commonName = filename.split("\\.")[0]; - abiFile = "src/test/resources/solidity/" + commonName + ".abi"; - binFile = "src/test/resources/solidity/" + commonName + ".bin"; - SolidityFunctionWrapperGenerator.main( - Arrays.asList( - "-a", abiFile, - "-b", binFile, - "-p", packageName, - "-o", tempDirPath) - .toArray(new String[0])); - } - System.out.println("generate successfully"); - } - - public SolidityFunctionWrapperGeneratorTest() throws IOException {} - - @Test - public void compileSolFilesToJavaTest() throws IOException { - File solFileList = new File("src/test/resources/contract"); - File[] solFiles = solFileList.listFiles(); - - for (File solFile : solFiles) { - - SolidityCompiler.Result res = - SolidityCompiler.compile(solFile, true, ABI, BIN, INTERFACE, METADATA); - System.out.println("Out: '" + res.output + "'"); - System.out.println("Err: '" + res.errors + "'"); - CompilationResult result = CompilationResult.parse(res.output); - System.out.println("contractname " + solFile.getName()); - Path source = Paths.get(solFile.getPath()); - String contractname = solFile.getName().split("\\.")[0]; - CompilationResult.ContractMetadata a = result.getContract(solFile.getName().split("\\.")[0]); - System.out.println("abi " + a.abi); - System.out.println("bin " + a.bin); - FileUtils.writeStringToFile( - new File("src/test/resources/solidity/" + contractname + ".abi"), a.abi); - FileUtils.writeStringToFile( - new File("src/test/resources/solidity/" + contractname + ".bin"), a.bin); - String binFile; - String abiFile; - String tempDirPath = new File("src/test/java/").getAbsolutePath(); - String packageName = "org.fisco.bcos.temp"; - String filename = contractname; - abiFile = "src/test/resources/solidity/" + filename + ".abi"; - binFile = "src/test/resources/solidity/" + filename + ".bin"; - SolidityFunctionWrapperGenerator.main( - Arrays.asList( - "-a", abiFile, - "-b", binFile, - "-p", packageName, - "-o", tempDirPath) - .toArray(new String[0])); - } - System.out.println("generate successfully"); - } -} diff --git a/src/test/java/org/fisco/bcos/web3j/solidity/SolidityTypeTest.java b/src/test/java/org/fisco/bcos/web3j/solidity/SolidityTypeTest.java index 76010376e..238713498 100644 --- a/src/test/java/org/fisco/bcos/web3j/solidity/SolidityTypeTest.java +++ b/src/test/java/org/fisco/bcos/web3j/solidity/SolidityTypeTest.java @@ -25,31 +25,31 @@ /** Created by Maximilian Schmidt on 25.09.2018. */ public class SolidityTypeTest { - @Test - public void ensureUnsignedInteger_isDecodedWithCorrectSignum() { - byte[] bigNumberByteArray = { - -13, -75, 19, 86, -119, 67, 112, -4, 118, -86, 98, -46, 103, -42, -126, 63, -60, -15, -87, 57, - 43, 11, -17, -52, 0, 3, -65, 14, -67, -40, 65, 119 - }; - SolidityType testObject = new SolidityType.UnsignedIntType("uint256"); - Object decode = testObject.decode(bigNumberByteArray); - assertEquals(decode.getClass(), BigInteger.class); - BigInteger actualBigInteger = (BigInteger) decode; - BigInteger expectedBigInteger = new BigInteger(Hex.toHexString(bigNumberByteArray), 16); - assertEquals(expectedBigInteger, actualBigInteger); - } + @Test + public void ensureUnsignedInteger_isDecodedWithCorrectSignum() { + byte[] bigNumberByteArray = { + -13, -75, 19, 86, -119, 67, 112, -4, 118, -86, 98, -46, 103, -42, -126, 63, -60, -15, + -87, 57, 43, 11, -17, -52, 0, 3, -65, 14, -67, -40, 65, 119 + }; + SolidityType testObject = new SolidityType.UnsignedIntType("uint256"); + Object decode = testObject.decode(bigNumberByteArray); + assertEquals(decode.getClass(), BigInteger.class); + BigInteger actualBigInteger = (BigInteger) decode; + BigInteger expectedBigInteger = new BigInteger(Hex.toHexString(bigNumberByteArray), 16); + assertEquals(expectedBigInteger, actualBigInteger); + } - @Test - public void ensureSignedInteger_isDecoded() { - byte[] bigNumberByteArray = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 127, -1, -1, -1, -1, - -1, -1, -1 - }; - SolidityType testObject = new SolidityType.IntType("int256"); - Object decode = testObject.decode(bigNumberByteArray); - assertEquals(decode.getClass(), BigInteger.class); - BigInteger actualBigInteger = (BigInteger) decode; - BigInteger expectedBigInteger = new BigInteger(bigNumberByteArray); - assertEquals(expectedBigInteger, actualBigInteger); - } + @Test + public void ensureSignedInteger_isDecoded() { + byte[] bigNumberByteArray = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 127, -1, -1, + -1, -1, -1, -1, -1 + }; + SolidityType testObject = new SolidityType.IntType("int256"); + Object decode = testObject.decode(bigNumberByteArray); + assertEquals(decode.getClass(), BigInteger.class); + BigInteger actualBigInteger = (BigInteger) decode; + BigInteger expectedBigInteger = new BigInteger(bigNumberByteArray); + assertEquals(expectedBigInteger, actualBigInteger); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/tx/ManagedTransactionTester.java b/src/test/java/org/fisco/bcos/web3j/tx/ManagedTransactionTester.java index eccc840b2..a70330fd2 100644 --- a/src/test/java/org/fisco/bcos/web3j/tx/ManagedTransactionTester.java +++ b/src/test/java/org/fisco/bcos/web3j/tx/ManagedTransactionTester.java @@ -18,67 +18,68 @@ public abstract class ManagedTransactionTester { - public static final String ADDRESS = "0x3d6cb163f7c72d20b0fcd6baae5889329d138a4a"; - public static final String TRANSACTION_HASH = "0xHASH"; - protected Web3j web3j; - protected TxHashVerifier txHashVerifier; + public static final String ADDRESS = "0x3d6cb163f7c72d20b0fcd6baae5889329d138a4a"; + public static final String TRANSACTION_HASH = "0xHASH"; + protected Web3j web3j; + protected TxHashVerifier txHashVerifier; - @Before - public void setUp() throws Exception { - web3j = mock(Web3j.class); - txHashVerifier = mock(TxHashVerifier.class); - when(txHashVerifier.verify(any(), any())).thenReturn(true); - } + @Before + public void setUp() throws Exception { + web3j = mock(Web3j.class); + txHashVerifier = mock(TxHashVerifier.class); + when(txHashVerifier.verify(any(), any())).thenReturn(true); + } - public TransactionManager getVerifiedTransactionManager( - Credentials credentials, int attempts, int sleepDuration) { - RawTransactionManager transactionManager = - new RawTransactionManager(web3j, credentials, attempts, sleepDuration); - transactionManager.setTxHashVerifier(txHashVerifier); - return transactionManager; - } + public TransactionManager getVerifiedTransactionManager( + Credentials credentials, int attempts, int sleepDuration) { + RawTransactionManager transactionManager = + new RawTransactionManager(web3j, credentials, attempts, sleepDuration); + transactionManager.setTxHashVerifier(txHashVerifier); + return transactionManager; + } - public TransactionManager getVerifiedTransactionManager(Credentials credentials) { - RawTransactionManager transactionManager = new RawTransactionManager(web3j, credentials); - transactionManager.setTxHashVerifier(txHashVerifier); - return transactionManager; - } + public TransactionManager getVerifiedTransactionManager(Credentials credentials) { + RawTransactionManager transactionManager = new RawTransactionManager(web3j, credentials); + transactionManager.setTxHashVerifier(txHashVerifier); + return transactionManager; + } - void prepareTransaction(TransactionReceipt transactionReceipt) throws IOException { - prepareBlockNumberRequest(); - prepareTransactionRequest(); - prepareTransactionReceipt(transactionReceipt); - } + void prepareTransaction(TransactionReceipt transactionReceipt) throws IOException { + prepareBlockNumberRequest(); + prepareTransactionRequest(); + prepareTransactionReceipt(transactionReceipt); + } - @SuppressWarnings("unchecked") - void prepareBlockNumberRequest() throws IOException { - BlockNumber ethBlockNumber = new BlockNumber(); - ethBlockNumber.setResult("0x1"); + @SuppressWarnings("unchecked") + void prepareBlockNumberRequest() throws IOException { + BlockNumber ethBlockNumber = new BlockNumber(); + ethBlockNumber.setResult("0x1"); - Request ethBlockNumberRequest = mock(Request.class); - when(ethBlockNumberRequest.send()).thenReturn(ethBlockNumber); - when(web3j.getBlockNumber()).thenReturn((Request) ethBlockNumberRequest); - when(web3j.getBlockNumberCache()).thenReturn(new BigInteger("1")); - } + Request ethBlockNumberRequest = mock(Request.class); + when(ethBlockNumberRequest.send()).thenReturn(ethBlockNumber); + when(web3j.getBlockNumber()).thenReturn((Request) ethBlockNumberRequest); + when(web3j.getBlockNumberCache()).thenReturn(new BigInteger("1")); + } - @SuppressWarnings("unchecked") - void prepareTransactionRequest() throws IOException { - SendTransaction sendTransaction = new SendTransaction(); - sendTransaction.setResult(TRANSACTION_HASH); + @SuppressWarnings("unchecked") + void prepareTransactionRequest() throws IOException { + SendTransaction sendTransaction = new SendTransaction(); + sendTransaction.setResult(TRANSACTION_HASH); - Request rawTransactionRequest = mock(Request.class); - when(rawTransactionRequest.send()).thenReturn(sendTransaction); - when(web3j.sendRawTransaction(any(String.class))).thenReturn((Request) rawTransactionRequest); - } + Request rawTransactionRequest = mock(Request.class); + when(rawTransactionRequest.send()).thenReturn(sendTransaction); + when(web3j.sendRawTransaction(any(String.class))) + .thenReturn((Request) rawTransactionRequest); + } - @SuppressWarnings("unchecked") - void prepareTransactionReceipt(TransactionReceipt transactionReceipt) throws IOException { - BcosTransactionReceipt ethGetTransactionReceipt = new BcosTransactionReceipt(); - ethGetTransactionReceipt.setResult(transactionReceipt); + @SuppressWarnings("unchecked") + void prepareTransactionReceipt(TransactionReceipt transactionReceipt) throws IOException { + BcosTransactionReceipt ethGetTransactionReceipt = new BcosTransactionReceipt(); + ethGetTransactionReceipt.setResult(transactionReceipt); - Request getTransactionReceiptRequest = mock(Request.class); - when(getTransactionReceiptRequest.send()).thenReturn(ethGetTransactionReceipt); - when(web3j.getTransactionReceipt(TRANSACTION_HASH)) - .thenReturn((Request) getTransactionReceiptRequest); - } + Request getTransactionReceiptRequest = mock(Request.class); + when(getTransactionReceiptRequest.send()).thenReturn(ethGetTransactionReceipt); + when(web3j.getTransactionReceipt(TRANSACTION_HASH)) + .thenReturn((Request) getTransactionReceiptRequest); + } } diff --git a/src/test/java/org/fisco/bcos/web3j/tx/PollingTransactionReceiptProcessorTest.java b/src/test/java/org/fisco/bcos/web3j/tx/PollingTransactionReceiptProcessorTest.java index 56841f227..9ac0b52bf 100644 --- a/src/test/java/org/fisco/bcos/web3j/tx/PollingTransactionReceiptProcessorTest.java +++ b/src/test/java/org/fisco/bcos/web3j/tx/PollingTransactionReceiptProcessorTest.java @@ -16,58 +16,60 @@ import org.junit.Test; public class PollingTransactionReceiptProcessorTest { - private static final String TRANSACTION_HASH = "0x00"; - private Web3j web3j; - private long sleepDuration; - private int attempts; - private PollingTransactionReceiptProcessor processor; + private static final String TRANSACTION_HASH = "0x00"; + private Web3j web3j; + private long sleepDuration; + private int attempts; + private PollingTransactionReceiptProcessor processor; - @Before - public void setUp() { - web3j = mock(Web3j.class); - sleepDuration = 100; - attempts = 3; - processor = new PollingTransactionReceiptProcessor(web3j, sleepDuration, attempts); - } + @Before + public void setUp() { + web3j = mock(Web3j.class); + sleepDuration = 100; + attempts = 3; + processor = new PollingTransactionReceiptProcessor(web3j, sleepDuration, attempts); + } - @Test - public void returnsTransactionReceiptWhenItIsAvailableInstantly() throws Exception { - TransactionReceipt transactionReceipt = new TransactionReceipt(); - doReturn(requestReturning(response(transactionReceipt))) - .when(web3j) - .getTransactionReceipt(TRANSACTION_HASH); + @Test + public void returnsTransactionReceiptWhenItIsAvailableInstantly() throws Exception { + TransactionReceipt transactionReceipt = new TransactionReceipt(); + doReturn(requestReturning(response(transactionReceipt))) + .when(web3j) + .getTransactionReceipt(TRANSACTION_HASH); - TransactionReceipt receipt = processor.waitForTransactionReceipt(TRANSACTION_HASH); + TransactionReceipt receipt = processor.waitForTransactionReceipt(TRANSACTION_HASH); - assertThat(receipt, sameInstance(transactionReceipt)); - } + assertThat(receipt, sameInstance(transactionReceipt)); + } - @Test - public void throwsTransactionExceptionWhenReceiptIsNotAvailableInTime() throws Exception { - doReturn(requestReturning(response(null))).when(web3j).getTransactionReceipt(TRANSACTION_HASH); + @Test + public void throwsTransactionExceptionWhenReceiptIsNotAvailableInTime() throws Exception { + doReturn(requestReturning(response(null))) + .when(web3j) + .getTransactionReceipt(TRANSACTION_HASH); - try { - processor.waitForTransactionReceipt(TRANSACTION_HASH); - fail("call should fail with TransactionException"); - } catch (TransactionException e) { - assertTrue(e.getTransactionHash().isPresent()); - assertEquals(e.getTransactionHash().get(), TRANSACTION_HASH); + try { + processor.waitForTransactionReceipt(TRANSACTION_HASH); + fail("call should fail with TransactionException"); + } catch (TransactionException e) { + assertTrue(e.getTransactionHash().isPresent()); + assertEquals(e.getTransactionHash().get(), TRANSACTION_HASH); + } } - } - private static > Request requestReturning(T response) { - Request request = mock(Request.class); - try { - when(request.send()).thenReturn(response); - } catch (IOException e) { - // this will never happen + private static > Request requestReturning(T response) { + Request request = mock(Request.class); + try { + when(request.send()).thenReturn(response); + } catch (IOException e) { + // this will never happen + } + return request; } - return request; - } - private static BcosTransactionReceipt response(TransactionReceipt transactionReceipt) { - BcosTransactionReceipt response = new BcosTransactionReceipt(); - response.setResult(transactionReceipt); - return response; - } + private static BcosTransactionReceipt response(TransactionReceipt transactionReceipt) { + BcosTransactionReceipt response = new BcosTransactionReceipt(); + response.setResult(transactionReceipt); + return response; + } } diff --git a/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.p12 b/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.p12 new file mode 100644 index 000000000..1b86128d7 Binary files /dev/null and b/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.p12 differ diff --git a/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.pem b/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.pem new file mode 100644 index 000000000..b448c4cd7 --- /dev/null +++ b/src/test/resources/0x0fc3c4bb89bd90299db4c62be0174c4966286c00.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgvFFrJgDuw6IW9FfcFM+D +oB7SLQ/CFJ/JEdwuxIb+V6OhRANCAATbv+5PdvWjvD28LmEnxKH1C3YUv/QTikSn +mu09QvZ/nHqnBXAgX5tgpYiMZBW2qDABJne0QVp5zNFTP+VjeGHf +-----END PRIVATE KEY----- diff --git a/src/test/resources/applicationContext-keystore-sample.xml b/src/test/resources/applicationContext-keystore-sample.xml new file mode 100644 index 000000000..6da5c7ead --- /dev/null +++ b/src/test/resources/applicationContext-keystore-sample.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/src/test/resources/applicationContext-sample.xml b/src/test/resources/applicationContext-sample.xml new file mode 100644 index 000000000..8eb34e59e --- /dev/null +++ b/src/test/resources/applicationContext-sample.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + 127.0.0.1:20200 + 127.0.0.1:20201 + + + + + + + + 127.0.0.1:20202 + 127.0.0.1:20203 + + + + + + + + + + + + + + diff --git a/src/test/resources/contract/LibInt.sol b/src/test/resources/contract/LibInt.sol new file mode 100644 index 000000000..00c91b154 --- /dev/null +++ b/src/test/resources/contract/LibInt.sol @@ -0,0 +1,224 @@ +/** +* file LibInt.sol +* author liaoyan +* time 2016-11-29 +* desc the defination of LibInt libary +*/ + +pragma solidity ^0.4.2; + +library LibInt { + using LibInt for *; + + function toString(uint _self) internal returns (string _ret) { + if (_self == 0) { + return "0"; + } + + uint8 len = 0; + uint tmp = _self; + while (tmp > 0) { + tmp /= 10; + len++; + } + + _ret = new string(len); + + uint8 i = len-1; + while (_self > 0) { + bytes(_ret)[i--] = byte(_self%10+0x30); + _self /= 10; + } + } + + function toHexString(uint _self) internal returns (string _ret) { + if (_self == 0) { + return "0x0"; + } + + uint8 len = 2; + uint tmp = _self; + while (tmp > 0) { + tmp /= 16; + len++; + } + + _ret = new string(len); + + uint8 i = len-1; + while (_self > 0) { + if (_self%16 > 9) { + bytes(_ret)[i--] = byte(_self%16+0x61-0xa); + } else { + bytes(_ret)[i--] = byte(_self%16+0x30); + } + + _self /= 16; + } + + bytes(_ret)[0] = byte(0x30); + bytes(_ret)[1] = byte(0x78); + } + + function toHexString64(uint _self) internal returns (string _ret) { + _ret = new string(66); + bytes(_ret)[0] = '0'; + bytes(_ret)[1] = 'x'; + + for (uint8 i=65; i>=2; --i) { + uint8 digit = uint8(_self&0x0F); + _self /= 16; + + if (digit < 10) + bytes(_ret)[i] = byte(digit+0x30); + else + bytes(_ret)[i] = byte(digit-10+0x61); + } + } + + function toString(int _self) internal returns (string _ret) { + if (_self == 0) { + return "0"; + } + + uint ui = uint(_self); + bool positive = true; + uint8 len = 0; + if (_self < 0) { + ui = uint(-_self); + positive = false; + len++; + } + + uint tmp = ui; + while (tmp > 0) { + tmp /= 10; + len++; + } + + _ret = new string(len); + if (!positive) { + bytes(_ret)[0] = '-'; + } + + uint8 i = len-1; + while (ui > 0) { + bytes(_ret)[i--] = byte(ui%10+0x30); + ui /= 10; + } + } + + function toAddrString(uint _self) internal returns (string _ret) { + _ret = new string(42); + bytes(_ret)[0] = '0'; + bytes(_ret)[1] = 'x'; + + for (uint8 i=41; i>=2; --i) { + uint8 digit = uint8(_self&0x0F); + _self /= 16; + + if (digit < 10) + bytes(_ret)[i] = byte(digit+0x30); + else + bytes(_ret)[i] = byte(digit-10+0x61); + } + } + + function toKeyValue(uint _self, string _key) internal returns (string _ret) { + uint len = bytes(_key).length+3; + + if (_self == 0) { + len += 1; + } else { + uint tmp = _self; + while (tmp > 0) { + tmp /= 10; + len++; + } + } + + _ret = new string(len); + + uint i = 0; + bytes(_ret)[i++] = '"'; + for (uint j=0; j < bytes(_key).length; j++) { + bytes(_ret)[i++] = bytes(_key)[j]; + } + bytes(_ret)[i++] = '"'; + + bytes(_ret)[i++] = ':'; + + i = len-1; + if (_self == 0) { + bytes(_ret)[i] = byte(0x30); + } else { + while (_self > 0) { + bytes(_ret)[i--] = byte(_self%10+0x30); + _self /= 10; + } + } + } + + function toKeyValue(int _self, string _key) internal returns (string _ret) { + uint ui = uint(_self); + bool positive = true; + uint len = bytes(_key).length+3; + if (_self < 0) { + ui = uint(-_self); + positive = false; + len++; + } + + if (_self == 0) { + len += 1; + } else { + uint tmp = ui; + while (tmp > 0) { + tmp /= 10; + len++; + } + } + + _ret = new string(len); + + uint i = 0; + bytes(_ret)[i++] = '"'; + for (uint j=0; j < bytes(_key).length; j++) { + bytes(_ret)[i++] = bytes(_key)[j]; + } + bytes(_ret)[i++] = '"'; + + bytes(_ret)[i++] = ':'; + + if (!positive) { + bytes(_ret)[i++] = '-'; + } + i = len-1; + if (_self == 0) { + bytes(_ret)[i] = byte(0x30); + } else { + while (ui > 0) { + bytes(_ret)[i--] = byte(ui%10+0x30); + ui /= 10; + } + } + } + + function recoveryToString(uint _self) internal returns (string _ret) { + uint tmp = _self; + uint len = 0; + while (tmp > 0) { + tmp /= 256; + len++; + } + + _ret = new string(len); + tmp = _self; + uint i = len-1; + while (tmp > 0) { + bytes(_ret)[i] = byte(tmp%256); + tmp /= 256; + i--; + } + } +} \ No newline at end of file diff --git a/src/test/resources/contract/LibString.sol b/src/test/resources/contract/LibString.sol new file mode 100644 index 000000000..d85a37c34 --- /dev/null +++ b/src/test/resources/contract/LibString.sol @@ -0,0 +1,885 @@ +/** +* file LibString.sol +* author liaoyan +* time 2016-11-29 +* desc the defination of LibString contract +*/ + +pragma solidity ^0.4.2; + +library LibString { + + using LibString for *; + + function memcpy(uint dest, uint src, uint len) private { + // Copy word-length chunks while possible + for(; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + uint mask = 256 ** (32 - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + // Returns the memory address of the first byte of the first occurrence of + // `needle` in `self`, or the first byte after `self` if not found. + function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private returns (uint) { + uint ptr; + uint idx; + + if (needlelen <= selflen) { + if (needlelen <= 32) { + // Optimized assembly for 68 gas per byte on short strings + assembly { + let mask := not(sub(exp(2, mul(8, sub(32, needlelen))), 1)) + let needledata := and(mload(needleptr), mask) + let end := add(selfptr, sub(selflen, needlelen)) + ptr := selfptr + loop: + jumpi(exit, eq(and(mload(ptr), mask), needledata)) + ptr := add(ptr, 1) + jumpi(loop, lt(sub(ptr, 1), end)) + ptr := add(selfptr, selflen) + exit: + } + return ptr; + } else { + // For long needles, use hashing + bytes32 hash; + assembly { hash := sha3(needleptr, needlelen) } + ptr = selfptr; + for (idx = 0; idx <= selflen - needlelen; idx++) { + bytes32 testHash; + assembly { testHash := sha3(ptr, needlelen) } + if (hash == testHash) + return ptr; + ptr += 1; + } + } + } + return selfptr + selflen; + } + + /* + function length(string _self) internal returns (uint _ret) { + _ret = bytes(_self).length; + } + */ + + function compare(string _self, string _str) internal returns (int8 _ret) { + for (uint i=0; i bytes(_str)[i]) { + return 1; + } else if (bytes(_self)[i] < bytes(_str)[i]) { + return -1; + } + } + + if (bytes(_self).length > bytes(_str).length) { + return 1; + } if (bytes(_self).length < bytes(_str).length) { + return -1; + } else { + return 0; + } + } + + function compareNoCase(string _self, string _str) internal returns (int8 _ret) { + for (uint i=0; i= 'a' && ch1 <='z' && ch2 >= 'a' && ch2 <='z') { + if (ch1 > ch2) { + return 1; + } else if (ch1 < ch2) { + return -1; + } + } else { + if (bytes(_self)[i] > bytes(_str)[i]) { + return 1; + } else if (bytes(_self)[i] < bytes(_str)[i]) { + return -1; + } + } + } + + if (bytes(_self).length > bytes(_str).length) { + return 1; + } if (bytes(_self).length < bytes(_str).length) { + return -1; + } else { + return 0; + } + } + + function equals(string _self, string _str) internal returns (bool _ret) { + if (bytes(_self).length != bytes(_str).length) { + return false; + } + + for (uint i=0; i= 'a' && ch1 <='z' && ch2 >= 'a' && ch2 <='z') { + if (ch1 != ch2) { + return false; + } + } else { + if (bytes(_self)[i] != bytes(_str)[i]) { + return false; + } + } + } + + return true; + } + + function substr(string _self, uint _start, uint _len) internal returns (string _ret) { + if (_len > bytes(_self).length-_start) { + _len = bytes(_self).length-_start; + } + + if (_len <= 0) { + _ret = ""; + return; + } + + _ret = new string(_len); + + uint selfptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + retptr := add(_ret, 0x20) + } + + memcpy(retptr, selfptr+_start, _len); + } + + function concat(string _self, string _str) internal returns (string _ret) { + _ret = new string(bytes(_self).length + bytes(_str).length); + + uint selfptr; + uint strptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + strptr := add(_str, 0x20) + retptr := add(_ret, 0x20) + } + + memcpy(retptr, selfptr, bytes(_self).length); + memcpy(retptr+bytes(_self).length, strptr, bytes(_str).length); + } + + function concat(string _self, string _str1, string _str2) + internal returns (string _ret) { + _ret = new string(bytes(_self).length + bytes(_str1).length + bytes(_str2).length); + + uint selfptr; + uint str1ptr; + uint str2ptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + str1ptr := add(_str1, 0x20) + str2ptr := add(_str2, 0x20) + retptr := add(_ret, 0x20) + } + + uint pos = 0; + memcpy(retptr+pos, selfptr, bytes(_self).length); + pos += bytes(_self).length; + memcpy(retptr+pos, str1ptr, bytes(_str1).length); + pos += bytes(_str1).length; + memcpy(retptr+pos, str2ptr, bytes(_str2).length); + pos += bytes(_str2).length; + } + + function concat(string _self, string _str1, string _str2, string _str3) + internal returns (string _ret) { + _ret = new string(bytes(_self).length + bytes(_str1).length + bytes(_str2).length + + bytes(_str3).length); + + uint selfptr; + uint str1ptr; + uint str2ptr; + uint str3ptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + str1ptr := add(_str1, 0x20) + str2ptr := add(_str2, 0x20) + str3ptr := add(_str3, 0x20) + retptr := add(_ret, 0x20) + } + + uint pos = 0; + memcpy(retptr+pos, selfptr, bytes(_self).length); + pos += bytes(_self).length; + memcpy(retptr+pos, str1ptr, bytes(_str1).length); + pos += bytes(_str1).length; + memcpy(retptr+pos, str2ptr, bytes(_str2).length); + pos += bytes(_str2).length; + memcpy(retptr+pos, str3ptr, bytes(_str3).length); + pos += bytes(_str3).length; + } + + function trim(string _self) internal returns (string _ret) { + uint i; + uint8 ch; + for (i=0; i0; --i) { + ch = uint8(bytes(_self)[i-1]); + if (!(ch == 0x20 || ch == 0x09 || ch == 0x0D || ch == 0x0A)) { + break; + } + } + uint end = i; + + _ret = new string(end-start); + + uint selfptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + retptr := add(_ret, 0x20) + } + + memcpy(retptr, selfptr+start, end-start); + } + + function trim(string _self, string _chars) internal returns (string _ret) { + uint16 i; + uint16 j; + bool matched; + for (i=0; i0; --i) { + matched = false; + for (j=0; j 0) { + ptr = findPtr(bytes(_self).length-pos, selfptr+pos, bytes(_delim).length, delimptr) - selfptr; + + if (ptr < bytes(_self).length) { + found = true; + } else { + ptr = bytes(_self).length; + } + } else { + ptr = bytes(_self).length; + } + + string memory elem = new string(ptr-pos); + uint elemptr; + assembly { + elemptr := add(elem, 0x20) + } + memcpy(elemptr, selfptr+pos, ptr-pos); + pos = ptr + bytes(_delim).length; + _array.push(elem); + + if (!found) { + break; + } + } + } + + function indexOf(string _self, string _str) internal returns (int _ret) { + uint selfptr; + uint strptr; + assembly { + selfptr := add(_self, 0x20) + strptr := add(_str, 0x20) + } + + uint ptr = findPtr(bytes(_self).length, selfptr, bytes(_str).length, strptr) - selfptr; + if (ptr < bytes(_self).length) { + _ret = int(ptr); + } else { + _ret = -1; + } + } + + function indexOf(string _self, string _str, uint pos) internal returns (int _ret) { + uint selfptr; + uint strptr; + assembly { + selfptr := add(_self, 0x20) + strptr := add(_str, 0x20) + } + + uint ptr = findPtr(bytes(_self).length-pos, selfptr+pos, bytes(_str).length, strptr) - selfptr; + if (ptr < bytes(_self).length) { + _ret = int(ptr); + } else { + _ret = -1; + } + } + + function toInt(string _self) internal returns (int _ret) { + _ret = 0; + if (bytes(_self).length == 0) { + return; + } + + uint16 i; + uint8 digit; + for (i=0; i= 0x30 && digit <= 0x39)) { + return; + } + _ret = _ret*10 + int(digit-0x30); + } + + if (!positive) { + _ret = -_ret; + } + } + + function toAddress(string _self) internal returns (address _ret) { + uint16 i; + uint8 digit; + for (i=0; i= 0x30 && digit <= 0x39) //'0'-'9' + digit -= 0x30; + else if (digit|0x20 >= 0x61 && digit|0x20 <= 0x66) //'a'-'f' + digit = digit-0x61+10; + else + return address(0); + + addr = addr*16+digit; + } + + return address(addr); + } + + function toKeyValue(string _self, string _key) internal returns (string _ret) { + _ret = new string(bytes(_self).length + bytes(_key).length + 5); + + uint selfptr; + uint keyptr; + uint retptr; + assembly { + selfptr := add(_self, 0x20) + keyptr := add(_key, 0x20) + retptr := add(_ret, 0x20) + } + + uint pos = 0; + + bytes(_ret)[pos++] = '"'; + memcpy(retptr+pos, keyptr, bytes(_key).length); + pos += bytes(_key).length; + bytes(_ret)[pos++] = '"'; + + bytes(_ret)[pos++] = ':'; + + bytes(_ret)[pos++] = '"'; + memcpy(retptr+pos, selfptr, bytes(_self).length); + pos += bytes(_self).length; + bytes(_ret)[pos++] = '"'; + } + + function toKeyValue(string[] storage _self, string _key) internal returns (string _ret) { + uint len = bytes(_key).length+5; + for (uint i=0; i<_self.length; ++i) { + if (i < _self.length-1) + len += bytes(_self[i]).length+3; + else + len += bytes(_self[i]).length+2; + } + + _ret = new string(len); + + uint pos = 0; + + bytes(_ret)[pos++] = '"'; + for (uint j=0; j= 0x30 && digit <= 0x39)) { + if (!positive) { + _ret = -_ret; + } + return; + } + _ret = _ret*10 + int(digit-0x30); + } + + if (!positive) { + _ret = -_ret; + } + } + + function getArrayValueByKey(string _self, string _key) internal returns (string _ret) { + int pos = -1; + uint searchStart = 0; + while (true) { + pos = _self.indexOf("\"".concat(_key, "\""), searchStart); + if (pos == -1) { + pos = _self.indexOf("'".concat(_key, "'"), searchStart); + if (pos == -1) { + return; + } + } + + pos += int(bytes(_key).length+2); + + bool colon = false; + while (uint(pos) < bytes(_self).length) { + if (bytes(_self)[uint(pos)] == ' ' || bytes(_self)[uint(pos)] == '\t' + || bytes(_self)[uint(pos)] == '\r' || bytes(_self)[uint(pos)] == '\n') { + pos++; + } else if (bytes(_self)[uint(pos)] == ':') { + pos++; + colon = true; + break; + } else { + break; + } + } + + if(uint(pos) == bytes(_self).length) { + return; + } + + if (colon) { + break; + } else { + searchStart = uint(pos); + } + } + + int start = _self.indexOf("[", uint(pos)); + if (start == -1) { + return; + } + start += 1; + + int end = _self.indexOf("]", uint(pos)); + if (end == -1) { + return; + } + + _ret = _self.substr(uint(start), uint(end-start)); + } + + function getArrayValueByKey(string _self, string _key, string[] storage _array) internal { + //Why can not use delete _array? + for (uint i=0; i<_array.length; ++i) { + delete _array[i]; + } + _array.length = 0; + + int pos = -1; + uint searchStart = 0; + while (true) { + pos = _self.indexOf("\"".concat(_key, "\""), searchStart); + if (pos == -1) { + pos = _self.indexOf("'".concat(_key, "'"), searchStart); + if (pos == -1) { + return; + } + } + + pos += int(bytes(_key).length+2); + + bool colon = false; + while (uint(pos) < bytes(_self).length) { + if (bytes(_self)[uint(pos)] == ' ' || bytes(_self)[uint(pos)] == '\t' + || bytes(_self)[uint(pos)] == '\r' || bytes(_self)[uint(pos)] == '\n') { + pos++; + } else if (bytes(_self)[uint(pos)] == ':') { + pos++; + colon = true; + break; + } else { + break; + } + } + + if(uint(pos) == bytes(_self).length) { + return; + } + + if (colon) { + break; + } else { + searchStart = uint(pos); + } + } + + int start = _self.indexOf("[", uint(pos)); + if (start == -1) { + return; + } + start += 1; + + int end = _self.indexOf("]", uint(pos)); + if (end == -1) { + return; + } + + string memory vals = _self.substr(uint(start), uint(end-start)).trim(" \t\r\n"); + + if (bytes(vals).length == 0) { + return; + } + + vals.split(",", _array); + + for (i=0; i<_array.length; ++i) { + _array[i] = _array[i].trim(" \t\r\n"); + _array[i] = _array[i].trim("'\""); + } + } + + function keyExists(string _self, string _key) internal returns (bool _ret) { + int pos = _self.indexOf("\"".concat(_key, "\"")); + if (pos == -1) { + pos = _self.indexOf("'".concat(_key, "'")); + if (pos == -1) { + return false; + } + } + + return true; + } + + function storageToUint(string _self) internal returns (uint _ret) { + uint len = bytes(_self).length; + if (len > 32) { + len = 32; + } + + _ret = 0; + for(uint i=0; i= 'a' && bytes(_self)[i] <= 'z') { + bytes(_self)[i] &= ~0x20; + } + } + + _ret = _self; + } + + function toLower(string _self) internal returns (string _ret) { + for (uint i=0; i= 'A' && bytes(_self)[i] <= 'Z') { + bytes(_self)[i] |= 0x20; + } + } + + _ret = _self; + } + } \ No newline at end of file diff --git a/src/test/resources/contract/ParallelOk.sol b/src/test/resources/contract/ParallelOk.sol index 216adc5b8..99a868a31 100644 --- a/src/test/resources/contract/ParallelOk.sol +++ b/src/test/resources/contract/ParallelOk.sol @@ -7,13 +7,21 @@ contract ParallelOk is ParallelContract { mapping (string => uint256) _balance; + // Just an example, overflow is ok, use 'SafeMath' if needed function transfer(string from, string to, uint256 num) public { - // Just an example, overflow is ok, use 'SafeMath' if needed _balance[from] -= num; _balance[to] += num; } + // Just for testing whether the parallel revert function is working well, no practical use + function transferWithRevert(string from, string to, uint256 num) public + { + _balance[from] -= num; + _balance[to] += num; + require(num <= 100); + } + function set(string name, uint256 num) public { _balance[name] = num; diff --git a/src/test/resources/contract/Table.sol b/src/test/resources/contract/Table.sol index 14896a86b..e275d4772 100644 --- a/src/test/resources/contract/Table.sol +++ b/src/test/resources/contract/Table.sol @@ -1,24 +1,26 @@ +pragma solidity ^0.4.24; + contract TableFactory { function openTable(string) public constant returns (Table); //open table - function createTable(string,string,string) public constant returns(Table); //create table + function createTable(string,string,string) public returns(int); //create table } //select condition contract Condition { - function EQ(string, int); - function EQ(string, string); + function EQ(string, int) public; + function EQ(string, string) public; - function NE(string, int); - function NE(string, string); + function NE(string, int) public; + function NE(string, string) public; - function GT(string, int); - function GE(string, int); + function GT(string, int) public; + function GE(string, int) public; - function LT(string, int); - function LE(string, int); + function LT(string, int) public; + function LE(string, int) public; - function limit(int); - function limit(int, int); + function limit(int) public; + function limit(int, int) public; } //one record @@ -51,4 +53,4 @@ contract Table { function newEntry() public constant returns(Entry); function newCondition() public constant returns(Condition); -} \ No newline at end of file +} diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties index 3b52d9778..7565d9852 100644 --- a/src/test/resources/log4j.properties +++ b/src/test/resources/log4j.properties @@ -1,25 +1,44 @@ ### set log levels ### -#log4j.rootLogger = DEBUG , C , D , E -log4j.rootLogger = DEBUG , D , E - -###output the log information to the console### -log4j.appender.C = org.apache.log4j.ConsoleAppender -log4j.appender.C.Target = System.out -log4j.appender.C.layout = org.apache.log4j.PatternLayout -log4j.appender.C.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n - -### output the INFO level log information to the =./log/demo_debug.log ### -log4j.appender.D = org.apache.log4j.DailyRollingFileAppender -log4j.appender.D.File = ./log/demo_debug.log -log4j.appender.D.Append = true -log4j.appender.D.Threshold = DEBUG -log4j.appender.D.layout = org.apache.log4j.PatternLayout -log4j.appender.D.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n - -### output the ERROR level log information to the=./log/demo_error.log ### -log4j.appender.E = org.apache.log4j.DailyRollingFileAppender -log4j.appender.E.File = ./log/demo_error.log -log4j.appender.E.Append = true -log4j.appender.E.Threshold = ERROR -log4j.appender.E.layout = org.apache.log4j.PatternLayout -log4j.appender.E.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n \ No newline at end of file +log4j.rootLogger=INFO, info, error +### output the TRACE level log information to the =./log/trace.log ### +log4j.appender.trace=org.apache.log4j.DailyRollingFileAppender +log4j.appender.trace.File=./log/trace.log +log4j.appender.trace.Append=true +log4j.appender.trace.Threshold=TRACE +log4j.appender.trace.filter.traceFilter=org.apache.log4j.varia.LevelRangeFilter +log4j.appender.trace.filter.traceFilter.levelMin=TRACE +log4j.appender.trace.filter.traceFilter.levelMax=TRACE +log4j.appender.trace.layout=org.apache.log4j.PatternLayout +log4j.appender.trace.layout.ConversionPattern=[%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n +### output the DEBUG level log information to the =./log/debug.log ### +log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender +log4j.appender.debug.File=./log/debug.log +log4j.appender.debug.Append=true +log4j.appender.debug.Threshold=DEBUG +log4j.appender.debug.filter.debugFilter=org.apache.log4j.varia.LevelRangeFilter +log4j.appender.debug.filter.debugFilter.levelMin=DEBUG +log4j.appender.debug.filter.debugFilter.levelMax=DEBUG +log4j.appender.debug.layout=org.apache.log4j.PatternLayout +log4j.appender.debug.layout.ConversionPattern=[%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n +### output the INFO level log information to the =./log/info.log ### +log4j.appender.info=org.apache.log4j.DailyRollingFileAppender +log4j.appender.info.File=./log/info.log +log4j.appender.info.Append=true +log4j.appender.info.Threshold=INFO +log4j.appender.info.filter.infoFilter=org.apache.log4j.varia.LevelRangeFilter +log4j.appender.info.filter.infoFilter.levelMin=INFO +log4j.appender.info.filter.infoFilter.levelMax=INFO +log4j.appender.info.layout=org.apache.log4j.PatternLayout +log4j.appender.info.layout.ConversionPattern=[%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n +### output the ERROR level log information to the=./log/error.log ### +log4j.appender.error=org.apache.log4j.DailyRollingFileAppender +log4j.appender.error.File=./log/error.log +log4j.appender.error.Append=true +log4j.appender.error.Threshold=ERROR +log4j.appender.error.layout=org.apache.log4j.PatternLayout +log4j.appender.error.layout.ConversionPattern=[%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n +###output the log information to the console ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C{1}.%M(%L) | %m%n diff --git a/src/test/resources/node.crt b/src/test/resources/node.crt deleted file mode 100644 index fee594e4c..000000000 --- a/src/test/resources/node.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICODCCASCgAwIBAgIJAOXAnJI6O0fjMA0GCSqGSIb3DQEBCwUAMDcxDzANBgNV -BAMMBmFnZW5jeTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5 -MB4XDTE5MDQxMjA2MTgyMFoXDTI5MDQwOTA2MTgyMFowMjEMMAoGA1UEAwwDc2Rr -MRMwEQYDVQQKDApmaXNjby1iY29zMQ0wCwYDVQQLDARub2RlMFYwEAYHKoZIzj0C -AQYFK4EEAAoDQgAEJP4rdjuHrljd+ec8BprytDbq9VtXep8TlNVdnIOwSbraSoS5 -S4Pm0kA/WexWYzf+22x2SMRlZ8K3Ep+8DRwF26MaMBgwCQYDVR0TBAIwADALBgNV -HQ8EBAMCBeAwDQYJKoZIhvcNAQELBQADggEBABFWc/izBX2oBwSL5yB4ciMfabBb -jLGX5p0tsdsLlgC9i9fUduk8c65Lq0kXEpKFIbnPyZRU+Z/Yt1F7oaZw+Pbcrqhy -mZiI3g7MohlrCwPm/PpOgtOKPU8xo5Bv0AuvyUOq6jJFaXmuGl+uCHSxHanWNZgc -sbYiE0qGhyVHQ9buUfbuPvOQcpwxQfGFsSsqBMZFIgFbGAgcpZdkg1arDibKYHi8 -mtzKZTphgE3oo2IP+H4F+BciiZbC1ftNa8ncgFlMNnCXBtuAhpqF3fCDL4O8HKGO -4MVk8Je/YAWIMgauHEjVUimQxs0AXHOqUGwo5/f9txPlcv3OTIW582er/a0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC/zCCAeegAwIBAgIJAJwDH4/8SArjMA0GCSqGSIb3DQEBCwUAMDUxDjAMBgNV -BAMMBWNoYWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAe -Fw0xOTA0MTIwNjE4MTlaFw0yOTA0MDkwNjE4MTlaMDcxDzANBgNVBAMMBmFnZW5j -eTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2zcesW8v2kW2VUIec7diTzx7PUlw9KdZ -8mvYAUJE/MtHIgtWNj1Ur+zUctaRr52vElWacnhwDxWWwtVjbevsu7K2lTg1WAcy -uP3wyoVYTnjsMuP6JYcfNDpRxENTWuSAO5S7awJehQPcTN1ttyyAAah9AoH88fNc -Tpn7sazbJA1iKD9W4Nn8Ww25KS4o0+nB5cblhiS2IT1ZkEiXoekbKszybDq8fmKr -QW2Kdu/U95vEwz2YGhd8phL99WLdHjGZYzkmeJB6SJCPw76L5sEhMBrq4XAPxP6M -SM/W2YADvdwQxZ/8Tfz3eniD8qqaz2M+v3lAhFDXuW7ANMUus/GJDQIDAQABoxAw -DjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCHt6SBifVjnVUDnuj6 -+9xgZgTIBXpyvgJ1Q4BjLnzkuTGzFiR2V+qxtmeS/uNnjr0VuGLY2ZYBOefwmhVs -lfvq/oMicqyNqVeGHjF2j4NADu/VBI5OivdijatKbm/0HFzQSMIUXgJGl3KSeYYF -fyQCbPXTrSsQ2HNZr8YT/nhlFCw96yxJlvSpmDfR7nJiQeym9S98uDdDEdayehIn -wQ/q4X9ZkAbZmQ3uBCBThPedn1wXgt9lCPh/6n4oMK5OSf9csTWUvYUFHjIubNcL -VFjUcemBIigvDLxhDfzVl9nWb2cSJHL6+Fj0nb2YjYEgCbKv6FHFOfjsJOX6B4XZ -rs1z ------END CERTIFICATE----- diff --git a/src/test/resources/node.key b/src/test/resources/node.key deleted file mode 100644 index 7ea09f354..000000000 --- a/src/test/resources/node.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgZ2tuJooUP6a4y8Nfdi+i -LduvGXwegsbaLi1r05Zu8jyhRANCAAQk/it2O4euWN355zwGmvK0Nur1W1d6nxOU -1V2cg7BJutpKhLlLg+bSQD9Z7FZjN/7bbHZIxGVnwrcSn7wNHAXb ------END PRIVATE KEY----- diff --git a/tools/bin/compile.sh b/tools/bin/compile.sh deleted file mode 100644 index bf93e9277..000000000 --- a/tools/bin/compile.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash -# arg1: java packege name - - -# @function: output log with red color (error log) -# @param: content: error message -function LOG_ERROR() -{ - local content=${1} - echo -e "\033[31m"${content}"\033[0m" -} - -# @function: output information log -# @param: content: information message -function LOG_INFO() -{ - local content=${1} - echo -e "\033[32m"${content}"\033[0m" -} - -# @function: execute command -# @params: 1. command: command to be executed -function execute_cmd() -{ - local command="${1}" - - eval ${command} - local ret=$? - if [ $ret -ne 0 ];then - LOG_ERROR "execute command ${command} FAILED" - exit 1 - fi -} -chmod a+x web3sdk - -dirpath="$(cd "$(dirname "$0")" && pwd)" - -cd $dirpath"/../contracts" - -WEB3J=$dirpath"/../bin/web3sdk" -SOLC=`which fisco-solc` -Output=$dirpath"/../output" -Contracts=$dirpath"/../contracts" - -if [ $# -lt 1 ]; then - LOG_ERROR "usage: \n\targ1: java packege name" - LOG_ERROR "\targ2: enable guomi or not (0: disable guomi; 1: enable guomi), default disable guomi" - LOG_ERROR "\targ3: compiler path of guomi, default is ${SOLC}-guomi" - exit 1 -fi - -LOG_INFO "... TO COMPILE SOLIDITY CODES AND GENERATE JAVA FILES...\n" - -function compile() -{ - #path of solc(default: which fisco-bcos) - local solc_bin="${1}" - local output_dir="${2}" - LOG_INFO "#### SOLC_BIN: ${solc_bin}, OUTPUT_DIR: ${output_dir} \n" - local Files=`ls *.sol` - for itemfile in ${Files} - do - item=`basename $itemfile ".sol"` - LOG_INFO "compiling ${itemfile} ..." - execute_cmd "${solc_bin} --abi --bin -o ${output_dir} ${itemfile} --overwrite" - done - LOG_INFO "... ... COMPILE SUCCESS ... ... " -} - -function generate_java_code() -{ - local package="${1}" - local output_dir="${2}" - local guomi_output="" - if [ $# -ge 3 ];then - guomi_output="${3}" - fi - local files=`ls *.sol` - for itemfile in ${files} - do - local item=`basename ${itemfile} ".sol"` - LOG_INFO "... generate java code according to ${item}.sol abi, bin file..." - if [ "${guomi_output}" != "" -a -d "${guomi_output}" ];then - execute_cmd "${WEB3J} solidity generate ${output_dir}/${item}.bin ${output_dir}/${item}.abi -g ${guomi_output}/${item}.bin -o ${output_dir} -p ${package}" - else - execute_cmd "${WEB3J} solidity generate ${output_dir}/${item}.bin ${output_dir}/${item}.abi -o ${output_dir} -p ${package}" - fi - done -} - -function compile_default() -{ - LOG_INFO "#### COMPILE with DEFAULT COMPILER, SOLC: ${SOLC}, OUTPUT: ${Output} \n" - if [ -f "${SOLC}" ];then - compile "${SOLC}" "${Output}" - else - LOG_ERROR "DEFAULT COMPILER NOT FOUND, EXIT NOW..." - exit 1 - fi -} - -function compile_guomi() -{ - #default compiler of guomi - solc_bin="${1}" - LOG_INFO "#### COMPILE ABI AND BIN OF GUOMI VERSION\n" - if [ -f "${solc_bin}" ];then - compile "${solc_bin}" "${Output}/guomi" - return 0 - else - LOG_ERROR "#### COMPILER OF GUOMI NOT FOUND, COMPILE WITH DEFAULT COMPILER\n" - return 1 - fi -} - -function compile_and_generate() -{ - local package="${1}" - local enable_guomi="0" - if [ $# -ge 2 ];then - enable_guomi=${2} - fi - local guomi_solc_path="${SOLC}-guomi" - if [ $# -ge 3 ];then - guomi_solc_path="${3}" - fi - local guomi_ret=0 - LOG_INFO "... default guomi_solc_path: ${guomi_solc_path}\n" - #=========compile to generate bin and abi files========== - #compile bin and abi with default compiler - compile_default - if [ "${enable_guomi}" == "1" ];then - #compile bin and abi with guomi compiler - LOG_INFO "#### ENABLE GUOMI COMPILING\n" - compile_guomi "${guomi_solc_path}" - guomi_ret=$? - fi - #========generate java code============= - if [ "${enable_guomi}" == "1" -a ${guomi_ret} -eq 0 ];then - LOG_INFO "... GENERATE GUOMI VERSION JAVA CODE ...\n" - generate_java_code "${package}" "${Output}" "${Output}/guomi" - else - LOG_INFO "... GENERATE DEFAULT VERSION JAVA CODE...\n" - generate_java_code "${package}" "${Output}" - fi -} -rm -rf ${Output} -compile $@ - - -echo "ending ." -cd ../bin diff --git a/tools/bin/counter_compile.sh b/tools/bin/counter_compile.sh deleted file mode 100644 index 73a5342ae..000000000 --- a/tools/bin/counter_compile.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# @function: output log with red color (error log) -# @param: content: error message -function LOG_ERROR() -{ - local content=${1} - echo -e "\033[31m"${content}"\033[0m" -} - -# @function: output information log -# @param: content: information message -function LOG_INFO() -{ - local content=${1} - echo -e "\033[32m"${content}"\033[0m" -} - -# @function: execute command -# @params: 1. command: command to be executed -function execute_cmd() -{ - local command="${1}" - local ignored=0 - if [ $# -gt 1 ];then - ignored=${2} - fi - - eval "${command}" - local ret=$? - if [ $ret -ne 0 ] && [ $ret -ne ${ignored} ];then - LOG_ERROR "execute command ${command} FAILED" - exit 1 - fi -} - - -function Usage() -{ - LOG_INFO "Usage": - LOG_INFO " ./counter_compile.sh ${pacakge_name}" -} - -#get demo -execute_cmd "wget https://raw.githubusercontent.com/FISCO-BCOS/FISCO-BCOS-DOC/master/docs/web3sdk/codes/Counter.sol -O Counter.sol" -#move Counter.sol to contract compiliation direcotry -execute_cmd "mv Counter.sol ../contracts" - -if [ $# -lt 1 ];then - Usage - exit 1 -fi -execute_cmd "chmod a+x compile.sh && ./compile.sh $@" - diff --git a/tools/bin/web3sdk b/tools/bin/web3sdk deleted file mode 100755 index 4bf7b4cc3..000000000 --- a/tools/bin/web3sdk +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env bash -# arg1: java packege name -LANG=zh_CN.UTF-8 -############################################################################## -## -## evidence start up script for UN*X -## -############################################################################## - -# @function: output log with red color (error log) -# @param: content: error message -function LOG_ERROR() -{ - local content=${1} - echo -e "\033[31m"${content}"\033[0m" -} - -# @function: output information log -# @param: content: information message -function LOG_INFO() -{ - local content=${1} - echo -e "\033[32m"${content}"\033[0m" -} - -# @function: execute command -# @params: 1. command: command to be executed -function execute_cmd() -{ - local command="${1}" - eval "${command}" - local ret=$? - if [ $ret -ne 0 ];then - LOG_ERROR "execute command ${command} FAILED" - exit 1 - fi - return 0 -} - -function Usage() { - LOG_INFO "###### Console TOOLS" - LOG_INFO "--Start console: \n\t./web3sdk -c [groupID] [privateKey]\n" - - LOG_INFO "###### SystemContract TOOLS(please refer to https://fisco-bcos-test.readthedocs.io/zh/latest/docs/web3sdk/advanced/index.html)" - LOG_INFO "--Deploy system contract: \n\t./web3sdk InitSystemContract\n" - LOG_INFO "--Get system contract routers: \n\t./web3sdk SystemProxy\n" - LOG_INFO "--Manager leaders: \n\t./web3sdk NodeAction all|registerNode|cancelNode\n" - LOG_INFO "--Manager black-list of certificates : \n\t./web3sdk CAAction all|add|remove\n" - LOG_INFO "--Manager system params of FISCO-BCOS blockchain: \n\t./web3sdk ConfigAction get|set\n" - LOG_INFO "--ConsensusControl: \n\t./web3sdk ConsensusControl deploy|turnoff|list\n" - LOG_INFO "--CNS tools: \n\t./web3sdk CNSAction add|update|get|list|historylist|reset\n" - LOG_INFO "\n" - LOG_INFO "###### Web3j API (please refer to https://fisco-bcos-test.readthedocs.io/zh/latest/docs/web3sdk/advanced/web3sdk_api.html)" - - LOG_INFO "--Obtain version of web3j: \n\t./web3sdk web3_clientVersion\n" - LOG_INFO "--Obtain account: \n\t./web3sdk eth_accounts\n" - LOG_INFO "--Obtain current block number: \n\t./web3sdk eth_blockNumber\n" - LOG_INFO "--Obtain current pbft view: \n\t./web3sdk eth_pbftView\n" - LOG_INFO "--Obtain binary code of specified contract: \n\t./web3sdk eth_getCode address blockNumber\n" - LOG_INFO "--Get transaction according to transaction hash: \n\t./web3sdk eth_getBlockTransactionCountByHash blockHash\n" - LOG_INFO "--Get transaction count of specified account located in specified block: \n\t./web3sdk eth_getTransactionCount address blockNumber\n" - LOG_INFO "--Get total count of transactions located in specifed block: \n\t./web3sdk eth_getBlockTransactionCountByNumber blockNumber\n" - LOG_INFO "--Send signed data to block-chain: \n\t./web3sdk eth_sendRawTransaction signTransactionData\n" - LOG_INFO "--Get specified block according to block hash: \n\t./web3sdk eth_getBlockByHash blockHash true|false\n" - LOG_INFO "--Get specified block according to block number: \n\t./web3sdk eth_getBlockByNumber blockNumber\n" - LOG_INFO "--Get specified transaction according to block height and transaction position: \n\t./web3sdk eth_getTransactionByBlockNumberAndIndex blockNumber transactionPosition\n" - LOG_INFO "--Get specified transaction according to block hash and transaction position: \n\t./web3sdk eth_getTransactionByBlockHashAndIndex blockHash transactionPosition\n" - LOG_INFO "--Get transaction receipt according to transaction hash: \n\t./web3sdk eth_getTransactionReceipt transactionHash\n" - LOG_INFO "\n" - LOG_INFO "###### Permission Control API(please refer to https://fisco-bcos-test.readthedocs.io/zh/latest/docs/web3sdk/advanced/web3sdk_api.html)" - LOG_INFO "--Deploy permission control contract: \n\t./web3sdk ARPI_Model\n" - LOG_INFO "--Obtain permission information: \n\t./web3sdk PermissionInfo\n" - LOG_INFO "--Add specified filter: \n\t./web3sdk FilterChain addFilter name1 version1 desc1\n" - LOG_INFO "--Delete specified filter: \n\t./web3sdk FilterChain delFilter num\n" - LOG_INFO "--Show all filters: \n\t./web3sdk FilterChain showFilter\n" - LOG_INFO "--Reset all filters: \n\t./web3sdk FilterChain resetFilter\n" - LOG_INFO "--Get status of specified filter: \n\t./web3sdk Filter getFilterStatus num\n" - LOG_INFO "--Enable specified filter: \n\t./web3sdk Filter enableFilter num\n" - LOG_INFO "--Disable specified filter: \n\t./web3sdk Filter disableFilter num\n" - LOG_INFO "--Set specified account to specified group: \n\t./web3sdk Filter setUsertoNewGroup num account\n" - LOG_INFO "--Add specified account to existed group: \n\t./web3sdk Filter setUsertoExistingGroup num account group\n" - LOG_INFO "--Query group information of speicifed account: \n\t./web3sdk Filter listUserGroup num account\n" - LOG_INFO "--Query whether specified account owned to specified group has been added to black-name list or not: \n\t./web3sdk Group getBlackStatus num account\n" - LOG_INFO "--Add specified account to black-name list: \n\t./web3sdk Group enableBlack num account\n" - LOG_INFO "--Remove specified account from black-name list: \n\t./web3sdk Group disableBlack num account\n" - LOG_INFO "--Query whether specified account has permission to deploy contracts: \n\t./web3sdk Group getDeployStatus num account\n" - LOG_INFO "--Enable the contract deployment permission for specified account: \n\t./web3sdk Group enableDeploy num account\n" - LOG_INFO "--Remove the contract deployment permission for specified account: \n\t./web3sdk Group disableDeploy num account\n" - LOG_INFO "--Add permission for specified account to callback function of specified contract: \n\t./web3sdk Group addPermission num account A.address fun(string)\n" - LOG_INFO "--Remove permission for specified account to callback function of specified contract: \n\t./web3sdk Group delPermission num account A.address fun(string)\n" - LOG_INFO "--Check whether specified account can callback specified function of specified contract: \n\t./web3sdk Group checkPermission num account A.address fun(string)\n" - LOG_INFO "--List permissons of account owned to specified group: \n\t./web3sdk Group listPermission num account\n" - LOG_INFO "\n" - LOG_INFO "###### UTXO API" - - LOG_INFO "UTXO Command reference is as follows" - LOG_INFO "--Init specified type tokens: \n\t./web3sdk InitTokens Type\n" - LOG_INFO "--Send tokens: \n\t./web3sdk SendSelectedTokens Type\n" - LOG_INFO "--Register Account: \n\t./web3sdk RegisterAccount Account\n" - LOG_INFO "--Track token transferred records : \n\t./web3sdk TokenTracking TokenKey\n" - LOG_INFO "--Get balance of specified account: \n\t./web3sdk GetBalance Account\n" - LOG_INFO "--Select specified amount of token from specified account: \n\t./web3sdk SelectTokens Account Value\n" - LOG_INFO "--Get token according to TokenKey: \n\t./web3sdk GetToken TokenKey\n" - LOG_INFO "--Get UTXO transaction according to TxKey: \n\t./web3sdk GetTx TxKey\n" - LOG_INFO "--Get value of specified token: \n\t./web3sdk GetVault Account TokenType\n" -} - -#第一个参数不能为空 -if [ $# -lt 1 ]; then - Usage - exit 1 -fi - -if [ "${1}" == "-h" ] || [ "${1}" == "--help" ] || [ "${1}" == "help" ];then - Usage - exit 0 -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/.." >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="web3j" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and WEB3J_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - LOG_INFO "$*" -} - -die ( ) { - LOG_INFO - LOG_INFO "$*" - LOG_INFO - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/conf - -for f in $APP_HOME/lib/*.jar -do -CLASSPATH=$CLASSPATH:$f -done - -for f in $APP_HOME/apps/*.jar -do -CLASSPATH=$CLASSPATH:$f -done - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`LOG_INFO "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`LOG_INFO "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `LOG_INFO args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `LOG_INFO args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And WEB3J_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $WEB3J_OPTS - -if [ $1 == "-c" ]; then - java -cp "../apps/*:../conf/:../lib/*" org.fisco.bcos.web3j.console.ConsoleClient $2 $3 - -else - exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" Runner "$@" -fi - - diff --git a/tools/contracts/Evidence.sol b/tools/contracts/Evidence.sol deleted file mode 100644 index 467fe14e3..000000000 --- a/tools/contracts/Evidence.sol +++ /dev/null @@ -1,105 +0,0 @@ -pragma solidity ^0.4.4; -contract EvidenceSignersDataABI{ function verify(address addr)public constant returns(bool){} -function getSigner(uint index)public constant returns(address){} -function getSignersSize() public constant returns(uint){} -} - -contract Evidence{ - - string evidence; - string evidenceInfo; - string evidenceId; - uint8[] _v; - bytes32[] _r; - bytes32[] _s; - address[] signers; - address public signersAddr; - - event addSignaturesEvent(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s); - event newSignaturesEvent(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s,address addr); - event errorNewSignaturesEvent(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s,address addr); - event errorAddSignaturesEvent(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s,address addr); - event addRepeatSignaturesEvent(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s); - event errorRepeatSignaturesEvent(string evi, string id, uint8 v, bytes32 r, bytes32 s, address addr); - - function CallVerify(address addr) public constant returns(bool) { - return EvidenceSignersDataABI(signersAddr).verify(addr); - } - - function Evidence(string evi, string info, string id, uint8 v, bytes32 r, bytes32 s, address addr, address sender) public { - signersAddr = addr; - if(CallVerify(sender)) - { - evidence = evi; - evidenceInfo = info; - evidenceId = id; - _v.push(v); - _r.push(r); - _s.push(s); - signers.push(sender); - newSignaturesEvent(evi,info,id,v,r,s,addr); - } - else - { - errorNewSignaturesEvent(evi,info,id,v,r,s,addr); - } - } - - function getEvidenceInfo() public constant returns(string){ - return evidenceInfo; - } - - function getEvidence() public constant returns(string,string,string,uint8[],bytes32[],bytes32[],address[]){ - uint length = EvidenceSignersDataABI(signersAddr).getSignersSize(); - address[] memory signerList = new address[](length); - for(uint i= 0 ;i ${keccak_256_tar} + else + keccak256sum="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" + echo ${keccak256sum} | base64 -d - > ${keccak_256_tar} + fi + tar -zxf ${keccak_256_tar} -C /tmp + chmod u+x ${keccak_256_bin} + fi + mkdir -p accounts +} + +LOG_INFO() +{ + local content=${1} + echo -e "\033[32m[INFO] ${content}\033[0m" +} + +check_env() { + [ ! -z "$(openssl version | grep 1.0.2)" ] || [ ! -z "$(openssl version | grep 1.1)" ] || [ ! -z "$(openssl version | grep reSSL)" ] || { + echo "please install openssl! use \"openssl version\" command to check." + LOG_INFO " Ubuntu : sudo apt install -y openssl" + LOG_INFO " CentOS : sudo yum install -y openssl" + LOG_INFO " macOS : brew install -y openssl" + exit 1 + } + if [ ! -z "$(openssl version | grep reSSL)" ];then + export PATH="/usr/local/opt/openssl/bin:$PATH" + fi +} + +calculate_address_pem() +{ + local pem_file=$1 + local no_print="$2" + prepare_keccak256 + privKey=$(openssl ec -in ${pem_file} -text -noout 2>/dev/null| sed -n '3,5p' | tr -d ": \n" | awk '{print $0}') + pubKey=$(openssl ec -in ${pem_file} -text -noout 2>/dev/null| sed -n '7,11p' | tr -d ": \n" | awk '{print substr($0,3);}') + accountAddress=$(echo ${pubKey}| ${keccak_256_bin} -x -l | tr -d ' -' | tail -c 41) + [ ! -z "${no_print}" ] || LOG_INFO "Account Address : 0x${accountAddress}" +} + +calculate_address_pkcs12() +{ + local p12_file=$1 + local pem_file="/tmp/.tmp.pem" + openssl pkcs12 -in ${p12_file} -out ${pem_file} -nodes + calculate_address_pem ${pem_file} + rm ${pem_file} +} + +main() +{ + while getopts "k:pP:h" option;do + case $option in + k) calculate_address_pem "$OPTARG" + exit 0;; + P) calculate_address_pkcs12 "$OPTARG" + exit 0;; + p) #pkcs12_file="$OPTARG" + pkcs12_file="true" + ;; + h) help;; + esac + done + check_env + prepare_keccak256 + openssl ecparam -out /tmp/secp256k1.param -name secp256k1 + openssl genpkey -paramfile /tmp/secp256k1.param -out ${output_path}/ecprivkey.pem + calculate_address_pem ${output_path}/ecprivkey.pem "true" + if [ -z "$pkcs12_file" ];then + mv ${output_path}/ecprivkey.pem ${output_path}/0x${accountAddress}.pem + LOG_INFO "Account Address : 0x${accountAddress}" + LOG_INFO "Private Key (pem) : ${output_path}/0x${accountAddress}.pem" + # echo "0x${privKey}" > ${output_path}/${accountAddress}.private.hex + # openssl ec -in ${output_path}/ecprivkey.pem -pubout -out ${output_path}/${accountAddress}.public.pem 2>/dev/null + # LOG_INFO "Public Key (pem) : ${output_path}/${accountAddress}.publick.pem" + else + openssl pkcs12 -export -name key -nocerts -inkey "${output_path}/ecprivkey.pem" -out "${output_path}/0x${accountAddress}.p12" # -passout "pass:${pkcs12_passwd}" + rm ${output_path}/ecprivkey.pem + LOG_INFO "Account Address : 0x${accountAddress}" + LOG_INFO "Private Key (p12) : ${output_path}/0x${accountAddress}.p12" + fi + # LOG_INFO "Private Key (hex) : 0x${privKey}" + # echo "0x${pubKey}" > ${output_path}/${accountAddress}.public.hex + # LOG_INFO "Public File(hex) : ${output_path}/${accountAddress}.public.hex" +} + +main $@ + diff --git a/tools/sol2java.sh b/tools/sol2java.sh deleted file mode 100644 index 385795424..000000000 --- a/tools/sol2java.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -LANG=zh_CN.UTF-8 -############################################################################## -## -## Console start up script for UN*X -## -############################################################################## - -# @function: output log with red color (error log) -# @param: content: error message -function LOG_ERROR() -{ - local content=${1} - echo -e "\033[31m"${content}"\033[0m" -} - -# @function: output information log -# @param: content: information message -function LOG_INFO() -{ - local content=${1} - echo -e "\033[32m"${content}"\033[0m" -} - -function Usage() { - LOG_INFO "# Compile Solidity TOOLS" - LOG_INFO "./sol2java [packageName]\n" -} - -if [ "${1}" == "-h" ] || [ "${1}" == "--help" ] || [ "${1}" == "help" ];then - Usage - exit 0 -else - java -cp "../apps/*:../lib/*" org.fisco.bcos.web3j.utils.CompileSolToJava $1 -fi - - diff --git a/tools/start.sh b/tools/start.sh deleted file mode 100755 index f2cdf4a92..000000000 --- a/tools/start.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -LANG=zh_CN.UTF-8 -############################################################################## -## -## Console start up script for UN*X -## -############################################################################## - -# @function: output log with red color (error log) -# @param: content: error message -function LOG_ERROR() -{ - local content=${1} - echo -e "\033[31m"${content}"\033[0m" -} - -# @function: output information log -# @param: content: information message -function LOG_INFO() -{ - local content=${1} - echo -e "\033[32m"${content}"\033[0m" -} - -function Usage() { - LOG_INFO "# Console TOOLS" - LOG_INFO "--Start console: \t./start [groupID] [privateKey]\n" -} - -if [ "${1}" == "-h" ] || [ "${1}" == "--help" ] || [ "${1}" == "help" ];then - Usage - exit 0 -else - java -cp "apps/*:conf/:lib/*:classes/" org.fisco.bcos.web3j.console.ConsoleClient $1 $2 -fi - -