Skip to content

Commit 3e602f0

Browse files
committed
solana-core: export secp256k1, add optional guardianSetData param
updated guardian sets
1 parent bfedcc6 commit 3e602f0

File tree

6 files changed

+141
-44
lines changed

6 files changed

+141
-44
lines changed

.github/workflows/publish.yml

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
- run: npm ci
1919
- run: npm run build --if-present
2020
- run: npm test
21+
env:
22+
ETH_RPC: ${{ secrets.ETH_RPC }}
2123
- run: |
2224
version="$GITHUB_REF_NAME"
2325

core/base/src/constants/guardians.ts

+75-37
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,78 @@
1-
import type { MapLevels} from './../utils/index.js';
2-
import { constMap, filterIndexes, zip, cartesianRightRecursive } from './../utils/index.js';
3-
import type { Network } from './networks.js';
4-
5-
// prettier-ignore
6-
const guardianKeyAndNameEntries = [[
7-
"Mainnet", [
8-
["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5", "JumpCrypto" ],
9-
["0xfF6CB952589BDE862c25Ef4392132fb9D4A42157", "Staked" ],
10-
["0x114De8460193bdf3A2fCf81f86a09765F4762fD1", "Figment" ],
11-
["0x107A0086b32d7A0977926A205131d8731D39cbEB", "ChainodeTech" ],
12-
["0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2", "Inotel" ],
13-
["0x11b39756C042441BE6D8650b69b54EbE715E2343", "HashQuark" ],
14-
["0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd", "Chainlayer" ],
15-
["0x15e7cAF07C4e3DC8e7C469f92C8Cd88FB8005a20", "xLabs" ],
16-
["0x74a3bf913953D695260D88BC1aA25A4eeE363ef0", "Forbole" ],
17-
["0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e", "StakingFund" ],
18-
["0xAF45Ced136b9D9e24903464AE889F5C8a723FC14", "MoonletWallet" ],
19-
["0xf93124b7c738843CBB89E864c862c38cddCccF95", "P2PValidator" ],
20-
["0xD2CC37A4dc036a8D232b48f62cDD4731412f4890", "01Node" ],
21-
["0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811", "MCF" ],
22-
["0x71AA1BE1D36CaFE3867910F99C09e347899C19C3", "Everstake" ],
23-
["0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf", "ChorusOne" ],
24-
["0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8", "Syncnode" ],
25-
["0x5E1487F35515d02A92753504a8D75471b9f49EdB", "Triton" ],
26-
["0x6FbEBc898F403E4773E95feB15E80C9A99c8348d", "StakingFacilities"],
27-
]], [
28-
"Testnet", [
29-
["0x13947Bd48b18E53fdAeEe77F3473391aC727C638", "Testnet guardian"]
30-
]]
31-
] as const satisfies MapLevels<[Network, string, string]>;
32-
33-
export const [guardianKeys, guardianNames] =
34-
filterIndexes(zip(cartesianRightRecursive(guardianKeyAndNameEntries)), [1, 2]);
35-
36-
export const guardianNameToKey = constMap(guardianKeyAndNameEntries, [[0, 2], 1]);
37-
export const guardianKeyToName = constMap(guardianKeyAndNameEntries, [1, [0, 2]]);
1+
import { replaceElement } from "./../utils/index.js";
2+
3+
// Mainnet guardian sets
4+
const guardianSet1 = [
5+
["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5", "Certus One"],
6+
["0xfF6CB952589BDE862c25Ef4392132fb9D4A42157", "Staked"],
7+
["0x114De8460193bdf3A2fCf81f86a09765F4762fD1", "Figment"],
8+
["0x107A0086b32d7A0977926A205131d8731D39cbEB", "ChainodeTech"],
9+
["0x8C82B2fd82FaeD2711d59AF0F2499D16e726f6b2", "Inotel"],
10+
["0x11b39756C042441BE6D8650b69b54EbE715E2343", "HashQuark"],
11+
["0x54Ce5B4D348fb74B958e8966e2ec3dBd4958a7cd", "ChainLayer"],
12+
["0xeB5F7389Fa26941519f0863349C223b73a6DDEE7", "DokiaCapital"],
13+
["0x74a3bf913953D695260D88BC1aA25A4eeE363ef0", "Forbole"],
14+
["0x000aC0076727b35FBea2dAc28fEE5cCB0fEA768e", "Staking Fund"],
15+
["0xAF45Ced136b9D9e24903464AE889F5C8a723FC14", "Moonlet"],
16+
["0xf93124b7c738843CBB89E864c862c38cddCccF95", "P2P Validator"],
17+
["0xD2CC37A4dc036a8D232b48f62cDD4731412f4890", "01node"],
18+
["0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811", "MCF"],
19+
["0x71AA1BE1D36CaFE3867910F99C09e347899C19C3", "Everstake"],
20+
["0x8192b6E7387CCd768277c17DAb1b7a5027c0b3Cf", "Chorus One"],
21+
["0x178e21ad2E77AE06711549CFBB1f9c7a9d8096e8", "syncnode"],
22+
["0x5E1487F35515d02A92753504a8D75471b9f49EdB", "Triton"],
23+
["0x6FbEBc898F403E4773E95feB15E80C9A99c8348d", "Staking Facilities"],
24+
] as const;
25+
26+
const guardianSet2 = replaceElement(guardianSet1, 7, [
27+
"0x66B9590e1c41e0B226937bf9217D1d67Fd4E91F5",
28+
"FTX",
29+
] as const);
30+
31+
const guardianSet3 = replaceElement(guardianSet2, 7, [
32+
"0x15e7cAF07C4e3DC8e7C469f92C8Cd88FB8005a20",
33+
"xLabs",
34+
] as const);
35+
36+
const guardianSet4 = replaceElement(guardianSet3, 0, [
37+
"0x5893B5A76c3f739645648885bDCcC06cd70a3Cd3",
38+
"RockawayX",
39+
] as const);
40+
41+
// Testnet guardian sets
42+
const testnetGuardianSet1 = [
43+
["0x13947Bd48b18E53fdAeEe77F3473391aC727C638", "Testnet guardian"],
44+
] as const;
45+
46+
// TODO: Attempting to use `constMap` results in a type instantiation too deep error
47+
const guardianSetsMap = {
48+
Mainnet: {
49+
1: guardianSet1,
50+
2: guardianSet2,
51+
3: guardianSet3,
52+
4: guardianSet4,
53+
},
54+
Testnet: {
55+
1: testnetGuardianSet1,
56+
},
57+
} as const;
58+
59+
type GuardianSetsMap = typeof guardianSetsMap;
60+
61+
type GuardianInfo = {
62+
address: string;
63+
name: string;
64+
};
65+
66+
export function getGuardianSet<N extends keyof GuardianSetsMap, I extends keyof GuardianSetsMap[N]>(
67+
network: N,
68+
index: I,
69+
): GuardianInfo[] {
70+
const guardianSet = guardianSetsMap[network][index] as readonly [string, string][];
71+
return guardianSet.map(([address, name]) => ({
72+
address,
73+
name,
74+
}));
75+
}
3876

