Skip to content

Commit 4046946

Browse files
committed
feat: first working impl.
1 parent 041540c commit 4046946

File tree

8 files changed

+738
-42
lines changed

8 files changed

+738
-42
lines changed

local-tests/setup/networkContext.json

Lines changed: 570 additions & 1 deletion
Large diffs are not rendered by default.

local-tests/setup/tinny-config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export interface ProcessEnvs {
2323
*/
2424
NETWORK: LIT_NETWORK_VALUES;
2525

26+
NETWORK_TYPE: 'mainnet' | 'cloneNet';
27+
2628
/**
2729
* The number of milliseconds to wait between each request.
2830
*/

local-tests/setup/tinny-environment.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class TinnyEnvironment {
3636
DEBUG: process.env['DEBUG'] === 'true',
3737
REQUEST_PER_KILOSECOND:
3838
parseInt(process.env['REQUEST_PER_KILOSECOND']) ||
39-
(process.env['NETWORK'] as LIT_NETWORK_VALUES) === 'datil-dev'
39+
(process.env['NETWORK'] as LIT_NETWORK_VALUES) === 'datil-dev'
4040
? 1
4141
: 200,
4242
LIT_RPC_URL: process.env['LIT_RPC_URL'],
@@ -50,6 +50,7 @@ export class TinnyEnvironment {
5050
TIME_TO_RELEASE_KEY: parseInt(process.env['TIME_TO_RELEASE_KEY']) || 10000,
5151
RUN_IN_BAND: process.env['RUN_IN_BAND'] === 'true',
5252
RUN_IN_BAND_INTERVAL: parseInt(process.env['RUN_IN_BAND_INTERVAL']) || 5000,
53+
NETWORK_TYPE: (process.env['NETWORK_TYPE'] || 'mainnet') as 'mainnet' | 'cloneNet',
5354

5455
// Available Accounts
5556
// ==================
@@ -242,18 +243,21 @@ export class TinnyEnvironment {
242243
debug: this.processEnvs.DEBUG,
243244
checkNodeAttestation: false, // disable node attestation check for local testing
244245
contractContext: networkContext,
246+
networkType: this.processEnvs.NETWORK_TYPE || 'mainnet',
245247
});
246248
} else if (centralisation === 'decentralised') {
247249
this.litNodeClient = new LitNodeClient({
248250
litNetwork: this.network,
249251
checkNodeAttestation: true,
250252
debug: this.processEnvs.DEBUG,
253+
networkType: this.processEnvs.NETWORK_TYPE || 'mainnet',
251254
});
252255
} else if (centralisation === 'centralised') {
253256
this.litNodeClient = new LitNodeClient({
254257
litNetwork: this.network,
255258
checkNodeAttestation: false,
256259
debug: this.processEnvs.DEBUG,
260+
networkType: this.processEnvs.NETWORK_TYPE || 'mainnet',
257261
});
258262
} else {
259263
throw new Error(`Network not supported: "${this.network}"`);

packages/contracts-sdk/src/lib/contracts-sdk.ts

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
EpochInfo,
77
GasLimitParam,
88
LIT_NETWORKS_KEYS,
9+
LitContract,
910
LitContractContext,
1011
LitContractResolverContext,
1112
MintCapacityCreditsContext,
@@ -636,7 +637,8 @@ export class LitContracts {
636637
network: LIT_NETWORKS_KEYS,
637638
contractName: string,
638639
context?: LitContractContext | LitContractResolverContext,
639-
rpcUrl?: string
640+
rpcUrl?: string,
641+
contractAddress?: string,
640642
): Promise<T> {
641643
let provider: ethers.providers.StaticJsonRpcProvider;
642644

@@ -692,7 +694,7 @@ export class LitContracts {
692694
}
693695

694696
return new ethers.Contract(
695-
contractContext.address,
697+
contractAddress || contractContext.address,
696698
contractContext.abi,
697699
provider
698700
) as T;
@@ -722,7 +724,7 @@ export class LitContracts {
722724
)?.contracts?.[0]?.ABI;
723725

724726
return new ethers.Contract(
725-
resolvedContract.address,
727+
contractAddress || resolvedContract.address,
726728
resolvedContract.abi ?? contractABI,
727729
provider
728730
) as T;
@@ -1064,6 +1066,109 @@ export class LitContracts {
10641066
return networks;
10651067
};
10661068

1069+
public static async _getAllActiveUnkickedValidatorStructsAndCounts(
1070+
network: LIT_NETWORKS_KEYS,
1071+
context?: LitContractContext | LitContractResolverContext,
1072+
rpcUrl?: string,
1073+
nodeProtocol?: typeof HTTP | typeof HTTPS | null,
1074+
) {
1075+
1076+
const cloneNetContract = await LitContracts.getContractInstance(
1077+
network,
1078+
'CloneNet',
1079+
context,
1080+
rpcUrl
1081+
);
1082+
1083+
// First get all the active staking contract addresses.
1084+
const activeStakingContractAddresses = await cloneNetContract['getActiveStakingContracts']();
1085+
1086+
// Then, for each active staking contract, get the epoch, current validator count, and active unkicked validator structs.
1087+
const stakingAggregateDetails = [];
1088+
1089+
for (let i = 0; i < activeStakingContractAddresses.length; i++) {
1090+
const stakingContractAddress = activeStakingContractAddresses[i];
1091+
1092+
const stakingContract = await LitContracts.getContractInstance(
1093+
network,
1094+
'Staking',
1095+
context,
1096+
rpcUrl,
1097+
stakingContractAddress
1098+
);
1099+
1100+
console.log("stakingContract.address:", stakingContract.address);
1101+
1102+
// Get the epoch, current validator count, and active unkicked validator structs.
1103+
const [epochInfo, minNodeCount, activeUnkickedValidatorStructs] =
1104+
await stakingContract['getActiveUnkickedValidatorStructsAndCounts']();
1105+
1106+
const typedEpochInfo: EpochInfo = {
1107+
epochLength: ethers.BigNumber.from(epochInfo[0]).toNumber(),
1108+
number: ethers.BigNumber.from(epochInfo[1]).toNumber(),
1109+
endTime: ethers.BigNumber.from(epochInfo[2]).toNumber(),
1110+
retries: ethers.BigNumber.from(epochInfo[3]).toNumber(),
1111+
timeout: ethers.BigNumber.from(epochInfo[4]).toNumber(),
1112+
};
1113+
1114+
const minNodeCountInt = ethers.BigNumber.from(minNodeCount).toNumber();
1115+
1116+
if (!minNodeCountInt) {
1117+
throw new Error('❌ Minimum validator count is not set');
1118+
}
1119+
1120+
if (activeUnkickedValidatorStructs.length < minNodeCountInt) {
1121+
throw new Error(
1122+
`❌ Active validator set does not meet the threshold. Required: ${minNodeCountInt} but got: ${activeUnkickedValidatorStructs.length}`
1123+
);
1124+
}
1125+
1126+
console.log("typedEpochInfo:", typedEpochInfo);
1127+
1128+
const activeValidatorStructs: ValidatorStruct[] =
1129+
activeUnkickedValidatorStructs.map((item: any) => {
1130+
return {
1131+
ip: item[0],
1132+
ipv6: item[1],
1133+
port: item[2],
1134+
nodeAddress: item[3],
1135+
reward: item[4],
1136+
seconderPubkey: item[5],
1137+
receiverPubkey: item[6],
1138+
};
1139+
});
1140+
1141+
const networks = activeValidatorStructs.map((item: ValidatorStruct) => {
1142+
// Convert the integer IP to a string format
1143+
const ip = intToIP(item.ip);
1144+
const port = item.port;
1145+
1146+
// Determine the protocol to use based on various conditions
1147+
const protocol =
1148+
// If nodeProtocol is defined, use it
1149+
nodeProtocol ||
1150+
// If port is 443, use HTTPS, otherwise use network-specific HTTP
1151+
(port === 443 ? HTTPS : HTTP_BY_NETWORK[network]) ||
1152+
// Fallback to HTTP if no other conditions are met
1153+
HTTP;
1154+
1155+
const url = `${protocol}${ip}:${port}`;
1156+
1157+
LitContracts.logger.debug("Validator's URL:", url);
1158+
1159+
return url;
1160+
});
1161+
1162+
stakingAggregateDetails.push({
1163+
stakingContract: stakingContract,
1164+
epochInfo: typedEpochInfo,
1165+
minNodeCount: minNodeCountInt,
1166+
bootstrapUrls: networks,
1167+
});
1168+
}
1169+
return stakingAggregateDetails;
1170+
}
1171+
10671172
/**
10681173
* Retrieves the connection information for a given network.
10691174
*
@@ -1082,18 +1187,22 @@ export class LitContracts {
10821187
networkContext,
10831188
rpcUrl,
10841189
nodeProtocol,
1190+
networkType,
10851191
}: {
10861192
litNetwork: LIT_NETWORKS_KEYS;
10871193
networkContext?: LitContractContext | LitContractResolverContext;
10881194
rpcUrl?: string;
10891195
nodeProtocol?: typeof HTTP | typeof HTTPS | null;
1196+
networkType?: 'mainnet' | 'cloneNet'
10901197
}): Promise<{
10911198
stakingContract: ethers.Contract;
10921199
epochInfo: EpochInfo;
10931200
minNodeCount: number;
10941201
bootstrapUrls: string[];
10951202
}> => {
10961203

1204+
console.log("networkType:", networkType);
1205+
10971206
const stakingContract = await LitContracts.getContractInstance(
10981207
litNetwork,
10991208
'Staking',
@@ -1102,18 +1211,22 @@ export class LitContracts {
11021211
);
11031212

11041213
if (litNetwork === 'datil-test') {
1105-
const cloneNetContract = await LitContracts.getContractInstance(
1214+
const connectionInfoWithCloneNet = await LitContracts._getAllActiveUnkickedValidatorStructsAndCounts(
11061215
litNetwork,
1107-
'CloneNet',
11081216
networkContext,
11091217
rpcUrl
11101218
);
1111-
console.log("cloneNetContract:", cloneNetContract);
1112-
console.log("cloneNetContract address:", cloneNetContract.address);
11131219

1114-
const test = await cloneNetContract['getActiveStakingContracts']();
1115-
console.log("test:", test);
1116-
process.exit();
1220+
console.log("connectionInfoWithCloneNet:", connectionInfoWithCloneNet);
1221+
1222+
const cloneNetInfo = connectionInfoWithCloneNet[0];
1223+
const mainNetInfo = connectionInfoWithCloneNet[1];
1224+
1225+
if (networkType === 'mainnet') {
1226+
return mainNetInfo;
1227+
} else {
1228+
return cloneNetInfo;
1229+
}
11171230
}
11181231

11191232
const [epochInfo, minNodeCount, activeUnkickedValidatorStructs] =

packages/core/src/lib/lit-core.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export type LitNodeClientConfigWithDefaults = Required<
112112
bootstrapUrls: string[];
113113
} & {
114114
nodeProtocol?: typeof HTTP | typeof HTTPS | null;
115+
networkType?: 'mainnet' | 'cloneNet';
115116
};
116117

117118
// On epoch change, we wait this many seconds for the nodes to update to the new epoch before using the new epoch #
@@ -145,6 +146,7 @@ export class LitCore {
145146
minNodeCount: 2, // Default value, should be replaced
146147
bootstrapUrls: [], // Default value, should be replaced
147148
nodeProtocol: null,
149+
networkType: 'mainnet',
148150
};
149151
connectedNodes = new Set<string>();
150152
serverKeys: Record<string, JsonHandshakeResponse> = {};
@@ -246,7 +248,7 @@ export class LitCore {
246248
* @returns An object containing the validator data.
247249
* @throws Error if minNodeCount is not provided, is less than or equal to 0, or if bootstrapUrls are not available.
248250
*/
249-
private async _getValidatorData(): Promise<{
251+
private async _getValidatorData(networkType: 'mainnet' | 'cloneNet'): Promise<{
250252
stakingContract: ethers.Contract;
251253
epochInfo: EpochInfo;
252254
minNodeCount: number;
@@ -258,6 +260,7 @@ export class LitCore {
258260
networkContext: this.config.contractContext,
259261
rpcUrl: this.config.rpcUrl,
260262
nodeProtocol: this.config.nodeProtocol,
263+
networkType,
261264
});
262265

263266
// Validate minNodeCount
@@ -297,7 +300,7 @@ export class LitCore {
297300
) {
298301
log(`New state detected: "${state}"`);
299302

300-
const validatorData = await this._getValidatorData();
303+
const validatorData = await this._getValidatorData(this.config.networkType || 'mainnet');
301304

302305
if (state === STAKING_STATES.Active) {
303306
// We always want to track the most recent epoch number on _all_ networks
@@ -519,7 +522,7 @@ export class LitCore {
519522

520523
// Re-use staking contract instance from previous connect() executions that succeeded to improve performance
521524
// noinspection ES6MissingAwait - intentionally not `awaiting` so we can run this in parallel below
522-
const validatorData = await this._getValidatorData();
525+
const validatorData = await this._getValidatorData(this.config.networkType || 'mainnet');
523526

524527
this._stakingContract = validatorData.stakingContract;
525528
this.config.minNodeCount = validatorData.minNodeCount;
@@ -671,11 +674,9 @@ export class LitCore {
671674
await Promise.race([
672675
new Promise((_resolve, reject) => {
673676
timeoutHandle = setTimeout(() => {
674-
const msg = `Error: Could not handshake with nodes after timeout of ${
675-
this.config.connectTimeout
676-
}ms. Could only connect to ${Object.keys(serverKeys).length} of ${
677-
this.config.bootstrapUrls.length
678-
} nodes. Please check your network connection and try again. Note that you can control this timeout with the connectTimeout config option which takes milliseconds.`;
677+
const msg = `Error: Could not handshake with nodes after timeout of ${this.config.connectTimeout
678+
}ms. Could only connect to ${Object.keys(serverKeys).length} of ${this.config.bootstrapUrls.length
679+
} nodes. Please check your network connection and try again. Note that you can control this timeout with the connectTimeout config option which takes milliseconds.`;
679680

680681
try {
681682
throw new InitError({}, msg);
@@ -952,7 +953,7 @@ export class LitCore {
952953
'epochinfo not found. Not a problem, fetching current epoch state from staking contract'
953954
);
954955
try {
955-
const validatorData = await this._getValidatorData();
956+
const validatorData = await this._getValidatorData(this.config.networkType || 'mainnet');
956957
epochInfo = validatorData.epochInfo;
957958
} catch (error) {
958959
throw new UnknownError(
@@ -981,8 +982,8 @@ export class LitCore {
981982
this._epochCache.currentNumber &&
982983
this._epochCache.startTime &&
983984
Math.floor(Date.now() / 1000) <
984-
this._epochCache.startTime +
985-
Math.floor(EPOCH_PROPAGATION_DELAY / 1000) &&
985+
this._epochCache.startTime +
986+
Math.floor(EPOCH_PROPAGATION_DELAY / 1000) &&
986987
this._epochCache.currentNumber >= 3 // FIXME: Why this check?
987988
) {
988989
return this._epochCache.currentNumber - 1;
@@ -1013,7 +1014,7 @@ export class LitCore {
10131014
data,
10141015
requestId,
10151016
}: // eslint-disable-next-line @typescript-eslint/no-explicit-any
1016-
SendNodeCommand): Promise<any> => {
1017+
SendNodeCommand): Promise<any> => {
10171018
// FIXME: Replace <any> usage with explicit, strongly typed handlers
10181019
data = { ...data, epoch: this.currentEpochNumber };
10191020

packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,7 @@ import type {
136136

137137
export class LitNodeClientNodeJs
138138
extends LitCore
139-
implements LitClientSessionManager, ILitNodeClient
140-
{
139+
implements LitClientSessionManager, ILitNodeClient {
141140
defaultAuthCallback?: (authSigParams: AuthCallbackParams) => Promise<AuthSig>;
142141

143142
// ========== Constructor ==========
@@ -1157,8 +1156,8 @@ export class LitNodeClientNodeJs
11571156
// -- optional params
11581157
...(params.authMethods &&
11591158
params.authMethods.length > 0 && {
1160-
authMethods: params.authMethods,
1161-
}),
1159+
authMethods: params.authMethods,
1160+
}),
11621161
};
11631162

11641163
logWithRequestId(requestId, 'reqBody:', reqBody);
@@ -1884,8 +1883,8 @@ export class LitNodeClientNodeJs
18841883
const sessionCapabilityObject = params.sessionCapabilityObject
18851884
? params.sessionCapabilityObject
18861885
: await this.generateSessionCapabilityObjectWithWildcards(
1887-
params.resourceAbilityRequests.map((r) => r.resource)
1888-
);
1886+
params.resourceAbilityRequests.map((r) => r.resource)
1887+
);
18891888
const expiration = params.expiration || LitNodeClientNodeJs.getExpiration();
18901889

18911890
// -- (TRY) to get the wallet signature
@@ -1969,10 +1968,10 @@ export class LitNodeClientNodeJs
19691968

19701969
const capabilities = params.capacityDelegationAuthSig
19711970
? [
1972-
...(params.capabilityAuthSigs ?? []),
1973-
params.capacityDelegationAuthSig,
1974-
authSig,
1975-
]
1971+
...(params.capabilityAuthSigs ?? []),
1972+
params.capacityDelegationAuthSig,
1973+
authSig,
1974+
]
19761975
: [...(params.capabilityAuthSigs ?? []), authSig];
19771976

19781977
const signingTemplate = {

packages/types/src/lib/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ export interface LitNodeClientConfig {
187187
storageProvider?: StorageProvider;
188188
defaultAuthCallback?: (authSigParams: AuthCallbackParams) => Promise<AuthSig>;
189189
rpcUrl?: string;
190+
networkType?: 'mainnet' | 'cloneNet';
190191
}
191192

192193
export type CustomNetwork = Pick<

0 commit comments

Comments
 (0)