Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ ext {
commonsIOVersion = '2.11.0'
commonsLang3Version = '3.12.0'
toml4jVersion = "0.7.2"
bcprovJDK15onVersion = '1.69'
bcprovJDK18onVersion = '1.75'
webankJavaCryptoVersion = "1.0.3"
junitVersion = '4.13.2'
commonsCollections4Version = "4.4"
bcosSdkJniVersion = "3.5.0"
bcosSdkJniVersion = "3.6.0-SNAPSHOT"
slf4jApiVerison = '1.7.36'
mockitoVersion = '4.8.0'
gsonVersion = '2.10.1'
Expand All @@ -40,7 +40,7 @@ allprojects {
apply plugin: 'maven-publish'
apply plugin: 'idea'
apply plugin: 'eclipse'

apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'jacoco'
Expand Down Expand Up @@ -125,13 +125,13 @@ googleJavaFormat {
}

dependencies {
api("org.fisco-bcos:fisco-bcos-tars-sdk" + ":${tarsSDKVersion}")
api("org.fisco-bcos:bcos-sdk-jni:${bcosSdkJniVersion}") {
exclude group : "org.slf4j"
exclude group : "com.fasterxml.jackson.core"
api("org.fisco-bcos:fisco-bcos-tars-sdk" + ":${tarsSDKVersion}")
api("org.fisco-bcos:bcos-sdk-jni:${bcosSdkJniVersion}") {
exclude group: "org.slf4j"
exclude group: "com.fasterxml.jackson.core"
}

api("org.bouncycastle:bcprov-jdk15on:${bcprovJDK15onVersion}")
api("org.bouncycastle:bcprov-jdk18on:${bcprovJDK18onVersion}")
api("com.google.code.gson:gson:${gsonVersion}")
api("org.apache.commons:commons-lang3:${commonsLang3Version}")
api("com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}")
Expand Down Expand Up @@ -177,10 +177,12 @@ javadoc {
}

task copyHooks(type: Copy) {
from("hooks") {
include "**"
if (!file(".git/hooks/pre-commit").exists()) {
from("hooks") {
include "**"
}
into ".git/hooks"
}
into ".git/hooks"
}

task sourcesJar(type: Jar) {
Expand Down Expand Up @@ -265,7 +267,7 @@ publishing {

jar {
// destinationDir file('dist/apps')
archiveFileName="fisco-bcos-" + project.name + '-' + project.version + '.jar'
archiveFileName = "fisco-bcos-" + project.name + '-' + project.version + '.jar'
exclude '**/*.xml'
exclude '**/*.properties'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
package org.fisco.bcos.sdk.v3.test.transaction.demo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.fisco.bcos.sdk.jni.common.JniException;
import org.fisco.bcos.sdk.jni.utilities.tx.TransactionBuilderJniObj;
import org.fisco.bcos.sdk.v3.BcosSDK;
import org.fisco.bcos.sdk.v3.client.Client;
import org.fisco.bcos.sdk.v3.codec.ContractCodecException;
import org.fisco.bcos.sdk.v3.model.ConstantConfig;
import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.v3.transaction.codec.decode.TransactionDecoderService;
import org.fisco.bcos.sdk.v3.transaction.manager.AssembleTransactionWithRemoteSignProcessor;
import org.fisco.bcos.sdk.v3.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.v3.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.v3.transaction.model.dto.TransactionResponse;
import org.fisco.bcos.sdk.v3.transaction.model.exception.NoSuchTransactionFileException;
import org.fisco.bcos.sdk.v3.transaction.model.exception.TransactionBaseException;
import org.fisco.bcos.sdk.v3.transaction.signer.RemoteSignProviderInterface;
import org.fisco.bcos.sdk.v3.utils.Hex;

public class AssembleTransactionWithRemoteSignProcessorSample {
private static final String configFile =
"src/integration-test/resources/" + ConstantConfig.CONFIG_FILE_NAME;

// 合约ABI文件目录
private static final String abiFile = "src/integration-test/resources/abi/";
// 合约BIN文件目录
private static final String binFile = "src/integration-test/resources/bin/";
// prepare sdk, read from the config file
private final BcosSDK sdk;
private final Client client;
// mock remote sign service
private final RemoteSignProviderInterface remoteSignProviderMock;
private final String abi;

private final AssembleTransactionWithRemoteSignProcessor
assembleTransactionWithRemoteSignProcessor;

public AssembleTransactionWithRemoteSignProcessorSample()
throws IOException, NoSuchTransactionFileException {
// create sdk by config file
sdk = BcosSDK.build(configFile);
client = this.sdk.getClient("group0");
// RemoteSignProviderMock 为mock服务,可以改为调用远程签名服务
remoteSignProviderMock = new RemoteSignProviderMock(this.client.getCryptoSuite());
// build processor
assembleTransactionWithRemoteSignProcessor =
TransactionProcessorFactory.createAssembleTransactionWithRemoteSignProcessor(
this.client,
this.client.getCryptoSuite().getCryptoKeyPair(),
abiFile,
binFile,
this.remoteSignProviderMock);
// 从contract loader内获取ABI字符串,也可以直接从外部传入
abi =
assembleTransactionWithRemoteSignProcessor
.getContractLoader()
.getABIByContractName("HelloWorld");
}

public String deployContract()
throws NoSuchTransactionFileException, ContractCodecException, JniException,
ExecutionException, InterruptedException, TimeoutException {

// 从contract loader内获取ABI字符串,也可以直接从外部传入
String abi =
assembleTransactionWithRemoteSignProcessor
.getContractLoader()
.getABIByContractName("HelloWorld");
// 从contract loader内获取BIN字符串,也可以直接从外部传入
String bin =
assembleTransactionWithRemoteSignProcessor
.getContractLoader()
.getBinaryByContractName("HelloWorld");

/// 1. 准备部署交易参数
List<Object> params = new ArrayList<>(Collections.singletonList("test"));
// 部署合约需要bin、abi、构造参数
/// 2. 构造交易体结构
// 构造交易结构,long是指针类型,使用完后需要主动释放
long transactionData =
assembleTransactionWithRemoteSignProcessor.getRawTransactionForConstructor(
abi, bin, params);

try {

/// 3. 使用交易体计算交易哈希
// 返回交易哈希,十六进制字符串
String rawTxHash =
TransactionBuilderJniObj.calcTransactionDataHash(
client.getCryptoSuite().cryptoTypeConfig, transactionData);

/// 4. 请求远程签名服务对交易哈希进行签名
CompletableFuture<TransactionReceipt> receiptCompletableFuture =
new CompletableFuture<>();

// 发起远程签名请求, 对bytes签名
remoteSignProviderMock.requestForSignAsync(
Hex.decode(rawTxHash),
this.client.getCryptoSuite().cryptoTypeConfig,
signatureResult -> {

/// 5. 获取到签名之后,拼装完整交易,并获取编码后的交易
String signedTransaction = null;
try {
signedTransaction =
TransactionBuilderJniObj.createSignedTransaction(
transactionData,
Hex.toHexString(signatureResult.encode()),
rawTxHash,
0);
} catch (JniException e) {
throw new RuntimeException(e);
}

/// 6. 将编码后的交易发送到链上
assembleTransactionWithRemoteSignProcessor.sendTransactionAsync(
signedTransaction,
new TransactionCallback() {
@Override
public void onResponse(TransactionReceipt receipt) {
receiptCompletableFuture.complete(receipt);
}
});
return 0;
});

TransactionReceipt transactionReceipt =
receiptCompletableFuture.get(10000, TimeUnit.MILLISECONDS);

String contractAddress = transactionReceipt.getContractAddress();
if (transactionReceipt.isStatusOK()) {
System.out.println("部署合约成功,合约地址:" + contractAddress);
}

return contractAddress;
} finally {
TransactionBuilderJniObj.destroyTransactionData(transactionData);
}
}

public TransactionResponse sendTransaction(String address, List<Object> params)
throws JniException, ContractCodecException, ExecutionException, InterruptedException,
TimeoutException {

// 1. 准备交易参数
// 2. 构造交易体
long transactionData =
assembleTransactionWithRemoteSignProcessor.getRawTransaction(
address, abi, "set", params);

try {

/// 3. 使用交易体计算交易哈希
// 返回交易哈希,十六进制字符串
String rawTxHash =
TransactionBuilderJniObj.calcTransactionDataHash(
client.getCryptoSuite().cryptoTypeConfig, transactionData);

/// 4. 请求远程签名服务对交易哈希进行签名
CompletableFuture<TransactionReceipt> receiptCompletableFuture =
new CompletableFuture<>();

// 发起远程签名请求, 对bytes签名
remoteSignProviderMock.requestForSignAsync(
Hex.decode(rawTxHash),
this.client.getCryptoSuite().cryptoTypeConfig,
signatureResult -> {

/// 5. 获取到签名之后,拼装完整交易,并获取编码后的交易
String signedTransaction = null;
try {
signedTransaction =
TransactionBuilderJniObj.createSignedTransaction(
transactionData,
Hex.toHexString(signatureResult.encode()),
rawTxHash,
0);
} catch (JniException e) {
throw new RuntimeException(e);
}

/// 6. 将编码后的交易发送到链上
assembleTransactionWithRemoteSignProcessor.sendTransactionAsync(
signedTransaction,
new TransactionCallback() {
@Override
public void onResponse(TransactionReceipt receipt) {
receiptCompletableFuture.complete(receipt);
}
});
return 0;
});

/// 5. 收到交易回执
TransactionReceipt transactionReceipt =
receiptCompletableFuture.get(10000, TimeUnit.MILLISECONDS);

/// 6. 解析交易回执
TransactionDecoderService transactionDecoderService =
new TransactionDecoderService(client.getCryptoSuite(), client.isWASM());

if (transactionReceipt.isStatusOK()) {
/// 7. 如果回执中存在事件
/// Map<String, List<List<Object>>> stringListMap =
// transactionDecoderService.decodeEvents(abi, transactionReceipt.getLogEntries());
/// 8. 如果合约有返回值
// TransactionResponse transactionResponse =
// transactionDecoderService.decodeReceiptWithValues(abi, "set",
// transactionReceipt);
/// 9. 如果合约无返回值
TransactionResponse transactionResponse =
transactionDecoderService.decodeReceiptWithoutValues(
abi, transactionReceipt);
return transactionResponse;
} else {
String revertMessage =
transactionDecoderService.decodeRevertMessage(
transactionReceipt.getOutput());
System.out.println("交易回滚,回滚信息:" + revertMessage);
return null;
}

} finally {
TransactionBuilderJniObj.destroyTransactionData(transactionData);
}
}

String callContract(String address) throws TransactionBaseException, ContractCodecException {
// get 方法没有参数
List<Object> params = new ArrayList<>();
CallResponse callResponse =
assembleTransactionWithRemoteSignProcessor.sendCall(
"", address, abi, "get", params);
List<Object> callResponseReturnObject = callResponse.getReturnObject();
return (String) callResponseReturnObject.get(0);
}

public static void main(String[] args)
throws TransactionBaseException, IOException, JniException, ContractCodecException,
ExecutionException, InterruptedException, TimeoutException {

AssembleTransactionWithRemoteSignProcessorSample
assembleTransactionWithRemoteSignProcessorSample =
new AssembleTransactionWithRemoteSignProcessorSample();

// 部署合约
String address = assembleTransactionWithRemoteSignProcessorSample.deployContract();

String param = "test";
TransactionResponse transactionResponse =
assembleTransactionWithRemoteSignProcessorSample.sendTransaction(
address, Collections.singletonList(param));

if (transactionResponse.getTransactionReceipt().isStatusOK()) {

String result = assembleTransactionWithRemoteSignProcessorSample.callContract(address);
assert param.equals(result);
System.out.println("调用合约结束。");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.fisco.bcos.sdk.v3.test.transaction.demo;

import org.fisco.bcos.sdk.jni.common.JniException;
import org.fisco.bcos.sdk.v3.crypto.signature.SignatureResult;
import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
import org.fisco.bcos.sdk.v3.transaction.manager.AssembleTransactionWithRemoteSignProcessor;
import org.fisco.bcos.sdk.v3.transaction.signer.RemoteSignCallbackInterface;
import org.fisco.bcos.sdk.v3.transaction.tools.JsonUtils;

public class RemoteSignCallbackMock implements RemoteSignCallbackInterface {

protected AssembleTransactionWithRemoteSignProcessor assembleTransactionWithRemoteSignProcessor;
protected long transactionData;
protected int txAttribute;

public RemoteSignCallbackMock(
AssembleTransactionWithRemoteSignProcessor assembleTransactionWithRemoteSignProcessor,
long transactionData,
int txAttribute) {
this.assembleTransactionWithRemoteSignProcessor =
assembleTransactionWithRemoteSignProcessor;
this.transactionData = transactionData;
this.txAttribute = txAttribute;
}

/**
* 签名结果回调的实现
*
* @param signatureStr 签名服务回调返回的签名结果串
* @return *
*/
@Override
public int handleSignedTransaction(SignatureResult signatureStr) {
System.out.println(System.currentTimeMillis() + " SignatureResult: " + signatureStr);
// send the transaction after sign it
TransactionReceipt tr = null;
try {
tr =
assembleTransactionWithRemoteSignProcessor.encodeAndPush(
transactionData, signatureStr.convertToString(), this.txAttribute);
} catch (JniException e) {
e.printStackTrace();
}
System.out.println(
"handleSignedTransaction transactionReceipt is: " + JsonUtils.toJson(tr));
return 0;
}
}
Loading