Skip to content

Commit 9f0c64b

Browse files
committed
revert to using two clients
1 parent 649d24c commit 9f0c64b

File tree

303 files changed

+21554
-624
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

303 files changed

+21554
-624
lines changed

contracts/javascore/lightclients/ics-08-tendermint/build.gradle

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ dependencies {
77
implementation project(':score-util')
88
implementation project(':ibc')
99
implementation project(':proto-lib')
10-
implementation project(':tendermint')
1110

1211
testImplementation 'com.google.protobuf:protobuf-javalite:3.16.3'
1312
testImplementation 'com.google.protobuf:protobuf-java-util:3.16.3'
@@ -36,7 +35,7 @@ tasks.named('compileJava') {
3635
}
3736

3837
optimizedJar {
39-
mainClassName = 'ibc.tendermint.ICS08LightClient'
38+
mainClassName = 'ibc.ics08.tendermint.ICS08TendermintLightClient'
4039
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
4140
from {
4241
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }

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

+335
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
package ibc.ics08.tendermint;
2+
3+
import static ibc.ics08.tendermint.TendermintHelper.*;
4+
5+
import java.math.BigInteger;
6+
import java.util.Arrays;
7+
8+
import ibc.icon.score.util.Proto;
9+
import tendermint.types.*;
10+
import google.protobuf.*;
11+
import ibc.lightclients.tendermint.v1.*;
12+
import score.Context;
13+
14+
public abstract class Tendermint {
15+
protected boolean verify(
16+
Duration trustingPeriod,
17+
Duration maxClockDrift,
18+
Fraction trustLevel,
19+
SignedHeader trustedHeader,
20+
ValidatorSet trustedVals,
21+
SignedHeader untrustedHeader,
22+
ValidatorSet untrustedVals,
23+
Timestamp currentTime) {
24+
verifyNewHeaderAndVals(untrustedHeader, untrustedVals, trustedHeader, currentTime, maxClockDrift);
25+
26+
boolean isAdjacent = untrustedHeader.getHeader().getHeight()
27+
.equals(trustedHeader.getHeader().getHeight().add(BigInteger.ONE));
28+
if (isAdjacent) {
29+
return verifyAdjacent(trustedHeader, untrustedHeader, untrustedVals, trustingPeriod, currentTime,
30+
maxClockDrift);
31+
}
32+
33+
return verifyNonAdjacent(
34+
trustedHeader,
35+
trustedVals,
36+
untrustedHeader,
37+
untrustedVals,
38+
trustingPeriod,
39+
currentTime,
40+
maxClockDrift,
41+
trustLevel);
42+
43+
}
44+
45+
protected boolean verifyAdjacent(
46+
SignedHeader trustedHeader,
47+
SignedHeader untrustedHeader,
48+
ValidatorSet untrustedVals,
49+
Duration trustingPeriod,
50+
Timestamp currentTime,
51+
Duration maxClockDrift) {
52+
53+
// Check the validator hashes are the same
54+
Context.require(
55+
Arrays.equals(untrustedHeader.getHeader().getValidatorsHash(),
56+
trustedHeader.getHeader().getNextValidatorsHash()),
57+
"expected old header next validators to match those from new header");
58+
59+
// Ensure that +2/3 of new validators signed correctly.
60+
return verifyCommitLight(
61+
untrustedVals,
62+
trustedHeader.getHeader().getChainId(),
63+
untrustedHeader.getCommit().getBlockId(),
64+
untrustedHeader.getHeader().getHeight(),
65+
untrustedHeader.getCommit());
66+
67+
}
68+
69+
protected boolean verifyNonAdjacent(
70+
SignedHeader trustedHeader,
71+
ValidatorSet trustedVals,
72+
SignedHeader untrustedHeader,
73+
ValidatorSet untrustedVals,
74+
Duration trustingPeriod,
75+
Timestamp currentTime,
76+
Duration maxClockDrift,
77+
Fraction trustLevel) {
78+
79+
// assert that trustedVals is NextValidators of last trusted header
80+
// to do this, we check that trustedVals.Hash() == consState.NextValidatorsHash
81+
Context.require(Arrays.equals(hash(trustedVals), trustedHeader.getHeader().getNextValidatorsHash()),
82+
"LC: headers trusted validators does not hash to latest trusted validators");
83+
84+
// Ensure that +`trustLevel` (default 1/3) or more of last trusted validators
85+
// signed correctly.
86+
verifyCommitLightTrusting(trustedVals, trustedHeader.getHeader().getChainId(), untrustedHeader.getCommit(),
87+
trustLevel);
88+
89+
// Ensure that +2/3 of new validators signed correctly.
90+
return verifyCommitLight(
91+
untrustedVals,
92+
trustedHeader.getHeader().getChainId(),
93+
untrustedHeader.getCommit().getBlockId(),
94+
untrustedHeader.getHeader().getHeight(),
95+
untrustedHeader.getCommit());
96+
97+
}
98+
99+
protected void verifyNewHeaderAndVals(
100+
SignedHeader untrustedHeader,
101+
ValidatorSet untrustedVals,
102+
SignedHeader trustedHeader,
103+
Timestamp currentTime,
104+
Duration maxClockDrift) {
105+
// SignedHeader validate basic
106+
Context.require(untrustedHeader.getHeader().getChainId().equals(trustedHeader.getHeader().getChainId()),
107+
"header belongs to another chain");
108+
Context.require(untrustedHeader.getCommit().getHeight().equals(untrustedHeader.getHeader().getHeight()),
109+
"header and commit height mismatch");
110+
111+
byte[] untrustedHeaderBlockHash = hash(untrustedHeader.getHeader());
112+
Context.require(Arrays.equals(untrustedHeaderBlockHash, untrustedHeader.getCommit().getBlockId().getHash()),
113+
"commit signs signs block failed");
114+
115+
Context.require(untrustedHeader.getHeader().getHeight().compareTo(trustedHeader.getHeader().getHeight()) > 0,
116+
"expected new header height to be greater than one of old header");
117+
Context.require(
118+
gt(untrustedHeader.getHeader().getTime(), trustedHeader.getHeader().getTime()),
119+
"expected new header time to be after old header time");
120+
121+
Timestamp curentTimestamp = new Timestamp();
122+
curentTimestamp.setSeconds(currentTime.getSeconds().add(maxClockDrift.getSeconds()));
123+
curentTimestamp.setNanos(currentTime.getNanos().add(maxClockDrift.getNanos()));
124+
Context.require(gt(curentTimestamp, untrustedHeader.getHeader().getTime()),
125+
"new header has time from the future");
126+
127+
byte[] validatorsHash = hash(untrustedVals);
128+
Context.require(Arrays.equals(untrustedHeader.getHeader().getValidatorsHash(), validatorsHash),
129+
"expected new header validators to match those that were supplied at height XX");
130+
}
131+
132+
protected boolean verifyCommitLightTrusting(
133+
ValidatorSet trustedVals,
134+
String chainID,
135+
Commit commit,
136+
Fraction trustLevel) {
137+
BigInteger talliedVotingPower = BigInteger.ZERO;
138+
boolean[] seenVals = new boolean[trustedVals.getValidators().size()];
139+
140+
CommitSig commitSig;
141+
BigInteger totalVotingPowerMulByNumerator = getTotalVotingPower(trustedVals)
142+
.multiply(trustLevel.getNumerator());
143+
BigInteger votingPowerNeeded = totalVotingPowerMulByNumerator.divide(trustLevel.getDenominator());
144+
145+
int signaturesLength = commit.getSignatures().size();
146+
for (int idx = 0; idx < signaturesLength; idx++) {
147+
commitSig = commit.getSignatures().get(idx);
148+
149+
// no need to verify absent or nil votes.
150+
if (commitSig.getBlockIdFlag() != BlockIDFlag.BLOCK_ID_FLAG_COMMIT) {
151+
continue;
152+
}
153+
154+
// We don't know the validators that committed this block, so we have to
155+
// check for each vote if its validator is already known.
156+
int valIdx = getByAddress(trustedVals, commitSig.getValidatorAddress());
157+
if (valIdx == -1) {
158+
continue;
159+
}
160+
161+
// check for double vote of validator on the same commit
162+
Context.require(!seenVals[valIdx], "double vote of validator on the same commit");
163+
seenVals[valIdx] = true;
164+
165+
Validator val = trustedVals.getValidators().get(valIdx);
166+
167+
// validate signature
168+
byte[] message = voteSignBytesDelim(commit, chainID, idx);
169+
byte[] sig = commitSig.getSignature();
170+
171+
if (!verifySig(val, message, sig)) {
172+
return false;
173+
}
174+
175+
talliedVotingPower = talliedVotingPower.add(val.getVotingPower());
176+
177+
if (talliedVotingPower.compareTo(votingPowerNeeded) > 0) {
178+
return true;
179+
}
180+
181+
}
182+
183+
return false;
184+
}
185+
186+
// VerifyCommitLight verifies +2/3 of the set had signed the given commit.
187+
//
188+
// This method is primarily used by the light client and does not check all the
189+
// signatures.
190+
protected boolean verifyCommitLight(
191+
ValidatorSet validators,
192+
String chainID,
193+
BlockID blockID,
194+
BigInteger height,
195+
Commit commit) {
196+
Context.require(validators.getValidators().size() == commit.getSignatures().size(),
197+
"invalid commmit signatures");
198+
199+
Context.require(height.equals(commit.getHeight()), "invalid commit height");
200+
201+
Context.require(commit.getBlockId().equals(blockID), "invalid commit -- wrong block ID");
202+
Validator val;
203+
CommitSig commitSig;
204+
205+
BigInteger talliedVotingPower = BigInteger.ZERO;
206+
BigInteger votingPowerNeeded = getTotalVotingPower(validators).multiply(BigInteger.TWO)
207+
.divide(BigInteger.valueOf(3));
208+
209+
int signaturesLength = commit.getSignatures().size();
210+
for (int i = 0; i < signaturesLength; i++) {
211+
commitSig = commit.getSignatures().get(i);
212+
213+
// no need to verify absent or nil votes.
214+
if (commitSig.getBlockIdFlag() != BlockIDFlag.BLOCK_ID_FLAG_COMMIT) {
215+
continue;
216+
}
217+
218+
val = validators.getValidators().get(i);
219+
220+
byte[] message = voteSignBytesDelim(commit, chainID, i);
221+
byte[] sig = commitSig.getSignature();
222+
223+
if (!verifySig(val, message, sig)) {
224+
return false;
225+
}
226+
227+
talliedVotingPower = talliedVotingPower.add(val.getVotingPower());
228+
229+
if (talliedVotingPower.compareTo(votingPowerNeeded) > 0) {
230+
return true;
231+
}
232+
}
233+
234+
return false;
235+
}
236+
237+
public boolean verifySig(
238+
Validator val,
239+
byte[] message,
240+
byte[] sig) {
241+
if (val.getPubKey().getEd25519() != null) {
242+
return verifySig("ed25519", message, sig, val.getPubKey().getEd25519());
243+
} else {
244+
return verifySig("ecdsa-secp256k1", message, sig, val.getPubKey().getSecp256k1());
245+
}
246+
}
247+
248+
public boolean verifySig(
249+
String alg,
250+
byte[] message,
251+
byte[] sig,
252+
byte[] pubKey) {
253+
return Context.verifySignature(alg, message, sig, pubKey);
254+
}
255+
256+
protected byte[] voteSignBytes(
257+
Commit commit,
258+
String chainID,
259+
int idx) {
260+
261+
return toCanonicalVote(commit, idx, chainID);
262+
}
263+
264+
protected byte[] voteSignBytesDelim(
265+
Commit commit,
266+
String chainID,
267+
int idx) {
268+
return Proto.encodeDelim(voteSignBytes(commit, chainID, idx));
269+
}
270+
}

0 commit comments

Comments
 (0)