Skip to content

Commit a7af666

Browse files
AntonAndellizyak
andauthored
feat: add IBC prefix for ics-08 clients and bugfixes (#826)
* feat: Add revision number to light client heights Add revision number but for now do not add support for resseting chain height * revert to using two clients * feat: add IBC prefix for ics-08 clients and bugfixes * fix: hash ack value before sending to verify membership for ics8 client --------- Co-authored-by: izyak <lbackup887@gmail.com>
1 parent 7d0585a commit a7af666

File tree

8 files changed

+231
-8
lines changed

8 files changed

+231
-8
lines changed

contracts/javascore/ibc/src/intTest/java/ibc/core/integration/IBCIntegrationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void setup() throws Exception {
6464
@Test
6565
@Order(0)
6666
void registerClient() {
67-
getClientInterface(owner).registerClient(clientType, mockLightClient._address());
67+
getClientInterface(owner).registerClient(clientType, mockLightClient._address(), 0);
6868
}
6969

7070
@Test

contracts/javascore/ibc/src/main/java/ibc/ics03/connection/IBCConnection.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package ibc.ics03.connection;
22

33
import java.math.BigInteger;
4-
import java.util.Arrays;
54
import java.util.List;
65

76
import icon.proto.core.client.Height;
87
import icon.proto.core.connection.ConnectionEnd;
98
import icon.proto.core.connection.Counterparty;
109
import icon.proto.core.connection.Version;
10+
import ibc.core.commitment.v1.MerklePrefix;
1111
import ibc.icon.score.util.ByteUtil;
1212
import ibc.icon.score.util.Logger;
1313
import ibc.ics02.client.IBCClient;
1414
import ibc.ics24.host.IBCCommitment;
15+
import ibc.ics24.host.IBCHost;
1516
import icon.ibc.interfaces.ILightClient;
1617
import icon.ibc.structs.messages.MsgConnectionOpenAck;
1718
import icon.ibc.structs.messages.MsgConnectionOpenConfirm;
@@ -24,6 +25,12 @@ public class IBCConnection extends IBCClient {
2425
public static final String v1Identifier = "1";
2526
public static final List<String> supportedV1Features = List.of("ORDER_ORDERED", "ORDER_UNORDERED");
2627

28+
public static final MerklePrefix ICS08PREFIX = new MerklePrefix();
29+
static {
30+
ICS08PREFIX.setKeyPrefix("ibc".getBytes());
31+
32+
}
33+
2734
Logger logger = new Logger("ibc-core");
2835

2936
public String _connectionOpenInit(MsgConnectionOpenInit msg) {
@@ -67,6 +74,9 @@ public String _connectionOpenTry(MsgConnectionOpenTry msg) {
6774
Counterparty expectedCounterparty = new Counterparty();
6875
expectedCounterparty.setClientId(msg.getClientId());
6976
expectedCounterparty.setConnectionId("");
77+
if (IBCCommitment.getHashType(msg.getClientId()) == IBCHost.HashType.ICS08.type) {
78+
expectedCounterparty.setPrefix(ICS08PREFIX);
79+
}
7080

7181
ConnectionEnd expectedConnection = new ConnectionEnd();
7282
expectedConnection.setClientId(counterparty.getClientId());
@@ -108,6 +118,9 @@ public byte[] _connectionOpenAck(MsgConnectionOpenAck msg) {
108118
Counterparty expectedCounterparty = new Counterparty();
109119
expectedCounterparty.setClientId(connection.getClientId());
110120
expectedCounterparty.setConnectionId(msg.getConnectionId());
121+
if (IBCCommitment.getHashType(connection.getClientId()) == IBCHost.HashType.ICS08.type) {
122+
expectedCounterparty.setPrefix(ICS08PREFIX);
123+
}
111124

112125
ConnectionEnd expectedConnection = new ConnectionEnd();
113126
expectedConnection.setClientId(connection.getCounterparty().getClientId());
@@ -150,6 +163,9 @@ public byte[] _connectionOpenConfirm(MsgConnectionOpenConfirm msg) {
150163
Counterparty expectedCounterparty = new Counterparty();
151164
expectedCounterparty.setClientId(connection.getClientId());
152165
expectedCounterparty.setConnectionId(msg.getConnectionId());
166+
if (IBCCommitment.getHashType(connection.getClientId()) == IBCHost.HashType.ICS08.type) {
167+
expectedCounterparty.setPrefix(ICS08PREFIX);
168+
}
153169

154170
ConnectionEnd expectedConnection = new ConnectionEnd();
155171
expectedConnection.setClientId(connection.getCounterparty().getClientId());

contracts/javascore/ibc/src/main/java/ibc/ics04/channel/IBCPacket.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,13 @@ public void _acknowledgePacket(Packet packet, byte[] acknowledgement, byte[] pro
181181

182182
byte[] packetAckPath = IBCCommitment.packetAcknowledgementCommitmentPath(packet.getDestinationPort(),
183183
packet.getDestinationChannel(), packet.getSequence());
184+
byte[] commitmentBytes = createAcknowledgmentCommitmentBytes(connection.getClientId(), acknowledgement);
184185
verifyPacketAcknowledgement(
185186
connection,
186187
proofHeight,
187188
proof,
188189
packetAckPath,
189-
acknowledgement);
190+
commitmentBytes);
190191

191192
if (channel.getOrdering() == Channel.Order.ORDER_ORDERED) {
192193
DictDB<String, BigInteger> nextSequenceAckSourcePort = nextSequenceAcknowledgements

contracts/javascore/ibc/src/main/java/ibc/ics23/commitment/types/Merkle.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class Merkle {
2020
Proof.getTendermintSpec()
2121
);
2222

23-
public static MerklePath applyPrefix(String path, String prefix) {
23+
public static MerklePath applyPrefix(String prefix, String path) {
2424
var mpath = new MerklePath();
2525
List<String> keyPath = new ArrayList<>();
2626
keyPath.add(prefix);

contracts/javascore/lightclients/ics-08-tendermint/src/main/java/ibc/ics08/tendermint/TendermintHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static BigInteger getTotalVotingPower(ValidatorSet validatorSet) {
5858
}
5959

6060
public static BigInteger getRevisionNumber(String chainId) {
61-
int id = chainId.indexOf("-");
61+
int id = chainId.lastIndexOf("-");
6262
if (id >= 0) {
6363
return new BigInteger(chainId.substring(id+1));
6464
}

contracts/javascore/lightclients/tendermint/src/main/java/ibc/tendermint/TendermintLightClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public void verifyMembership(
213213

214214
var root = consensusState.getRoot();
215215
var merkleProof = MerkleProof.decode(proof);
216-
var merklePath = applyPrefix(new String(path), StringUtil.bytesToHex("wasm".getBytes()));
216+
var merklePath = applyPrefix(StringUtil.bytesToHex("wasm".getBytes()), new String(path));
217217

218218
Merkle.verifyMembership(merkleProof, Merkle.SDK_SPEC, root, merklePath, value);
219219
}
@@ -240,7 +240,7 @@ public void verifyNonMembership(
240240

241241
var root = consensusState.getRoot();
242242
var merkleProof = MerkleProof.decode(proof);
243-
var merklePath = applyPrefix(new String(path), StringUtil.bytesToHex("wasm".getBytes()));
243+
var merklePath = applyPrefix(StringUtil.bytesToHex("wasm".getBytes()), new String(path));
244244

245245
Merkle.verifyNonMembership(merkleProof, Merkle.SDK_SPEC, root, merklePath);
246246
}

contracts/javascore/score-util/src/main/java/ibc/icon/score/util/Proto.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public static byte[] encodeBooleanArray(int order, List<Boolean> items) {
170170
}
171171

172172
public static byte[] encode(int order, Boolean item) {
173-
if (item == null) {
173+
if (item == null || item == false) {
174174
return new byte[0];
175175
}
176176

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
syntax = "proto3";
2+
package tendermint.light;
3+
4+
option go_package = "libraries/go/common/tendermint;tendermint";
5+
import "gogoproto/gogo.proto";
6+
7+
message Fraction {
8+
uint64 numerator = 1;
9+
uint64 denominator = 2;
10+
}
11+
12+
// https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp
13+
message Duration {
14+
int64 seconds = 1;
15+
int32 nanos = 2;
16+
}
17+
18+
message Consensus {
19+
uint64 block = 1;
20+
uint64 app = 2;
21+
}
22+
23+
message ClientState {
24+
option (gogoproto.goproto_getters) = false;
25+
26+
string chain_id = 1;
27+
Fraction trust_level = 2;
28+
29+
// duration of the period since the LastestTimestamp during which the
30+
// submitted headers are valid for upgrade
31+
Duration trusting_period = 3;
32+
// duration of the staking unbonding period
33+
Duration unbonding_period = 4;
34+
// defines how much new (untrusted) header's Time can drift into the future.
35+
Duration max_clock_drift = 5;
36+
// Block height when the client was frozen due to a misbehaviour
37+
//ibc.core.client.v1.Height frozen_height = 6;
38+
int64 frozen_height = 6;
39+
// Latest height the client was updated to
40+
int64 latest_height = 7;
41+
// This flag, when set to true, will allow governance to recover a client
42+
// which has expired
43+
bool allow_update_after_expiry = 8;
44+
// This flag, when set to true, will allow governance to unfreeze a client
45+
// whose chain has experienced a misbehaviour event
46+
bool allow_update_after_misbehaviour = 9;
47+
}
48+
49+
// ConsensusState defines the consensus state from Tendermint.
50+
message ConsensusState {
51+
option (gogoproto.goproto_getters) = false;
52+
// timestamp that corresponds to the block height in which the ConsensusState
53+
// was stored.
54+
Timestamp timestamp = 1;
55+
56+
// commitment root (i.e app hash)
57+
MerkleRoot root = 2;
58+
bytes next_validators_hash = 3;
59+
}
60+
61+
// MerkleRoot defines a merkle root hash.
62+
// In the Cosmos SDK, the AppHash of a block header becomes the root.
63+
message MerkleRoot {
64+
bytes hash = 1;
65+
}
66+
67+
enum BlockIDFlag {
68+
BLOCK_ID_FLAG_UNKNOWN = 0;
69+
BLOCK_ID_FLAG_ABSENT = 1;
70+
BLOCK_ID_FLAG_COMMIT = 2;
71+
BLOCK_ID_FLAG_NIL = 3;
72+
}
73+
74+
enum SignedMsgType {
75+
SIGNED_MSG_TYPE_UNKNOWN = 0;
76+
// Votes
77+
SIGNED_MSG_TYPE_PREVOTE = 1;
78+
SIGNED_MSG_TYPE_PRECOMMIT = 2;
79+
80+
// Proposals
81+
SIGNED_MSG_TYPE_PROPOSAL = 32;
82+
}
83+
84+
message CanonicalPartSetHeader {
85+
uint32 total = 1;
86+
bytes hash = 2;
87+
}
88+
89+
message CanonicalBlockID {
90+
bytes hash = 1;
91+
CanonicalPartSetHeader part_set_header = 2;
92+
}
93+
94+
message CanonicalVote {
95+
SignedMsgType type = 1;
96+
sfixed64 height = 2;
97+
sfixed64 round = 3;
98+
BlockID block_id = 4;
99+
Timestamp timestamp = 5;
100+
string chain_id = 6;
101+
}
102+
103+
message Vote {
104+
SignedMsgType type = 1;
105+
int64 height = 2;
106+
int32 round = 3;
107+
BlockID block_id = 4;
108+
Timestamp timestamp = 5;
109+
bytes validator_address = 6;
110+
int32 validator_index = 7;
111+
bytes signature = 8;
112+
}
113+
114+
message ValidatorSet {
115+
repeated Validator validators = 1;
116+
Validator proposer = 2;
117+
int64 total_voting_power = 3;
118+
}
119+
120+
message Validator {
121+
bytes address = 1;
122+
PublicKey pub_key = 2;
123+
int64 voting_power = 3;
124+
int64 proposer_priority = 4;
125+
}
126+
127+
message SimpleValidator {
128+
PublicKey pub_key = 1;
129+
int64 voting_power = 2;
130+
}
131+
132+
message PublicKey {
133+
oneof sum {
134+
bytes ed25519 = 1;
135+
bytes secp256k1 = 2;
136+
bytes sr25519 = 3;
137+
}
138+
}
139+
140+
message PartSetHeader {
141+
uint32 total = 1;
142+
bytes hash= 2;
143+
}
144+
145+
message BlockID {
146+
bytes hash = 1;
147+
PartSetHeader part_set_header = 2;
148+
}
149+
150+
message Commit {
151+
int64 height = 1;
152+
int32 round = 2;
153+
BlockID block_id = 3;
154+
repeated CommitSig signatures = 4;
155+
}
156+
157+
// CommitSig is a part of the Vote included in a Commit.
158+
message CommitSig {
159+
BlockIDFlag block_id_flag = 1;
160+
bytes validator_address = 2;
161+
Timestamp timestamp = 3;
162+
bytes signature = 4;
163+
}
164+
165+
message Timestamp {
166+
// Represents seconds of UTC time since Unix epoch
167+
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
168+
// 9999-12-31T23:59:59Z inclusive.
169+
int64 seconds = 1;
170+
171+
// Non-negative fractions of a second at nanosecond resolution. Negative
172+
// second values with fractions must still have non-negative nanos values
173+
// that count forward in time. Must be from 0 to 999,999,999
174+
// inclusive.
175+
int32 nanos = 2;
176+
}
177+
178+
message LightHeader {
179+
Consensus version = 1;
180+
string chain_id = 2;
181+
int64 height = 3;
182+
Timestamp time = 4;
183+
BlockID last_block_id = 5;
184+
bytes last_commit_hash = 6; // commit from validators from the last block
185+
bytes data_hash = 7; // transactions
186+
bytes validators_hash = 8; // validators for the current block
187+
bytes next_validators_hash = 9; // validators for the next block
188+
bytes consensus_hash = 10; // consensus params for current block
189+
bytes app_hash = 11; // state after txs from the previous block
190+
bytes last_results_hash = 12; // root hash of all results from the txs from the previous block
191+
bytes evidence_hash = 13; // evidence included in the block
192+
bytes proposer_address = 14; // original proposer of the block
193+
}
194+
195+
message SignedHeader {
196+
LightHeader header = 1;
197+
Commit commit = 2;
198+
}
199+
200+
message TmHeader {
201+
SignedHeader signed_header = 1;
202+
ValidatorSet validator_set = 2;
203+
204+
int64 trusted_height = 3;
205+
ValidatorSet trusted_validators = 4;
206+
}

0 commit comments

Comments
 (0)