3977
export const devnetGuardianPrivateKey =
4078
"cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";

core/base/src/utils/array.ts

+15
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,18 @@ export type Cartesian<L, R> =
174174
: R extends RoArray
175175
? [...{ [K in keyof R]: K extends `${number}` ? [L, R[K]] : never }]
176176
: [L, R];
177+
178+
export type ReplaceElement<A extends RoArray, I extends number, NE> = {
179+
readonly [K in keyof A]: K extends `${I}` ? NE : A[K];
180+
};
181+
182+
export const replaceElement = <
183+
const A extends RoArray,
184+
const I extends number,
185+
const NE
186+
>(arr: A, index: I, newElement: NE,
187+
) => {
188+
const newArr = [...arr];
189+
newArr[index] = newElement;
190+
return newArr as ReplaceElement<A, I, NE>;
191+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { describe, test } from '@jest/globals';
2+
import { ethers } from 'ethers';
3+
import { EvmWormholeCore } from '@wormhole-foundation/sdk-evm-core';
4+
import { contracts } from '@wormhole-foundation/sdk-connect';
5+
import { guardians } from '@wormhole-foundation/sdk-base';
6+
7+
import '@wormhole-foundation/sdk-evm-core';
8+
9+
describe('Core tests', function () {
10+
test('Check latest mainnet guardian set', async () => {
11+
const rpc = process.env.ETH_RPC
12+
? new ethers.JsonRpcProvider(process.env.ETH_RPC)
13+
: ethers.getDefaultProvider('mainnet');
14+
15+
const core = new EvmWormholeCore('Mainnet', 'Ethereum', rpc, {
16+
coreBridge: contracts.coreBridge.get('Mainnet', 'Ethereum'),
17+
});
18+
19+
const index = await core.getGuardianSetIndex();
20+
// If this test fails, the guardian set index may have been updated
21+
expect(index).toBe(4);
22+
23+
const guardianSet = await core.getGuardianSet(index);
24+
expect(guardianSet.index).toBe(index);
25+
26+
const localGuardianSet = [...guardians.getGuardianSet('Mainnet', 4)];
27+
expect(localGuardianSet.length).toBe(guardianSet.keys.length);
28+
29+
for (let i = 0; i < guardianSet.keys.length; i++) {
30+
expect(guardianSet.keys[i]).toBe(localGuardianSet[i]?.address);
31+
}
32+
});
33+
});

platforms/solana/protocols/core/src/utils/instructions/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export * from './governance.js';
33
export * from './initialize.js';
44
export * from './postMessage.js';
55
export * from './postVaa.js';
6+
export * from './secp256k1.js';
67
export * from './verifySignature.js';

platforms/solana/protocols/core/src/utils/instructions/verifySignature.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import {
1212
} from '@solana/web3.js';
1313
import type { VAA } from '@wormhole-foundation/sdk-connect';
1414
import { createReadOnlyWormholeProgramInterface } from '../program.js';
15-
import { deriveGuardianSetKey, getGuardianSet } from './../accounts/index.js';
15+
import {
16+
GuardianSetData,
17+
deriveGuardianSetKey,
18+
getGuardianSet,
19+
} from './../accounts/index.js';
1620
import { createSecp256k1Instruction } from './secp256k1.js';
1721

1822
const MAX_LEN_GUARDIAN_KEYS = 19;
@@ -35,6 +39,7 @@ const MAX_LEN_GUARDIAN_KEYS = 19;
3539
* @param {SignedVaa | ParsedVaa} vaa - either signed VAA bytes or parsed VAA
3640
* @param {PublicKeyInitData} signatureSet - address to account of verified signatures
3741
* @param {web3.ConfirmOptions} [options] - Solana confirmation options
42+
* @param {GuardianSetData} [guardianSetData] - guardian set data
3843
*/
3944
export async function createVerifySignaturesInstructions(
4045
connection: Connection,
@@ -43,14 +48,17 @@ export async function createVerifySignaturesInstructions(
4348
vaa: VAA<any>,
4449
signatureSet: PublicKeyInitData,
4550
commitment?: Commitment,
51+
guardianSetData?: GuardianSetData,
4652
): Promise<TransactionInstruction[]> {
4753
const guardianSetIndex = vaa.guardianSet;
48-
const guardianSetData = await getGuardianSet(
49-
connection,
50-
wormholeProgramId,
51-
guardianSetIndex,
52-
commitment,
53-
);
54+
if (guardianSetData === undefined) {
55+
guardianSetData = await getGuardianSet(
56+
connection,
57+
wormholeProgramId,
58+
guardianSetIndex,
59+
commitment,
60+
);
61+
}
5462

5563
const guardianSignatures = vaa.signatures;
5664
const guardianKeys = guardianSetData.keys;

0 commit comments

Comments
 (0)