|
30 | 30 | import cn.hutool.crypto.digest.DigestUtil; |
31 | 31 | import com.alibaba.fastjson.JSON; |
32 | 32 | import com.alibaba.fastjson.JSONArray; |
| 33 | +import com.alibaba.fastjson.JSONObject; |
33 | 34 | import com.alibaba.fastjson.JSONPath; |
34 | 35 | import com.alipay.antchain.bridge.commons.bbc.AbstractBBCContext; |
35 | 36 | import com.alipay.antchain.bridge.commons.bbc.syscontract.AuthMessageContract; |
36 | 37 | import com.alipay.antchain.bridge.commons.bbc.syscontract.ContractStatusEnum; |
37 | 38 | import com.alipay.antchain.bridge.commons.bbc.syscontract.SDPContract; |
38 | 39 | import com.alipay.antchain.bridge.commons.core.base.CrossChainMessage; |
39 | 40 | import com.alipay.antchain.bridge.commons.core.base.CrossChainMessageReceipt; |
40 | | -import com.alipay.antchain.bridge.plugins.eos.types.EosBlockInfo; |
41 | | -import com.alipay.antchain.bridge.plugins.eos.types.EosTransactionStatusEnum; |
42 | | -import com.alipay.antchain.bridge.plugins.eos.types.EosTxActions; |
43 | | -import com.alipay.antchain.bridge.plugins.eos.types.EosTxInfo; |
| 41 | +import com.alipay.antchain.bridge.plugins.eos.types.*; |
44 | 42 | import com.alipay.antchain.bridge.plugins.eos.utils.Utils; |
45 | 43 | import com.alipay.antchain.bridge.plugins.lib.BBCService; |
46 | 44 | import com.alipay.antchain.bridge.plugins.spi.bbc.AbstractBBCService; |
|
61 | 59 | import one.block.eosiojava.session.TransactionProcessor; |
62 | 60 | import one.block.eosiojava.session.TransactionSession; |
63 | 61 | import one.block.eosiojavaabieosserializationprovider.AbiEosSerializationProviderImpl; |
| 62 | +import one.block.eosiojavarpcprovider.error.EosioJavaRpcProviderCallError; |
64 | 63 | import one.block.eosiojavarpcprovider.error.EosioJavaRpcProviderInitializerError; |
65 | 64 | import one.block.eosiojavarpcprovider.implementations.EosioJavaRpcProviderImpl; |
66 | 65 | import one.block.eosiosoftkeysignatureprovider.SoftKeySignatureProviderImpl; |
@@ -184,6 +183,16 @@ public class EosBBCService extends AbstractBBCService { |
184 | 183 | */ |
185 | 184 | private static final String AM_RECV_PKG_FROM_RELAYER_PARAMETER_FORMAT = "{\"invoker\": \"%s\", \"pkg_hex\": \"%s\"}"; |
186 | 185 |
|
| 186 | + /** |
| 187 | + * reject the message when calling {@code recvrelayerx} failed |
| 188 | + */ |
| 189 | + private static final String AM_REJECT_AM_FROM_RELAYER_ACTION = "rejectamx"; |
| 190 | + |
| 191 | + /** |
| 192 | + * - 参数格式 |
| 193 | + */ |
| 194 | + private static final String AM_REJECT_AM_FROM_RELAYER_PARAMETER_FORMAT = "{\"invoker\": \"%s\", \"pkg_hex\": \"%s\"}"; |
| 195 | + |
187 | 196 | // ============================== 插件基本变量 ============================== |
188 | 197 | private EosConfig config; |
189 | 198 |
|
@@ -389,7 +398,16 @@ public CrossChainMessageReceipt readCrossChainMessageReceipt(String txHash) { |
389 | 398 | crossChainMessageReceipt.setSuccessful(txInfo.isSuccess()); |
390 | 399 | crossChainMessageReceipt.setConfirmed(txInfo.isConfirmed()); |
391 | 400 | crossChainMessageReceipt.setTxhash(txHash); |
392 | | - crossChainMessageReceipt.setErrorMsg(crossChainMessageReceipt.isSuccessful() ? "SUCCESS" : txInfo.getStatus().getStatus()); |
| 401 | + if (txInfo.containsAction(config.getAmContractAddressDeployed(), AM_REJECT_AM_FROM_RELAYER_ACTION)) { |
| 402 | + crossChainMessageReceipt.setErrorMsg( |
| 403 | + "call biz failed but seq updated: " + (crossChainMessageReceipt.isSuccessful() ? "SUCCESS" : txInfo.getStatus().getStatus()) |
| 404 | + ); |
| 405 | + crossChainMessageReceipt.setSuccessful(false); |
| 406 | + } else { |
| 407 | + crossChainMessageReceipt.setErrorMsg( |
| 408 | + "call biz: " + (crossChainMessageReceipt.isSuccessful() ? "SUCCESS" : txInfo.getStatus().getStatus()) |
| 409 | + ); |
| 410 | + } |
393 | 411 |
|
394 | 412 | getBBCLogger().info("cross chain message receipt for tx {} : {}", crossChainMessageReceipt.getTxhash(), crossChainMessageReceipt.getErrorMsg()); |
395 | 413 |
|
@@ -555,6 +573,9 @@ public void setProtocol(String protocolAddress, String protocolType) { |
555 | 573 | }, |
556 | 574 | } |
557 | 575 | ); |
| 576 | + if (ObjectUtil.isNull(sendTransactionResponse)) { |
| 577 | + throw new RuntimeException("null transaction response means that calling tx failed"); |
| 578 | + } |
558 | 579 | EosTxInfo txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
559 | 580 | if (ObjectUtil.isNull(txInfo)) { |
560 | 581 | throw new RuntimeException(String.format("failed to get transaction info %s", sendTransactionResponse.getTransactionId())); |
@@ -659,6 +680,9 @@ public void setAmContract(String contractAddress) { |
659 | 680 | }, |
660 | 681 | } |
661 | 682 | ); |
| 683 | + if (ObjectUtil.isNull(sendTransactionResponse)) { |
| 684 | + throw new RuntimeException("null transaction response means that calling tx failed"); |
| 685 | + } |
662 | 686 | EosTxInfo txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
663 | 687 | if (ObjectUtil.isNull(txInfo)) { |
664 | 688 | throw new RuntimeException(String.format("failed to get transaction info %s", sendTransactionResponse.getTransactionId())); |
@@ -716,6 +740,9 @@ public void setLocalDomain(String domain) { |
716 | 740 | }, |
717 | 741 | } |
718 | 742 | ); |
| 743 | + if (ObjectUtil.isNull(sendTransactionResponse)) { |
| 744 | + throw new RuntimeException("null transaction response means that calling tx failed"); |
| 745 | + } |
719 | 746 | EosTxInfo txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
720 | 747 | if (ObjectUtil.isNull(txInfo)) { |
721 | 748 | throw new RuntimeException(String.format("failed to get transaction info %s", sendTransactionResponse.getTransactionId())); |
@@ -792,39 +819,82 @@ public CrossChainMessageReceipt relayAuthMessage(byte[] rawMessage) { |
792 | 819 | HexUtil.encodeHexStr(rawMessage), this.bbcContext.getAuthMessageContract().getContractAddress()); |
793 | 820 |
|
794 | 821 | // 2. invoke am contract |
795 | | - SendTransactionResponse sendTransactionResponse = bbcInvokeContractsOnRpc( |
796 | | - new String[][]{ |
797 | | - { |
798 | | - this.bbcContext.getAuthMessageContract().getContractAddress(), |
799 | | - AM_RECV_PKG_FROM_RELAYER_ACTION, |
800 | | - String.format( |
801 | | - AM_RECV_PKG_FROM_RELAYER_PARAMETER_FORMAT, |
802 | | - this.config.getUserName(), |
803 | | - generateRandomPrefix() + HexUtil.encodeHexStr(rawMessage) |
804 | | - ) |
805 | | - }, |
806 | | - } |
807 | | - ); |
808 | | - EosTxInfo txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
809 | | - if (ObjectUtil.isNull(txInfo)) { |
810 | | - throw new RuntimeException(String.format("failed to get transaction info %s", sendTransactionResponse.getTransactionId())); |
| 822 | + String baseMsg = "call biz"; |
| 823 | + EosTxInfo txInfo = null; |
| 824 | + SendTransactionResponse sendTransactionResponse = bbcInvokeContractsOnRpc(getRelayAuthMessageArgs(rawMessage)); |
| 825 | + if (ObjectUtil.isNotNull(sendTransactionResponse)) { |
| 826 | + txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
| 827 | + if (ObjectUtil.isNull(txInfo)) { |
| 828 | + throw new RuntimeException(String.format("failed to get transaction info %s", sendTransactionResponse.getTransactionId())); |
| 829 | + } |
| 830 | + waitUntilTxIrreversible(txInfo); |
811 | 831 | } |
812 | 832 |
|
813 | | - waitUntilTxIrreversible(txInfo); |
| 833 | + if (ObjectUtil.isNull(txInfo) || !txInfo.isSuccess()) { |
| 834 | + getBBCLogger().error("failed to call biz contract with tx {}", ObjectUtil.isNull(txInfo) ? "no tx sent" : txInfo.getTxId()); |
| 835 | + |
| 836 | + sendTransactionResponse = bbcInvokeContractsOnRpc(getRejectAuthMessageArgs(rawMessage)); |
| 837 | + if (ObjectUtil.isNull(sendTransactionResponse)) { |
| 838 | + getBBCLogger().error("calling `rejectamx` failed"); |
| 839 | + } else { |
| 840 | + txInfo = bbcGetTxInfoByTransactionHashOnRpc(sendTransactionResponse.getTransactionId()); |
| 841 | + if (ObjectUtil.isNull(txInfo)) { |
| 842 | + throw new RuntimeException(String.format("failed to get transaction info %s for adding seq", sendTransactionResponse.getTransactionId())); |
| 843 | + } |
| 844 | + |
| 845 | + baseMsg = "call biz failed but seq updated"; |
| 846 | + getBBCLogger().info("send tx {} to add sequence by 1", txInfo.getTxId()); |
| 847 | + } |
| 848 | + } |
814 | 849 |
|
815 | 850 | // 3. check transaction |
816 | 851 | CrossChainMessageReceipt crossChainMessageReceipt = new CrossChainMessageReceipt(); |
817 | 852 |
|
818 | | - crossChainMessageReceipt.setSuccessful(txInfo.isSuccess()); |
819 | | - crossChainMessageReceipt.setConfirmed(txInfo.isConfirmed()); |
820 | | - crossChainMessageReceipt.setTxhash(txInfo.getTxId()); |
821 | | - crossChainMessageReceipt.setErrorMsg(crossChainMessageReceipt.isSuccessful() ? "" : txInfo.getStatus().getStatus()); |
| 853 | + crossChainMessageReceipt.setSuccessful(ObjectUtil.isNotNull(txInfo) && txInfo.isSuccess()); |
| 854 | + crossChainMessageReceipt.setConfirmed(ObjectUtil.isNotNull(txInfo) && txInfo.isConfirmed()); |
| 855 | + crossChainMessageReceipt.setTxhash(ObjectUtil.isNotNull(txInfo) ? txInfo.getTxId() : ""); |
| 856 | + |
| 857 | + String errorMsg = StrUtil.format( |
| 858 | + "{}: {}", |
| 859 | + baseMsg, |
| 860 | + crossChainMessageReceipt.isSuccessful() ? "SUCCESS" |
| 861 | + : ObjectUtil.isNull(txInfo) ? "FAILED TO CALL" : txInfo.getStatus().getStatus() |
| 862 | + ); |
| 863 | + crossChainMessageReceipt.setErrorMsg(errorMsg); |
822 | 864 |
|
823 | | - getBBCLogger().info("relay auth message by tx {}", txInfo.getTxId()); |
| 865 | + getBBCLogger().info("relay auth message by tx {} with msg {}", crossChainMessageReceipt.getTxhash(), errorMsg); |
824 | 866 |
|
825 | 867 | return crossChainMessageReceipt; |
826 | 868 | } |
827 | 869 |
|
| 870 | + private String[][] getRelayAuthMessageArgs(byte[] rawMessage) { |
| 871 | + return new String[][]{ |
| 872 | + { |
| 873 | + this.bbcContext.getAuthMessageContract().getContractAddress(), |
| 874 | + AM_RECV_PKG_FROM_RELAYER_ACTION, |
| 875 | + String.format( |
| 876 | + AM_RECV_PKG_FROM_RELAYER_PARAMETER_FORMAT, |
| 877 | + this.config.getUserName(), |
| 878 | + generateRandomPrefix() + HexUtil.encodeHexStr(rawMessage) |
| 879 | + ) |
| 880 | + }, |
| 881 | + }; |
| 882 | + } |
| 883 | + |
| 884 | + private String[][] getRejectAuthMessageArgs(byte[] rawMessage) { |
| 885 | + return new String[][]{ |
| 886 | + { |
| 887 | + this.bbcContext.getAuthMessageContract().getContractAddress(), |
| 888 | + AM_REJECT_AM_FROM_RELAYER_ACTION, |
| 889 | + String.format( |
| 890 | + AM_REJECT_AM_FROM_RELAYER_PARAMETER_FORMAT, |
| 891 | + this.config.getUserName(), |
| 892 | + generateRandomPrefix() + HexUtil.encodeHexStr(rawMessage) |
| 893 | + ) |
| 894 | + }, |
| 895 | + }; |
| 896 | + } |
| 897 | + |
828 | 898 | private String generateRandomPrefix() { |
829 | 899 | return StrUtil.sub(DigestUtil.sha256Hex(UUID.randomUUID().toString()), 0, 8); |
830 | 900 | } |
@@ -865,6 +935,18 @@ private SendTransactionResponse bbcInvokeContractsOnRpc(String[][] invokeParams) |
865 | 935 | } catch (TransactionPrepareError e) { |
866 | 936 | throw new RuntimeException("failed to prepare invoke contract action", e); |
867 | 937 | } catch (TransactionSignAndBroadCastError e) { |
| 938 | + if (e.getCause().getCause().getCause() instanceof EosioJavaRpcProviderCallError) { |
| 939 | + EosioJavaRpcProviderCallError callError = (EosioJavaRpcProviderCallError) e.getCause().getCause().getCause(); |
| 940 | + if (callError.getRpcResponseError().getCode().equals(BigInteger.valueOf(500))) { |
| 941 | + getBBCLogger().error( |
| 942 | + "failed to call biz contract: ( code: {}, msg: {}, detail: {} ) ", |
| 943 | + callError.getRpcResponseError().getCode(), |
| 944 | + callError.getRpcResponseError().getMessage(), |
| 945 | + JSON.toJSONString(callError.getRpcResponseError().getError()) |
| 946 | + ); |
| 947 | + return null; |
| 948 | + } |
| 949 | + } |
868 | 950 | throw new RuntimeException("failed to sign and broadcast invoke contract action", e); |
869 | 951 | } |
870 | 952 | } |
@@ -903,6 +985,12 @@ private EosTxInfo bbcGetTxInfoByTransactionHashOnRpc(String txHash) { |
903 | 985 | (String) JSONPath.extract(response, "$.trx.receipt.status") |
904 | 986 | ) |
905 | 987 | ); |
| 988 | + |
| 989 | + JSONArray actions = (JSONArray) JSONPath.extract(response, "$.trx.trx.actions"); |
| 990 | + if (ObjectUtil.isNotNull(actions)) { |
| 991 | + txInfo.setActions(actions.toJavaList(EosTxAction.class)); |
| 992 | + } |
| 993 | + |
906 | 994 | return txInfo; |
907 | 995 | } |
908 | 996 |
|
|
0 commit comments