Ardor
如何將加密消息附加到合約內的支付交易中?
如何從合約內部將加密消息附加到支付交易?在 2.2.0e 版本中,只需使用 .messageToEncrypt 呼叫 SendMoneyCall API 即可:
SendMoneyCall sendMoneyCall = SendMoneyCall.create(<chain id>) .recipient(<recipient account>) .amountNQT(<amount>) .messageToEncrypt("test message");
這似乎不適用於 2.2.1 版。我現在必須手動執行嗎?就像首先加密和壓縮消息,然後通過
sendMoneyCall.message(“test message”)
?
我已經在 ardors slack 開發者頻道中提出了這個問題,並將其發佈在此處以獲取文件。在一個小對話之後,我用一個小範例契約詳細說明了發生的錯誤,我得到了一個有效解決方案的解釋:
關於 messageToEncrypt 參數,問題在於,當合約送出交易時,它首先生成時沒有使用 secretPhrase,然後簽名並廣播。這意味著在生成交易時無法對消息進行加密。因此,要在您的合約中送出加密消息,您需要使用範例合約 IgnisArdorRates 第 94 行中的技術自行對其進行加密:
// Encrypt the message EncryptedData encryptedData = context.getConfig().encryptTo(Account.getPublicKey(context.getSenderId()), Convert.toBytes(response.toJSONString(), true), true); // Send a message back to the user who requested the information SendMessageCall sendMessageCall = SendMessageCall.create(context.getChainOfTransaction().getId()).recipient(context.getSenderId()). encryptedMessageData(encryptedData.getData()). encryptedMessageNonce(encryptedData.getNonce()). encryptedMessageIsPrunable(true); return context.createTransaction(sendMessageCall);
我已經根據這個答案調整了我的範例契約並將其發佈在此處以分享解決方案:
契約範例:
package com.jelurida.ardor.contracts; import nxt.account.Account; import nxt.addons.AbstractContract; import nxt.addons.JO; import nxt.addons.TransactionContext; import nxt.crypto.EncryptedData; import nxt.http.callers.SendMoneyCall; import nxt.http.responses.TransactionResponse; import nxt.util.Convert; public class TestContract extends AbstractContract { @Override public JO processTransaction(TransactionContext context) { TransactionResponse transaction = context.getTransaction(); EncryptedData encryptedData = context.getConfig().encryptTo(Account.getPublicKey(context.getSenderId()), Convert.toBytes("test message", true), true); SendMoneyCall sendMoneyCall = SendMoneyCall.create(transaction.getChainId()) .recipient(transaction.getSender()) .amountNQT(transaction.getAmount()) .encryptedMessageData(encryptedData.getData()) .encryptedMessageNonce(encryptedData.getNonce()) .encryptedMessageIsPrunable(true); return context.createTransaction(sendMoneyCall); } }
單元測試:
package com.jelurida.ardor.contracts; import nxt.addons.JO; import nxt.blockchain.Block; import nxt.blockchain.ChildTransaction; import nxt.blockchain.FxtTransaction; import nxt.messaging.PrunableEncryptedMessageAppendix; import nxt.util.Convert; import org.junit.Assert; import org.junit.Test; import static nxt.blockchain.ChildChain.IGNIS; public class TestContractTest extends AbstractContractTest { @Test public void encryptedMessageTest() { String contractName = ContractTestHelper.deployContract(TestContract.class); JO messageJson = new JO(); messageJson.put("contract", contractName); String message = messageJson.toJSONString(); ContractTestHelper.bobPaysContract(message, IGNIS); generateBlock(); Block lastBlock = getLastBlock(); boolean transactionFound = false; for (FxtTransaction transaction : lastBlock.getFxtTransactions()) { for (ChildTransaction childTransaction : transaction.getSortedChildTransactions()) { transactionFound = true; Assert.assertEquals("test message", extractMessage(childTransaction)); } } Assert.assertTrue(transactionFound); } private String extractMessage(ChildTransaction transaction) { PrunableEncryptedMessageAppendix appendix = (PrunableEncryptedMessageAppendix) transaction.getAppendages().stream().filter(a -> a instanceof PrunableEncryptedMessageAppendix).findFirst().orElse(null); byte[] compressedData = appendix.getEncryptedData().decrypt(BOB.getSecretPhrase(), ALICE.getPublicKey()); byte[] data = Convert.uncompress(compressedData); return Convert.toString(data, true); }
希望它有幫助:)。