Skip to content

Commit

Permalink
feat: response message solidity (#234)
Browse files Browse the repository at this point in the history
* feat: xcall upgradeable (#179)

* feat: xcall upgradeable

* fix: foundry toml fix

* deploy mock script

* fix: remapping

* fix: env name changed

* fix: script reformed

* fix: upgradeable using openzeppelin

* fix: upgradeable using openzeppelin

* fix: deploy scripts fix

* fix: deploy scripts fix

* forge install: openzeppelin-foundry-upgrades

* fix: Make simple dapp to use same logic as dapp multi (#195)

* fix: adapters deployment scripts added

* fix: adapters included in script

---------

Co-authored-by: AntonAndell <[email protected]>

* fix: network address validation fixed (#212)

* fix: not authorized issue by making handleMessage public (#202)

* fix: not authorized issue by making handleMessage public

* feat: handleBTPMessage tests added

* fix: add fixes for handle Error

* fix: code order optmization in handle message

Signed-off-by: gcranju <[email protected]>

* fix:revert message added in handleRequest

* fix: versions openzeppelin fix

* fix: foundry upgrades deleted

---------

Signed-off-by: gcranju <[email protected]>

* ci: add job to update CHANGELOG.md (#207)

* fix: added rpsc in foundry.toml

* fix: fix env.example

* fix: new message type added in solidity

* feat: add centralized connections in solidity and java (#196)

* feat: solidity xcall connection added

* feat: icon xcall connection added

* fix: checkfee added

* feat: relayer address in centralized connection

* feat: added build scripts

* feat: solidity tests for centralized connection added

* feat: centralized connection name changed for icon

* fix: review comments addressed for solidity part

* fix: variable admin used for relayer/admin

* fix: review comments addressed for javascore part

* fix: variables in build.gradle in centralized cnnection

* fix: java score constructor

* fix: removed void from constructor

* fix: type of receipts to boolean

* fix: solitity tests resolved

* fix: logic corrected for duplicate message

* fix: fee check added in connection

* fix: centralized connection test added in solidity

* fix: admin check removed from getReceipts

Co-authored-by: redlarva <[email protected]>

* fix: onlyAdmin function

* fix: architecture updated (#214)

* fix: architecture updated

* fix: use connectio sn

* style: formatting code

* added scripts for centralized connections

* feat: centralized-connection javascore tests added

* feat: clam fees tests added

---------

Co-authored-by: red__larva <[email protected]>
Co-authored-by: redlarva <[email protected]>

* fix: unnecessary event log removed

* fix: sendBTPMessage renamed to sendToConnection

* fix: unnecessary event log removed

* feat: add centralized connections in solidity and java (#196)

* feat: solidity xcall connection added

* feat: icon xcall connection added

* fix: checkfee added

* feat: relayer address in centralized connection

* feat: added build scripts

* feat: solidity tests for centralized connection added

* feat: centralized connection name changed for icon

* fix: review comments addressed for solidity part

* fix: variable admin used for relayer/admin

* fix: review comments addressed for javascore part

* fix: variables in build.gradle in centralized cnnection

* fix: java score constructor

* fix: removed void from constructor

* fix: type of receipts to boolean

* fix: solitity tests resolved

* fix: logic corrected for duplicate message

* fix: fee check added in connection

* fix: centralized connection test added in solidity

* fix: admin check removed from getReceipts

Co-authored-by: redlarva <[email protected]>

* fix: onlyAdmin function

* fix: architecture updated (#214)

* fix: architecture updated

* fix: use connectio sn

* style: formatting code

* added scripts for centralized connections

* feat: centralized-connection javascore tests added

* feat: clam fees tests added

---------

Co-authored-by: red__larva <[email protected]>
Co-authored-by: redlarva <[email protected]>

* fix: centralized-connection test fixed

* fix: proxy request structure with data hash added

* fix: getFee method

* fix: message encoding decoding fixed

* fix: logs removed

* feat: response message solidity

* fix: review changes

* feat: tests added

* fix merge issues

---------

Signed-off-by: gcranju <[email protected]>
Co-authored-by: AntonAndell <[email protected]>
Co-authored-by: DeepakBomjan <[email protected]>
Co-authored-by: izyak <[email protected]>
Co-authored-by: red__larva <[email protected]>
Co-authored-by: redlarva <[email protected]>
  • Loading branch information
6 people authored Jan 18, 2024
1 parent cc29590 commit fa211ca
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 141 deletions.
193 changes: 135 additions & 58 deletions contracts/evm/contracts/xcall/CallService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
mapping(uint256 => mapping(string => bool)) private pendingResponses;

mapping(string => address) private defaultConnections;
bytes private callReply;
Types.ProxyRequest private replyState;

address private owner;
address private adminAddress;
Expand Down Expand Up @@ -125,8 +127,6 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
return _sendCallMessage(_to, _data, _rollback, src, dst);
}



function sendCall(
string memory _to,
bytes memory _data
Expand Down Expand Up @@ -157,16 +157,21 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
bytes memory _msg = req.encodeCSMessageRequest();
require(_msg.length <= MAX_DATA_SIZE, "MaxDataSizeExceeded");

uint256 sendSn = result.needResponse ? sn : 0;
if (isReply(netTo, envelope.sources) && !result.needResponse) {
delete replyState;
callReply = _msg;

Check warning on line 162 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L161-L162

Added lines #L161 - L162 were not covered by tests
} else {
uint256 sendSn = result.needResponse ? sn : 0;

sendMessage(
envelope.sources,
netTo,
Types.CS_REQUEST,
int(sendSn),
_msg
);
claimProtocolFee();
sendMessage(
envelope.sources,
netTo,
Types.CS_REQUEST,
int(sendSn),
_msg
);
claimProtocolFee();
}
emit CallMessageSent(caller, _to, sn);
return sn;
}
Expand All @@ -187,14 +192,7 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
for (uint i = 0; i < sources.length; i++) {
address conn = sources[i].parseAddress("IllegalArgument");
uint256 requiredFee = _getFee(conn, netTo, sn);
sendToConnection(
conn,
requiredFee,
netTo,
msgType,
sn,
data
);
sendToConnection(conn, requiredFee, netTo, msgType, sn, data);
}
}
}
Expand Down Expand Up @@ -245,28 +243,23 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
Types.XCallEnvelope memory envelope;

if (_rollback.length == 0) {

Types.CallMessage memory _msg = Types.CallMessage(_data);
envelope = Types.XCallEnvelope(
Types.CALL_MESSAGE_TYPE,
_msg.data,
sources,
destinations
);
} else {

Types.CallMessageWithRollback memory _msg = Types.CallMessageWithRollback(
_data,
_rollback
Types.CALL_MESSAGE_TYPE,
_msg.data,
sources,
destinations
);
} else {
Types.CallMessageWithRollback memory _msg = Types
.CallMessageWithRollback(_data, _rollback);

envelope = Types.XCallEnvelope(
Types.CALL_MESSAGE_ROLLBACK_TYPE,
_msg.encodeCallMessageWithRollback(),
sources,
destinations
);

Types.CALL_MESSAGE_ROLLBACK_TYPE,
_msg.encodeCallMessageWithRollback(),
sources,
destinations
);
}

return sendCall(_to, envelope.encodeXCallEnvelope());
Expand All @@ -290,20 +283,34 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
else if (
req.messageType == Types.CALL_MESSAGE_ROLLBACK_TYPE
) {
int256 code = tryExecuteCall(_reqId, req.to, req.from, _data, protocols);
replyState = req;
int256 code = tryExecuteCall(
_reqId,
req.to,
req.from,
_data,
protocols
);
delete replyState;

bytes memory message;
if (callReply.length > 0 && code == Types.CS_RESP_SUCCESS) {
message = callReply;
delete callReply;

Check warning on line 299 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L298-L299

Added lines #L298 - L299 were not covered by tests
}
Types.CSMessageResult memory response = Types.CSMessageResult(
req.sn,
code
code,
message
);

sendMessage(
protocols,
req.from.nid(),
Types.CS_RESULT,
int256(req.sn)*-1,
int256(req.sn) * -1,
response.encodeCSMessageResult()
);
);
} else {
revert("Message type is not yet supported");

Check warning on line 315 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L315

Added line #L315 was not covered by tests
}
Expand Down Expand Up @@ -411,7 +418,10 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
}

function handleError(uint256 _sn) public override {
handleResult(Types.CSMessageResult(_sn, Types.CS_RESP_FAILURE));
handleResult(
Types.CSMessageResult(_sn, Types.CS_RESP_FAILURE, bytes(""))
);

}

function sendToConnection(
Expand All @@ -436,8 +446,8 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
) internal {
Types.CSMessageRequest memory req = msgPayload.decodeCSMessageRequest();
string memory fromNID = req.from.nid();
require(netFrom.compareTo(fromNID),"Invalid NID");

require(netFrom.compareTo(fromNID), "Invalid NID");
bytes32 dataHash = keccak256(req.data);
if (req.protocols.length > 1) {
pendingReqs[dataHash][msg.sender.toString()] = true;
Expand All @@ -450,7 +460,10 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
delete pendingReqs[dataHash][req.protocols[i]];
}
} else if (req.protocols.length == 1) {
require(msg.sender == req.protocols[0].parseAddress("IllegalArgument"), "NotAuthorized");
require(
msg.sender == req.protocols[0].parseAddress("IllegalArgument"),
"NotAuthorized"
);
} else {
require(msg.sender == defaultConnections[fromNID], "NotAuthorized");
}
Expand All @@ -468,40 +481,71 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
emit CallMessage(req.from, req.to, req.sn, reqId, req.data);
}

function handleResult(Types.CSMessageResult memory res) internal {
Types.RollbackData memory req = rollbacks[res.sn];
function handleReply(
Types.RollbackData memory rollback,
Types.CSMessageRequest memory reply
) internal {
require(
keccak256(bytes(rollback.to)) ==
keccak256(bytes(reply.from.nid())),
"Invalid Reply"
);

uint256 reqId = getNextReqId();

require(req.from != address(0), "CallRequestNotFound");
emit CallMessage(reply.from, reply.to, reply.sn, reqId, reply.data);

if (req.sources.length > 1) {
proxyReqs[reqId] = Types.ProxyRequest(
reply.from,
reply.to,
reply.sn,
reply.messageType,
keccak256(reply.data),
rollback.sources
);
}

function handleResult(Types.CSMessageResult memory res) internal {
Types.RollbackData memory rollback = rollbacks[res.sn];
require(rollback.from != address(0), "CallRequestNotFound");

if (rollback.sources.length > 1) {
pendingResponses[res.sn][msg.sender.toString()] = true;
for (uint i = 0; i < req.sources.length; i++) {
if (!pendingResponses[res.sn][req.sources[i]]) {
for (uint i = 0; i < rollback.sources.length; i++) {
if (!pendingResponses[res.sn][rollback.sources[i]]) {
return;
}
}

for (uint i = 0; i < req.sources.length; i++) {
delete pendingResponses[res.sn][req.sources[i]];
for (uint i = 0; i < rollback.sources.length; i++) {
delete pendingResponses[res.sn][rollback.sources[i]];
}
} else if (req.sources.length == 1) {
} else if (rollback.sources.length == 1) {
require(
msg.sender == req.sources[0].parseAddress("IllegalArgument"),
msg.sender ==
rollback.sources[0].parseAddress("IllegalArgument"),
"NotAuthorized"
);
} else {
require(msg.sender == defaultConnections[req.to], "NotAuthorized");
require(
msg.sender == defaultConnections[rollback.to],
"NotAuthorized"
);
}

emit ResponseMessage(res.sn, res.code);
if (res.code == Types.CS_RESP_SUCCESS) {
cleanupCallRequest(res.sn);
if (res.message.length > 0) {
handleReply(rollback, res.message.decodeCSMessageRequest());
}
successfulResponses[res.sn] = true;
} else {
//emit rollback event
require(req.rollback.length > 0, "NoRollbackData");
req.enabled = true;
rollbacks[res.sn] = req;
require(rollback.rollback.length > 0, "NoRollbackData");
rollback.enabled = true;
rollbacks[res.sn] = rollback;

emit RollbackMessage(res.sn);
}
}
Expand Down Expand Up @@ -592,6 +636,9 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
string[] memory _sources
) external view override returns (uint256) {
uint256 fee = protocolFee;
if (isReply(_net, _sources) && !_rollback) {
return fee;

Check warning on line 640 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L639-L640

Added lines #L639 - L640 were not covered by tests
}
for (uint i = 0; i < _sources.length; i++) {
address conn = _sources[i].parseAddress("IllegalArgument");
fee = fee + _getFee(conn, _net, _rollback);
Expand All @@ -600,6 +647,36 @@ contract CallService is IBSH, ICallService, IFeeManage, Initializable {
return fee;
}

function isReply(
string memory _net,
string[] memory _sources
) internal view returns (bool) {
if (keccak256(bytes(replyState.from)) != keccak256(bytes(""))) {
return
keccak256(bytes(replyState.from.nid())) ==
keccak256(bytes(_net)) &&
areArraysEqual(replyState.protocols, _sources);

Check warning on line 658 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L655-L658

Added lines #L655 - L658 were not covered by tests
}
return false;
}

function areArraysEqual(
string[] memory array1,
string[] memory array2
) internal pure returns (bool) {
if (array1.length != array2.length) {
return false;

Check warning on line 668 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L667-L668

Added lines #L667 - L668 were not covered by tests
}

for (uint256 i = 0; i < array1.length; i++) {
if (keccak256(bytes(array1[i])) != keccak256(bytes(array2[i]))) {
return false;

Check warning on line 673 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L671-L673

Added lines #L671 - L673 were not covered by tests
}
}

return true;

Check warning on line 677 in contracts/evm/contracts/xcall/CallService.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/xcall/CallService.sol#L677

Added line #L677 was not covered by tests
}

function verifySuccess(uint256 _sn) external view returns (bool) {
return successfulResponses[_sn];
}
Expand Down
Loading

0 comments on commit fa211ca

Please sign in to comment.