From ae6b1d3a4899ae6bffc9598b6ac476d2d24d2697 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 22 Feb 2024 14:55:52 +0800 Subject: [PATCH 01/17] [feat][*][*]: sdp message v2 upgraded --- antchain-bridge-bcdns/pom.xml | 2 +- antchain-bridge-commons/pom.xml | 2 +- .../commons/core/sdp/AtomicFlagEnum.java | 104 ++++++++++++++++++ .../bridge/commons/core/sdp/ISDPMessage.java | 95 ++++++++++++++++ .../commons/core/sdp/SDPMessageFactory.java | 9 ++ .../bridge/commons/core/sdp/SDPMessageV1.java | 10 ++ .../bridge/commons/core/sdp/SDPMessageV2.java | 42 +++++-- .../bridge/commons/SDPMessageTest.java | 42 ++++++- antchain-bridge-plugin-lib/pom.xml | 2 +- antchain-bridge-plugin-manager/pom.xml | 2 +- antchain-bridge-spi/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 294 insertions(+), 20 deletions(-) create mode 100644 antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java diff --git a/antchain-bridge-bcdns/pom.xml b/antchain-bridge-bcdns/pom.xml index 877b1d85..a147b311 100644 --- a/antchain-bridge-bcdns/pom.xml +++ b/antchain-bridge-bcdns/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-bcdns - 0.2.1 + 0.2.2 8 diff --git a/antchain-bridge-commons/pom.xml b/antchain-bridge-commons/pom.xml index 54a64955..32af3ccb 100644 --- a/antchain-bridge-commons/pom.xml +++ b/antchain-bridge-commons/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-commons - 0.2.1 + 0.2.2 8 diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java new file mode 100644 index 00000000..decd5f83 --- /dev/null +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java @@ -0,0 +1,104 @@ +package com.alipay.antchain.bridge.commons.core.sdp; + +import cn.hutool.core.util.ByteUtil; +import com.alipay.antchain.bridge.commons.exception.AntChainBridgeCommonsException; +import com.alipay.antchain.bridge.commons.exception.CommonsErrorCodeEnum; +import lombok.Getter; + +/** + * Enum {@code AtomicFlagEnum} gives all types for SDP packet. + */ +@Getter +public enum AtomicFlagEnum { + + /** + * {@code NONE_ATOMIC} means that this request has no atomic feature + * and no ack response expected. Sender contract has no need to + * implement ack processing interfaces for this type requests. + */ + NONE_ATOMIC((byte) 0), + + /** + * {@code ATOMIC_REQUEST} means this sdp packet is cross-chain sending to + * another blockchain which expected to receive the message contained in + * packet payload. This request expect an ack response from receiving + * blockchain to notify the sender contract that cross-chain calling success + * or not. + */ + ATOMIC_REQUEST((byte) 1), + + /** + * {@code ACK_SUCCESS} means this sdp packet has been processed + * successfully on receiving blockchain and send an ack response back. + */ + ACK_SUCCESS((byte) 2), + + /** + * {@code ACK_ERROR} means this sdp packet has been processed + * with errors when calling receiver contract on receiving blockchain. + * But there is no transaction revert on receiving blockchain and all + * state changes about cross-chain system contracts saved, for example + * sequence added. And then an ack response sent back. + */ + ACK_ERROR((byte) 3), + + /** + *

+ * {@code ACK_RECEIVE_TX_FAILED} means that sdp packet has been processed + * with errors and receiving transaction has been reverted. This is usually + * caused by bugs of cross-chain system contract implementation or receiving + * blockchain account. + *

+ *

+ * This type ack response wouldn't protect by ledger verification executed and signed by + * {@code PTC} because that no state update on receiving blockchain with transaction revert. + * Relayer would commit this ack response by a special {@code BBCService} method. + * So sender contract's developer must know this ack response is unsafe. + *

+ */ + ACK_RECEIVE_TX_FAILED((byte) 4), + + /** + *

+ * {@code ACK_UNKNOWN_EXCEPTION} means that some unexpected situations happened + * like retry out of times or some timeout stuff. + *

+ *

+ * This type ack response wouldn't protect by ledger verification executed and signed by + * {@code PTC} because that no state update on receiving blockchain. + * Relayer would commit this ack response by a special {@code BBCService} method. + * So sender contract's developer must know this ack response is unsafe. + *

+ */ + ACK_UNKNOWN_EXCEPTION((byte) 5); + + public static AtomicFlagEnum parseFrom(byte value) { + if (value == NONE_ATOMIC.value) { + return NONE_ATOMIC; + } else if (value == ATOMIC_REQUEST.value) { + return ATOMIC_REQUEST; + } else if (value == ACK_SUCCESS.value) { + return ACK_SUCCESS; + } else if (value == ACK_ERROR.value) { + return ACK_ERROR; + } else if (value == ACK_RECEIVE_TX_FAILED.value) { + return ACK_RECEIVE_TX_FAILED; + } else if (value == ACK_UNKNOWN_EXCEPTION.value) { + return ACK_UNKNOWN_EXCEPTION; + } + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + "no sdp atomic flag found for " + ByteUtil.byteToUnsignedInt(value) + ); + } + + AtomicFlagEnum(byte value) { + this.value = value; + } + + public boolean isAtomic() { + return this == ATOMIC_REQUEST; + } + + private final byte value; +} diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java index 5501f769..59e5d3f0 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java @@ -20,17 +20,112 @@ import com.alipay.antchain.bridge.commons.core.base.CrossChainIdentity; import com.alipay.antchain.bridge.commons.core.base.IMessage; +/** + * Interface {@code ISDPMessage} defines all methods for the SDP + * message object. + * + *

+ * Smart-contract Datagram Protocol, SDP in short, provides the + * crosschain communication ability between contracts on different + * blockchains. The SDP contract is supposed to pre-deployed on each + * blockchain involved in crosschain network. During the communication + * processing, SDP contracts pack the message from sender contract into + * SDP packet and sink the raw packet bytes into AM packet. After + * ACB network relaying the cross-chain message onto receiving blockchain, + * the SDP contract on receiving blockchain would unpack the SDP packet + * and deliver the message from sender contract to the identified + * receiver contract. + *

+ *

+ * SDP now provides two versions of implementations, version one and two. + * Version one provides ability to sending ordered or unordered messages + * to another contract. And version two offer the atomic type message sending + * to another contract expecting multiple type acknowledge responses + * in different situations. And version two is good at preventing replay attacks. + *

+ */ public interface ISDPMessage extends IMessage { + /** + * Get the receiving blockchain domain name. + * + * @return receiving blockchain domain name + */ CrossChainDomain getTargetDomain(); + /** + * Get the receiving contract identity. + * + *

+ * All crosschain identity in AntChain Bridge crosschain network is 32 bytes + * fixed. Usually crosschain identity is hash value of 256 bit length or less + * bytes value with padding zeros as prefix. + *

+ * @return crosschain identity + */ CrossChainIdentity getTargetIdentity(); + /** + * Return the sequence value in SDP packet. + *

+ * If sequence greater than or equal to zero, it means ordered SDP packet. + * Ordered SDP packet would be committed to receiving blockchain by order. + * If the SDP packet with last sequence number is not committed on receiving + * blockchain, the next SDP packet can't be delivered successfully to receiving + * blockchain. + *

+ *

+ * If sequence is {@code 0xFFFFFFFF}, it means unordered SDP packet. + * Unordered SDP packet is parallel sent to receiving blockchain. + *

+ * + * @return the sequence value in SDP packet + */ int getSequence(); + /** + * The message bytes from sender contract. + * + * @return raw message + */ byte[] getPayload(); + /** + * Version number of this SDP packet. + * + * @return version + */ int getVersion(); + /** + * The nonce value for unordered packet. + * + *

+ * In crosschain channel between sender and receiver, the nonce of each SDP + * packet is unique. The receiving SDP contract would check if the SDP packet + * has been processed by recording its nonce value. + *

+ * + *

+ * Only version two has this work. + *

+ * + * @return nonce value + */ + long getNonce(); + + /** + * Shows that is this SDP packet atomic. + * + * @return atomic or not + */ boolean getAtomic(); + + /** + * Method {@code getAtomicFlag} return the flag value shows that + * which atomic type of this sdp packet, details please check + * {@link AtomicFlagEnum} + * @return flag value to show the type + */ + AtomicFlagEnum getAtomicFlag(); } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java index 69a1a20b..f7701072 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java @@ -30,6 +30,10 @@ public static ISDPMessage createSDPMessage(byte[] rawMessage) { } public static ISDPMessage createSDPMessage(int version, String targetDomain, byte[] targetIdentity, int sequence, byte[] payload) { + return createSDPMessage(version, targetDomain, targetIdentity, AtomicFlagEnum.NONE_ATOMIC, -1, sequence, payload); + } + + public static ISDPMessage createSDPMessage(int version, String targetDomain, byte[] targetIdentity, AtomicFlagEnum atomicFlag, long nonce, int sequence, byte[] payload) { AbstractSDPMessage sdpMessage = createAbstractSDPMessage(version); sdpMessage.setTargetDomain(new CrossChainDomain(targetDomain)); @@ -37,6 +41,11 @@ public static ISDPMessage createSDPMessage(int version, String targetDomain, byt sdpMessage.setSequence(sequence); sdpMessage.setPayload(payload); + if (version == SDPMessageV2.MY_VERSION) { + ((SDPMessageV2) sdpMessage).setNonce(nonce); + ((SDPMessageV2) sdpMessage).setAtomicFlag(atomicFlag); + } + return sdpMessage; } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java index 17c5727e..f3c651bd 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java @@ -132,4 +132,14 @@ public void setPayload(byte[] payload) { public boolean getAtomic() { return false; } + + @Override + public AtomicFlagEnum getAtomicFlag() { + return AtomicFlagEnum.NONE_ATOMIC; + } + + @Override + public long getNonce() { + return -1; + } } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java index 9c700a0e..239f9267 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java @@ -25,7 +25,10 @@ import com.alipay.antchain.bridge.commons.exception.AntChainBridgeCommonsException; import com.alipay.antchain.bridge.commons.exception.CommonsErrorCodeEnum; import lombok.Getter; +import lombok.Setter; +@Setter +@Getter public class SDPMessageV2 extends AbstractSDPMessage { public static final int MY_VERSION = 2; @@ -33,21 +36,23 @@ public class SDPMessageV2 extends AbstractSDPMessage { @Getter public static class SDPPayloadV2 implements ISDPPayload { - private byte[] payload; + private final byte[] payload; public SDPPayloadV2(byte[] payload) { this.payload = payload; } } - private boolean atomic; + private AtomicFlagEnum atomicFlag; + + private long nonce; @Override public void decode(byte[] rawMessage) { - if (rawMessage.length < 49) { + if (rawMessage.length < 57) { throw new AntChainBridgeCommonsException( CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, - String.format("length of message v2 supposes to be 49 bytes at least but get %d . ", rawMessage.length) + String.format("length of message v2 supposes to be 57 bytes at least but get %d . ", rawMessage.length) ); } @@ -56,13 +61,14 @@ public void decode(byte[] rawMessage) { offset = extractTargetDomain(rawMessage, offset); offset = extractTargetIdentity(rawMessage, offset); offset = extractAtomic(rawMessage, offset); + offset = extractNonce(rawMessage, offset); offset = extractSequence(rawMessage, offset); extractPayload(rawMessage, offset); } @Override public byte[] encode() { - byte[] rawMessage = new byte[49 + byte[] rawMessage = new byte[57 + this.getTargetDomain().toBytes().length + this.getPayload().length]; @@ -70,6 +76,7 @@ public byte[] encode() { offset = putTargetDomain(rawMessage, offset); offset = putTargetIdentity(rawMessage, offset); offset = putAtomic(rawMessage, offset); + offset = putNonce(rawMessage, offset); offset = putSequence(rawMessage, offset); putPayload(rawMessage, offset); @@ -86,12 +93,9 @@ public int getVersion() { return MY_VERSION; } - public void setAtomic(boolean atomic) { - this.atomic = atomic; - } - + @Override public boolean getAtomic() { - return atomic; + return atomicFlag.isAtomic(); } private int extractTargetDomain(byte[] rawMessage, int offset) { @@ -114,7 +118,16 @@ private int extractTargetDomain(byte[] rawMessage, int offset) { } private int extractAtomic(byte[] rawMessage, int offset) { - this.setAtomic(ByteUtil.byteToUnsignedInt(rawMessage[--offset]) != 0); + this.setAtomicFlag(AtomicFlagEnum.parseFrom(rawMessage[--offset])); + return offset; + } + + private int extractNonce(byte[] rawMessage, int offset) { + offset -= 8; + byte[] rawSeq = new byte[8]; + System.arraycopy(rawMessage, offset, rawSeq, 0, 8); + this.setNonce(ByteUtil.bytesToLong(rawSeq, ByteOrder.BIG_ENDIAN)); + return offset; } @@ -185,6 +198,13 @@ private int putAtomic(byte[] rawMessage, int offset) { return offset; } + private int putNonce(byte[] rawMessage, int offset) { + offset -= 8; + System.arraycopy(ByteUtil.longToBytes(this.getNonce(), ByteOrder.BIG_ENDIAN), 0, rawMessage, offset, 8); + + return offset; + } + private int putSequence(byte[] rawMessage, int offset) { offset -= 4; System.arraycopy(ByteUtil.intToBytes(this.getSequence(), ByteOrder.BIG_ENDIAN), 0, rawMessage, offset, 4); diff --git a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java index 67d89812..f13c0c17 100644 --- a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java +++ b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java @@ -1,9 +1,10 @@ package com.alipay.antchain.bridge.commons; +import java.nio.ByteOrder; + +import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.HexUtil; -import com.alipay.antchain.bridge.commons.core.sdp.AbstractSDPMessage; -import com.alipay.antchain.bridge.commons.core.sdp.ISDPMessage; -import com.alipay.antchain.bridge.commons.core.sdp.SDPMessageFactory; +import com.alipay.antchain.bridge.commons.core.sdp.*; import org.junit.Assert; import org.junit.Test; @@ -17,6 +18,16 @@ public class SDPMessageTest { private static final String PAYLOAD_V1 = RAW_MESSAGE_HEX_V1.substring(64, 128) + RAW_MESSAGE_HEX_V1.substring(0, 16); + private static final String RAW_MESSAGE_HEX_V2 = "17943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf200000028ffffffff000000000000000001000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000aff000002"; + + private static final String TARGET_DOMAIN_V2 = HexUtil.decodeHexStr(RAW_MESSAGE_HEX_V2.substring(178, 198)); + + private static final String TARGET_ID_V2 = RAW_MESSAGE_HEX_V2.substring(114, 178); + + private static final String PAYLOAD_V2 = RAW_MESSAGE_HEX_V2.substring(0, 80); + + private static final long NONCE_V2 = ByteUtil.bytesToLong(HexUtil.decodeHex(RAW_MESSAGE_HEX_V2.substring(96, 112)), ByteOrder.BIG_ENDIAN); + @Test public void testSDPMessageV1Decode() { ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage(HexUtil.decodeHex(RAW_MESSAGE_HEX_V1)); @@ -33,4 +44,29 @@ public void testSDPMessageV1Encode() { HexUtil.decodeHex(TARGET_ID_V1), AbstractSDPMessage.UNORDERED_SEQUENCE, HexUtil.decodeHex(PAYLOAD_V1)); Assert.assertEquals(RAW_MESSAGE_HEX_V1, HexUtil.encodeHexStr(sdpMessage.encode())); } + + @Test + public void testSDPMessageV2Encode() { + ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage( + 2, + TARGET_DOMAIN_V2, + HexUtil.decodeHex(TARGET_ID_V2), + AtomicFlagEnum.ATOMIC_REQUEST, + NONCE_V2, + AbstractSDPMessage.UNORDERED_SEQUENCE, + HexUtil.decodeHex(PAYLOAD_V2) + ); + Assert.assertTrue(sdpMessage instanceof SDPMessageV2); + Assert.assertEquals(RAW_MESSAGE_HEX_V2, HexUtil.encodeHexStr(sdpMessage.encode())); + } + + @Test + public void testSDPMessageV2Decode() { + ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage(HexUtil.decodeHex(RAW_MESSAGE_HEX_V2)); + Assert.assertTrue(sdpMessage instanceof SDPMessageV2); + Assert.assertEquals(TARGET_DOMAIN_V2, sdpMessage.getTargetDomain().getDomain()); + Assert.assertEquals(TARGET_ID_V2, sdpMessage.getTargetIdentity().toHex()); + Assert.assertEquals(NONCE_V2, sdpMessage.getNonce()); + Assert.assertEquals(PAYLOAD_V2, HexUtil.encodeHexStr(sdpMessage.getPayload())); + } } diff --git a/antchain-bridge-plugin-lib/pom.xml b/antchain-bridge-plugin-lib/pom.xml index a98da612..a70d8873 100644 --- a/antchain-bridge-plugin-lib/pom.xml +++ b/antchain-bridge-plugin-lib/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-lib - 0.2.1 + 0.2.2 8 diff --git a/antchain-bridge-plugin-manager/pom.xml b/antchain-bridge-plugin-manager/pom.xml index bb2b6600..aa502c5c 100644 --- a/antchain-bridge-plugin-manager/pom.xml +++ b/antchain-bridge-plugin-manager/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-manager - 0.2.1 + 0.2.2 8 diff --git a/antchain-bridge-spi/pom.xml b/antchain-bridge-spi/pom.xml index e971af79..49e0cb01 100644 --- a/antchain-bridge-spi/pom.xml +++ b/antchain-bridge-spi/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-spi - 0.2.1 + 0.2.2 8 diff --git a/pom.xml b/pom.xml index 131f1e9d..a0d998e8 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.alipay.antchain.bridge antchain-bridge-sdk - 0.2.1 + 0.2.2 antchain-bridge-commons From 4040c0c0457f1732b87cde346151180098af3c6a Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 22 Feb 2024 16:02:02 +0800 Subject: [PATCH 02/17] [fix][*][*]: sdp message v2 atomic flag encode incorrect --- .../alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java index 239f9267..f98fdf6b 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java @@ -18,7 +18,6 @@ import java.nio.ByteOrder; -import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ByteUtil; import com.alipay.antchain.bridge.commons.core.base.CrossChainDomain; import com.alipay.antchain.bridge.commons.core.base.CrossChainIdentity; @@ -194,7 +193,7 @@ private int putTargetIdentity(byte[] rawMessage, int offset) { } private int putAtomic(byte[] rawMessage, int offset) { - rawMessage[--offset] = BooleanUtil.toByte(this.getAtomic()); + rawMessage[--offset] = this.getAtomicFlag().getValue(); return offset; } From fca2fbe30dddd6e45ff624cb805d985f8fc80126 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 22 Feb 2024 16:02:28 +0800 Subject: [PATCH 03/17] [feat][*][*]: sdp message v2 solidity interface --- .../onchain-plugin/solidity/sys/SDPMsg.sol | 8 +++ .../solidity/sys/interfaces/ISDPMessage.sol | 51 +++++++++++++++++-- .../solidity/sys/lib/utils/Ownable.sol | 2 +- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index b930ca55..fc71af13 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -81,6 +81,14 @@ contract SDPMsg is ISDPMessage, Ownable { _afterSendUnordered(); } + function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) override external returns (uint32) { + return 0; + } + + function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint64) { + return 0; + } + function recvMessage(string calldata senderDomain, bytes32 senderID, bytes calldata pkg) override external onlyAM { _beforeRecv(senderDomain, senderID, pkg); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol index 34eb5abc..8db40b79 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol @@ -17,7 +17,7 @@ import "./ISubProtocol.sol"; interface ISDPMessage is ISubProtocol { /** - * @dev When SDP contract receive msg from AuthMessage contract, SDP contract would call the receiver + * @dev When SDP contract receive msg in SDPv1 from AuthMessage contract, SDP contract would call the receiver * contract decoded from sdp msg. And then, the result of calling receiver contract would emit this event * `receiveMessage` to show detail about this calling. * @@ -31,7 +31,39 @@ interface ISDPMessage is ISubProtocol { event receiveMessage(string senderDomain, bytes32 senderID, address receiverID, uint32 sequence, bool result, string errMsg); /** - * @dev Smart contracts that want to cross-chain need to call this method to send orderly cross-chain messages. + * @dev When SDP contract receive msg in SDPv2 from AuthMessage contract, SDP contract would call the receiver + * contract decoded from sdp msg. And then, the result of calling receiver contract would emit this event + * `receiveMessage` to show detail about this calling. + * + * @param senderDomain the domain name of the sending blockchain. + * @param senderID the id of the sender. + * @param receiverID the address of the receiver. + * @param sequence the sequence number for this sdp msg + * @param nonce the unique nonce number for unordered packet. + * @param atomic_flag the number identifies the type for this SDP packet + * @param result result of receiver contract calling + * @param errMsg the error msg if calling failed, default null + */ + event receiveMessageV2(string senderDomain, bytes32 senderID, address receiverID, uint32 sequence, uint64 nonce, uint8 atomic_flag, bool result, string errMsg); + + /** + * @dev Smart contracts need to call this method to send orderly cross-chain messages in SDPv2. + * + * The domain name of the sending blockchain, the address of the sender, the domain name of the + * receiving blockchain and the address of the receiver uniquely determine a cross-chain channel. + * Each channel maintains a sequence number which increases from zero to ensure that the cross-chain + * messages of the channel are submitted on blockchain in an orderly manner. + * + * @param receiverDomain the domain name of the receiving blockchain. + * @param receiverID the address of the receiver. + * @param message the raw message from DApp contracts + * + * @return the sequence of SDP packet sent. + */ + function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint32); + + /** + * @dev Smart contracts need to call this method to send orderly cross-chain messages in SDPv1. * * The domain name of the sending blockchain, the address of the sender, the domain name of the * receiving blockchain and the address of the receiver uniquely determine a cross-chain channel. @@ -45,7 +77,20 @@ interface ISDPMessage is ISubProtocol { function sendMessage(string calldata receiverDomain, bytes32 receiverID, bytes calldata message) external; /** - * @dev Smart contracts that want to cross-chain need to call this method to send cross-chain messages out of order. + * @dev Smart contracts call this method to send cross-chain messages out of order in SDPv2. + * + * The sequence number for unordered message is `0xffffffff` means that this message is out of order. + * + * @param receiverDomain the domain name of the receiving blockchain. + * @param receiverID the address of the receiver. + * @param message the raw message from DApp contracts + * + * @return the nonce of SDP packet sent. + */ + function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint64); + + /** + * @dev Smart contracts call this method to send cross-chain messages out of order in SDPv1. * * The sequence number for unordered message is `0xffffffff` means that this message is out of order. * diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Ownable.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Ownable.sol index e5f0258a..834c8026 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Ownable.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Ownable.sol @@ -23,7 +23,7 @@ abstract contract Ownable is Context { /** * @dev Initializes the contract setting the deployer as the initial owner. */ - constructor () internal { + constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); From 9bcd929bb29f47add1d71ea14fc736eb6c0ddb0d Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 22 Feb 2024 16:58:34 +0800 Subject: [PATCH 04/17] [feat][*][*]: app contract interface --- .../sys/interfaces/IContractUsingSDP.sol | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol index 1478fa16..c34ae2af 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol @@ -3,7 +3,73 @@ pragma solidity ^0.8.0; interface IContractUsingSDP { + /** + * @dev SDP contract would call this function to deliver the message from sender contract + * on sender blockchain. This message sent with no order and in parallel. + * + * @param senderDomain the domain name of the sending blockchain. + * @param author the id of the sender. + * @param message the raw message from sender contract. + */ function recvUnorderedMessage(string memory senderDomain, bytes32 author, bytes memory message) external; + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed successfully on receiving + * blockchain. And the original sdp packet is sent as unordered message. + * + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param nonce unique number of original message from sender to receiver. + * @param message the message sent to receiver. + */ + function ackOnUnorderedMessageSuccess(string memory receiverDomain, bytes32 receiver, uint64 nonce, bytes memory message) external; + + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed with errors on receiving + * blockchain. And the original sdp packet is sent as unordered message. + * + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param nonce unique number of original message from sender to receiver. + * @param message the message sent to receiver. + * @param errorMsg the error msg from receiver. + */ + function ackOnUnorderedMessageError(string memory receiverDomain, bytes32 receiver, uint64 nonce, bytes memory message, string memory errorMsg) external; + + /** + * @dev SDP contract would call this function to deliver the message from sender contract + * on sender blockchain. This message sent with order. + * + * @param senderDomain the domain name of the sending blockchain. + * @param author the id of the sender. + * @param message the raw message from sender contract. + */ function recvMessage(string memory senderDomain, bytes32 author, bytes memory message) external; + + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed successfully on receiving + * blockchain. And the original sdp packet is sent as ordered message. + * + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param sequence sequence number of original message from sender to receiver. + * @param message the message sent to receiver. + */ + function ackOnSuccess(string memory receiverDomain, bytes32 receiver, uint32 sequence, bytes memory message) external; + + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed with errors on receiving + * blockchain. And the original sdp packet is sent as ordered message. + * + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param sequence sequence number of original message from sender to receiver. + * @param message the message sent to receiver. + * @param errorMsg the error msg from receiver. + */ + function ackOnError(string memory receiverDomain, bytes32 receiver, uint32 sequence, bytes memory message, string memory errorMsg) external; } From 5b8aa548e9135b4553db64b746c53f349c03a984 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 22 Feb 2024 18:06:51 +0800 Subject: [PATCH 05/17] [feat][*][*]: SDPPayloadV2 provides methods to get the error msg and original message from error ack resp --- .../bridge/commons/core/sdp/SDPMessageV2.java | 51 +++++++++++++++++++ .../bridge/commons/SDPMessageTest.java | 22 ++++++++ 2 files changed, 73 insertions(+) diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java index f98fdf6b..207788cc 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java @@ -40,6 +40,53 @@ public static class SDPPayloadV2 implements ISDPPayload { public SDPPayloadV2(byte[] payload) { this.payload = payload; } + + public SDPPayloadV2(byte[] message, String errorMsg) { + byte[] rawErrorMsg = errorMsg.getBytes(); + this.payload = new byte[8 + message.length + rawErrorMsg.length]; + System.arraycopy(ByteUtil.intToBytes(message.length, ByteOrder.BIG_ENDIAN), 0, this.payload, 0, 4); + System.arraycopy(message, 0, this.payload, 4, message.length); + System.arraycopy(ByteUtil.intToBytes(rawErrorMsg.length, ByteOrder.BIG_ENDIAN), 0, this.payload, 4 + message.length, 4); + System.arraycopy(rawErrorMsg, 0, this.payload, 8 + message.length, rawErrorMsg.length); + } + + public String getErrorMsgFromErrorAck() { + if (payload.length < 8) { + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + "payload at least 8 bytes but get " + payload.length + ); + } + + int offset = 0; + byte[] rawPayloadLen = new byte[4]; + System.arraycopy(payload, offset, rawPayloadLen, 0, 4); + offset = 4 + ByteUtil.bytesToInt(rawPayloadLen, ByteOrder.BIG_ENDIAN); + + byte[] rawErrorMsgLen = new byte[4]; + System.arraycopy(payload, offset, rawErrorMsgLen, 0, 4); + byte[] rawErrorMsg = new byte[ByteUtil.bytesToInt(rawErrorMsgLen, ByteOrder.BIG_ENDIAN)]; + System.arraycopy(payload, offset + 4, rawErrorMsg, 0, rawErrorMsg.length); + + return new String(rawErrorMsg); + } + + public byte[] getOriginalMessageFromErrorAck() { + if (payload.length < 8) { + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + "payload at least 8 bytes but get " + payload.length + ); + } + + byte[] rawPayloadLen = new byte[4]; + System.arraycopy(payload, 0, rawPayloadLen, 0, 4); + + byte[] originalMsg = new byte[ByteUtil.bytesToInt(rawPayloadLen, ByteOrder.BIG_ENDIAN)]; + System.arraycopy(payload, 4, originalMsg, 0, originalMsg.length); + + return originalMsg; + } } private AtomicFlagEnum atomicFlag; @@ -97,6 +144,10 @@ public boolean getAtomic() { return atomicFlag.isAtomic(); } + public SDPPayloadV2 getSDPPayloadV2() { + return (SDPPayloadV2) getSdpPayload(); + } + private int extractTargetDomain(byte[] rawMessage, int offset) { offset -= 4; byte[] rawPayloadLen = new byte[4]; diff --git a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java index f13c0c17..2ac415b1 100644 --- a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java +++ b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java @@ -28,6 +28,8 @@ public class SDPMessageTest { private static final long NONCE_V2 = ByteUtil.bytesToLong(HexUtil.decodeHex(RAW_MESSAGE_HEX_V2.substring(96, 112)), ByteOrder.BIG_ENDIAN); + private static final String RAW_MESSAGE_HEX_ACK_ERROR_V2 = "0000002817943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf2000000056572726f7200000035ffffffff000000000000000001000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000aff000002"; + @Test public void testSDPMessageV1Decode() { ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage(HexUtil.decodeHex(RAW_MESSAGE_HEX_V1)); @@ -58,6 +60,18 @@ public void testSDPMessageV2Encode() { ); Assert.assertTrue(sdpMessage instanceof SDPMessageV2); Assert.assertEquals(RAW_MESSAGE_HEX_V2, HexUtil.encodeHexStr(sdpMessage.encode())); + + ISDPMessage sdpMessageAckError = SDPMessageFactory.createSDPMessage( + 2, + TARGET_DOMAIN_V2, + HexUtil.decodeHex(TARGET_ID_V2), + AtomicFlagEnum.ATOMIC_REQUEST, + NONCE_V2, + AbstractSDPMessage.UNORDERED_SEQUENCE, + new SDPMessageV2.SDPPayloadV2(HexUtil.decodeHex(PAYLOAD_V2), "error").getPayload() + ); + Assert.assertTrue(sdpMessageAckError instanceof SDPMessageV2); + Assert.assertEquals(RAW_MESSAGE_HEX_ACK_ERROR_V2, HexUtil.encodeHexStr(sdpMessageAckError.encode())); } @Test @@ -68,5 +82,13 @@ public void testSDPMessageV2Decode() { Assert.assertEquals(TARGET_ID_V2, sdpMessage.getTargetIdentity().toHex()); Assert.assertEquals(NONCE_V2, sdpMessage.getNonce()); Assert.assertEquals(PAYLOAD_V2, HexUtil.encodeHexStr(sdpMessage.getPayload())); + + sdpMessage = SDPMessageFactory.createSDPMessage(HexUtil.decodeHex(RAW_MESSAGE_HEX_ACK_ERROR_V2)); + Assert.assertTrue(sdpMessage instanceof SDPMessageV2); + Assert.assertEquals(TARGET_DOMAIN_V2, sdpMessage.getTargetDomain().getDomain()); + Assert.assertEquals(TARGET_ID_V2, sdpMessage.getTargetIdentity().toHex()); + Assert.assertEquals(NONCE_V2, sdpMessage.getNonce()); + Assert.assertEquals(PAYLOAD_V2, HexUtil.encodeHexStr(((SDPMessageV2) sdpMessage).getSDPPayloadV2().getOriginalMessageFromErrorAck())); + Assert.assertEquals("error", ((SDPMessageV2) sdpMessage).getSDPPayloadV2().getErrorMsgFromErrorAck()); } } From a5b50cd334f5ed4d6a772f5ff137372da0d22df3 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 29 Feb 2024 15:33:17 +0800 Subject: [PATCH 06/17] [feat][*][*]: sdpv2 sending msg in eth contracts --- .../onchain-plugin/solidity/sys/SDPMsg.sol | 65 +++++++++++-- .../solidity/sys/lib/sdp/SDPLib.sol | 91 ++++++++++++++++++- .../solidity/sys/lib/utils/TypesToBytes.sol | 19 ++++ 3 files changed, 163 insertions(+), 12 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index fc71af13..e06360fe 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -9,7 +9,8 @@ import "./lib/utils/Ownable.sol"; contract SDPMsg is ISDPMessage, Ownable { - uint32 constant UNORDERED_SEQUENCE = 0xffffffff; + using SDPLib for SDPMessage; + using SDPLib for SDPMessageV2; address public amAddress; @@ -18,6 +19,8 @@ contract SDPMsg is ISDPMessage, Ownable { mapping(bytes32 => uint32) sendSeq; mapping(bytes32 => uint32) recvSeq; + mapping(bytes32 => uint32) sendNonce; + modifier onlyAM() { require( amAddress == msg.sender, @@ -55,7 +58,7 @@ contract SDPMsg is ISDPMessage, Ownable { } ); - bytes memory rawMsg = SDPLib.encodeSDPMessage(sdpMessage); + bytes memory rawMsg = sdpMessage.encodeSDPMessage(); IAuthMessage(amAddress).recvFromProtocol(msg.sender, rawMsg); @@ -70,36 +73,71 @@ contract SDPMsg is ISDPMessage, Ownable { receiveDomain: receiverDomain, receiver: receiverID, message: message, - sequence: UNORDERED_SEQUENCE + sequence: SDPLib.UNORDERED_SEQUENCE } ); - bytes memory rawMsg = SDPLib.encodeSDPMessage(sdpMessage); - - IAuthMessage(amAddress).recvFromProtocol(msg.sender, rawMsg); + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); _afterSendUnordered(); } function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) override external returns (uint32) { - return 0; + _beforeSend(receiverDomain, receiverID, message); + + SDPMessageV2 memory sdpMessage = SDPMessageV2( + { + version: 2, + receiveDomain: receiverDomain, + receiver: receiverID, + atomicFlag: atomic ? SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST : SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC, + nonce: SDPLib.MAX_NONCE, + sequence: _getAndUpdateSendSeq(receiverDomain, msg.sender, receiverID), + message: message + } + ); + + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); + + _afterSend(); + + return sdpMessage.sequence; } function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint64) { - return 0; + _beforeSendUnordered(receiverDomain, receiverID, message); + + SDPMessageV2 memory sdpMessage = SDPMessageV2( + { + version: 2, + receiveDomain: receiverDomain, + receiver: receiverID, + atomicFlag: atomic ? SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST : SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC, + nonce: _getAndUpdateSendNonce(receiverDomain, msg.sender, receiverID), + sequence: SDPLib.UNORDERED_SEQUENCE, + message: message + } + ); + + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); + + _afterSendUnordered(); + + return sdpMessage.nonce; } function recvMessage(string calldata senderDomain, bytes32 senderID, bytes calldata pkg) override external onlyAM { _beforeRecv(senderDomain, senderID, pkg); - SDPMessage memory sdpMessage = SDPLib.decodeSDPMessage(pkg); + SDPMessage memory sdpMessage; + sdpMessage.decodeSDPMessage(pkg); require( keccak256(abi.encodePacked(sdpMessage.receiveDomain)) == localDomainHash, "SDPMsg: wrong receiving domain" ); - if (sdpMessage.sequence == UNORDERED_SEQUENCE) { + if (sdpMessage.sequence == SDPLib.UNORDERED_SEQUENCE) { _routeUnorderedMessage(senderDomain, senderID, sdpMessage); } else { _routeOrderedMessage(senderDomain, senderID, sdpMessage); @@ -162,6 +200,13 @@ contract SDPMsg is ISDPMessage, Ownable { return seq; } + function _getAndUpdateSendNonce(string memory receiveDomain, address sender, bytes32 receiver) internal returns (uint32) { + bytes32 nonceKey = SDPLib.getSendingSeqID(receiveDomain, sender, receiver); + uint32 nonce = sendNonce[nonceKey]; + sendNonce[nonceKey]++; + return nonce; + } + function _beforeSend(string calldata receiverDomain, bytes32 receiverID, bytes calldata message) internal {} function _afterSend() internal {} diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol index 38065f1e..33622d38 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol @@ -12,8 +12,35 @@ struct SDPMessage { uint32 sequence; } +struct SDPMessageV2 { + uint32 version; + string receiveDomain; + bytes32 receiver; + uint8 atomicFlag; + uint64 nonce; + uint32 sequence; + bytes message; +} + library SDPLib { + uint8 constant SDP_V2_ATOMIC_FLAG_NONE_ATOMIC = 0; + + uint8 constant SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST = 1; + + uint8 constant SDP_V2_ATOMIC_FLAG_ACK_SUCCESS = 2; + + uint8 constant SDP_V2_ATOMIC_FLAG_ACK_ERROR = 3; + + uint8 constant SDP_V2_ATOMIC_FLAG_ACK_RECEIVE_TX_FAILED = 4; + + uint8 constant SDP_V2_ATOMIC_FLAG_ACK_UNKNOWN_EXCEPTION = 5; + + uint32 constant UNORDERED_SEQUENCE = 0xffffffff; + + // @notice only for orderred msg + uint64 constant MAX_NONCE = 0xffffffffffffffff; + function encodeSDPMessage(SDPMessage memory sdpMessage) pure internal returns (bytes memory) { uint256 len = SizeOf.sizeOfBytes(sdpMessage.message) + 4 + 32 + SizeOf.sizeOfString(sdpMessage.receiveDomain); @@ -40,7 +67,7 @@ library SDPLib { return pkg; } - function decodeSDPMessage(bytes memory rawMessage) pure internal returns (SDPMessage memory) { + function decodeSDPMessage(SDPMessage memory sdpMessage, bytes memory rawMessage) pure internal { uint256 offset = rawMessage.length; uint32 dest_domain_len = BytesToTypes.bytesToUint32(offset, rawMessage) + 32; @@ -59,7 +86,7 @@ library SDPLib { BytesToTypes.bytesToString(offset, rawMessage, message); offset -= SizeOf.sizeOfBytes(message); - return SDPMessage( + sdpMessage = SDPMessage( { receiveDomain: string(dest_domain), receiver: receiver, @@ -69,6 +96,66 @@ library SDPLib { ); } + function encodeSDPMessage(SDPMessageV2 memory sdpMessage) pure internal returns (bytes memory) { + require( + sdpMessage.version == 2, + "encodeSDPMessage: wrong version" + ); + + require( + sdpMessage.message.length <= 0xFFFFFFFF, + "encodeSDPMessage: body length overlimit" + ); + + uint total_size = 57 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; + bytes memory pkg = new bytes(total_size); + uint offset = total_size; + + TypesToBytes.uintToBytes(offset, sdpMessage.version, pkg); + offset -= SizeOf.sizeOfInt(32); + + TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.receiveDomain), pkg); + + TypesToBytes.bytes32ToBytes(offset, sdpMessage.receiver, pkg); + offset -= SizeOf.sizeOfBytes32(); + + TypesToBytes.byteToBytes(offset, sdpMessage.atomicFlag, pkg); + offset -= 1; + + TypesToBytes.uint64ToBytes(offset, sdpMessage.atomicFlag, pkg); + offset -= SizeOf.sizeOfInt(64); + + TypesToBytes.uint32ToBytes(offset, sdpMessage.sequence, pkg); + offset -= SizeOf.sizeOfInt(32); + + TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + + return pkg; + } + + function decodeSDPMessage(SDPMessageV2 memory sdpMessage, bytes memory rawMessage) internal pure { + uint256 offset = rawMessage.length; + + sdpMessage.version = BytesToTypes.bytesToUint32(offset, rawMessage); + offset -= SizeOf.sizeOfUint(32); + + sdpMessage.receiveDomain = string(BytesToTypes.bytesToVarBytes(offset, rawMessage)); + + sdpMessage.receiver = BytesToTypes.bytesToBytes32(offset, rawMessage); + offset -= SizeOf.sizeOfBytes32(); + + sdpMessage.atomicFlag = BytesToTypes.bytesToUint8(offset, rawMessage); + offset -= 1; + + sdpMessage.nonce = BytesToTypes.bytesToUint64(offset, rawMessage); + offset -= 8; + + sdpMessage.sequence = BytesToTypes.bytesToUint32(offset, rawMessage); + offset -= 4; + + sdpMessage.message = BytesToTypes.bytesToVarBytes(offset, rawMessage); + } + function getSendingSeqID(string memory receiveDomain, address sender, bytes32 receiver) pure internal returns (bytes32) { bytes32 sender32 = TypesToBytes.addressToBytes32(sender); return keccak256(abi.encodePacked(sender32, keccak256(abi.encodePacked(receiveDomain)), receiver)); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol index a2cd6f5a..eb56c488 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol @@ -31,6 +31,13 @@ library TypesToBytes { } } + function byteToBytes(uint _offset, uint8 _input, bytes memory _output) internal pure { + + assembly { + mstore(add(_output, _offset), _input) + } + } + function boolToBytes(uint _offset, bool _input, bytes memory _output) internal pure { uint8 x = _input == false ? 0 : 1; assembly { @@ -161,4 +168,16 @@ library TypesToBytes { } } + function uint64ToBytes(uint _offset, uint64 _input, bytes memory _output) internal pure { + + assembly { + let prev_word_pos := add(_output, _offset) + let prev_word := mload(prev_word_pos) + + mstore(add(prev_word_pos, 8), _input) + + mstore(prev_word_pos, prev_word) + } + } + } From 9a415cc06041f79ebf40c8bcddf1dadee7594bc1 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Wed, 6 Mar 2024 17:10:47 +0800 Subject: [PATCH 07/17] [refactor][*][*]: add message id and error msg --- .../commons/core/sdp/AtomicFlagEnum.java | 5 + .../commons/core/sdp/SDPMessageFactory.java | 22 +++- .../bridge/commons/core/sdp/SDPMessageId.java | 44 +++++++ .../bridge/commons/core/sdp/SDPMessageV2.java | 124 ++++++++++-------- .../bridge/commons/SDPMessageTest.java | 21 +-- 5 files changed, 149 insertions(+), 67 deletions(-) create mode 100644 antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java index decd5f83..4d58b67a 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AtomicFlagEnum.java @@ -1,6 +1,7 @@ package com.alipay.antchain.bridge.commons.core.sdp; import cn.hutool.core.util.ByteUtil; +import cn.hutool.core.util.ObjectUtil; import com.alipay.antchain.bridge.commons.exception.AntChainBridgeCommonsException; import com.alipay.antchain.bridge.commons.exception.CommonsErrorCodeEnum; import lombok.Getter; @@ -92,6 +93,10 @@ public static AtomicFlagEnum parseFrom(byte value) { ); } + public static boolean withErrorMsg(AtomicFlagEnum atomicFlag) { + return ObjectUtil.isNotNull(atomicFlag) && atomicFlag.value > ACK_SUCCESS.value; + } + AtomicFlagEnum(byte value) { this.value = value; } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java index f7701072..0247d4e3 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java @@ -29,11 +29,21 @@ public static ISDPMessage createSDPMessage(byte[] rawMessage) { return sdpMessage; } - public static ISDPMessage createSDPMessage(int version, String targetDomain, byte[] targetIdentity, int sequence, byte[] payload) { - return createSDPMessage(version, targetDomain, targetIdentity, AtomicFlagEnum.NONE_ATOMIC, -1, sequence, payload); + public static ISDPMessage createSDPMessage(int version, byte[] messageId, String targetDomain, byte[] targetIdentity, int sequence, byte[] payload) { + return createSDPMessage(version, messageId, targetDomain, targetIdentity, AtomicFlagEnum.NONE_ATOMIC, -1, sequence, payload, null); } - public static ISDPMessage createSDPMessage(int version, String targetDomain, byte[] targetIdentity, AtomicFlagEnum atomicFlag, long nonce, int sequence, byte[] payload) { + public static ISDPMessage createSDPMessage( + int version, + byte[] messageId, + String targetDomain, + byte[] targetIdentity, + AtomicFlagEnum atomicFlag, + long nonce, + int sequence, + byte[] payload, + String errorMsg + ) { AbstractSDPMessage sdpMessage = createAbstractSDPMessage(version); sdpMessage.setTargetDomain(new CrossChainDomain(targetDomain)); @@ -42,14 +52,18 @@ public static ISDPMessage createSDPMessage(int version, String targetDomain, byt sdpMessage.setPayload(payload); if (version == SDPMessageV2.MY_VERSION) { + ((SDPMessageV2) sdpMessage).setMessageId(new SDPMessageId(messageId)); ((SDPMessageV2) sdpMessage).setNonce(nonce); ((SDPMessageV2) sdpMessage).setAtomicFlag(atomicFlag); + if (AtomicFlagEnum.withErrorMsg(atomicFlag)) { + ((SDPMessageV2) sdpMessage).setErrorMsg(errorMsg); + } } return sdpMessage; } - public static ISDPMessage createSDPMessage(int version) { + private static ISDPMessage createSDPMessage(int version) { return createAbstractSDPMessage(version); } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java new file mode 100644 index 00000000..fbc1f11d --- /dev/null +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java @@ -0,0 +1,44 @@ +package com.alipay.antchain.bridge.commons.core.sdp; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alipay.antchain.bridge.commons.exception.AntChainBridgeCommonsException; +import com.alipay.antchain.bridge.commons.exception.CommonsErrorCodeEnum; +import lombok.NonNull; +import lombok.Setter; + +@Setter +public class SDPMessageId { + + public SDPMessageId(@NonNull String messageIdHex) { + this(HexUtil.decodeHex(messageIdHex)); + } + + public SDPMessageId(byte[] messageId) { + if (ObjectUtil.isNull(messageId)) { + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + "message id is null" + ); + } + if (messageId.length != 32) { + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + StrUtil.format("expected 32 bytes but get {}", messageId.length) + ); + } + this.messageId = messageId; + } + + private byte[] messageId; + + public String toHexStr() { + return HexUtil.encodeHexStr(this.messageId); + } + + public byte[] toByte32() { + return messageId; + } +} diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java index 207788cc..ee530bb7 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV2.java @@ -40,97 +40,60 @@ public static class SDPPayloadV2 implements ISDPPayload { public SDPPayloadV2(byte[] payload) { this.payload = payload; } - - public SDPPayloadV2(byte[] message, String errorMsg) { - byte[] rawErrorMsg = errorMsg.getBytes(); - this.payload = new byte[8 + message.length + rawErrorMsg.length]; - System.arraycopy(ByteUtil.intToBytes(message.length, ByteOrder.BIG_ENDIAN), 0, this.payload, 0, 4); - System.arraycopy(message, 0, this.payload, 4, message.length); - System.arraycopy(ByteUtil.intToBytes(rawErrorMsg.length, ByteOrder.BIG_ENDIAN), 0, this.payload, 4 + message.length, 4); - System.arraycopy(rawErrorMsg, 0, this.payload, 8 + message.length, rawErrorMsg.length); - } - - public String getErrorMsgFromErrorAck() { - if (payload.length < 8) { - throw new AntChainBridgeCommonsException( - CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, - "payload at least 8 bytes but get " + payload.length - ); - } - - int offset = 0; - byte[] rawPayloadLen = new byte[4]; - System.arraycopy(payload, offset, rawPayloadLen, 0, 4); - offset = 4 + ByteUtil.bytesToInt(rawPayloadLen, ByteOrder.BIG_ENDIAN); - - byte[] rawErrorMsgLen = new byte[4]; - System.arraycopy(payload, offset, rawErrorMsgLen, 0, 4); - byte[] rawErrorMsg = new byte[ByteUtil.bytesToInt(rawErrorMsgLen, ByteOrder.BIG_ENDIAN)]; - System.arraycopy(payload, offset + 4, rawErrorMsg, 0, rawErrorMsg.length); - - return new String(rawErrorMsg); - } - - public byte[] getOriginalMessageFromErrorAck() { - if (payload.length < 8) { - throw new AntChainBridgeCommonsException( - CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, - "payload at least 8 bytes but get " + payload.length - ); - } - - byte[] rawPayloadLen = new byte[4]; - System.arraycopy(payload, 0, rawPayloadLen, 0, 4); - - byte[] originalMsg = new byte[ByteUtil.bytesToInt(rawPayloadLen, ByteOrder.BIG_ENDIAN)]; - System.arraycopy(payload, 4, originalMsg, 0, originalMsg.length); - - return originalMsg; - } } private AtomicFlagEnum atomicFlag; private long nonce; + private SDPMessageId messageId; + + private String errorMsg; + @Override public void decode(byte[] rawMessage) { - if (rawMessage.length < 57) { + if (rawMessage.length < 89) { throw new AntChainBridgeCommonsException( CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, - String.format("length of message v2 supposes to be 57 bytes at least but get %d . ", rawMessage.length) + String.format("length of message v2 supposes to be 89 bytes at least but get %d . ", rawMessage.length) ); } int offset = rawMessage.length - 4; + offset = extractMessageId(rawMessage, offset); offset = extractTargetDomain(rawMessage, offset); offset = extractTargetIdentity(rawMessage, offset); offset = extractAtomic(rawMessage, offset); offset = extractNonce(rawMessage, offset); offset = extractSequence(rawMessage, offset); - extractPayload(rawMessage, offset); + offset = extractPayload(rawMessage, offset); + if (AtomicFlagEnum.withErrorMsg(getAtomicFlag())) { + extractErrorMsg(rawMessage, offset); + } } @Override public byte[] encode() { - byte[] rawMessage = new byte[57 - + this.getTargetDomain().toBytes().length - + this.getPayload().length]; + byte[] rawMessage = new byte[calcMessageLength()]; int offset = putVersion(rawMessage, rawMessage.length); + offset = putMessageId(rawMessage, offset); offset = putTargetDomain(rawMessage, offset); offset = putTargetIdentity(rawMessage, offset); offset = putAtomic(rawMessage, offset); offset = putNonce(rawMessage, offset); offset = putSequence(rawMessage, offset); - putPayload(rawMessage, offset); + offset = putPayload(rawMessage, offset); + if (AtomicFlagEnum.withErrorMsg(getAtomicFlag())) { + putErrorMsg(rawMessage, offset); + } return rawMessage; } @Override - void setPayload(byte[] payload) { + public void setPayload(byte[] payload) { this.setSdpPayload(new SDPPayloadV2(payload)); } @@ -148,6 +111,15 @@ public SDPPayloadV2 getSDPPayloadV2() { return (SDPPayloadV2) getSdpPayload(); } + private int extractMessageId(byte[] rawMessage, int offset) { + offset -= 32; + byte[] msgId = new byte[32]; + System.arraycopy(rawMessage, offset, msgId, 0, 32); + this.setMessageId(new SDPMessageId(msgId)); + + return offset; + } + private int extractTargetDomain(byte[] rawMessage, int offset) { offset -= 4; byte[] rawPayloadLen = new byte[4]; @@ -218,6 +190,25 @@ private int extractPayload(byte[] rawMessage, int offset) { return offset; } + private int extractErrorMsg(byte[] rawMessage, int offset) { + offset -= 4; + byte[] rawErrorMsgLen = new byte[4]; + System.arraycopy(rawMessage, offset, rawErrorMsgLen, 0, 4); + + byte[] errorMsg = new byte[ByteUtil.bytesToInt(rawErrorMsgLen, ByteOrder.BIG_ENDIAN)]; + offset -= errorMsg.length; + if (offset < 0) { + throw new AntChainBridgeCommonsException( + CommonsErrorCodeEnum.SDP_MESSAGE_DECODE_ERROR, + "length of error message in SDPv2 is incorrect" + ); + } + System.arraycopy(rawMessage, offset, errorMsg, 0, errorMsg.length); + this.setErrorMsg(new String(errorMsg)); + + return offset; + } + private int putVersion(byte[] rawMessage, int offset) { offset -= 4; System.arraycopy(ByteUtil.intToBytes(this.getVersion(), ByteOrder.BIG_ENDIAN), 0, rawMessage, offset, 4); @@ -225,6 +216,13 @@ private int putVersion(byte[] rawMessage, int offset) { return offset; } + private int putMessageId(byte[] rawMessage, int offset) { + offset -= 32; + System.arraycopy(this.getMessageId().toByte32(), 0, rawMessage, offset, 32); + + return offset; + } + private int putTargetDomain(byte[] rawMessage, int offset) { offset -= 4; byte[] rawTargetDomain = this.getTargetDomain().toBytes(); @@ -271,4 +269,20 @@ private int putPayload(byte[] rawMessage, int offset) { return offset; } + + private int putErrorMsg(byte[] rawMessage, int offset) { + offset -= 4; + System.arraycopy(ByteUtil.intToBytes(this.getErrorMsg().getBytes().length, ByteOrder.BIG_ENDIAN), 0, rawMessage, offset, 4); + + offset -= this.getErrorMsg().length(); + System.arraycopy(this.getErrorMsg().getBytes(), 0, rawMessage, offset, this.getErrorMsg().length()); + + return offset; + } + + private int calcMessageLength() { + return AtomicFlagEnum.withErrorMsg(getAtomicFlag()) ? + 89 + this.getTargetDomain().toBytes().length + this.getPayload().length + 4 + this.getErrorMsg().length() : + 89 + this.getTargetDomain().toBytes().length + this.getPayload().length; + } } diff --git a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java index 2ac415b1..6b0b665a 100644 --- a/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java +++ b/antchain-bridge-commons/src/test/java/com/alipay/antchain/bridge/commons/SDPMessageTest.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.HexUtil; +import cn.hutool.crypto.digest.DigestUtil; import com.alipay.antchain.bridge.commons.core.sdp.*; import org.junit.Assert; import org.junit.Test; @@ -18,7 +19,7 @@ public class SDPMessageTest { private static final String PAYLOAD_V1 = RAW_MESSAGE_HEX_V1.substring(64, 128) + RAW_MESSAGE_HEX_V1.substring(0, 16); - private static final String RAW_MESSAGE_HEX_V2 = "17943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf200000028ffffffff000000000000000001000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000aff000002"; + private static final String RAW_MESSAGE_HEX_V2 = "17943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf200000028ffffffff000000000000000001000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000ae3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ff000002"; private static final String TARGET_DOMAIN_V2 = HexUtil.decodeHexStr(RAW_MESSAGE_HEX_V2.substring(178, 198)); @@ -28,7 +29,7 @@ public class SDPMessageTest { private static final long NONCE_V2 = ByteUtil.bytesToLong(HexUtil.decodeHex(RAW_MESSAGE_HEX_V2.substring(96, 112)), ByteOrder.BIG_ENDIAN); - private static final String RAW_MESSAGE_HEX_ACK_ERROR_V2 = "0000002817943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf2000000056572726f7200000035ffffffff000000000000000001000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000aff000002"; + private static final String RAW_MESSAGE_HEX_ACK_ERROR_V2 = "6572726f720000000517943daf4ed8cb477ef2e0048f5baede046f6bf797943daf4ed8cb477ef2e0048f5baede046f6bf200000028ffffffff000000000000000003000000000000000000000000d9145cce52d386f254917e481eb44e9943f3913874657374646f6d61696e0000000ae3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ff000002"; @Test public void testSDPMessageV1Decode() { @@ -42,7 +43,7 @@ public void testSDPMessageV1Decode() { @Test public void testSDPMessageV1Encode() { - ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage(1, TARGET_DOMAIN_V1, + ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage(1, null, TARGET_DOMAIN_V1, HexUtil.decodeHex(TARGET_ID_V1), AbstractSDPMessage.UNORDERED_SEQUENCE, HexUtil.decodeHex(PAYLOAD_V1)); Assert.assertEquals(RAW_MESSAGE_HEX_V1, HexUtil.encodeHexStr(sdpMessage.encode())); } @@ -51,24 +52,28 @@ public void testSDPMessageV1Encode() { public void testSDPMessageV2Encode() { ISDPMessage sdpMessage = SDPMessageFactory.createSDPMessage( 2, + DigestUtil.sha256(""), TARGET_DOMAIN_V2, HexUtil.decodeHex(TARGET_ID_V2), AtomicFlagEnum.ATOMIC_REQUEST, NONCE_V2, AbstractSDPMessage.UNORDERED_SEQUENCE, - HexUtil.decodeHex(PAYLOAD_V2) + HexUtil.decodeHex(PAYLOAD_V2), + null ); Assert.assertTrue(sdpMessage instanceof SDPMessageV2); Assert.assertEquals(RAW_MESSAGE_HEX_V2, HexUtil.encodeHexStr(sdpMessage.encode())); ISDPMessage sdpMessageAckError = SDPMessageFactory.createSDPMessage( 2, + DigestUtil.sha256(""), TARGET_DOMAIN_V2, HexUtil.decodeHex(TARGET_ID_V2), - AtomicFlagEnum.ATOMIC_REQUEST, + AtomicFlagEnum.ACK_ERROR, NONCE_V2, AbstractSDPMessage.UNORDERED_SEQUENCE, - new SDPMessageV2.SDPPayloadV2(HexUtil.decodeHex(PAYLOAD_V2), "error").getPayload() + HexUtil.decodeHex(PAYLOAD_V2), + "error" ); Assert.assertTrue(sdpMessageAckError instanceof SDPMessageV2); Assert.assertEquals(RAW_MESSAGE_HEX_ACK_ERROR_V2, HexUtil.encodeHexStr(sdpMessageAckError.encode())); @@ -88,7 +93,7 @@ public void testSDPMessageV2Decode() { Assert.assertEquals(TARGET_DOMAIN_V2, sdpMessage.getTargetDomain().getDomain()); Assert.assertEquals(TARGET_ID_V2, sdpMessage.getTargetIdentity().toHex()); Assert.assertEquals(NONCE_V2, sdpMessage.getNonce()); - Assert.assertEquals(PAYLOAD_V2, HexUtil.encodeHexStr(((SDPMessageV2) sdpMessage).getSDPPayloadV2().getOriginalMessageFromErrorAck())); - Assert.assertEquals("error", ((SDPMessageV2) sdpMessage).getSDPPayloadV2().getErrorMsgFromErrorAck()); + Assert.assertEquals(PAYLOAD_V2, HexUtil.encodeHexStr(sdpMessage.getPayload())); + Assert.assertEquals("error", ((SDPMessageV2) sdpMessage).getErrorMsg()); } } From 0961d468856e3d711b8f82bae5795fe677e266e0 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Wed, 6 Mar 2024 18:05:05 +0800 Subject: [PATCH 08/17] [refactor][*][*]: add message id and error msg into eth-solidity contracts --- .../onchain-plugin/solidity/sys/SDPMsg.sol | 28 ++++--- .../solidity/sys/interfaces/ISDPMessage.sol | 4 +- .../solidity/sys/lib/sdp/SDPLib.sol | 81 +++++++++++++++++-- 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index e06360fe..edc8d84e 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -58,7 +58,7 @@ contract SDPMsg is ISDPMessage, Ownable { } ); - bytes memory rawMsg = sdpMessage.encodeSDPMessage(); + bytes memory rawMsg = sdpMessage.encode(); IAuthMessage(amAddress).recvFromProtocol(msg.sender, rawMsg); @@ -77,60 +77,66 @@ contract SDPMsg is ISDPMessage, Ownable { } ); - IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encode()); _afterSendUnordered(); } - function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) override external returns (uint32) { + function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) override external returns (bytes32) { _beforeSend(receiverDomain, receiverID, message); SDPMessageV2 memory sdpMessage = SDPMessageV2( { version: 2, + messageId: bytes32(0), receiveDomain: receiverDomain, receiver: receiverID, atomicFlag: atomic ? SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST : SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC, nonce: SDPLib.MAX_NONCE, sequence: _getAndUpdateSendSeq(receiverDomain, msg.sender, receiverID), - message: message + message: message, + errorMsg: "" } ); + sdpMessage.calcMessageId(); - IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encode()); _afterSend(); - return sdpMessage.sequence; + return sdpMessage.messageId; } - function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint64) { + function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (bytes32) { _beforeSendUnordered(receiverDomain, receiverID, message); SDPMessageV2 memory sdpMessage = SDPMessageV2( { version: 2, + messageId: bytes32(0), receiveDomain: receiverDomain, receiver: receiverID, atomicFlag: atomic ? SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST : SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC, nonce: _getAndUpdateSendNonce(receiverDomain, msg.sender, receiverID), sequence: SDPLib.UNORDERED_SEQUENCE, - message: message + message: message, + errorMsg: "" } ); + sdpMessage.calcMessageId(); - IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encodeSDPMessage()); + IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encode()); _afterSendUnordered(); - return sdpMessage.nonce; + return sdpMessage.messageId; } function recvMessage(string calldata senderDomain, bytes32 senderID, bytes calldata pkg) override external onlyAM { _beforeRecv(senderDomain, senderID, pkg); SDPMessage memory sdpMessage; - sdpMessage.decodeSDPMessage(pkg); + sdpMessage.decode(pkg); require( keccak256(abi.encodePacked(sdpMessage.receiveDomain)) == localDomainHash, diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol index 8db40b79..96d7fe22 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol @@ -60,7 +60,7 @@ interface ISDPMessage is ISubProtocol { * * @return the sequence of SDP packet sent. */ - function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint32); + function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (bytes32); /** * @dev Smart contracts need to call this method to send orderly cross-chain messages in SDPv1. @@ -87,7 +87,7 @@ interface ISDPMessage is ISubProtocol { * * @return the nonce of SDP packet sent. */ - function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (uint64); + function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (bytes32); /** * @dev Smart contracts call this method to send cross-chain messages out of order in SDPv1. diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol index 33622d38..36721ee7 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol @@ -14,12 +14,14 @@ struct SDPMessage { struct SDPMessageV2 { uint32 version; + bytes32 messageId; string receiveDomain; bytes32 receiver; uint8 atomicFlag; uint64 nonce; uint32 sequence; bytes message; + string errorMsg; } library SDPLib { @@ -41,7 +43,7 @@ library SDPLib { // @notice only for orderred msg uint64 constant MAX_NONCE = 0xffffffffffffffff; - function encodeSDPMessage(SDPMessage memory sdpMessage) pure internal returns (bytes memory) { + function encode(SDPMessage memory sdpMessage) pure internal returns (bytes memory) { uint256 len = SizeOf.sizeOfBytes(sdpMessage.message) + 4 + 32 + SizeOf.sizeOfString(sdpMessage.receiveDomain); @@ -67,7 +69,7 @@ library SDPLib { return pkg; } - function decodeSDPMessage(SDPMessage memory sdpMessage, bytes memory rawMessage) pure internal { + function decode(SDPMessage memory sdpMessage, bytes memory rawMessage) pure internal { uint256 offset = rawMessage.length; uint32 dest_domain_len = BytesToTypes.bytesToUint32(offset, rawMessage) + 32; @@ -96,24 +98,37 @@ library SDPLib { ); } - function encodeSDPMessage(SDPMessageV2 memory sdpMessage) pure internal returns (bytes memory) { + function encode(SDPMessageV2 memory sdpMessage) pure internal returns (bytes memory) { require( sdpMessage.version == 2, "encodeSDPMessage: wrong version" ); - require( sdpMessage.message.length <= 0xFFFFFFFF, "encodeSDPMessage: body length overlimit" ); + require( + sdpMessage.messageId != bytes32(0), + "encodeSDPMessage: zero message id" + ); + + uint total_size; + bool withErrorMsg = sdpMessage.atomicFlag > SDP_V2_ATOMIC_FLAG_ACK_SUCCESS; + if (withErrorMsg) { + total_size = 89 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length + 4 + bytes(sdpMessage.errorMsg).length; + } else { + total_size = 89 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; + } - uint total_size = 57 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; bytes memory pkg = new bytes(total_size); uint offset = total_size; TypesToBytes.uintToBytes(offset, sdpMessage.version, pkg); offset -= SizeOf.sizeOfInt(32); + TypesToBytes.bytes32ToBytes(offset, sdpMessage.messageId, pkg); + offset -= SizeOf.sizeOfBytes32(); + TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.receiveDomain), pkg); TypesToBytes.bytes32ToBytes(offset, sdpMessage.receiver, pkg); @@ -122,7 +137,7 @@ library SDPLib { TypesToBytes.byteToBytes(offset, sdpMessage.atomicFlag, pkg); offset -= 1; - TypesToBytes.uint64ToBytes(offset, sdpMessage.atomicFlag, pkg); + TypesToBytes.uint64ToBytes(offset, sdpMessage.nonce, pkg); offset -= SizeOf.sizeOfInt(64); TypesToBytes.uint32ToBytes(offset, sdpMessage.sequence, pkg); @@ -130,15 +145,23 @@ library SDPLib { TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + if (withErrorMsg) { + TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.errorMsg), pkg); + } + return pkg; } - function decodeSDPMessage(SDPMessageV2 memory sdpMessage, bytes memory rawMessage) internal pure { + function decode(SDPMessageV2 memory sdpMessage, bytes memory rawMessage) internal pure { uint256 offset = rawMessage.length; + bool withErrorMsg = sdpMessage.atomicFlag > SDP_V2_ATOMIC_FLAG_ACK_SUCCESS; sdpMessage.version = BytesToTypes.bytesToUint32(offset, rawMessage); offset -= SizeOf.sizeOfUint(32); + sdpMessage.messageId = BytesToTypes.bytesToBytes32(offset, rawMessage); + offset -= SizeOf.sizeOfBytes32(); + sdpMessage.receiveDomain = string(BytesToTypes.bytesToVarBytes(offset, rawMessage)); sdpMessage.receiver = BytesToTypes.bytesToBytes32(offset, rawMessage); @@ -154,6 +177,50 @@ library SDPLib { offset -= 4; sdpMessage.message = BytesToTypes.bytesToVarBytes(offset, rawMessage); + + if (withErrorMsg) { + sdpMessage.errorMsg = string(BytesToTypes.bytesToVarBytes(offset, rawMessage)); + } + } + + function calcMessageId(SDPMessageV2 memory sdpMessage) internal pure { + require( + sdpMessage.version == 2, + "encodeSDPMessage: wrong version" + ); + require( + sdpMessage.message.length <= 0xFFFFFFFF, + "encodeSDPMessage: body length overlimit" + ); + require( + sdpMessage.messageId != bytes32(0), + "encodeSDPMessage: zero message id" + ); + + uint total_size = 57 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; + bytes memory pkg = new bytes(total_size); + uint offset = total_size; + + TypesToBytes.uintToBytes(offset, sdpMessage.version, pkg); + offset -= SizeOf.sizeOfInt(32); + + TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.receiveDomain), pkg); + + TypesToBytes.bytes32ToBytes(offset, sdpMessage.receiver, pkg); + offset -= SizeOf.sizeOfBytes32(); + + TypesToBytes.byteToBytes(offset, sdpMessage.atomicFlag, pkg); + offset -= 1; + + TypesToBytes.uint64ToBytes(offset, sdpMessage.nonce, pkg); + offset -= SizeOf.sizeOfInt(64); + + TypesToBytes.uint32ToBytes(offset, sdpMessage.sequence, pkg); + offset -= SizeOf.sizeOfInt(32); + + TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + + sdpMessage.messageId = keccak256(pkg); } function getSendingSeqID(string memory receiveDomain, address sender, bytes32 receiver) pure internal returns (bytes32) { From aad59583e7c755cdbb89674a33bc70478226e93e Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 7 Mar 2024 15:47:31 +0800 Subject: [PATCH 09/17] [refactor][*][*]: solidity interfaces for sdpv2 updated --- .../sys/interfaces/IContractUsingSDP.sol | 50 ------------------- .../sys/interfaces/IContractWithAcks.sol | 34 +++++++++++++ .../solidity/sys/interfaces/ISDPMessage.sol | 24 +++++++-- .../solidity/sys/interfaces/ISubProtocol.sol | 4 +- 4 files changed, 55 insertions(+), 57 deletions(-) create mode 100644 pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractWithAcks.sol diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol index c34ae2af..e2b62787 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractUsingSDP.sol @@ -13,31 +13,6 @@ interface IContractUsingSDP { */ function recvUnorderedMessage(string memory senderDomain, bytes32 author, bytes memory message) external; - /** - * @dev SDP contract would call this function to deliver the ack response from receiver - * contract. The original message being acked now is processed successfully on receiving - * blockchain. And the original sdp packet is sent as unordered message. - * - * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. - * @param receiver the id of the receiver for original message. - * @param nonce unique number of original message from sender to receiver. - * @param message the message sent to receiver. - */ - function ackOnUnorderedMessageSuccess(string memory receiverDomain, bytes32 receiver, uint64 nonce, bytes memory message) external; - - /** - * @dev SDP contract would call this function to deliver the ack response from receiver - * contract. The original message being acked now is processed with errors on receiving - * blockchain. And the original sdp packet is sent as unordered message. - * - * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. - * @param receiver the id of the receiver for original message. - * @param nonce unique number of original message from sender to receiver. - * @param message the message sent to receiver. - * @param errorMsg the error msg from receiver. - */ - function ackOnUnorderedMessageError(string memory receiverDomain, bytes32 receiver, uint64 nonce, bytes memory message, string memory errorMsg) external; - /** * @dev SDP contract would call this function to deliver the message from sender contract * on sender blockchain. This message sent with order. @@ -47,29 +22,4 @@ interface IContractUsingSDP { * @param message the raw message from sender contract. */ function recvMessage(string memory senderDomain, bytes32 author, bytes memory message) external; - - /** - * @dev SDP contract would call this function to deliver the ack response from receiver - * contract. The original message being acked now is processed successfully on receiving - * blockchain. And the original sdp packet is sent as ordered message. - * - * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. - * @param receiver the id of the receiver for original message. - * @param sequence sequence number of original message from sender to receiver. - * @param message the message sent to receiver. - */ - function ackOnSuccess(string memory receiverDomain, bytes32 receiver, uint32 sequence, bytes memory message) external; - - /** - * @dev SDP contract would call this function to deliver the ack response from receiver - * contract. The original message being acked now is processed with errors on receiving - * blockchain. And the original sdp packet is sent as ordered message. - * - * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. - * @param receiver the id of the receiver for original message. - * @param sequence sequence number of original message from sender to receiver. - * @param message the message sent to receiver. - * @param errorMsg the error msg from receiver. - */ - function ackOnError(string memory receiverDomain, bytes32 receiver, uint32 sequence, bytes memory message, string memory errorMsg) external; } diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractWithAcks.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractWithAcks.sol new file mode 100644 index 00000000..1a9ba107 --- /dev/null +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/IContractWithAcks.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +interface IContractWithAcks { + + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed successfully on receiving + * blockchain. And the original sdp packet is sent as unordered message. + * + * @param messageId the message id for sdp packet used to send + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param sequence sequence number of original message from sender to receiver. + * @param nonce unique number of original message from sender to receiver. + * @param message the message sent to receiver. + */ + function ackOnSuccess(bytes32 messageId, string memory receiverDomain, bytes32 receiver, uint32 sequence, uint64 nonce, bytes memory message) external; + + /** + * @dev SDP contract would call this function to deliver the ack response from receiver + * contract. The original message being acked now is processed with errors on receiving + * blockchain. And the original sdp packet is sent as unordered message. + * + * @param messageId the message id for sdp packet used to send + * @param receiverDomain the domain name of the receiving blockchain for original message and where the ack response from. + * @param receiver the id of the receiver for original message. + * @param sequence sequence number of original message from sender to receiver. + * @param nonce unique number of original message from sender to receiver. + * @param message the message sent to receiver. + * @param errorMsg the error msg from receiver. + */ + function ackOnError(bytes32 messageId, string memory receiverDomain, bytes32 receiver, uint32 sequence, uint64 nonce, bytes memory message, string memory errorMsg) external; +} diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol index 96d7fe22..faa40356 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISDPMessage.sol @@ -37,14 +37,26 @@ interface ISDPMessage is ISubProtocol { * * @param senderDomain the domain name of the sending blockchain. * @param senderID the id of the sender. + * @param receiverDomain the domain name of the receiving blockchain. * @param receiverID the address of the receiver. * @param sequence the sequence number for this sdp msg * @param nonce the unique nonce number for unordered packet. - * @param atomic_flag the number identifies the type for this SDP packet + * @param atomicFlag the number identifies the type for this SDP packet * @param result result of receiver contract calling - * @param errMsg the error msg if calling failed, default null + * @param errMsg the error msg if calling failed, default empty */ - event receiveMessageV2(string senderDomain, bytes32 senderID, address receiverID, uint32 sequence, uint64 nonce, uint8 atomic_flag, bool result, string errMsg); + event ReceiveMessageV2( + bytes32 messageId, + string senderDomain, + bytes32 senderID, + string receiverDomain, + address receiverID, + uint32 sequence, + uint64 nonce, + uint8 atomicFlag, + bool result, + string errMsg + ); /** * @dev Smart contracts need to call this method to send orderly cross-chain messages in SDPv2. @@ -56,9 +68,10 @@ interface ISDPMessage is ISubProtocol { * * @param receiverDomain the domain name of the receiving blockchain. * @param receiverID the address of the receiver. + * @param atomic if sending the atomic request. * @param message the raw message from DApp contracts * - * @return the sequence of SDP packet sent. + * @return the message id of SDP packet sent. */ function sendMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (bytes32); @@ -83,9 +96,10 @@ interface ISDPMessage is ISubProtocol { * * @param receiverDomain the domain name of the receiving blockchain. * @param receiverID the address of the receiver. + * @param atomic if sending the atomic request. * @param message the raw message from DApp contracts * - * @return the nonce of SDP packet sent. + * @return the message id of SDP packet sent. */ function sendUnorderedMessageV2(string calldata receiverDomain, bytes32 receiverID, bool atomic, bytes calldata message) external returns (bytes32); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISubProtocol.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISubProtocol.sol index a88f84d7..4d25f4a1 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISubProtocol.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/interfaces/ISubProtocol.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; interface ISubProtocol { /** - * @dev AM contract that want to forward the message to the receiving blockchain need to call this method to send auth message. + * @dev AM contract that want to forward the message to the receiving blockchain need to call this method to send auth message. * * @param senderDomain the domain name of the sending blockchain. * @param senderID the address of the sender. @@ -13,7 +13,7 @@ interface ISubProtocol { function recvMessage(string calldata senderDomain, bytes32 senderID, bytes calldata pkg) external; /** - * @dev SDP contract are based on the AuthMessage contract. Here we set the AuthMessage contract address. + * @dev SDP contract are based on the AuthMessage contract. Here we set the AuthMessage contract address. * * @param newAmContract the address of the AuthMessage contract. */ From 404f4743f67a63cec0e8506783b7445dc725c5ba Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 7 Mar 2024 17:48:58 +0800 Subject: [PATCH 10/17] [refactor][*][*]: interfaces for sdpv2 updated in SDK --- antchain-bridge-bcdns/pom.xml | 2 +- antchain-bridge-commons/pom.xml | 2 +- .../antchain/bridge/commons/core/sdp/ISDPMessage.java | 6 ++++++ .../antchain/bridge/commons/core/sdp/SDPMessageId.java | 3 ++- .../antchain/bridge/commons/core/sdp/SDPMessageV1.java | 5 +++++ antchain-bridge-plugin-lib/pom.xml | 2 +- antchain-bridge-plugin-manager/pom.xml | 2 +- antchain-bridge-spi/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 19 insertions(+), 7 deletions(-) diff --git a/antchain-bridge-bcdns/pom.xml b/antchain-bridge-bcdns/pom.xml index a147b311..a1ae4899 100644 --- a/antchain-bridge-bcdns/pom.xml +++ b/antchain-bridge-bcdns/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-bcdns - 0.2.2 + 0.2.3 8 diff --git a/antchain-bridge-commons/pom.xml b/antchain-bridge-commons/pom.xml index 32af3ccb..aca9ebd1 100644 --- a/antchain-bridge-commons/pom.xml +++ b/antchain-bridge-commons/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-commons - 0.2.2 + 0.2.3 8 diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java index 59e5d3f0..3eb0683c 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/ISDPMessage.java @@ -97,6 +97,12 @@ public interface ISDPMessage extends IMessage { */ int getVersion(); + /** + * Return the message id represents the sdp packet + * @return + */ + SDPMessageId getMessageId(); + /** * The nonce value for unordered packet. * diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java index fbc1f11d..2a6c0ac8 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageId.java @@ -1,6 +1,5 @@ package com.alipay.antchain.bridge.commons.core.sdp; -import cn.hutool.core.lang.Assert; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -12,6 +11,8 @@ @Setter public class SDPMessageId { + public static final SDPMessageId ZERO_MESSAGE_ID = new SDPMessageId(new byte[32]); + public SDPMessageId(@NonNull String messageIdHex) { this(HexUtil.decodeHex(messageIdHex)); } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java index f3c651bd..b371e95f 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java @@ -142,4 +142,9 @@ public AtomicFlagEnum getAtomicFlag() { public long getNonce() { return -1; } + + @Override + public SDPMessageId getMessageId() { + return SDPMessageId.ZERO_MESSAGE_ID; + } } diff --git a/antchain-bridge-plugin-lib/pom.xml b/antchain-bridge-plugin-lib/pom.xml index a70d8873..ded39613 100644 --- a/antchain-bridge-plugin-lib/pom.xml +++ b/antchain-bridge-plugin-lib/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-lib - 0.2.2 + 0.2.3 8 diff --git a/antchain-bridge-plugin-manager/pom.xml b/antchain-bridge-plugin-manager/pom.xml index aa502c5c..4c0f9b0a 100644 --- a/antchain-bridge-plugin-manager/pom.xml +++ b/antchain-bridge-plugin-manager/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-manager - 0.2.2 + 0.2.3 8 diff --git a/antchain-bridge-spi/pom.xml b/antchain-bridge-spi/pom.xml index 49e0cb01..58902832 100644 --- a/antchain-bridge-spi/pom.xml +++ b/antchain-bridge-spi/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-spi - 0.2.2 + 0.2.3 8 diff --git a/pom.xml b/pom.xml index a0d998e8..86a8a5c4 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.alipay.antchain.bridge antchain-bridge-sdk - 0.2.2 + 0.2.3 antchain-bridge-commons From 29bd86c5c0a13684f62c3f8d13336173fc7a6d04 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Mon, 11 Mar 2024 18:10:55 +0800 Subject: [PATCH 11/17] [feat][*][*]: receiving sdpv2 in progress --- .../commons/core/sdp/AbstractSDPMessage.java | 6 + .../commons/core/sdp/SDPMessageFactory.java | 2 +- .../bridge/commons/core/sdp/SDPMessageV1.java | 15 ++ .../onchain-plugin/solidity/sys/SDPMsg.sol | 141 ++++++++++++++++-- .../solidity/sys/lib/sdp/SDPLib.sol | 28 ++++ .../solidity/sys/lib/utils/TypesToBytes.sol | 2 +- 6 files changed, 179 insertions(+), 15 deletions(-) diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AbstractSDPMessage.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AbstractSDPMessage.java index e8121a19..01658454 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AbstractSDPMessage.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/AbstractSDPMessage.java @@ -66,4 +66,10 @@ public byte[] getPayload() { } abstract void setPayload(byte[] payload); + + public abstract void setNonce(long nonce); + + public abstract void setAtomicFlag(AtomicFlagEnum atomicFlag); + + public abstract void setMessageId(SDPMessageId messageId); } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java index 0247d4e3..afcaba82 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageFactory.java @@ -63,7 +63,7 @@ public static ISDPMessage createSDPMessage( return sdpMessage; } - private static ISDPMessage createSDPMessage(int version) { + public static ISDPMessage createSDPMessage(int version) { return createAbstractSDPMessage(version); } diff --git a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java index b371e95f..b828073f 100644 --- a/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java +++ b/antchain-bridge-commons/src/main/java/com/alipay/antchain/bridge/commons/core/sdp/SDPMessageV1.java @@ -147,4 +147,19 @@ public long getNonce() { public SDPMessageId getMessageId() { return SDPMessageId.ZERO_MESSAGE_ID; } + + @Override + public void setNonce(long nonce) { + + } + + @Override + public void setAtomicFlag(AtomicFlagEnum atomicFlag) { + + } + + @Override + public void setMessageId(SDPMessageId messageId) { + + } } diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index edc8d84e..bd161225 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -135,18 +135,13 @@ contract SDPMsg is ISDPMessage, Ownable { function recvMessage(string calldata senderDomain, bytes32 senderID, bytes calldata pkg) override external onlyAM { _beforeRecv(senderDomain, senderID, pkg); - SDPMessage memory sdpMessage; - sdpMessage.decode(pkg); - - require( - keccak256(abi.encodePacked(sdpMessage.receiveDomain)) == localDomainHash, - "SDPMsg: wrong receiving domain" - ); - - if (sdpMessage.sequence == SDPLib.UNORDERED_SEQUENCE) { - _routeUnorderedMessage(senderDomain, senderID, sdpMessage); + uint32 version = SDPLib.getSDPVersionFrom(pkg); + if (version == 1) { + _processSDPv1(senderDomain, senderID, pkg); + } else if (verison == 2) { + _processSDPv2(senderDomain, senderID, pkg); } else { - _routeOrderedMessage(senderDomain, senderID, sdpMessage); + revert("unsupport sdp version"); } _afterRecv(); @@ -162,6 +157,22 @@ contract SDPMsg is ISDPMessage, Ownable { return seq; } + function _processSDPv1(string calldata senderDomain, bytes32 senderID, bytes memory pkg) internal { + SDPMessage memory sdpMessage; + sdpMessage.decode(pkg); + + require( + keccak256(abi.encodePacked(sdpMessage.receiveDomain)) == localDomainHash, + "SDPMsg: wrong receiving domain" + ); + + if (sdpMessage.sequence == SDPLib.UNORDERED_SEQUENCE) { + _routeUnorderedMessage(senderDomain, senderID, sdpMessage); + } else { + _routeOrderedMessage(senderDomain, senderID, sdpMessage); + } + } + function _routeOrderedMessage(string calldata senderDomain, bytes32 senderID, SDPMessage memory sdpMessage) internal { uint32 seqExpected = _getAndUpdateRecvSeq(senderDomain, senderID, sdpMessage.receiver); require( @@ -171,7 +182,7 @@ contract SDPMsg is ISDPMessage, Ownable { bool res = false; string memory errMsg; - address receiver = SDPLib.encodeCrossChainIDIntoAddress(sdpMessage.receiver); + address receiver = sdpMessage.getReceiverAddress(); try IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) { @@ -188,10 +199,114 @@ contract SDPMsg is ISDPMessage, Ownable { } function _routeUnorderedMessage(string calldata senderDomain, bytes32 senderID, SDPMessage memory sdpMessage) internal { - IContractUsingSDP(SDPLib.encodeCrossChainIDIntoAddress(sdpMessage.receiver)) + IContractUsingSDP(sdpMessage.getReceiverAddress()) .recvUnorderedMessage(senderDomain, senderID, sdpMessage.message); } + function _processSDPv2(string calldata senderDomain, bytes32 senderID, bytes memory pkg) { + SDPMessageV2 memory sdpMessage; + sdpMessage.decode(pkg); + + require( + keccak256(abi.encodePacked(sdpMessage.receiveDomain)) == localDomainHash, + "SDPMsg: wrong receiving domain" + ); + + if ( + sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC + || sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST + ) { + _processSDPv2Request(senderDomain, senderID, sdpMessage); + } else if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ACK_SUCCESS) { + + } else { + revert("unexpected atomic flag"); + } + } + + function _processSDPv2Request(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) { + bool res; + string memory errMsg; + if (sdpMessage.sequence == SDPLib.UNORDERED_SEQUENCE) { + (res, errMsg) = _routeUnorderedMessageV2(senderDomain, senderID, sdpMessage); + if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_NONE_ATOMIC) { + require(res, errMsg); + } + } else { + (res, errMsg) = _routeOrderedMessageV2(senderDomain, senderID, sdpMessage); + } + + emit ReceiveMessageV2( + sdpMessage.messageId, + senderDomain, + senderID, + sdpMessage.receiveDomain, + sdpMessage.getReceiverAddress(), + sdpMessage.sequence, + sdpMessage.nonce, + sdpMessage.atomicFlag, + res, + errMsg + ); + + if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST) { + ackSDPv2Request(sdpMessage, senderDomain, senderID, res, errMsg); + } + } + + function _routeOrderedMessageV2(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal returns (bool, string memory) { + uint32 seqExpected = _getAndUpdateRecvSeq(senderDomain, senderID, sdpMessage.receiver); + if (sdpMessage.sequence != seqExpected) { + return (false, "SDPMsg: sequence not equal"); + } + + bool res = false; + string memory errMsg; + address receiver = sdpMessage.getReceiverAddress(); + try + IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) + { + res = true; + } catch Error( + string memory reason + ) { + errMsg = reason; + } catch ( + bytes memory /*lowLevelData*/ + ) {} + + return (res, errMsg); + } + + function _routeUnorderedMessageV2(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal returns (bool, string memory) { + bool res = false; + string memory errMsg; + try + IContractUsingSDP(sdpMessage.getReceiverAddress()).recvUnorderedMessage(senderDomain, senderID, sdpMessage.message) + { + res = true; + } catch Error( + string memory reason + ) { + errMsg = reason; + } catch ( + bytes memory /*lowLevelData*/ + ) {} + + return (res, errMsg); + } + + function ackSDPv2Request(SDPMessageV2 memory sdpMessage, string calldata senderDomain, bytes32 senderID, bool res, string memory errMsg) internal { + address receiverAddr = sdpMessage.getReceiverAddress(); + + sdpMessage.receiveDomain = senderDomain; + sdpMessage.receiver = senderID; + sdpMessage.atomicFlag = res ? SDPLib.SDP_V2_ATOMIC_FLAG_ACK_SUCCESS : SDP_V2_ATOMIC_FLAG_ACK_ERROR; + sdpMessage.errorMsg = res ? "" : errMsg; + + IAuthMessage(amAddress).recvFromProtocol(receiverAddr, sdpMessage.encode()); + } + function _getAndUpdateSendSeq(string memory receiveDomain, address sender, bytes32 receiver) internal returns (uint32) { bytes32 seqKey = SDPLib.getSendingSeqID(receiveDomain, sender, receiver); uint32 seq = sendSeq[seqKey]; diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol index 36721ee7..9fc9c73c 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol @@ -43,6 +43,26 @@ library SDPLib { // @notice only for orderred msg uint64 constant MAX_NONCE = 0xffffffffffffffff; + function getSDPVersionFrom(bytes memory pkg) pure internal returns (uint32) { + bytes1 firstByte; + uint l = pkg.length; + assembly { + firstByte := mload(add(add(pkg, 32), sub(l, 4))) + } + + if (firstByte == 0xff) { + uint32 version; + bytes memory rawVersion = new bytes(4); + assembly { + mstore(add(rawVersion, 33), mload(add(pkg, add(32, sub(l, 3))))) + version := mload(add(rawVersion, 4)) + } + return version; + } + + return 1; + } + function encode(SDPMessage memory sdpMessage) pure internal returns (bytes memory) { uint256 len = SizeOf.sizeOfBytes(sdpMessage.message) + 4 + 32 + SizeOf.sizeOfString(sdpMessage.receiveDomain); @@ -237,4 +257,12 @@ library SDPLib { TypesToBytes.bytes32ToBytes(32, id, rawId); return BytesToTypes.bytesToAddress(32, rawId); } + + function getReceiverAddress(SDPMessageV2 memory sdpMessage) pure internal returns (address) { + return encodeCrossChainIDIntoAddress(sdpMessage.receiver); + } + + function getReceiverAddress(SDPMessage memory sdpMessage) pure internal returns (address) { + return encodeCrossChainIDIntoAddress(sdpMessage.receiver); + } } diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol index eb56c488..edd106ac 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol @@ -44,7 +44,7 @@ library TypesToBytes { mstore(add(_output, _offset), x) } } - +0x010203ff000001 function varBytesToBytes(uint _offset, bytes memory _input, bytes memory _output) internal pure { uint32 body_len = uint32(_input.length); TypesToBytes.uintToBytes(_offset, body_len, _output); From d84ac822f43a24de6aa1d345b6f47b30071b16de Mon Sep 17 00:00:00 2001 From: zouxyan Date: Tue, 12 Mar 2024 15:09:19 +0800 Subject: [PATCH 12/17] [feat][*][*]: receiving sdpv2 --- .../onchain-plugin/solidity/sys/SDPMsg.sol | 64 +++++++++++++++++-- .../solidity/sys/lib/utils/TypesToBytes.sol | 2 +- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index bd161225..bb075d50 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import "./interfaces/ISDPMessage.sol"; import "./interfaces/IAuthMessage.sol"; import "./interfaces/IContractUsingSDP.sol"; +import "./interfaces/IContractWithAcks.sol"; import "./lib/sdp/SDPLib.sol"; import "./lib/utils/Ownable.sol"; @@ -138,7 +139,7 @@ contract SDPMsg is ISDPMessage, Ownable { uint32 version = SDPLib.getSDPVersionFrom(pkg); if (version == 1) { _processSDPv1(senderDomain, senderID, pkg); - } else if (verison == 2) { + } else if (version == 2) { _processSDPv2(senderDomain, senderID, pkg); } else { revert("unsupport sdp version"); @@ -203,7 +204,7 @@ contract SDPMsg is ISDPMessage, Ownable { .recvUnorderedMessage(senderDomain, senderID, sdpMessage.message); } - function _processSDPv2(string calldata senderDomain, bytes32 senderID, bytes memory pkg) { + function _processSDPv2(string calldata senderDomain, bytes32 senderID, bytes memory pkg) internal { SDPMessageV2 memory sdpMessage; sdpMessage.decode(pkg); @@ -218,13 +219,15 @@ contract SDPMsg is ISDPMessage, Ownable { ) { _processSDPv2Request(senderDomain, senderID, sdpMessage); } else if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ACK_SUCCESS) { - + _processSDPv2AckSuccess(senderDomain, senderID, sdpMessage); + } else if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ACK_ERROR) { + _processSDPv2AckError(senderDomain, senderID, sdpMessage); } else { revert("unexpected atomic flag"); } } - function _processSDPv2Request(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) { + function _processSDPv2Request(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal { bool res; string memory errMsg; if (sdpMessage.sequence == SDPLib.UNORDERED_SEQUENCE) { @@ -250,7 +253,7 @@ contract SDPMsg is ISDPMessage, Ownable { ); if (sdpMessage.atomicFlag == SDPLib.SDP_V2_ATOMIC_FLAG_ATOMIC_REQUEST) { - ackSDPv2Request(sdpMessage, senderDomain, senderID, res, errMsg); + _ackSDPv2Request(sdpMessage, senderDomain, senderID, res, errMsg); } } @@ -296,17 +299,64 @@ contract SDPMsg is ISDPMessage, Ownable { return (res, errMsg); } - function ackSDPv2Request(SDPMessageV2 memory sdpMessage, string calldata senderDomain, bytes32 senderID, bool res, string memory errMsg) internal { + function _ackSDPv2Request(SDPMessageV2 memory sdpMessage, string calldata senderDomain, bytes32 senderID, bool res, string memory errMsg) internal { address receiverAddr = sdpMessage.getReceiverAddress(); sdpMessage.receiveDomain = senderDomain; sdpMessage.receiver = senderID; - sdpMessage.atomicFlag = res ? SDPLib.SDP_V2_ATOMIC_FLAG_ACK_SUCCESS : SDP_V2_ATOMIC_FLAG_ACK_ERROR; + sdpMessage.atomicFlag = res ? SDPLib.SDP_V2_ATOMIC_FLAG_ACK_SUCCESS : SDPLib.SDP_V2_ATOMIC_FLAG_ACK_ERROR; sdpMessage.errorMsg = res ? "" : errMsg; IAuthMessage(amAddress).recvFromProtocol(receiverAddr, sdpMessage.encode()); } + function _processSDPv2AckSuccess(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal { + IContractWithAcks(sdpMessage.getReceiverAddress()).ackOnSuccess( + sdpMessage.messageId, + senderDomain, + senderID, + sdpMessage.sequence, + sdpMessage.nonce, + sdpMessage.message + ); + emit ReceiveMessageV2( + sdpMessage.messageId, + senderDomain, + senderID, + sdpMessage.receiveDomain, + sdpMessage.getReceiverAddress(), + sdpMessage.sequence, + sdpMessage.nonce, + sdpMessage.atomicFlag, + true, + "success" + ); + } + + function _processSDPv2AckError(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal { + IContractWithAcks(sdpMessage.getReceiverAddress()).ackOnError( + sdpMessage.messageId, + senderDomain, + senderID, + sdpMessage.sequence, + sdpMessage.nonce, + sdpMessage.message, + sdpMessage.errorMsg + ); + emit ReceiveMessageV2( + sdpMessage.messageId, + senderDomain, + senderID, + sdpMessage.receiveDomain, + sdpMessage.getReceiverAddress(), + sdpMessage.sequence, + sdpMessage.nonce, + sdpMessage.atomicFlag, + true, + sdpMessage.errorMsg + ); + } + function _getAndUpdateSendSeq(string memory receiveDomain, address sender, bytes32 receiver) internal returns (uint32) { bytes32 seqKey = SDPLib.getSendingSeqID(receiveDomain, sender, receiver); uint32 seq = sendSeq[seqKey]; diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol index edd106ac..eb56c488 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol @@ -44,7 +44,7 @@ library TypesToBytes { mstore(add(_output, _offset), x) } } -0x010203ff000001 + function varBytesToBytes(uint _offset, bytes memory _input, bytes memory _output) internal pure { uint32 body_len = uint32(_input.length); TypesToBytes.uintToBytes(_offset, body_len, _output); From 90b776b570b5d7091bc91381985c66c16d7550cd Mon Sep 17 00:00:00 2001 From: zouxyan Date: Wed, 13 Mar 2024 17:21:35 +0800 Subject: [PATCH 13/17] [fix][*][*]: `bytesToVarBytes` bug in eth sdp contract fixed --- .../solidity/sys/lib/utils/BytesToTypes.sol | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/BytesToTypes.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/BytesToTypes.sol index f2c6cb81..84e18ab1 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/BytesToTypes.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/BytesToTypes.sol @@ -41,13 +41,6 @@ library BytesToTypes { } } - function getStringSizeFromUint32(uint _offset, bytes memory _input) internal pure returns(uint size) { - - assembly { - size := shr(224, mload(add(_input,_offset))) - } - } - function bytesToString(uint _offset, bytes memory _input, bytes memory _output) internal pure { uint size = 32; @@ -74,7 +67,7 @@ library BytesToTypes { function bytesToVarBytes(uint _offset, bytes memory _input) internal pure returns (bytes memory) { - uint len = getStringSizeFromUint32(_offset, _input); + uint len = bytesToUint32(_offset, _input); _offset -= 4; require( len <= _offset, From f101de49cdb8cda429c9dbc954c0599566bd1e40 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 14 Mar 2024 19:59:30 +0800 Subject: [PATCH 14/17] [fix][*][*]: put local domain and sender into sdp message id --- .../ethereum/onchain-plugin/solidity/sys/SDPMsg.sol | 4 ++-- .../onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index bb075d50..8b620b02 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -99,7 +99,7 @@ contract SDPMsg is ISDPMessage, Ownable { errorMsg: "" } ); - sdpMessage.calcMessageId(); + sdpMessage.calcMessageId(localDomainHash); IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encode()); @@ -124,7 +124,7 @@ contract SDPMsg is ISDPMessage, Ownable { errorMsg: "" } ); - sdpMessage.calcMessageId(); + sdpMessage.calcMessageId(localDomainHash); IAuthMessage(amAddress).recvFromProtocol(msg.sender, sdpMessage.encode()); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol index 9fc9c73c..177e3261 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol @@ -203,7 +203,7 @@ library SDPLib { } } - function calcMessageId(SDPMessageV2 memory sdpMessage) internal pure { + function calcMessageId(SDPMessageV2 memory sdpMessage, bytes32 localDomainHash) internal view { require( sdpMessage.version == 2, "encodeSDPMessage: wrong version" @@ -212,10 +212,6 @@ library SDPLib { sdpMessage.message.length <= 0xFFFFFFFF, "encodeSDPMessage: body length overlimit" ); - require( - sdpMessage.messageId != bytes32(0), - "encodeSDPMessage: zero message id" - ); uint total_size = 57 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; bytes memory pkg = new bytes(total_size); @@ -240,6 +236,9 @@ library SDPLib { TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + TypesToBytes.addressToBytes(offset, msg.sender, pkg); + TypesToBytes.bytes32ToBytes(offset, localDomainHash, pkg); + sdpMessage.messageId = keccak256(pkg); } From 069b35bea1afff6fb338bbcdd43a3ccc19d9f014 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Fri, 15 Mar 2024 18:12:42 +0800 Subject: [PATCH 15/17] [fix][ethereum-bbc][*]: revert when seq not equal for sdp v2 --- pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index 8b620b02..32ec40aa 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -259,9 +259,7 @@ contract SDPMsg is ISDPMessage, Ownable { function _routeOrderedMessageV2(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal returns (bool, string memory) { uint32 seqExpected = _getAndUpdateRecvSeq(senderDomain, senderID, sdpMessage.receiver); - if (sdpMessage.sequence != seqExpected) { - return (false, "SDPMsg: sequence not equal"); - } + require(sdpMessage.sequence == seqExpected, "SDPMsg: sequence not equal"); bool res = false; string memory errMsg; From 5b4ce047fac64245c737bc06173998d933ef58c0 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Wed, 10 Apr 2024 16:15:20 +0800 Subject: [PATCH 16/17] [fix][ethereum-bbc][*]: wrong way to copy value in `memcpy` [fix][ethereum-bbc][*]: incorrect sdp v2 deserialization [fix][ethereum-bbc][*]: incorrect sdp v2 serialization [fix][ethereum-bbc][*]: incorrect sdp v1 decode --- .../onchain-plugin/solidity/sys/SDPMsg.sol | 81 +++++++++++-------- .../solidity/sys/lib/am/AMLib.sol | 8 +- .../solidity/sys/lib/sdp/SDPLib.sol | 40 ++++----- .../solidity/sys/lib/utils/TypesToBytes.sol | 27 ++++--- .../solidity/sys/lib/utils/Utils.sol | 4 + 5 files changed, 94 insertions(+), 66 deletions(-) diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol index 32ec40aa..68e35a8c 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/SDPMsg.sol @@ -184,17 +184,22 @@ contract SDPMsg is ISDPMessage, Ownable { bool res = false; string memory errMsg; address receiver = sdpMessage.getReceiverAddress(); - try - IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) - { - res = true; - } catch Error( - string memory reason - ) { - errMsg = reason; - } catch ( - bytes memory /*lowLevelData*/ - ) {} + if (receiver.code.length == 0) { + res = false; + errMsg = "receiver has no code"; + } else { + try + IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) + { + res = true; + } catch Error( + string memory reason + ) { + errMsg = reason; + } catch ( + bytes memory /*lowLevelData*/ + ) {} + } emit receiveMessage(senderDomain, senderID, receiver, seqExpected, res, errMsg); } @@ -264,17 +269,22 @@ contract SDPMsg is ISDPMessage, Ownable { bool res = false; string memory errMsg; address receiver = sdpMessage.getReceiverAddress(); - try - IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) - { - res = true; - } catch Error( - string memory reason - ) { - errMsg = reason; - } catch ( - bytes memory /*lowLevelData*/ - ) {} + if (receiver.code.length == 0) { + res = false; + errMsg = "receiver has no code"; + } else { + try + IContractUsingSDP(receiver).recvMessage(senderDomain, senderID, sdpMessage.message) + { + res = true; + } catch Error( + string memory reason + ) { + errMsg = reason; + } catch ( + bytes memory /*lowLevelData*/ + ) {} + } return (res, errMsg); } @@ -282,17 +292,22 @@ contract SDPMsg is ISDPMessage, Ownable { function _routeUnorderedMessageV2(string calldata senderDomain, bytes32 senderID, SDPMessageV2 memory sdpMessage) internal returns (bool, string memory) { bool res = false; string memory errMsg; - try - IContractUsingSDP(sdpMessage.getReceiverAddress()).recvUnorderedMessage(senderDomain, senderID, sdpMessage.message) - { - res = true; - } catch Error( - string memory reason - ) { - errMsg = reason; - } catch ( - bytes memory /*lowLevelData*/ - ) {} + if (sdpMessage.getReceiverAddress().code.length == 0) { + res = false; + errMsg = "receiver has no code"; + } else { + try + IContractUsingSDP(sdpMessage.getReceiverAddress()).recvUnorderedMessage(senderDomain, senderID, sdpMessage.message) + { + res = true; + } catch Error( + string memory reason + ) { + errMsg = reason; + } catch ( + bytes memory /*lowLevelData*/ + ) {} + } return (res, errMsg); } diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/am/AMLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/am/AMLib.sol index 921e6d2b..407cd7a0 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/am/AMLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/am/AMLib.sol @@ -201,13 +201,13 @@ library AMLib { bytes memory pkg = new bytes(len); uint offset = len; - TypesToBytes.uintToBytes(offset, message.version, pkg); + TypesToBytes.uint32ToBytes(offset, message.version, pkg); offset -= SizeOf.sizeOfInt(32); TypesToBytes.bytes32ToBytes(offset, message.author, pkg); offset -= SizeOf.sizeOfBytes32(); - TypesToBytes.uintToBytes(offset, message.protocolType, pkg); + TypesToBytes.uint32ToBytes(offset, message.protocolType, pkg); offset -= SizeOf.sizeOfInt(32); TypesToBytes.stringToBytes(offset, message.body, pkg); @@ -232,13 +232,13 @@ library AMLib { bytes memory pkg = new bytes(len); uint offset = len; - TypesToBytes.uintToBytes(offset, message.version, pkg); + TypesToBytes.uint32ToBytes(offset, message.version, pkg); offset -= SizeOf.sizeOfInt(32); TypesToBytes.bytes32ToBytes(offset, message.author, pkg); offset -= SizeOf.sizeOfBytes32(); - TypesToBytes.uintToBytes(offset, message.protocolType, pkg); + TypesToBytes.uint32ToBytes(offset, message.protocolType, pkg); offset -= SizeOf.sizeOfInt(32); TypesToBytes.varBytesToBytes(offset, message.body, pkg); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol index 177e3261..db193dd9 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/sdp/SDPLib.sol @@ -79,7 +79,7 @@ library SDPLib { offset -= SizeOf.sizeOfBytes32(); // 填充sequence - TypesToBytes.uintToBytes(offset, sdpMessage.sequence, pkg); + TypesToBytes.uint32ToBytes(offset, sdpMessage.sequence, pkg); offset -= SizeOf.sizeOfUint(32); // 填充消息 @@ -108,14 +108,10 @@ library SDPLib { BytesToTypes.bytesToString(offset, rawMessage, message); offset -= SizeOf.sizeOfBytes(message); - sdpMessage = SDPMessage( - { - receiveDomain: string(dest_domain), - receiver: receiver, - message: message, - sequence: sequence - } - ); + sdpMessage.receiveDomain = string(dest_domain); + sdpMessage.receiver = receiver; + sdpMessage.sequence = sequence; + sdpMessage.message = message; } function encode(SDPMessageV2 memory sdpMessage) pure internal returns (bytes memory) { @@ -143,13 +139,15 @@ library SDPLib { bytes memory pkg = new bytes(total_size); uint offset = total_size; - TypesToBytes.uintToBytes(offset, sdpMessage.version, pkg); + TypesToBytes.uintToBytes(offset, sdpMessage.version + 0xff000000, pkg); offset -= SizeOf.sizeOfInt(32); TypesToBytes.bytes32ToBytes(offset, sdpMessage.messageId, pkg); offset -= SizeOf.sizeOfBytes32(); - TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.receiveDomain), pkg); + bytes memory raw_recv_domain = bytes(sdpMessage.receiveDomain); + TypesToBytes.varBytesToBytes(offset, raw_recv_domain, pkg); + offset -= 4 + raw_recv_domain.length; TypesToBytes.bytes32ToBytes(offset, sdpMessage.receiver, pkg); offset -= SizeOf.sizeOfBytes32(); @@ -164,6 +162,7 @@ library SDPLib { offset -= SizeOf.sizeOfInt(32); TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + offset -= 4 + sdpMessage.message.length; if (withErrorMsg) { TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.errorMsg), pkg); @@ -174,15 +173,16 @@ library SDPLib { function decode(SDPMessageV2 memory sdpMessage, bytes memory rawMessage) internal pure { uint256 offset = rawMessage.length; - bool withErrorMsg = sdpMessage.atomicFlag > SDP_V2_ATOMIC_FLAG_ACK_SUCCESS; - sdpMessage.version = BytesToTypes.bytesToUint32(offset, rawMessage); + sdpMessage.version = getSDPVersionFrom(rawMessage); offset -= SizeOf.sizeOfUint(32); sdpMessage.messageId = BytesToTypes.bytesToBytes32(offset, rawMessage); offset -= SizeOf.sizeOfBytes32(); - sdpMessage.receiveDomain = string(BytesToTypes.bytesToVarBytes(offset, rawMessage)); + bytes memory raw_recv_domain = BytesToTypes.bytesToVarBytes(offset, rawMessage); + sdpMessage.receiveDomain = string(raw_recv_domain); + offset -= 4 + raw_recv_domain.length; sdpMessage.receiver = BytesToTypes.bytesToBytes32(offset, rawMessage); offset -= SizeOf.sizeOfBytes32(); @@ -197,8 +197,9 @@ library SDPLib { offset -= 4; sdpMessage.message = BytesToTypes.bytesToVarBytes(offset, rawMessage); + offset -= 4 + sdpMessage.message.length; - if (withErrorMsg) { + if (sdpMessage.atomicFlag > SDP_V2_ATOMIC_FLAG_ACK_SUCCESS) { sdpMessage.errorMsg = string(BytesToTypes.bytesToVarBytes(offset, rawMessage)); } } @@ -213,14 +214,16 @@ library SDPLib { "encodeSDPMessage: body length overlimit" ); - uint total_size = 57 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; + uint total_size = 121 + bytes(sdpMessage.receiveDomain).length + sdpMessage.message.length; bytes memory pkg = new bytes(total_size); uint offset = total_size; - TypesToBytes.uintToBytes(offset, sdpMessage.version, pkg); + TypesToBytes.uintToBytes(offset, sdpMessage.version + 0xff000000, pkg); offset -= SizeOf.sizeOfInt(32); - TypesToBytes.varBytesToBytes(offset, bytes(sdpMessage.receiveDomain), pkg); + bytes memory raw_recv_domain = bytes(sdpMessage.receiveDomain); + TypesToBytes.varBytesToBytes(offset, raw_recv_domain, pkg); + offset -= 4 + raw_recv_domain.length; TypesToBytes.bytes32ToBytes(offset, sdpMessage.receiver, pkg); offset -= SizeOf.sizeOfBytes32(); @@ -235,6 +238,7 @@ library SDPLib { offset -= SizeOf.sizeOfInt(32); TypesToBytes.varBytesToBytes(offset, sdpMessage.message, pkg); + offset -= 4 + sdpMessage.message.length; TypesToBytes.addressToBytes(offset, msg.sender, pkg); TypesToBytes.bytes32ToBytes(offset, localDomainHash, pkg); diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol index eb56c488..d642336a 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/TypesToBytes.sol @@ -34,7 +34,12 @@ library TypesToBytes { function byteToBytes(uint _offset, uint8 _input, bytes memory _output) internal pure { assembly { - mstore(add(_output, _offset), _input) + let my_pos := add(_output, _offset) + let prev_word_pos := sub(my_pos, 1) + let prev_word := mload(prev_word_pos) + + mstore(my_pos, _input) + mstore(prev_word_pos, prev_word) } } @@ -47,7 +52,7 @@ library TypesToBytes { function varBytesToBytes(uint _offset, bytes memory _input, bytes memory _output) internal pure { uint32 body_len = uint32(_input.length); - TypesToBytes.uintToBytes(_offset, body_len, _output); + TypesToBytes.uint32ToBytes(_offset, body_len, _output); _offset -= 4; require( @@ -147,11 +152,11 @@ library TypesToBytes { function uint16ToBytes(uint _offset, uint16 _input, bytes memory _output) internal pure { assembly { - let prev_word_pos := add(_output, _offset) + let my_pos := add(_output, _offset) + let prev_word_pos := sub(my_pos, 2) let prev_word := mload(prev_word_pos) - mstore(add(prev_word_pos, 2), _input) - + mstore(my_pos, _input) mstore(prev_word_pos, prev_word) } } @@ -159,11 +164,11 @@ library TypesToBytes { function uint32ToBytes(uint _offset, uint32 _input, bytes memory _output) internal pure { assembly { - let prev_word_pos := add(_output, _offset) + let my_pos := add(_output, _offset) + let prev_word_pos := sub(my_pos, 4) let prev_word := mload(prev_word_pos) - mstore(add(prev_word_pos, 4), _input) - + mstore(my_pos, _input) mstore(prev_word_pos, prev_word) } } @@ -171,11 +176,11 @@ library TypesToBytes { function uint64ToBytes(uint _offset, uint64 _input, bytes memory _output) internal pure { assembly { - let prev_word_pos := add(_output, _offset) + let my_pos := add(_output, _offset) + let prev_word_pos := sub(my_pos, 8) let prev_word := mload(prev_word_pos) - mstore(add(prev_word_pos, 8), _input) - + mstore(my_pos, _input) mstore(prev_word_pos, prev_word) } } diff --git a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Utils.sol b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Utils.sol index 8c774171..0e400214 100644 --- a/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Utils.sol +++ b/pluginset/ethereum/onchain-plugin/solidity/sys/lib/utils/Utils.sol @@ -386,6 +386,10 @@ library Utils { src += 32; } + if (len == 0) { + return; + } + // uint mask = SafeMath.pwr(256, (32 - len)) - 1; uint mask = 256 ** (32 - len) - 1; assembly { From 575c5c647d4be21e212d99a8ea7d144dd4f1bbb2 Mon Sep 17 00:00:00 2001 From: zouxyan Date: Thu, 11 Apr 2024 19:45:38 +0800 Subject: [PATCH 17/17] [fix][*][*]: incorrect version and load class with prefix `com.alipay.antchain.bridge.plugins.spi&commons` and `org.slf4j` from AppClzLoader instead of plugin clz loader --- antchain-bridge-bcdns/pom.xml | 2 +- antchain-bridge-commons/pom.xml | 2 +- antchain-bridge-plugin-lib/pom.xml | 2 +- antchain-bridge-plugin-manager/pom.xml | 2 +- .../pf4j/PrefixBannedPluginClassloader.java | 65 +++++++++++++++++++ antchain-bridge-spi/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/antchain-bridge-bcdns/pom.xml b/antchain-bridge-bcdns/pom.xml index a1ae4899..a147b311 100644 --- a/antchain-bridge-bcdns/pom.xml +++ b/antchain-bridge-bcdns/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-bcdns - 0.2.3 + 0.2.2 8 diff --git a/antchain-bridge-commons/pom.xml b/antchain-bridge-commons/pom.xml index aca9ebd1..32af3ccb 100644 --- a/antchain-bridge-commons/pom.xml +++ b/antchain-bridge-commons/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-commons - 0.2.3 + 0.2.2 8 diff --git a/antchain-bridge-plugin-lib/pom.xml b/antchain-bridge-plugin-lib/pom.xml index ded39613..a70d8873 100644 --- a/antchain-bridge-plugin-lib/pom.xml +++ b/antchain-bridge-plugin-lib/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-lib - 0.2.3 + 0.2.2 8 diff --git a/antchain-bridge-plugin-manager/pom.xml b/antchain-bridge-plugin-manager/pom.xml index 4c0f9b0a..aa502c5c 100644 --- a/antchain-bridge-plugin-manager/pom.xml +++ b/antchain-bridge-plugin-manager/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-plugin-manager - 0.2.3 + 0.2.2 8 diff --git a/antchain-bridge-plugin-manager/src/main/java/com/alipay/antchain/bridge/plugins/manager/pf4j/PrefixBannedPluginClassloader.java b/antchain-bridge-plugin-manager/src/main/java/com/alipay/antchain/bridge/plugins/manager/pf4j/PrefixBannedPluginClassloader.java index 6f72c953..a74c1818 100644 --- a/antchain-bridge-plugin-manager/src/main/java/com/alipay/antchain/bridge/plugins/manager/pf4j/PrefixBannedPluginClassloader.java +++ b/antchain-bridge-plugin-manager/src/main/java/com/alipay/antchain/bridge/plugins/manager/pf4j/PrefixBannedPluginClassloader.java @@ -25,13 +25,21 @@ import org.pf4j.PluginClassLoader; import org.pf4j.PluginDescriptor; import org.pf4j.PluginManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PrefixBannedPluginClassloader extends PluginClassLoader { + private static final Logger log = LoggerFactory.getLogger(PrefixBannedPluginClassloader.class); + private static final String JAVA_PACKAGE_PREFIX = "java."; private static final String PLUGIN_PACKAGE_PREFIX = "org.pf4j."; + private static final String ACB_SPI_PACKAGE_PREFIX = "com.alipay.antchain.bridge.plugins.spi"; + + private static final String ACB_COMMONS_PACKAGE_PREFIX = "com.alipay.antchain.bridge.plugins.commons"; + /** * Banned the dependency with the prefix path to read the resource */ @@ -134,4 +142,61 @@ public Enumeration getResources(String name) throws IOException { return Collections.enumeration(resources); } + + @Override + public Class loadClass(String className) throws ClassNotFoundException { + synchronized (getClassLoadingLock(className)) { + // first check whether it's a system class, delegate to the system loader + if (className.startsWith(JAVA_PACKAGE_PREFIX)) { + return findSystemClass(className); + } + + // if the class is part of the plugin engine use parent class loader + if ( + (className.startsWith(PLUGIN_PACKAGE_PREFIX) && !className.startsWith("org.pf4j.demo") && !className.startsWith("org.pf4j.test")) || + className.startsWith(ACB_SPI_PACKAGE_PREFIX) || + className.startsWith(ACB_COMMONS_PACKAGE_PREFIX) || + className.startsWith("org.slf4j.") + ) { +// log.trace("Delegate the loading of PF4J class '{}' to parent", className); + return getParent().loadClass(className); + } + + log.trace("Received request to load class '{}'", className); + + // second check whether it's already been loaded + Class loadedClass = findLoadedClass(className); + if (loadedClass != null) { + log.trace("Found loaded class '{}'", className); + return loadedClass; + } + + for (ClassLoadingStrategy.Source classLoadingSource : classLoadingStrategy.getSources()) { + Class c = null; + try { + switch (classLoadingSource) { + case APPLICATION: + c = super.loadClass(className); + break; + case PLUGIN: + c = findClass(className); + break; + case DEPENDENCIES: + c = loadClassFromDependencies(className); + break; + } + } catch (ClassNotFoundException ignored) { + } + + if (c != null) { + log.trace("Found class '{}' in {} classpath", className, classLoadingSource); + return c; + } else { + log.trace("Couldn't find class '{}' in {} classpath", className, classLoadingSource); + } + } + + throw new ClassNotFoundException(className); + } + } } diff --git a/antchain-bridge-spi/pom.xml b/antchain-bridge-spi/pom.xml index 58902832..49e0cb01 100644 --- a/antchain-bridge-spi/pom.xml +++ b/antchain-bridge-spi/pom.xml @@ -6,7 +6,7 @@ com.alipay.antchain.bridge antchain-bridge-spi - 0.2.3 + 0.2.2 8 diff --git a/pom.xml b/pom.xml index 86a8a5c4..a0d998e8 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.alipay.antchain.bridge antchain-bridge-sdk - 0.2.3 + 0.2.2 antchain-bridge-commons