Private-Blockchain
“所需的氣體超過限額或總是失敗的交易”是什麼問題
我使用 solc 和 web3j 將智能合約翻譯成 Java,但我遇到了“所需的氣體超過限額或交易總是失敗”的問題。
這是我的智能合約。
當我使用 Remix 在我的私有鏈上部署時,它是有效的。當我使用 solc 和 web3j 將智能合約翻譯成 Java 時,這個 Java 版本不起作用。
我的作業系統版本:Ubuntu 18.04.2 LTS
我的 solc 版本:0.5.7+commit.6da8b019.Linux.g++
我的 web3j 版本:4.2.0
智能合約Java程式碼:
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.web3j.abi.EventEncoder; import org.web3j.abi.TypeReference; import org.web3j.abi.datatypes.Event; import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.RemoteCall; import org.web3j.protocol.core.methods.request.EthFilter; import org.web3j.protocol.core.methods.response.Log; import org.web3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.tx.Contract; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; /** * <p>Auto generated code. * <p><strong>Do not modify!</strong> * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>, * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the * <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update. * * <p>Generated with web3j version 4.2.0. */ public class Hello extends Contract { private static final String BINARY = "60806040526005600055348015601457600080fd5b506098806100236000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806313bdfacd14602d575b600080fd5b60336035565b005b60005460408051918252517f909c57d5c6ac08245cf2a6de3900e2b868513fa59099b92b27d8db823d92df9c9181900360200190a156fea165627a7a723058203b5d233e1ef9461ed0361b73be5990af6f29a72874bd3a87184a427417c991a50029"; public static final String FUNC_PRINT = "print"; public static final Event LOG_EVENT = new Event("Log", Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {})); ; @Deprecated protected Hello(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } protected Hello(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated protected Hello(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } protected Hello(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } public RemoteCall<TransactionReceipt> print() { final Function function = new Function( FUNC_PRINT, Arrays.<Type>asList(), Collections.<TypeReference<?>>emptyList()); return executeRemoteCallTransaction(function); } public List<LogEventResponse> getLogEvents(TransactionReceipt transactionReceipt) { List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(LOG_EVENT, transactionReceipt); ArrayList<LogEventResponse> responses = new ArrayList<LogEventResponse>(valueList.size()); for (Contract.EventValuesWithLog eventValues : valueList) { LogEventResponse typedResponse = new LogEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.txmessage = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } public Flowable<LogEventResponse> logEventFlowable(EthFilter filter) { return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function<Log, LogEventResponse>() { @Override public LogEventResponse apply(Log log) { Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(LOG_EVENT, log); LogEventResponse typedResponse = new LogEventResponse(); typedResponse.log = log; typedResponse.txmessage = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } }); } public Flowable<LogEventResponse> logEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(LOG_EVENT)); return logEventFlowable(filter); } @Deprecated public static Hello load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { return new Hello(contractAddress, web3j, credentials, gasPrice, gasLimit); } @Deprecated public static Hello load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { return new Hello(contractAddress, web3j, transactionManager, gasPrice, gasLimit); } public static Hello load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { return new Hello(contractAddress, web3j, credentials, contractGasProvider); } public static Hello load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { return new Hello(contractAddress, web3j, transactionManager, contractGasProvider); } public static RemoteCall<Hello> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { return deployRemoteCall(Hello.class, web3j, credentials, contractGasProvider, BINARY, ""); } @Deprecated public static RemoteCall<Hello> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { return deployRemoteCall(Hello.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); } public static RemoteCall<Hello> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { return deployRemoteCall(Hello.class, web3j, transactionManager, contractGasProvider, BINARY, ""); } @Deprecated public static RemoteCall<Hello> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { return deployRemoteCall(Hello.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); } public static class LogEventResponse { public Log log; public BigInteger txmessage; } }
我的 GasProvider Java 程式碼:
import java.math.BigInteger; import org.web3j.tx.Contract; import org.web3j.tx.gas.StaticGasProvider; public class myGasProvider extends StaticGasProvider { public static final BigInteger GAS_LIMIT = BigInteger.valueOf(3000000); public static final BigInteger GAS_PRICE = BigInteger.valueOf(0); public myGasProvider() { super(GAS_PRICE, GAS_LIMIT); } }
這是用於部署和使用智能合約的 Java 程式碼。
import java.io.File; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import org.omg.CORBA.Environment; import org.web3j.abi.datatypes.Uint; import org.web3j.abi.datatypes.Utf8String; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.crypto.CipherException; import org.web3j.crypto.WalletUtils; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.protocol.core.methods.response.Web3ClientVersion; import org.web3j.protocol.http.HttpService; import org.web3j.tx.gas.ContractGasProvider; import org.web3j.tx.gas.DefaultGasProvider; import jnr.unixsocket.Credentials; public class QuickStart { private static Web3j web3j; public static void main(String[] args) throws Exception { web3j = Web3j.build(new HttpService("http://192.168.80.128:8545/")); Web3ClientVersion web3ClientVersion = null; try { web3ClientVersion = web3j.web3ClientVersion().send(); String clientVersion = web3ClientVersion.getWeb3ClientVersion(); System.out.println("clientVersion " + clientVersion); String filePath = "./key/"; String fileName; fileName = WalletUtils.generateNewWalletFile("123456", new File(filePath), false); org.web3j.crypto.Credentials credentials = WalletUtils.loadCredentials("123456",filePath+fileName); //System.out.println(fileName);//保存你的加密文件資訊 System.out.println("Eth address: "+credentials.getAddress());//钱包地址 System.out.println("Eth address private key: "+credentials.getEcKeyPair().getPrivateKey());//私钥 System.out.println("Eth address public key: "+credentials.getEcKeyPair().getPublicKey());//公钥 ContractGasProvider contractGasProvider = new myGasProvider(); //BigInteger GAS_LIMIT = BigInteger.valueOf(3000000); //BigInteger GAS_PRICE = BigInteger.valueOf(0); Hello contract= Hello.deploy(web3j, credentials,contractGasProvider).send(); System.out.println("Smart Contrac address:"+contract.getContractAddress()); System.out.println("Smart Contrac Usage:"+contract.isValid()); TransactionReceipt transactionReceipt=contract.print().send(); System.out.println("transaction hash:"+transactionReceipt.getTransactionHash()); System.out.println("transaction data:"+transactionReceipt.toString()); } catch (IOException e) { e.printStackTrace(); } } }
馬文:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Test</groupId> <artifactId>Test</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>io.reactivex.rxjava2</groupId> <artifactId>rxjava</artifactId> <version>2.1.12</version> </dependency> </dependencies> </project>
程序結果
clientVersion Geth/v1.9.0-unstable-9a58a9b9/linux-amd64/go1.10.4 Eth address: 0xe2232ad9fd8a2e7c879500ddbf146670244798ab Eth address private key: 47678188744480457656968595668529367483035979819489762803117503272466348282724 Eth address public key: 9875770019807071285812783255049855080295070551278042833113719057002229716018811513481131655753052174064293298860327874461667018196051277952135391995718979 Smart Contract address:0xef8b6c0d7adad1b416b21806d3cb6d541ba26a19 Smart Contract Usage:true transaction hash:0xf9f50c7823cb77a612ae91d721058eb15003135c858bbb4fb6af616bddc93ff8 transaction data:TransactionReceipt{transactionHash='0xf9f50c7823cb77a612ae91d721058eb15003135c858bbb4fb6af616bddc93ff8', transactionIndex='0x0', blockHash='0x60f1b8664edb0a76231f97262f7861ae12b3de3632f71489dd7eb2b517d6d51f', blockNumber='0x2a0', cumulativeGasUsed='0x2dc6c0', gasUsed='0x2dc6c0', contractAddress='null', root='0xb028fd4ac6173b30c8945fb988d408238f794faccbc20805e81cc57146fced7c', status='null', from='0xe2232ad9fd8a2e7c879500ddbf146670244798ab', to='0xef8b6c0d7adad1b416b21806d3cb6d541ba26a19', logs=[], logsBloom='0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'}
我的交易日誌為空,結果是通過 Remix 與智能合約 adderss 互動。
煤氣都用完了,但契約花不了多少錢。我覺得很奇怪,不知道會發生什麼。請給我一些建議。謝謝你的幫助。
您可以將 Solidity 版本從 “0.5.7+commit.6da8b019.Linux.g++” 更改為以前的版本(如***“0.5.2+commit.1df8f40c.Emscripten.clang”***),這將解決問題。
您可以檢查 geth 節點日誌以找出實際問題。
我遇到了類似的問題,錯誤是err=“invalid opcode 0x1c”
您可以使用以前的編譯器版本從 remix 中部署智能合約,並使用 java 中的合約地址來載入合約以解決錯誤。
或者您可能需要更新您的 geth 版本以支持新功能。
希望這會有所幫助
該操作碼是最近在君士坦丁堡版本中添加到 geth 的。您需要將以下內容添加到您的 genesis 以啟用君士坦丁堡:
"constantinopleBlock":0,