You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从HSM获取签名:Hedera自定义签名交易执行报错问题

问题排查:自定义HSM签名Hedera交易失败的原因

核心问题:签名对象错误

你当前代码对交易哈希(transaction.getTransactionHash())进行签名,但Hedera网络要求签名的是冻结后的完整交易字节流,而非交易哈希。这就是SDK自带sign()方法能成功的原因——它内部是对正确的交易字节做签名。

具体修正步骤

  1. 替换签名输入数据:把transaction.getTransactionHash()换成transaction.toBytes()
  2. 你的Ed25519签名算法实现本身是正确的,仅需调整签名对象即可

修改后的关键代码片段

// 替换获取交易哈希的逻辑,改为获取冻结后的交易字节流
byte[] transactionBytes = transaction.toBytes();

// 使用交易字节流执行签名
transaction.addSignature(fundedPrivateKey.getPublicKey(), this.sign(transactionBytes, fundedPrivateKey));

补充说明

  • Hedera节点的验证逻辑要求签名必须对应完整的交易序列化字节,这样节点才能重新序列化交易并验证签名匹配性。
  • 你代码里的本地签名验证能通过,是因为确实正确签名了交易哈希,但这和Hedera节点的验证要求不匹配,所以提交后会报错。

完整修正后的testSigner方法

public void testSigner() throws PrecheckStatusException, TimeoutException, CryptoException, ReceiptStatusException {
    PrivateKey fundedPrivateKey = PrivateKey.fromStringED25519(MY_PRIVATE_KEY);
    Client client = Client.forTestnet();
    AccountId fundedAccountId = AccountId.fromString("0.0.3672483");
    client.setOperator(fundedAccountId, fundedPrivateKey);

    PrivateKey emptyPrivateKey = PrivateKey.generateED25519();
    PublicKey publicKey = emptyPrivateKey.getPublicKey();
    TransactionResponse newAccountCreateTX = new AccountCreateTransaction()
          .setKey(publicKey)
          .setInitialBalance(Hbar.from(0))
          .execute(client);

    client.setOperator(newAccountCreateTX.getReceipt(client).accountId, emptyPrivateKey);

    // Create a transaction that needs to be signed with the fundedPrivateKey
    assert client.getOperatorAccountId() != null;
    TransferTransaction transaction = new TransferTransaction()
          .addHbarTransfer(client.getOperatorAccountId(), Hbar.from(10))
          .addHbarTransfer(fundedAccountId, Hbar.from(-10))
          .setTransactionId(TransactionId.generate(fundedAccountId))
          .freezeWith(client)
//          .sign(fundedPrivateKey)
          .sign(emptyPrivateKey);
    
    // 替换为获取冻结后的交易字节流
    byte[] transactionBytes = transaction.toBytes();
    
    // Add the signature to the transaction
    transaction.addSignature(fundedPrivateKey.getPublicKey(), this.sign(transactionBytes, fundedPrivateKey));

    // Execute the transaction
    TransactionResponse response = transaction.execute(client);
    TransactionId transactionId = response.transactionId;
    System.out.println("Transaction ID: " + transactionId);
}

内容的提问来源于stack exchange,提问作者Micha Roon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:13:16