-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: IIBC-26-javascore-xcall-contract-code-update (#166)
* update build.gradle to implement IBC project * update settings.gradle to implement use xCall * move and update xCall service for IBC * add xCall readme * move and update xCall service for IBC * update xCall to support IBC messages on HandleBTPMessage * remove tests for now * feat(javascore): implement IBCModule on xCall app (#228) * feat(javascore): implement IBCModule on xCall app * feat: IIBC-26-javascore-xcall-contract-code-update-review (#286) * remove commented test files * remove commented lines for ```checkService``` * set destinationChannel from counterPartyChannelId * use sequenceNumber from IBCHandler for IBC specific sequence number for IBC Message. * remove order for ```setTimeoutHeight_unauthorized()``` as they are tested on separate deployments * remove order as they are tested on separate deployments --------- Co-authored-by: redlarva <[email protected]> Co-authored-by: Night Owl <[email protected]>
- Loading branch information
1 parent
db12f58
commit c0c063d
Showing
21 changed files
with
2,158 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
contracts/javascore/lib/src/main/java/ibc/icon/interfaces/ICallServiceReceiver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright 2022 ICON Foundation | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package ibc.icon.interfaces; | ||
|
||
import foundation.icon.score.client.ScoreInterface; | ||
import score.annotation.External; | ||
|
||
@ScoreInterface | ||
public interface ICallServiceReceiver { | ||
|
||
/** | ||
* Handles the call message received from the source chain. | ||
* Only called from the Call Message Service. | ||
* | ||
* @param _from The BTP address of the caller on the source chain | ||
* @param _data The calldata delivered from the caller | ||
*/ | ||
@External | ||
void handleCallMessage(String _from, byte[] _data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
version = '0.1.0' | ||
|
||
dependencies { | ||
implementation project(':lib') | ||
implementation project(':score-util') | ||
} | ||
|
||
tasks.named('compileJava') { | ||
dependsOn(':score-util:jar') | ||
dependsOn(':lib:jar') | ||
} | ||
|
||
optimizedJar { | ||
dependsOn(project(':lib').jar) | ||
dependsOn(project(':score-util').jar) | ||
|
||
mainClassName = 'ibc.mockapp.MockDApp' | ||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE | ||
from { | ||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } | ||
} | ||
} | ||
|
||
deployJar { | ||
endpoints { | ||
berlin { | ||
uri = 'https://berlin.net.solidwallet.io/api/v3' | ||
nid = 0x7 | ||
} | ||
lisbon { | ||
uri = 'https://lisbon.net.solidwallet.io/api/v3' | ||
nid = 0x2 | ||
} | ||
local { | ||
uri = 'http://localhost:9082/api/v3' | ||
nid = 0x3 | ||
} | ||
} | ||
keystore = rootProject.hasProperty('keystoreName') ? "$keystoreName" : '' | ||
password = rootProject.hasProperty('keystorePass') ? "$keystorePass" : '' | ||
parameters { | ||
arg('_callService', 'hxb6b5791be0b5ef67063b3c10b840fb81514db2fd') | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
contracts/javascore/modules/mock-dapp/src/main/java/ibc/mockapp/MockDApp.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright 2022 ICON Foundation | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package ibc.mockapp; | ||
|
||
import ibc.icon.interfaces.ICallServiceReceiver; | ||
import java.math.BigInteger; | ||
import score.Address; | ||
import score.Context; | ||
import score.DictDB; | ||
import score.UserRevertedException; | ||
import score.VarDB; | ||
import score.annotation.EventLog; | ||
import score.annotation.External; | ||
import score.annotation.Optional; | ||
import score.annotation.Payable; | ||
|
||
|
||
public class MockDApp implements ICallServiceReceiver { | ||
private final Address callSvc; | ||
private final VarDB<BigInteger> id = Context.newVarDB("id", BigInteger.class); | ||
private final DictDB<BigInteger, RollbackData> rollbacks = Context.newDictDB("rollbacks", RollbackData.class); | ||
|
||
public MockDApp(Address _callService) { | ||
this.callSvc = _callService; | ||
} | ||
|
||
private void onlyCallService() { | ||
Context.require(Context.getCaller().equals(this.callSvc), "onlyCallService"); | ||
} | ||
|
||
private BigInteger getNextId() { | ||
BigInteger _id = this.id.getOrDefault(BigInteger.ZERO); | ||
_id = _id.add(BigInteger.ONE); | ||
this.id.set(_id); | ||
return _id; | ||
} | ||
|
||
@Payable | ||
@External | ||
public void sendMessage(String _to, byte[] _data, @Optional byte[] _rollback) { | ||
if (_rollback != null) { | ||
// The code below is not actually necessary because the _rollback data is stored on the xCall side, | ||
// but in this example, it is needed for testing to compare the _rollback data later. | ||
var id = getNextId(); | ||
Context.println("DAppProxy: store rollback data with id=" + id); | ||
RollbackData rbData = new RollbackData(id, _rollback); | ||
var ssn = _sendCallMessage(Context.getValue(), _to, _data, rbData.toBytes()); | ||
rbData.setSvcSn(ssn); | ||
rollbacks.set(id, rbData); | ||
} else { | ||
// This is for one-way message | ||
_sendCallMessage(Context.getValue(), _to, _data, null); | ||
} | ||
} | ||
|
||
private BigInteger _sendCallMessage(BigInteger value, String to, byte[] data, byte[] rollback) { | ||
try { | ||
return Context.call(BigInteger.class, value, this.callSvc, "sendCallMessage", to, data, rollback); | ||
} catch (UserRevertedException e) { | ||
// propagate the error code to the caller | ||
Context.revert(e.getCode(), "UserReverted"); | ||
return BigInteger.ZERO; // call flow does not reach here, but make compiler happy | ||
} | ||
} | ||
|
||
@External | ||
public void handleCallMessage(String _from, byte[] _data) { | ||
onlyCallService(); | ||
Context.println("handleCallMessage: from=" + _from + ", data=" + new String(_data)); | ||
if (Context.getAddress().equals(Address.fromString(_from))) { | ||
// handle rollback data here | ||
// In this example, just compare it with the stored one. | ||
RollbackData received = RollbackData.fromBytes(_data); | ||
var id = received.getId(); | ||
RollbackData stored = rollbacks.get(id); | ||
Context.require(stored != null, "invalid received id"); | ||
Context.require(received.equals(stored), "rollbackData mismatch"); | ||
rollbacks.set(id, null); // cleanup | ||
RollbackDataReceived(_from, stored.getSvcSn(), received.getRollback()); | ||
} else { | ||
// normal message delivery | ||
MessageReceived(_from, _data); | ||
} | ||
} | ||
|
||
@EventLog | ||
public void MessageReceived(String _from, byte[] _data) {} | ||
|
||
@EventLog | ||
public void RollbackDataReceived(String _from, BigInteger _ssn, byte[] _rollback) {} | ||
} |
103 changes: 103 additions & 0 deletions
103
contracts/javascore/modules/mock-dapp/src/main/java/ibc/mockapp/RollbackData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright 2022 ICON Foundation | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package ibc.mockapp; | ||
|
||
import java.math.BigInteger; | ||
import score.ByteArrayObjectWriter; | ||
import score.Context; | ||
import score.ObjectReader; | ||
import score.ObjectWriter; | ||
|
||
public class RollbackData { | ||
private final BigInteger id; | ||
private final byte[] rollback; | ||
private BigInteger ssn; | ||
|
||
public RollbackData(BigInteger id, byte[] rollback) { | ||
this.id = id; | ||
this.rollback = rollback; | ||
} | ||
|
||
public BigInteger getId() { | ||
return id; | ||
} | ||
|
||
public byte[] getRollback() { | ||
return rollback; | ||
} | ||
|
||
public BigInteger getSvcSn() { | ||
return ssn; | ||
} | ||
|
||
public void setSvcSn(BigInteger ssn) { | ||
this.ssn = ssn; | ||
} | ||
|
||
public static void writeObject(ObjectWriter w, RollbackData data) { | ||
w.beginList(3); | ||
w.write(data.id); | ||
w.write(data.rollback); | ||
w.writeNullable(data.ssn); | ||
w.end(); | ||
} | ||
|
||
public static RollbackData readObject(ObjectReader r) { | ||
r.beginList(); | ||
RollbackData rbData = new RollbackData( | ||
r.readBigInteger(), | ||
r.readByteArray() | ||
); | ||
rbData.setSvcSn(r.readNullable(BigInteger.class)); | ||
r.end(); | ||
return rbData; | ||
} | ||
|
||
public byte[] toBytes() { | ||
ByteArrayObjectWriter writer = Context.newByteArrayObjectWriter("RLPn"); | ||
writeObject(writer, this); | ||
return writer.toByteArray(); | ||
} | ||
|
||
public static RollbackData fromBytes(byte[] bytes) { | ||
ObjectReader reader = Context.newByteArrayObjectReader("RLPn", bytes); | ||
return readObject(reader); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} else if (!(obj instanceof RollbackData)) { | ||
return false; | ||
} else { | ||
RollbackData other = (RollbackData) obj; | ||
if (this.rollback == null || other.rollback == null) { | ||
return false; | ||
} | ||
if (this.rollback.length != other.rollback.length) { | ||
return false; | ||
} | ||
for (int i = 0; i < this.rollback.length; i++) { | ||
if (this.rollback[i] != other.rollback[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Arbitrary Call Service | ||
|
||
The reference implementation of the arbitrary call service (a.k.a. `xcall`) specification between ICON to ICON. | ||
|
||
## How to test | ||
|
||
Assuming the [gochain-local](https://github.com/icon-project/gochain-local) docker container is running, | ||
you can start integration testing with the following command. | ||
|
||
``` | ||
$ ./gradlew clean xcall:test -PintegrationTest=true \ | ||
-Pscore-test.default.keyStore=<path_to_god_wallet_json> -Pscore-test.default.keyPassword=gochain | ||
``` |
Oops, something went wrong.