案例合约
pragma solidity ^0.6.4;
pragma experimental ABIEncoderV2;
contract arrTest
{
、、、、、、、、、、、、、、、、、、
function createArrayInt(int[] memory source)
public
pure
returns (int[] memory)
{
int[] memory data=source;
return data;
}
}
部署合约
deployContract
部署合约,同步方式调用。
请确保在部署合约时使用的是编译器正常编译后生成的合约字节码,避免使用其他渠道获得的合约字节码,以免部署时出现合约校验失败的问题。
函数原型
public DeployContractResponse deployContract(DeployContractRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 部署合约的请求 |
DeployContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
acctId | true |
| 部署合约的账户 ID |
contractId | true |
| 合约 ID |
code | true | byte[] | 合约代码 |
vmTypeEnum | true |
| 虚拟机类型:
|
parameters | true |
| 合约参数 |
value | false |
| 合约金额 |
返回字段
返回字段 | 字段类型 | 说明 |
response |
| 部署合约的响应 |
DeployContractResponse,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt |
| 交易收据 |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
TransactionReceipt,具体参数见下表。
参数 | 类型 | 说明 |
result | long | 交易执行结果,0 代表成功,其他值代表失败 |
gasUsed | BigInteger | 交易执行所花费的gas费用 |
logs |
| 交易结果日志输出 |
output | byte[] | 交易的输出,此处为虚拟机的执行结果 |
LogEntry,具体参数见下表。
参数 | 类型 | 说明 |
from |
| 交易结果日志中的字段,代表交易发送者 |
to |
| 交易结果日志中的字段,代表交易j接收者 |
topics | List<String> | 交易结果日志中的字段,交易执行的事件主题 |
logData | byte[] | 交易结果日志中的字段,交易执行中的日志数据 |
示例
public void deployContract() {
String contractName = "contractName";
String accountName = "tester";
EVMParameter evmParameter = new EVMParameter();
String contractCodeString = "608060405234801561001057600080fd5b50610c73806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806361df56c8146100465780636767574a14610076578063a61eed31146100a6575b600080fd5b610060600480360381019061005b91906102cd565b6100d6565b60405161006d91906104d7565b60405180910390f35b610090600480360381019061008b919061034f565b6100e5565b60405161009d91906104f9565b60405180910390f35b6100c060048036038101906100bb919061030e565b61010a565b6040516100cd91906104f9565b60405180910390f35b60608082905080915050919050565b60608082816000815181106100f657fe5b602002602001018190525080915050919050565b60608082905080915050919050565b600082601f83011261012a57600080fd5b813561013d61013882610548565b61051b565b9150818183526020840193506020810190508385602084028201111561016257600080fd5b60005b8381101561019257816101788882610210565b845260208401935060208301925050600181019050610165565b5050505092915050565b600082601f8301126101ad57600080fd5b81356101c06101bb82610570565b61051b565b9150818183526020840193506020810190508360005b8381101561020657813586016101ec8882610225565b8452602084019350602083019250506001810190506101d6565b5050505092915050565b60008135905061021f816106db565b92915050565b600082601f83011261023657600080fd5b813561024961024482610598565b61051b565b9150808252602083016020830185838301111561026557600080fd5b610270838284610688565b50505092915050565b600082601f83011261028a57600080fd5b813561029d610298826105c4565b61051b565b915080825260208301602083018583830111156102b957600080fd5b6102c4838284610688565b50505092915050565b6000602082840312156102df57600080fd5b600082013567ffffffffffffffff8111156102f957600080fd5b61030584828501610119565b91505092915050565b60006020828403121561032057600080fd5b600082013567ffffffffffffffff81111561033a57600080fd5b6103468482850161019c565b91505092915050565b60006020828403121561036157600080fd5b600082013567ffffffffffffffff81111561037b57600080fd5b61038784828501610279565b91505092915050565b600061039c838361048f565b60208301905092915050565b60006103b4838361049e565b905092915050565b60006103c782610610565b6103d1818561064b565b93506103dc836105f0565b8060005b8381101561040d5781516103f48882610390565b97506103ff83610631565b9250506001810190506103e0565b5085935050505092915050565b60006104258261061b565b61042f818561065c565b93508360208202850161044185610600565b8060005b8581101561047d578484038952815161045e85826103a8565b94506104698361063e565b925060208a01995050600181019050610445565b50829750879550505050505092915050565b6104988161067e565b82525050565b60006104a982610626565b6104b3818561066d565b93506104c3818560208601610697565b6104cc816106ca565b840191505092915050565b600060208201905081810360008301526104f181846103bc565b905092915050565b60006020820190508181036000830152610513818461041a565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561053e57600080fd5b8060405250919050565b600067ffffffffffffffff82111561055f57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561058757600080fd5b602082029050602081019050919050565b600067ffffffffffffffff8211156105af57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff8211156105db57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000819050919050565b82818337600083830152505050565b60005b838110156106b557808201518184015260208101905061069a565b838111156106c4576000848401525b50505050565b6000601f19601f8301169050919050565b6106e48161067e565b81146106ef57600080fd5b5056fea467616e74696e666f7905327b22636f6d6d656e7473223a22222c22636f6d70696c6572223a7b2276657273696f6e223a22302e362e342b636f6d6d69742e3831323031373135227d2c22636f6e74726163745f6769745f6964223a22222c22636f6e74726163745f76657273696f6e223a302c226c616e6775616765223a22536f6c6964697479222c226f7574707574223a7b22616269223a5b7b22696e70757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22736f75726365222c2274797065223a22737472696e675b5d227d5d2c226e616d65223a226372656174654172726179222c226f757470757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22222c2274797065223a22737472696e675b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d2c7b22696e70757473223a5b7b22696e7465726e616c54797065223a22696e743235365b5d222c226e616d65223a22736f75726365222c2274797065223a22696e743235365b5d227d5d2c226e616d65223a226372656174654172726179496e74222c226f757470757473223a5b7b22696e7465726e616c54797065223a22696e743235365b5d222c226e616d65223a22222c2274797065223a22696e743235365b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d2c7b22696e70757473223a5b7b22696e7465726e616c54797065223a22737472696e67222c226e616d65223a2273222c2274797065223a22737472696e67227d5d2c226e616d65223a226372656174654172726179537472696e67222c226f757470757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22222c2274797065223a22737472696e675b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d5d2c22646576646f63223a7b226d6574686f6473223a7b7d7d2c2275736572646f63223a7b226d6574686f6473223a7b7d7d7d2c2273657474696e6773223a7b22636f6d70696c6174696f6e546172676574223a7b222f686f6d652f646174612f636f6e74726163742f736f6c69646974792f617272546573742e736f6c223a2261727254657374227d2c2265766d56657273696f6e223a22697374616e62756c222c226c6962726172696573223a7b7d2c226d65746164617461223a7b2262797465636f646548617368223a2269706673227d2c226f7074696d697a6572223a7b22656e61626c6564223a66616c73652c2272756e73223a3230307d2c2272656d617070696e6773223a5b5d7d2c22736f7572636573223a7b222f686f6d652f646174612f636f6e74726163742f736f6c69646974792f617272546573742e736f6c223a7b226b656363616b323536223a22307864373632383864613062313266336164626531396338623731393166663432643939316539373361333338373132646430383030373431653239656566336531222c2275726c73223a5b22627a7a2d7261773a2f2f37366363643566636536333831613765313365366433666265663065303362303035623436393866646666613634653933313830323738363766383063666138222c22647765623a2f697066732f516d6477684e367532597a333567536135694b6b7a507532465741725550475954514b55715a72566b704461597a225d7d7d2c2276657273696f6e223a317d646970667358221220839707e4119966fc9ac4ac6ddcc048f1a4a30c2bb25ce57c5e640f920614904864736f6c63430006046b636f6d70696c655f6d6f646130057e";
DeployContractRequest deployContractRequest = new DeployContractRequest(Utils.getIdentityByName(accountName), Utils.getIdentityByName(contractName), ByteUtils.hexStringToBytes(contractCodeString), VMTypeEnum.EVM, evmParameter, BigInteger.ZERO);
DeployContractResponse deployContractResponse = sdk.getContractService().deployContract(deployContractRequest);
if (!deployContractResponse.isSuccess()) {
logger.error("deployContract failed, errorCode :{}, errorDesc: {}", deployContractResponse.getErrorCode().getErrorCode(), deployContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = deployContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("deployContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("deployContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
asyncDeployContract
部署合约,异步方式调用。
函数原型
public int asyncDeployContract(DeployContractRequest request, IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 部署合约的请求 |
callback | true |
| 回调函数 |
DeployContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
acctId | true | Identity | 部署合约的账户 ID |
contractId | true | Identity | 合约 ID |
code | true | byte[] | 合约代码 |
vmTypeEnum | true |
| 虚拟机类型:
|
parameters | true | Parameters | 合约参数 |
value | false | BigInteger | 合约金额 |
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
(DeployContractResponse)Response,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void asyncDeployContract() {
String contractName = "contractName";
String accountName = "tester";
EVMParameter evmParameter = new EVMParameter();
String contractCodeString = "608060405234801561001057600080fd5b50610c73806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806361df56c8146100465780636767574a14610076578063a61eed31146100a6575b600080fd5b610060600480360381019061005b91906102cd565b6100d6565b60405161006d91906104d7565b60405180910390f35b610090600480360381019061008b919061034f565b6100e5565b60405161009d91906104f9565b60405180910390f35b6100c060048036038101906100bb919061030e565b61010a565b6040516100cd91906104f9565b60405180910390f35b60608082905080915050919050565b60608082816000815181106100f657fe5b602002602001018190525080915050919050565b60608082905080915050919050565b600082601f83011261012a57600080fd5b813561013d61013882610548565b61051b565b9150818183526020840193506020810190508385602084028201111561016257600080fd5b60005b8381101561019257816101788882610210565b845260208401935060208301925050600181019050610165565b5050505092915050565b600082601f8301126101ad57600080fd5b81356101c06101bb82610570565b61051b565b9150818183526020840193506020810190508360005b8381101561020657813586016101ec8882610225565b8452602084019350602083019250506001810190506101d6565b5050505092915050565b60008135905061021f816106db565b92915050565b600082601f83011261023657600080fd5b813561024961024482610598565b61051b565b9150808252602083016020830185838301111561026557600080fd5b610270838284610688565b50505092915050565b600082601f83011261028a57600080fd5b813561029d610298826105c4565b61051b565b915080825260208301602083018583830111156102b957600080fd5b6102c4838284610688565b50505092915050565b6000602082840312156102df57600080fd5b600082013567ffffffffffffffff8111156102f957600080fd5b61030584828501610119565b91505092915050565b60006020828403121561032057600080fd5b600082013567ffffffffffffffff81111561033a57600080fd5b6103468482850161019c565b91505092915050565b60006020828403121561036157600080fd5b600082013567ffffffffffffffff81111561037b57600080fd5b61038784828501610279565b91505092915050565b600061039c838361048f565b60208301905092915050565b60006103b4838361049e565b905092915050565b60006103c782610610565b6103d1818561064b565b93506103dc836105f0565b8060005b8381101561040d5781516103f48882610390565b97506103ff83610631565b9250506001810190506103e0565b5085935050505092915050565b60006104258261061b565b61042f818561065c565b93508360208202850161044185610600565b8060005b8581101561047d578484038952815161045e85826103a8565b94506104698361063e565b925060208a01995050600181019050610445565b50829750879550505050505092915050565b6104988161067e565b82525050565b60006104a982610626565b6104b3818561066d565b93506104c3818560208601610697565b6104cc816106ca565b840191505092915050565b600060208201905081810360008301526104f181846103bc565b905092915050565b60006020820190508181036000830152610513818461041a565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561053e57600080fd5b8060405250919050565b600067ffffffffffffffff82111561055f57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561058757600080fd5b602082029050602081019050919050565b600067ffffffffffffffff8211156105af57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff8211156105db57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000819050919050565b82818337600083830152505050565b60005b838110156106b557808201518184015260208101905061069a565b838111156106c4576000848401525b50505050565b6000601f19601f8301169050919050565b6106e48161067e565b81146106ef57600080fd5b5056fea467616e74696e666f7905327b22636f6d6d656e7473223a22222c22636f6d70696c6572223a7b2276657273696f6e223a22302e362e342b636f6d6d69742e3831323031373135227d2c22636f6e74726163745f6769745f6964223a22222c22636f6e74726163745f76657273696f6e223a302c226c616e6775616765223a22536f6c6964697479222c226f7574707574223a7b22616269223a5b7b22696e70757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22736f75726365222c2274797065223a22737472696e675b5d227d5d2c226e616d65223a226372656174654172726179222c226f757470757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22222c2274797065223a22737472696e675b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d2c7b22696e70757473223a5b7b22696e7465726e616c54797065223a22696e743235365b5d222c226e616d65223a22736f75726365222c2274797065223a22696e743235365b5d227d5d2c226e616d65223a226372656174654172726179496e74222c226f757470757473223a5b7b22696e7465726e616c54797065223a22696e743235365b5d222c226e616d65223a22222c2274797065223a22696e743235365b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d2c7b22696e70757473223a5b7b22696e7465726e616c54797065223a22737472696e67222c226e616d65223a2273222c2274797065223a22737472696e67227d5d2c226e616d65223a226372656174654172726179537472696e67222c226f757470757473223a5b7b22696e7465726e616c54797065223a22737472696e675b5d222c226e616d65223a22222c2274797065223a22737472696e675b5d227d5d2c2273746174654d75746162696c697479223a2270757265222c2274797065223a2266756e6374696f6e227d5d2c22646576646f63223a7b226d6574686f6473223a7b7d7d2c2275736572646f63223a7b226d6574686f6473223a7b7d7d7d2c2273657474696e6773223a7b22636f6d70696c6174696f6e546172676574223a7b222f686f6d652f646174612f636f6e74726163742f736f6c69646974792f617272546573742e736f6c223a2261727254657374227d2c2265766d56657273696f6e223a22697374616e62756c222c226c6962726172696573223a7b7d2c226d65746164617461223a7b2262797465636f646548617368223a2269706673227d2c226f7074696d697a6572223a7b22656e61626c6564223a66616c73652c2272756e73223a3230307d2c2272656d617070696e6773223a5b5d7d2c22736f7572636573223a7b222f686f6d652f646174612f636f6e74726163742f736f6c69646974792f617272546573742e736f6c223a7b226b656363616b323536223a22307864373632383864613062313266336164626531396338623731393166663432643939316539373361333338373132646430383030373431653239656566336531222c2275726c73223a5b22627a7a2d7261773a2f2f37366363643566636536333831613765313365366433666265663065303362303035623436393866646666613634653933313830323738363766383063666138222c22647765623a2f697066732f516d6477684e367532597a333567536135694b6b7a507532465741725550475954514b55715a72566b704461597a225d7d7d2c2276657273696f6e223a317d646970667358221220839707e4119966fc9ac4ac6ddcc048f1a4a30c2bb25ce57c5e640f920614904864736f6c63430006046b636f6d70696c655f6d6f646130057e";
DeployContractRequest deployContractRequest = new DeployContractRequest(Utils.getIdentityByName(accountName), Utils.getIdentityByName(contractName), ByteUtils.hexStringToBytes(contractCodeString), VMTypeEnum.EVM, evmParameter, BigInteger.ZERO);
int result = sdk.getContractService().asyncDeployContract(deployContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
// 请参考错误信息章节,检查返回的数据
DeployContractResponse deployContractResponse = (DeployContractResponse) response;
if (!deployContractResponse.isSuccess()) {
logger.error("deployContract failed, errorCode :{}, errorDesc: {}", deployContractResponse.getErrorCode().getErrorCode(), deployContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = deployContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("deployContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("deployContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
});
}
调用合约
callContract
调用合约,同步方式调用。
函数原型
public CallContractResponse callContract(CallContractRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 调用合约的请求 |
CallContractRequest
调用合约的参数:
参数 | 必选 | 类型 | 说明 |
acctId | true |
| 提交交易的账户 ID |
contractId | true |
| 合约 ID |
parameters | true |
| 合约参数 |
vmTypeEnum | true |
| 虚拟机类型: NATIVE(0, "NATIVE CONTRACT") EVM(1, "EVM CONTRACT") WASM(2, "WASM CONTRACT") DCVM(4, "DATA CONTRACT") NATIVE_PRECOMPILE(-2, "NATIVE PRECOMPILE") |
value | false |
| 合约金额 |
返回字段
返回字段 | 字段类型 | 说明 |
result |
| 调用合约的响应 |
CallContractResponse,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void callContract() {
String contractName = "contractName";
String accountName = "tester";
EVMParameter parameters = new EVMParameter("createArrayInt(int256[])");
// 检查参数是否错误
DynamicArray<Int> dynamicArray = new DynamicArray<Int>(new Int(BigInteger.valueOf(1)), new Int(BigInteger.valueOf(2)), new Int(BigInteger.valueOf(3)));
parameters.addArray(dynamicArray);
// build CallContractRequest
CallContractRequest request = new CallContractRequest(Utils.getIdentityByName(accountName), Utils.getIdentityByName(contractName), parameters, BigInteger.ZERO, VMTypeEnum.EVM);
CallContractResponse callContractResponse = sdk.getContractService().callContract(request);
if (!callContractResponse.isSuccess()) {
logger.error("callContract failed, errorCode :{}, errorDesc: {}", callContractResponse.getErrorCode().getErrorCode(), callContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = callContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("callContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("callContract success.返回信息: {}", transactionReceipt.toString());
// 手动抛出的错误可在evmOutput中查看
EVMOutput evmOutput = new EVMOutput(Hex.toHexString(transactionReceipt.getOutput()));
//获取要解析的类型
logger.info("callContract success.返回信息:{}", evmOutput.getIntDynamicArray().toString());
}
}
}
asyncCallContract
调用合约,异步方式调用。
函数原型
public int asyncCallContract(CallContractRequest request, IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 调用合约的请求 |
callback | true |
| 回调函数 |
CallContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
acctId | true |
| 提交交易的账户 ID |
contractId | true |
| 合约 ID |
parameters | true |
| 合约参数 |
vmTypeEnum | true |
| 虚拟机类型:
|
value | false |
| 合约金额 |
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
(CallContractResponse)Response,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void asyncCallContract() {
String contractName = "contractName";
String accountName = "tester";
EVMParameter parameters = new EVMParameter("createArrayInt(int256[])");
// 检查参数是否错误
DynamicArray<Int> dynamicArray = new DynamicArray<Int>(new Int(BigInteger.valueOf(1)), new Int(BigInteger.valueOf(2)), new Int(BigInteger.valueOf(3)));
parameters.addArray(dynamicArray);
// build CallContractRequest
CallContractRequest request = new CallContractRequest(Utils.getIdentityByName(accountName), Utils.getIdentityByName(contractName), parameters, BigInteger.ZERO, VMTypeEnum.EVM);
int result = sdk.getContractService().asyncCallContract(request, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
// 请参考错误信息章节,检查返回的数据
CallContractResponse callContractResponse = (CallContractResponse) response;
if (!callContractResponse.isSuccess()) {
logger.error("callContract failed, errorCode :{}, errorDesc: {}", callContractResponse.getErrorCode().getErrorCode(), callContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = callContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("callContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("callContract success.返回信息: {}", transactionReceipt.toString());
// 手动抛出的错误可在evmOutput中查看
EVMOutput evmOutput = new EVMOutput(Hex.toHexString(transactionReceipt.getOutput()));
//获取要解析的类型
logger.info("callContract success.返回信息:{},", evmOutput.getIntDynamicArray().toString());
}
}
}
});
}
升级合约
updateContract
升级合约,同步方式调用。
函数原型
public UpdateContractResponse updateContract(UpdateContractRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 升级合约的请求 |
UpdateContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
contractId | true | Identity | 合约 ID |
code | true | byte[] | 目标合约的字节码,采用 16 进制表示,无需“0x”作为前缀。 |
vmTypeEnum | true |
| 虚拟机类型:
|
升级合约时,传入的 bytecode
字节码为 runtime
字节码。如果使用二进制 solc 编译工具,可直接获取 --bin-runtime
参数,即正常 --bin
参数编译的字节码的子集。runtime
字节码也可通过本地执行合约部署操作来获取。
返回字段
返回字段 | 字段类型 | 说明 |
response |
| 升级合约的响应 |
UpdateContractResponse,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void updateContract() {
String contractName = "contractName";
UpdateContractRequest updateContractRequest = new UpdateContractRequest(Utils.getIdentityByName(contractName), ByteUtils.hexStringToBytes(contractCodeString), VMTypeEnum.EVM);
UpdateContractResponse updateContractResponse = sdk.getContractService().updateContract(updateContractRequest);
if (!updateContractResponse.isSuccess()) {
logger.error("updateContract failed, errorCode :{}, errorDesc: {}", updateContractResponse.getErrorCode().getErrorCode(), updateContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = updateContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("updateContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("updateContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
asyncUpdateContract
升级合约,异步方式调用。
函数原型
public int asyncUpdateContract(UpdateContractRequest request, IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 升级合约的请求 |
callback | true |
| 回调函数 |
UpdateContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
contractId | true | Identity | 合约 ID |
code | true | byte[] | 目标合约的字节码,采用 16 进制表示,无需“0x”作为前缀。 |
vmTypeEnum | true |
| 虚拟机类型:
|
升级合约时,传入的 bytecode
字节码为 runtime
字节码。如果使用二进制 solc 编译工具,可直接获取 --bin-runtime
参数,即正常 --bin
参数编译的字节码的子集。runtime
字节码也可通过本地执行合约部署操作来获取。
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
(UpdateContractResponse)Response,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void asyncUpdateContract() {
String contractName = "contractName";
UpdateContractRequest updateContractRequest = new UpdateContractRequest(Utils.getIdentityByName(contractName), ByteUtils.hexStringToBytes(contractCodeString), VMTypeEnum.EVM);
int result = sdk.getContractService().asyncUpdateContract(updateContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
// 请参考错误信息章节,检查返回的数据
UpdateContractResponse updateContractResponse = (UpdateContractResponse) response;
if (!updateContractResponse.isSuccess()) {
logger.error("updateContract failed, errorCode :{}, errorDesc: {}", updateContractResponse.getErrorCode().getErrorCode(), updateContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = updateContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("updateContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("updateContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
});
}
冻结合约
freezeContract
冻结合约,同步方式调用。
函数原型
public FreezeContractResponse freezeContract(FreezeContractRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 冻结合约的请求 |
FreezeContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
from | true | Identity | 冻结合约的操作者id(admin或者是合约本身) |
to | true | Identity | 待冻结的合约 ID |
返回字段
返回字段 | 字段类型 | 说明 |
response |
| 冻结合约的响应 |
FreezeContractResponse,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void freezeContract() {
String contractName = "contractName";
FreezeContractRequest freezeContractRequest = new FreezeContractRequest(Utils.getIdentityByName("Administrator"), Utils.getIdentityByName(contractName));
FreezeContractResponse freezeContractResponse = sdk.getContractService().freezeContract(freezeContractRequest);
if (!freezeContractResponse.isSuccess()) {
logger.error("freezeContract failed, errorCode :{}, errorDesc: {}", freezeContractResponse.getErrorCode().getErrorCode(), freezeContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = freezeContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("freezeContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("freezeContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
asyncFreezeContract
冻结合约,异步方式调用。
函数原型
public int asyncFreezeContract(FreezeContractRequest request,IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 冻结合约的请求 |
callback | true |
| 回调函数 |
FreezeContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
from | true | Identity | 冻结合约的操作者id(admin或者是合约本身) |
to | true | Identity | 待冻结的合约 ID |
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
(FreezeContractResponse)Response,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void asyncFreezeContract() {
String contractName = "contractName";
FreezeContractRequest freezeContractRequest = new FreezeContractRequest(Utils.getIdentityByName("Administrator"), Utils.getIdentityByName(contractName));
int result = sdk.getContractService().asyncFreezeContract(freezeContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
// 请参考错误信息章节,检查返回的数据
FreezeContractResponse freezeContractResponse = (FreezeContractResponse) response;
if (!freezeContractResponse.isSuccess()) {
logger.error("freezeContract failed, errorCode :{}, errorDesc: {}", freezeContractResponse.getErrorCode().getErrorCode(), freezeContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = freezeContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("freezeContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("freezeContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
});
}
解冻合约
unFreezeContract
解除冻结合约,同步方式调用。
函数原型
public UnFreezeContractResponse unFreezeContract(UnFreezeContractRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 解除冻结合约的请求 |
UnfreezeContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
from | true | Identity | 解冻合约的操作者(必须为admin) |
to | true | Identity | 待解冻的合约 ID |
返回字段
返回字段 | 字段类型 | 说明 |
response |
| 解除冻结合约的响应 |
UnFreezeContractResponse,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void unFreezeContract() {
String contractName = "contractName";
UnFreezeContractRequest unFreezeContractRequest = new UnFreezeContractRequest(Utils.getIdentityByName("Administrator"), Utils.getIdentityByName(contractName));
UnFreezeContractResponse unFreezeContractResponse = sdk.getContractService().unFreezeContract(unFreezeContractRequest);
if (!unFreezeContractResponse.isSuccess()) {
logger.error("unFreezeContract failed, errorCode :{}, errorDesc: {}", unFreezeContractResponse.getErrorCode().getErrorCode(), unFreezeContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = unFreezeContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("unFreezeContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("unFreezeContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
asyncUnFreezeContract
解除冻结合约,异步方式调用。
函数原型
public int asyncUnFreezeContract(UnFreezeContractRequest request,IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 解除冻结合约的请求 |
callback | true |
| 回调函数 |
UnfreezeContractRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
from | true | Identity | 解冻合约的操作者 (必须为admin) |
to | true | Identity | 待解冻的合约 ID |
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
(UnFreezeContractResponse)Response,具体参数见下表。
参数 | 类型 | 说明 |
transactionReceipt | 交易收据 | |
blockNumber | BigInteger | 区块号 |
txIndex | int | 交易偏移量 |
txHash | Hash | 交易hash |
isLocalTransaction | boolean | 是否为本地交易 |
示例
public void asyncUnFreezeContract() {
String contractName = "contractName";
UnFreezeContractRequest unFreezeContractRequest = new UnFreezeContractRequest(Utils.getIdentityByName("Administrator"), Utils.getIdentityByName(contractName));
int result = sdk.getContractService().asyncUnFreezeContract(unFreezeContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
// 请参考错误信息章节,检查返回的数据
UnFreezeContractResponse unFreezeContractResponse = (UnFreezeContractResponse) response;
if (!unFreezeContractResponse.isSuccess()) {
logger.error("unFreezeContract failed, errorCode :{}, errorDesc: {}", unFreezeContractResponse.getErrorCode().getErrorCode(), unFreezeContractResponse.getErrorCode().getErrorDesc());
} else {
// 交易收据
TransactionReceipt transactionReceipt = unFreezeContractResponse.getTransactionReceipt();
if (transactionReceipt.getResult() != 0) {
logger.error("unFreezeContract failed, errorCode :{}, errorDesc: {}", ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorCode(), ErrorCode.valueOf((int) transactionReceipt.getResult()).getErrorDesc());
} else {
logger.info("unFreezeContract success.返回信息: {}", transactionReceipt.toString());
}
}
}
});
}
获取数据合约Schema
getContractSchema
调用 getContractSchema 接口获取数据合约的Schema,同步方式调用。
函数原型
public GetContractSchemaResponse getContractSchema(GetContractSchemaRequest request)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 获取数据合约的请求 |
GetContractSchemaRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
acctId | true | Identity | 发起交易的账户id |
contractId | true | Identity | 被调用的数据合约id |
vmTypeEnum | true | VMTypeEnum | 合约类型(VMTypeEnum.DCVM) |
返回字段
返回字段 | 字段类型 | 说明 |
response |
| 获取数据合约的响应 |
GetContractSchemaResponse,无参数,通过方法获取值,请参考示例中的写法。
示例
@Test
public void testgetContractSchemaTest() throws IOException {
// byte[] schema = IOUtil.inputStreamToByte(ContractServiceTest.class.getResourceAsStream("/contract_schema"));
//部署数据合约
//schema内容,请根据实际项目中业务场景赋值
byte[] schema = new byte[]{1, 2, 3, 4, 5, 6, 7};
DeployContractRequest deployContractRequest = new DeployContractRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(yourTestDCVMContractId), schema,
VMTypeEnum.DCVM);
DeployContractResponse result = sdk.getContractService().deployContract(deployContractRequest);
assertTrue(result.isSuccess());
assertEquals(0, result.getTransactionReceipt().getResult());
//设置合约访问权限
ContractAccessControl acl = new ContractAccessControl(yourAccount.getIdentity());
acl.setDataRead(true);
acl.setSchemaRead(true);
List<ContractAccessControl> contractAccessControls = new ArrayList<>();
contractAccessControls.add(acl);
SetContractAccessControlRequest setContractAccessControlRequest =
new SetContractAccessControlRequest(Utils.getIdentityByName(yourTestDCVMContractId), contractAccessControls);
SetContractAccessControlResponse setContractAccessControlResponse =
sdk.getContractService().setContractAccessControl(setContractAccessControlRequest);
assertTrue(setContractAccessControlResponse.isSuccess());
//查询合约访问权限
List<Identity> identities = Arrays.asList(yourAccount.getIdentity());
GetContractAccessControlRequest getContractAccessControlRequest = new GetContractAccessControlRequest(Utils.getIdentityByName(yourTestDCVMContractId), identities);
GetContractAccessControlResponse getContractAccessControlResponse = sdk.getContractService().getContractAccessControl(getContractAccessControlRequest);
assertTrue(getContractAccessControlResponse.isSuccess());
assertEquals(getContractAccessControlRequest.getSequenceId(), getContractAccessControlResponse.getSequenceId());
assertEquals(getContractAccessControlResponse.getTransactionReceipt().getResult(), 0);
assertNull(getContractAccessControlResponse.getContractAccessControls(identities).getSecond());
List<ContractAccessControl> aclResult = getContractAccessControlResponse.getContractAccessControls(identities).getFirst();
assertTrue(aclResult.size() > 0);
assertTrue(aclResult.get(0).isDataRead());
assertFalse(aclResult.get(0).isDataWrite());
assertTrue(aclResult.get(0).isSchemaRead());
assertFalse(aclResult.get(0).isSchemaWrite());
//获取Schema
GetContractSchemaRequest getContractSchemaRequest = new GetContractSchemaRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(yourTestDCVMContractId), VMTypeEnum.DCVM);
GetContractSchemaResponse getContractSchemaResponse = sdk.getContractService().getContractSchema(getContractSchemaRequest);
assertTrue(getContractSchemaResponse.isSuccess());
assertEquals(getContractSchemaResponse.getSequenceId(), getContractSchemaRequest.getSequenceId());
assertEquals(getContractSchemaResponse.getTransactionReceipt().getResult(), 0);
if(getContractSchemaResponse.getContractSchema().getFirst()!=null) {
String schemaString = getContractSchemaResponse.getContractSchema().getFirst();
assertEquals(ByteUtils.toHexString(schema), schemaString);
}else{
fail();
}
//更新合约
//schema内容,请根据实际项目中业务场景赋值
schema = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
UpdateContractRequest updateContractRequest = new UpdateContractRequest(Utils.getIdentityByName(yourTestDCVMContractId), schema, VMTypeEnum.DCVM);
UpdateContractResponse updateContractResponse = sdk.getContractService().updateContract(updateContractRequest);
assertTrue(updateContractResponse.isSuccess());
assertEquals(updateContractResponse.getSequenceId(), updateContractRequest.getSequenceId());
assertEquals(updateContractResponse.getTransactionReceipt().getResult(), 0);
//重新获取合约Schema
getContractSchemaRequest = new GetContractSchemaRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(yourTestDCVMContractId), VMTypeEnum.DCVM);
getContractSchemaResponse = sdk.getContractService().getContractSchema(getContractSchemaRequest);
assertTrue(getContractSchemaResponse.isSuccess());
assertEquals(getContractSchemaResponse.getSequenceId(), getContractSchemaRequest.getSequenceId());
assertEquals(getContractSchemaResponse.getTransactionReceipt().getResult(), 0);
if(getContractSchemaResponse.getContractSchema().getFirst()!=null) {
String schemaString = getContractSchemaResponse.getContractSchema().getFirst();
assertEquals(ByteUtils.toHexString(schema), schemaString);
}else{
fail();
}
}
asyncGetContractSchema
调用 asyncGetContractSchema 接口获取数据合约的Schema,异步方式调用。
函数原型
public int asyncGetContractSchema(GetContractSchemaRequest request, IAsyncCallback callback)
请求参数
参数 | 必选 | 类型 | 说明 |
request | true |
| 获取数据合约的请求 |
callback | true |
| 回调函数 |
GetContractSchemaRequest,具体参数见下表。
参数 | 必选 | 类型 | 说明 |
acctId | true | Identity | 发起交易的账户id |
contractId | true | Identity | 被调用的数据合约id |
vmTypeEnum | true | VMTypeEnum | 合约类型(VMTypeEnum.DCVM) |
同步返回字段
返回字段 | 字段类型 | 说明 |
result | int | 发送返回值,success时为0 |
异步返回字段
返回字段 | 字段类型 | 说明 |
errorCode | int | SDK发送消息返回的错误码,success时为0。 |
response |
| 平台返回的响应,其中 |
GetContractSchemaResponse,无参数,通过方法获取值,请参考示例中的写法。
示例
public void testAsyncGetContractSchemaTest() throws IOException, InterruptedException {
// byte[] schema = IOUtil.inputStreamToByte(ContractServiceTest.class.getResourceAsStream("/contract_schema_random"));
//部署合约
//schema内容,请根据实际项目中业务场景赋值
final byte[] schema = new byte[]{1, 2, 3, 4, 5, 6, 7};
DeployContractRequest deployContractRequest = new DeployContractRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(testDCVMContractId), schema,
VMTypeEnum.DCVM);
final CountDownLatch deployCountDownLatch = new CountDownLatch(1);
int returnCode = sdk.getContractService().asyncDeployContract(deployContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof DeployContractResponse)
assertTrue(response.isSuccess());
assertEquals(0, ((DeployContractResponse) response).getTransactionReceipt().getResult());
deployCountDownLatch.countDown();
}
});
assertEquals(returnCode, 0);
assertTrue(deployCountDownLatch.await(5, TimeUnit.SECONDS));
//设置合约访问权限
ContractAccessControl acl = new ContractAccessControl(yourAccount.getIdentity());
acl.setDataRead(true);
acl.setSchemaRead(true);
List<ContractAccessControl> contractAccessControls = new ArrayList<>();
contractAccessControls.add(acl);
final CountDownLatch countDownLatch = new CountDownLatch(1);
SetContractAccessControlRequest setContractAccessControlRequest =
new SetContractAccessControlRequest(Utils.getIdentityByName(testDCVMContractId), contractAccessControls);
returnCode =
sdk.getContractService().asyncSetContractAccessControl(setContractAccessControlRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof SetContractAccessControlResponse) {
assertTrue(((SetContractAccessControlResponse) response).isSuccess());
countDownLatch.countDown();
}
}
});
assertEquals(returnCode, 0);
assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
//查询合约访问权限
final List<Identity> identities = Arrays.asList(yourAccount.getIdentity());
final GetContractAccessControlRequest getContractAccessControlRequest = new GetContractAccessControlRequest(
Utils.getIdentityByName(testDCVMContractId), identities);
final CountDownLatch getContractAccessControlCountDownLatch = new CountDownLatch(1);
returnCode = sdk.getContractService().
asyncGetContractAccessControlResponse(getContractAccessControlRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof GetContractAccessControlResponse) {
assertTrue(((GetContractAccessControlResponse) response).isSuccess());
assertEquals(((GetContractAccessControlResponse) response).getSequenceId(), getContractAccessControlRequest.getSequenceId());
assertEquals(((GetContractAccessControlResponse) response).getTransactionReceipt().getResult(), 0);
assertNull(((GetContractAccessControlResponse) response).getContractAccessControls(identities).getSecond());
List<ContractAccessControl> aclResult = ((GetContractAccessControlResponse) response).getContractAccessControls(identities).getFirst();
assertTrue(aclResult.size() > 0);
assertTrue(aclResult.get(0).isDataRead());
assertFalse(aclResult.get(0).isDataWrite());
assertTrue(aclResult.get(0).isSchemaRead());
assertFalse(aclResult.get(0).isSchemaWrite());
getContractAccessControlCountDownLatch.countDown();
}
}
});
assertEquals(returnCode, 0);
assertTrue(getContractAccessControlCountDownLatch.await(5, TimeUnit.SECONDS));
//获取合约Schema
final GetContractSchemaRequest callContractRequest = new GetContractSchemaRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(testDCVMContractId), VMTypeEnum.DCVM);
final CountDownLatch getSchemaCountDownLatch = new CountDownLatch(1);
returnCode = sdk.getContractService().asyncGetContractSchema(callContractRequest, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof GetContractSchemaResponse) {
GetContractSchemaResponse getContractSchemaResponse = (GetContractSchemaResponse)response;
assertTrue(getContractSchemaResponse.isSuccess());
assertEquals(getContractSchemaResponse.getSequenceId(), callContractRequest.getSequenceId());
assertEquals(getContractSchemaResponse.getTransactionReceipt().getResult(), 0);
String schemaString = getContractSchemaResponse.getContractSchema().getFirst();
assertEquals(ByteUtils.toHexString(schema), schemaString);
getSchemaCountDownLatch.countDown();
}
}
});
assertEquals(returnCode, 0);
assertTrue(getSchemaCountDownLatch.await(5, TimeUnit.SECONDS));
//更新合约
//schema内容,请根据实际项目中业务场景赋值
final byte[] schema2 = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
final UpdateContractRequest updateContractRequest = new UpdateContractRequest(
Utils.getIdentityByName(testDCVMContractId), schema2, VMTypeEnum.DCVM);
final CountDownLatch updateContractCountDownLatch = new CountDownLatch(1);
returnCode = sdk.getContractService().asyncUpdateContract(updateContractRequest,
new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof UpdateContractResponse) {
assertTrue(((UpdateContractResponse) response).isSuccess());
assertEquals(((UpdateContractResponse) response).getSequenceId(), updateContractRequest.getSequenceId());
assertEquals(((UpdateContractResponse) response).getTransactionReceipt().getResult(), 0);
updateContractCountDownLatch.countDown();
}
}
});
assertEquals(returnCode, 0);
assertTrue(updateContractCountDownLatch.await(5, TimeUnit.SECONDS));
//重新获取合约Schema
final GetContractSchemaRequest callContractRequest3 = new GetContractSchemaRequest(yourAccount.getIdentity(),
Utils.getIdentityByName(testDCVMContractId), VMTypeEnum.DCVM);
final CountDownLatch getSchema2 = new CountDownLatch(1);
returnCode = sdk.getContractService().asyncGetContractSchema(callContractRequest3, new IAsyncCallback() {
@Override
public void onResponse(int errorCode, Response response) {
if (errorCode == 0 && response instanceof GetContractSchemaResponse) {
GetContractSchemaResponse getContractSchemaResponse = (GetContractSchemaResponse)response;
assertTrue(getContractSchemaResponse.isSuccess());
assertEquals(getContractSchemaResponse.getSequenceId(), callContractRequest3.getSequenceId());
assertEquals(getContractSchemaResponse.getTransactionReceipt().getResult(), 0);
String schemaString = getContractSchemaResponse.getContractSchema().getFirst();
assertEquals(ByteUtils.toHexString(schema2), schemaString);
getSchema2.countDown();
}
}
});
assertEquals(returnCode, 0);
assertTrue(getSchema2.await(5, TimeUnit.SECONDS));
}
合约参数对象
参数对象用于编码合约方法和参数。
EVM 合约参数对象
EVMParameter
函数名称 | 参数类型 | 参数说明 |
setMethodSignature() |
| 添加函数选择器,即方法与参数列表构成的字符串 |
getEncodedData() | - | - |
addInt() |
| 添加静态的 int 类型的数据 |
addUInt() |
| 添加静态的 uint 类型的数据 |
addBool() |
| 添加静态的 bool 类型的数据 |
addIdentity() |
| 添加静态的 identity 类型的数据 |
addString () |
| 添加动态的 string 类型的数据 |
addBytes() |
| 添加动态的 bytes 类型的数据 |
addBytesN() |
| 添加静态的 bytes 类型的数据 |
addIntArray() |
| 添加动态的 int 数组类型的数据 |
addUIntArray() |
| 添加动态的 uint 数组类型的数据 |
addBooleanArray() |
| 添加动态的 bool 数组类型的数据 |
getMethodSignature() | - | - |
addStruct() |
| 添加Struct类型参数,类似于Java集合中的List |
addArray() |
| 添加动态数组 |
addIdentityArray() |
| 添加Indentity的byte[]集合 |
addBytes32Array() |
| 添加32位的byte[]集合 |
addBytes32() |
| 添加32位的byte[],必须为32位 |
其中addBytesN() 已废弃,但仍可以继续使用。
EVM 数据解析
EVMOutput,解析交易收据的 logData 和 output,可参考 EVM 合约编码说明 中的脚本示例。
函数名称 | 参数类型 | 参数说明 |
getInt() |
| 获取静态的 int 类型的数据 |
getUInt() |
| 获取静态的 uint 类型的数据 |
getIdentity() |
| 获取 identity 类型的数据 |
getString () |
| 获取 string 类型的数据 |
getBytes() |
| 获取的 bytes 类型的数据 |
getBytesN() |
| 获取 bytes 类型的数据 |
evmRevertDecoder() | byte[] | 添加针对result=10201时,output转换为String的解码器 |
EVM 合约编码说明
EVM 的参数和返回值编码规则一致,都与 Solidity 合约一样。对于静态类型的变量,直接编码为 32 字节按顺序拼接。对应动态数据类型,则用一个 32 字节偏移量占住位置,所有动态数据类型的真实数据按顺序以 LV 的格式放在后面。其中 L 表示数据的实际长度,L 占用 32 字节;V 为实际数据。
下面通过示例进行详细说明。
要返回的多值结果列表:
类型 | 值 |
uint | 100 |
String | “abc” |
String | “0123456789abcdefghijklmnopqrstuvwxyz” |
boolean | true |
Identity | “1e7d3e769f3f593dadcb8634cc5b09fc90dd3a61c4a06a79cb0923662fe6fae6b” |
编码结果:
0000000000000000000000000000000000000000000000000000000000000064
00000000000000000000000000000000000000000000000000000000000000a0
00000000000000000000000000000000000000000000000000000000000000e0
0000000000000000000000000000000000000000000000000000000000000001
e7d3e769f3f593dadcb8634cc5b09fc90dd3a61c4a06a79cb0923662fe6fae6b
0000000000000000000000000000000000000000000000000000000000000003
6162630000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000024
303132333435363738396162636465666768696a6b6c6d6e6f70717273747576
7778797a00000000000000000000000000000000000000000000000000000000
具体解析如下:
0000000000000000000000000000000000000000000000000000000000000064
为“100”的编码,uint 类型,定长 32 字节,是大端编码。00000000000000000000000000000000000000000000000000000000000000a0
“abc”为动态类型,这里的 a0 为其实际数据编码所处偏移位置。因为这里一共 5 个变量,每个变量占用 0x20 个字节,所以第一个动态类型的数据偏移位置就是 5*0x20=0xA0,偏移量的编码规则和 uint 一样。000000000000000000000000000000000000000000000000000000000000000e0
“0123456789abcdefghijklmopqrstuvwxyz”是动态类型,这里e0
为其实际数据编码所处偏移位置。本数据在“abc”之后,由于“abc”的长度和数据各占 0x20 字节,所以本数据就在 0xA0+0x40=0xE0 的位置。00000000000000000000000000000000000000000000000000000000000000001
“true”的编码,bool
型数据占用定长 32 字节,true 最后一个字节为 01,false 最后一个字节为 00。1e7d3e769f3f593dadcb8634cc5b09fc90dd3a61c4a06a79cb0923662fe6fae6b
是一个”Identity”类型的编码,与源数据完全一致。00000000000000000000000000000000000000000000000000000000000000003
“abc”的长度,编码规则和uint
一样。61626300000000000000000000000000000000000000000000000000000000000
“abc”的实际数据,String
类型的数据占用长度为 32 的整数倍,实际数据靠左编码,后面填充 00。00000000000000000000000000000000000000000000000000000000000000024
为“0123456789abcdefghijklmnopqrstuvwxyz”的长度为 36=0x24。303132333435363738396162636465666768696a6b6c6d6e6f70717273747576
,7778797a00000000000000000000000000000000000000000000000000000000
为“0123456789abcdefghijklmnopqrstuvwxyz”的实际数据编码。
// 获取返回值解码示例
EVMOutput evmOutput = new EVMOutput(ByteUtils.toHexString(transactionReceipt.getOutput()));
//按顺序获得返回值
BigInteger bigInteger = evmOutput.getUint(); // 100
String string = evmOutput.getString(); // "abc"
// "0123456789abcdefghijklmnopqrstuvwxyz"
String string1 = evmOutput.getString();
boolean b = evmOutput.getBoolean(); // true
// "1e7d3e769f3f593dadcb8634cc5b09fc90dd3a61c4a06a79cb0923662fe6fae6b"
Identity id = evmOutput.getIdentity();
WASM 合约参数对象
WASMParameter
函数名称 | 参数类型 | 参数说明 |
setMethodSignature() |
| 添加函数选择器,方法与参数列表构成的字符串。 |
getEncodedData() |
| WASM 参数字节码 |
addInt8() |
| 添加静态的 int_8 类型的数据 |
addInt16() |
| 添加静态的 int_16 类型的数据 |
addInt32() |
| 添加静态的 int_32 类型的数据 |
addInt64() |
| 添加静态的 int_64 类型的数据 |
addInt128() |
| 添加静态的 int_128 类型的数据 |
addUInt8() |
| 添加静态的 uint_8 类型的数据 |
addUInt16() |
| 添加静态的 uint_16 类型的数据 |
addUInt32() |
| 添加静态的 uint_32 类型的数据 |
addUInt64() |
| 添加静态的 uint_64 类型的数据 |
addUInt128() |
| 添加静态的 uint_128 类型的数据 |
addBool() |
| 添加静态的 bool 类型的数据 |
addIdentity() |
| 添加静态的 Hash 类型的数据 |
addString() |
| 添加动态的 string 类型的数据 |
addBytes() |
| 添加动态的 bytes 类型的数据 |
addInt8Array() |
| 添加动态的 int_8 数组类型的数据 |
addInt16Array() |
| 添加动态的 int_16 数组类型的数据 |
addInt32Array() |
| 添加动态的 int_32 数组类型的数据 |
addInt64Array() |
| 添加动态的 int_64 数组类型的数据 |
addInt128Array() |
| 添加动态的 int_128 数组类型的数据 |
addUInt8Array() |
| 添加动态的 uint_8 数组类型的数据 |
addUInt16Array() |
| 添加动态的 uint_16 数组类型的数据 |
addUInt32Array() |
| 添加动态的 uint_32 数组类型的数据 |
addUInt64Array() |
| 添加动态的 uint_64 数组类型的数据 |
addUint128Array() |
| 添加动态的 uint_128 数组类型的数据 |
addBooleanArray() |
| 添加动态的 bool 数组类型的数据 |
addUtfStringArray() |
| 添加动态 String 数组的数据 |
WASM 数据解析
WasmOutput,解析交易收据的 logData 和 output,可参考示例。
函数名称 | 参数类型 | 参数说明 |
getInt8() |
| 获取静态的 int_8 类型的数据 |
getInt16() |
| 获取静态的 int_16 类型的数据 |
getInt32() |
| 获取静态的 int_32 类型的数据 |
getInt64() |
| 获取静态的 int_64 类型的数据 |
getInt128() |
| 获取静态的 int_128 类型的数据 |
getUInt8() |
| 获取静态的 uint_8 类型的数据 |
getUInt16() |
| 获取静态的 uint_16 类型的数据 |
getUInt32() |
| 获取静态的 uint_32 类型的数据 |
getUInt64() |
| 获取静态的 uint_64 类型的数据 |
getUint128() |
| 获取静态的 uint_128 类型的数据 |
getString() |
| 获取动态的 string 类型的数据 |
getBytes() |
| 获取动态的 bytes 类型的数据 |
getIntAndUintDynamicArray(Class type) |
| 获取 int 或者 uint 的动态数组 |
getBooleanDynamicArray() |
| 获取 bool 的动态数组 |
getStringDynamicArray() |
| 获取 String 的动态数组 |
WASM 合约编码说明
C++ 合约中的 pack 函数按照下面的规则进行序列化:
编码表(字节序均为小端)
类型 | 编码 | 字节数 | 编码示例(编码后数据以 16 进制展示) | C++ 类型 | Java SDK/JS SDK 类型 |
bool | 原码 | 1 |
| bool | Bool |
uint8 | 原码 | 1 |
| uint8_t | Uint8 |
uint16 | 原码 | 2 |
| uint16_t | Uint16 |
uint32 | 原码 | 4 |
| uint32_t | Uint32 |
uint64 | 原码 | 8 |
| uint64_t | Uint64 |
int8 | 补码 | 1 |
| int8_t | Int8 |
int16 | 补码 | 2 |
| int16_t | Int16 |
int32 | 补码 | 4 |
| int32_t | Int32 |
int64 | 补码 | 8 |
| int64_t | Int64 |
任何指针 | 编译时报错 | T * | |||
string,字符串,每个元素为字符类型 | 元素字符用 utf-8 编码 | 先入以 LEB128 编码的 uint32 表达元素个数,然后遍历放入元素。 |
| std::string | Utf8String |
array,数组,元素必为上述内置整型或 string 类型 | 先入以 LEB128 编码的 uint32 表达元素个数,然后遍历放入元素。 | int32 数组:
string数组
| std::vector | DynamicArray | |
bytes,字节流, 操作接口和 array 一致 | 先入以 LEB128 编码的 uint32 表达元素个数,然后遍历放入元素。 | bytes:
| std::vector | Bytes |
自定义可序列化的类型
C++ 合约中可以使用SERIALIZE
宏将自定义数据类型(struct/class)序列化。
SERIALIZE(结构体名, (成员变量1)(成员变量2)...(成员变量n))
示例
struct Foo {
int32_t x;
std::string y;
bool z;
int32_t tmp_value; //如果SERIALIZE中不写tmp_value, 则tmp_value不参与序列化
SERIALIZE(Foo, (y)(x)(z))
};
Foo f;
f.x = -1234567890;
f.y = "hello世界";
f.z = true;
基于 编码表 中对基本类型的编码,Foo 类型的 f 变量的编码相当于按照SERIALIZE
指定的顺序依次编码各成员,未声明的成员不参与编码。上述示例中,按 y—>x—>z 进行顺次编码,首尾相接,结果为0B,68,65,6C,6C,6F,E4,B8,96,E7,95,8C,2E,FD,69,B6,01
。
// 获取返回值解码示例,假设返回了“0B,68,65,6C,6C,6F,E4,B8,96,E7,95,8C,2E,FD,69,B6,01”
WASMOutput wasmOutput = new WASMOutput(ByteUtils.toHexString(transactionReceipt.getOutput()));
String string = wasmOutput.getString(); // "hello世界"
BigInteger integer1 = wasmOutput.getInt32(); // -1234567890
boolean b = wasmOutput.getBoolean(); // true