咨询一下关于获取交易hash的方法的两个问题,请大神指教~

CITA文档中,对于交易首先进行了建立:

long currentHeight = currentBlockNumber();
long validUntilBlock = currentHeight + 80;
Random random = new Random(System.currentTimeMillis());
String nonce = String.valueOf(Math.abs(random.nextLong()));
long quota = 1000000;
Transaction tx = Transaction.createContractTransaction(nonce, quota, validUntilBlock, contractCode);

然后对交易进行了签名:

String rawTx = tx.sign(privateKey);

//TODO,第一个问题,我想获取此时tx的hash值,要通过调用sdk中哪个方法可以获取到?

CITAj service = CITAj.build(new HttpService(ipAddr + ":" + port));
AppSendTransaction result = service.appSendRawTransaction(rawTx).send();

第二个问题,若第一个问题能获取到hash,这个hash和下面代码中链上及时返回的txHash是否一致?

//得到回执和回执中的合约部署地址
String txHash = result.getSendTransactionResult().getHash();
TransactionReceipt txReceipt = service.appGetTransactionReceipt(txHash).send().getTransactionReceipt();
String contractAddress = txReceipt.getContractAddress();
//对交易签名并且发送
Transaction tx = Transaction.createFunctionCallTransaction(contractAddress, nonce, quota, validUntilBlock, functionCallData);
String rawTx = tx.sign(privateKey);
String txHash =  service.appSendRawTransaction(rawTx).send().getSendTransactionResult().getHash();

首先,我对你的文本进行了一个更改。请使用 Markdown 格式编辑你的代码,可以使人更易读。
一般来说,你需要发送后才能获得交易Hash。
第一个问题,是你需要调用 发送 接口后才会获得交易 hash。
第二个问题,一样。

如果我想之前就知道这个交易hash,并且入库,为了返回之后匹配做后续操作,用sdk中哪些函数的组合能完成这个需求?

@baojun, 我们的 SDK 提供有相应的接口吗?
如果没有,我需要看一下底层链是怎么计算的,然后看能不能由用户自己根据底层链的算法计算出来。

目前我没找到通过Transaction这个数据结构得到Transaction 的hash的方法,于是需要求助大神。

sdk没有计算hash的接口

@psxf91, 你稍等我一下,我需要研究一下 CITA 的代码,然后把 Transaction hash 的计算方法告诉你,你在用户层用相同的方法计算一下看看。

  1. 构造 Transaction 对象 tx ,填充 to(to_v1) , nonce , valid_until_block , quota , data , value , chain_id(chain_id_v1) , version 8 个字段。
  2. tx 对象 protobuf 序列化后按照指定的哈希算法做哈希计算, 得到 hash 值。

大概过程是这样,这是cita-proto 的 repo: https://github.com/cryptape/cita-proto

可以等 @leeyr 帮你找下示例代码

我看了一下 CITA 的代码,tx_hash 是使用 rust 反序列化后的 Transaction 结构来计算的。具体计算方法是:

#[cfg(feature = "sha3hash")]
impl<T> Hashable for T
where
    T: AsRef<[u8]>,
{
    fn crypt_hash_into(&self, dest: &mut [u8]) {
        let input: &[u8] = self.as_ref();
        tiny_keccak::Keccak::keccak256(input, dest);
    }
}

#[cfg(feature = "blake2bhash")]
impl<T> Hashable for T
where
    T: AsRef<[u8]>,
{
    fn crypt_hash_into(&self, dest: &mut [u8]) {
        let input: &[u8] = self.as_ref();

        unsafe {
            blake2b::blake2b(
                dest.as_mut_ptr(),
                dest.len(),
                input.as_ptr(),
                input.len(),
                BLAKE2BKEY.as_bytes().as_ptr(),
                BLAKE2BKEY.len(),
            );
        }
    }
}

#[cfg(feature = "sm3hash")]
impl<T> Hashable for T
where
    T: AsRef<[u8]>,
{
    fn crypt_hash_into(&self, dest: &mut [u8]) {
        let input: &[u8] = self.as_ref();
        dest.copy_from_slice(libsm::sm3::hash::Sm3Hash::new(input).get_hash().as_ref());
    }
}

所以,我感觉在 java 上是算不出来的,因为 java 下是不知道 Transaction 在 rust 下的反序列化结构的。

如果一定要做这个事,估计要用 rust 开发个小工具来获取。

另外,想了解一下,你们是一定要提前获取 tx_hash 吗?为什么要这么做?