|
@@ -3,13 +3,13 @@ import { DeliverTxResponse, StdFee } from "@cosmjs/stargate";
|
|
|
import axios from "axios";
|
|
import axios from "axios";
|
|
|
import pkg from "protobufjs";
|
|
import pkg from "protobufjs";
|
|
|
const { Field, Type } = pkg;
|
|
const { Field, Type } = pkg;
|
|
|
-import * as sdk from "wormhole-chain-sdk";
|
|
|
|
|
|
|
+import * as sdk from "@wormhole-foundation/wormhole-chain-sdk";
|
|
|
import {
|
|
import {
|
|
|
fromAccAddress,
|
|
fromAccAddress,
|
|
|
fromValAddress,
|
|
fromValAddress,
|
|
|
toBase64,
|
|
toBase64,
|
|
|
toValAddress,
|
|
toValAddress,
|
|
|
-} from "wormhole-chain-sdk";
|
|
|
|
|
|
|
+} from "@wormhole-foundation/wormhole-chain-sdk";
|
|
|
import {
|
|
import {
|
|
|
DEVNET_GUARDIAN2_PRIVATE_KEY,
|
|
DEVNET_GUARDIAN2_PRIVATE_KEY,
|
|
|
DEVNET_GUARDIAN2_PUBLIC_KEY,
|
|
DEVNET_GUARDIAN2_PUBLIC_KEY,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
} from "./consts.js";
|
|
} from "./consts.js";
|
|
|
import { signValidatorAddress } from "./utils/walletHelpers.js";
|
|
import { signValidatorAddress } from "./utils/walletHelpers.js";
|
|
|
|
|
|
|
|
-import fs from 'fs';
|
|
|
|
|
|
|
+import fs from "fs";
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
getAddress,
|
|
getAddress,
|
|
@@ -59,37 +59,61 @@ async function fullBootstrapProcess() {
|
|
|
|
|
|
|
|
//verify that guardian 1 is the only bonded validator
|
|
//verify that guardian 1 is the only bonded validator
|
|
|
const validators = await queryClient.staking.queryValidators({});
|
|
const validators = await queryClient.staking.queryValidators({});
|
|
|
- expectEqual("Initial bonded validators", validators.data.validators?.map((x) => x.operator_address), [GUARDIAN_VALIDATOR_VALADDR])
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Initial bonded validators",
|
|
|
|
|
+ validators.data.validators?.map((x) => x.operator_address),
|
|
|
|
|
+ [GUARDIAN_VALIDATOR_VALADDR]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- const Guardian1ValidatorAddress: string = getValidatorAddressBase64('../../validators/first_validator/config/priv_validator_key.json')
|
|
|
|
|
- const Guardian2ValidatorAddress: string = getValidatorAddressBase64('../../validators/second_validator/config/priv_validator_key.json')
|
|
|
|
|
|
|
+ const Guardian1ValidatorAddress: string = getValidatorAddressBase64(
|
|
|
|
|
+ "../../validators/first_validator/config/priv_validator_key.json"
|
|
|
|
|
+ );
|
|
|
|
|
+ const Guardian2ValidatorAddress: string = getValidatorAddressBase64(
|
|
|
|
|
+ "../../validators/second_validator/config/priv_validator_key.json"
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//verify that guardian 1 is producing blocks
|
|
//verify that guardian 1 is producing blocks
|
|
|
let latestBlock = await getLatestBlock();
|
|
let latestBlock = await getLatestBlock();
|
|
|
let validatorSet = latestBlock.block.last_commit.signatures;
|
|
let validatorSet = latestBlock.block.last_commit.signatures;
|
|
|
|
|
|
|
|
- expectEqual("Signers on first block", validatorSet.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Signers on first block",
|
|
|
|
|
+ validatorSet.map((sig: any) => sig.validator_address),
|
|
|
|
|
+ [Guardian1ValidatorAddress]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//verify that guardian 1 is registered to test wallet 1.
|
|
//verify that guardian 1 is registered to test wallet 1.
|
|
|
let response = await queryClient.core.queryGuardianValidatorAll();
|
|
let response = await queryClient.core.queryGuardianValidatorAll();
|
|
|
const guardianValidators = response.data.guardianValidator || [];
|
|
const guardianValidators = response.data.guardianValidator || [];
|
|
|
- const tiltnetGuardian = {guardianKey: TILTNET_GUARDIAN_PUBKEY, validatorAddr: toBase64(fromValAddress(GUARDIAN_VALIDATOR_VALADDR))}
|
|
|
|
|
- expectEqual("Initial guardian validators", guardianValidators.map((x) => ({guardianKey: x.guardianKey, validatorAddr: x.validatorAddr})), [tiltnetGuardian] )
|
|
|
|
|
|
|
+ const tiltnetGuardian = {
|
|
|
|
|
+ guardianKey: TILTNET_GUARDIAN_PUBKEY,
|
|
|
|
|
+ validatorAddr: toBase64(fromValAddress(GUARDIAN_VALIDATOR_VALADDR)),
|
|
|
|
|
+ };
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Initial guardian validators",
|
|
|
|
|
+ guardianValidators.map((x) => ({
|
|
|
|
|
+ guardianKey: x.guardianKey,
|
|
|
|
|
+ validatorAddr: x.validatorAddr,
|
|
|
|
|
+ })),
|
|
|
|
|
+ [tiltnetGuardian]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//verify that the latest guardian set is 1
|
|
//verify that the latest guardian set is 1
|
|
|
const response2 = await queryClient.core.queryLatestGuardianSetIndex();
|
|
const response2 = await queryClient.core.queryLatestGuardianSetIndex();
|
|
|
let index = response2.data.latestGuardianSetIndex;
|
|
let index = response2.data.latestGuardianSetIndex;
|
|
|
- expectEqual("Initial \"latest\" guardian set", index, 0)
|
|
|
|
|
|
|
+ expectEqual('Initial "latest" guardian set', index, 0);
|
|
|
|
|
|
|
|
//verify that the consensus guardian set is 1
|
|
//verify that the consensus guardian set is 1
|
|
|
const response3 = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
const response3 = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
|
index = response3.data.ConsensusGuardianSetIndex?.index;
|
|
index = response3.data.ConsensusGuardianSetIndex?.index;
|
|
|
- expectEqual("Initial consensus guardian set", index, 0)
|
|
|
|
|
|
|
+ expectEqual("Initial consensus guardian set", index, 0);
|
|
|
|
|
|
|
|
//verify that the only guardian public key is guardian public key 1.
|
|
//verify that the only guardian public key is guardian public key 1.
|
|
|
const response4 = await queryClient.core.queryGuardianSet(0);
|
|
const response4 = await queryClient.core.queryGuardianSet(0);
|
|
|
const guardianSet = response4.data || null;
|
|
const guardianSet = response4.data || null;
|
|
|
- expectEqual("Guardian set 0", guardianSet.GuardianSet?.keys, [TILTNET_GUARDIAN_PUBKEY])
|
|
|
|
|
|
|
+ expectEqual("Guardian set 0", guardianSet.GuardianSet?.keys, [
|
|
|
|
|
+ TILTNET_GUARDIAN_PUBKEY,
|
|
|
|
|
+ ]);
|
|
|
|
|
|
|
|
//process upgrade VAA
|
|
//process upgrade VAA
|
|
|
const msg = signingClient.core.msgExecuteGovernanceVAA({
|
|
const msg = signingClient.core.msgExecuteGovernanceVAA({
|
|
@@ -101,7 +125,7 @@ async function fullBootstrapProcess() {
|
|
|
[msg],
|
|
[msg],
|
|
|
getZeroFee()
|
|
getZeroFee()
|
|
|
);
|
|
);
|
|
|
- expectTxSuccess("guardian set upgrade VAA", receipt)
|
|
|
|
|
|
|
+ expectTxSuccess("guardian set upgrade VAA", receipt);
|
|
|
|
|
|
|
|
const guardianKey2base64 = Buffer.from(
|
|
const guardianKey2base64 = Buffer.from(
|
|
|
DEVNET_GUARDIAN2_PUBLIC_KEY,
|
|
DEVNET_GUARDIAN2_PUBLIC_KEY,
|
|
@@ -111,22 +135,28 @@ async function fullBootstrapProcess() {
|
|
|
//verify only guardian 2 is in guardian set 1.
|
|
//verify only guardian 2 is in guardian set 1.
|
|
|
const response7 = await queryClient.core.queryGuardianSet(1);
|
|
const response7 = await queryClient.core.queryGuardianSet(1);
|
|
|
const guardianSet7 = response7.data || null;
|
|
const guardianSet7 = response7.data || null;
|
|
|
- expectEqual("Guardian set 1", guardianSet7.GuardianSet?.keys, [guardianKey2base64])
|
|
|
|
|
|
|
+ expectEqual("Guardian set 1", guardianSet7.GuardianSet?.keys, [
|
|
|
|
|
+ guardianKey2base64,
|
|
|
|
|
+ ]);
|
|
|
|
|
|
|
|
//verify latest guardian set is 1
|
|
//verify latest guardian set is 1
|
|
|
const response5 = await queryClient.core.queryLatestGuardianSetIndex();
|
|
const response5 = await queryClient.core.queryLatestGuardianSetIndex();
|
|
|
let index5 = response5.data.latestGuardianSetIndex || null;
|
|
let index5 = response5.data.latestGuardianSetIndex || null;
|
|
|
- expectEqual("Latest guardian set after upgrade", index5, 1)
|
|
|
|
|
|
|
+ expectEqual("Latest guardian set after upgrade", index5, 1);
|
|
|
|
|
|
|
|
//verify consensus guardian set is 0
|
|
//verify consensus guardian set is 0
|
|
|
const response6 = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
const response6 = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
|
let index6 = response6.data.ConsensusGuardianSetIndex?.index;
|
|
let index6 = response6.data.ConsensusGuardianSetIndex?.index;
|
|
|
- expectEqual("Consensus guardian set after upgrade", index6, 0)
|
|
|
|
|
|
|
+ expectEqual("Consensus guardian set after upgrade", index6, 0);
|
|
|
|
|
|
|
|
//verify guardian 1 is still producing blocks
|
|
//verify guardian 1 is still producing blocks
|
|
|
let latestBlock2 = await getLatestBlock();
|
|
let latestBlock2 = await getLatestBlock();
|
|
|
let validatorSet2 = latestBlock2.block.last_commit.signatures;
|
|
let validatorSet2 = latestBlock2.block.last_commit.signatures;
|
|
|
- expectEqual("Validators after upgrade", validatorSet2.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Validators after upgrade",
|
|
|
|
|
+ validatorSet2.map((sig: any) => sig.validator_address),
|
|
|
|
|
+ [Guardian1ValidatorAddress]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//TODO attempt to register guardian2 to validator2, exception because validator2 is not bonded.
|
|
//TODO attempt to register guardian2 to validator2, exception because validator2 is not bonded.
|
|
|
|
|
|
|
@@ -163,15 +193,26 @@ async function fullBootstrapProcess() {
|
|
|
[bondMsg],
|
|
[bondMsg],
|
|
|
getZeroFee()
|
|
getZeroFee()
|
|
|
);
|
|
);
|
|
|
- expectTxSuccess("second validator registration", createValidatorReceipt)
|
|
|
|
|
|
|
+ expectTxSuccess("second validator registration", createValidatorReceipt);
|
|
|
|
|
|
|
|
//confirm validator2 is bonded
|
|
//confirm validator2 is bonded
|
|
|
const validators2 = await queryClient.staking.queryValidators({});
|
|
const validators2 = await queryClient.staking.queryValidators({});
|
|
|
- expectEqual("Second bonded validators", validators2.data.validators?.map((x) => x.operator_address).sort(), [GUARDIAN_VALIDATOR_VALADDR, toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2))].sort())
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Second bonded validators",
|
|
|
|
|
+ validators2.data.validators?.map((x) => x.operator_address).sort(),
|
|
|
|
|
+ [
|
|
|
|
|
+ GUARDIAN_VALIDATOR_VALADDR,
|
|
|
|
|
+ toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2)),
|
|
|
|
|
+ ].sort()
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
let latestBlock3 = await getLatestBlock();
|
|
let latestBlock3 = await getLatestBlock();
|
|
|
let validatorSet3 = latestBlock3.block.last_commit.signatures;
|
|
let validatorSet3 = latestBlock3.block.last_commit.signatures;
|
|
|
- expectEqual("Signers after second validator bonded", validatorSet3.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Signers after second validator bonded",
|
|
|
|
|
+ validatorSet3.map((sig: any) => sig.validator_address),
|
|
|
|
|
+ [Guardian1ValidatorAddress]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//attempt to register guardian2 to validator2
|
|
//attempt to register guardian2 to validator2
|
|
|
//TODO what encoding for the guardian key & how to sign the validator address?
|
|
//TODO what encoding for the guardian key & how to sign the validator address?
|
|
@@ -188,27 +229,45 @@ async function fullBootstrapProcess() {
|
|
|
[registerMsg],
|
|
[registerMsg],
|
|
|
getZeroFee()
|
|
getZeroFee()
|
|
|
);
|
|
);
|
|
|
- expectTxSuccess("second guardian registration", registerMsgReceipe)
|
|
|
|
|
|
|
+ expectTxSuccess("second guardian registration", registerMsgReceipe);
|
|
|
|
|
|
|
|
//confirm validator2 is also now registered as a guardian validator
|
|
//confirm validator2 is also now registered as a guardian validator
|
|
|
let guardianValResponse =
|
|
let guardianValResponse =
|
|
|
await queryClient.core.queryGuardianValidatorAll();
|
|
await queryClient.core.queryGuardianValidatorAll();
|
|
|
const guardianValidators2 =
|
|
const guardianValidators2 =
|
|
|
guardianValResponse.data.guardianValidator || [];
|
|
guardianValResponse.data.guardianValidator || [];
|
|
|
- const secondGuardian = {guardianKey: Buffer.from(DEVNET_GUARDIAN2_PUBLIC_KEY, "hex").toString( "base64"), validatorAddr: toBase64(fromAccAddress(TEST_WALLET_ADDRESS_2))}
|
|
|
|
|
- expectEqual("Updated guardian validators", guardianValidators2.map((x) => ({guardianKey: x.guardianKey, validatorAddr: x.validatorAddr})).sort(), [secondGuardian, tiltnetGuardian].sort())
|
|
|
|
|
|
|
+ const secondGuardian = {
|
|
|
|
|
+ guardianKey: Buffer.from(DEVNET_GUARDIAN2_PUBLIC_KEY, "hex").toString(
|
|
|
|
|
+ "base64"
|
|
|
|
|
+ ),
|
|
|
|
|
+ validatorAddr: toBase64(fromAccAddress(TEST_WALLET_ADDRESS_2)),
|
|
|
|
|
+ };
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Updated guardian validators",
|
|
|
|
|
+ guardianValidators2
|
|
|
|
|
+ .map((x) => ({
|
|
|
|
|
+ guardianKey: x.guardianKey,
|
|
|
|
|
+ validatorAddr: x.validatorAddr,
|
|
|
|
|
+ }))
|
|
|
|
|
+ .sort(),
|
|
|
|
|
+ [secondGuardian, tiltnetGuardian].sort()
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
//confirm consensus guardian set is now 2
|
|
//confirm consensus guardian set is now 2
|
|
|
const conResponse = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
const conResponse = await queryClient.core.queryConsensusGuardianSetIndex();
|
|
|
index = conResponse.data.ConsensusGuardianSetIndex?.index;
|
|
index = conResponse.data.ConsensusGuardianSetIndex?.index;
|
|
|
- expectEqual("Updated consensus guardian set", index, 1)
|
|
|
|
|
|
|
+ expectEqual("Updated consensus guardian set", index, 1);
|
|
|
|
|
|
|
|
//confirm blocks are only signed by validator2
|
|
//confirm blocks are only signed by validator2
|
|
|
- console.log("Waiting 4 seconds for latest block...")
|
|
|
|
|
|
|
+ console.log("Waiting 4 seconds for latest block...");
|
|
|
await new Promise((resolve) => setTimeout(resolve, 4000));
|
|
await new Promise((resolve) => setTimeout(resolve, 4000));
|
|
|
latestBlock = await getLatestBlock();
|
|
latestBlock = await getLatestBlock();
|
|
|
validatorSet = latestBlock.block.last_commit.signatures;
|
|
validatorSet = latestBlock.block.last_commit.signatures;
|
|
|
- expectEqual("Signing validators on final block", validatorSet.map((sig: any) => sig.validator_address), [Guardian2ValidatorAddress])
|
|
|
|
|
|
|
+ expectEqual(
|
|
|
|
|
+ "Signing validators on final block",
|
|
|
|
|
+ validatorSet.map((sig: any) => sig.validator_address),
|
|
|
|
|
+ [Guardian2ValidatorAddress]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
console.log("Successfully completed bootstrap process.");
|
|
console.log("Successfully completed bootstrap process.");
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
@@ -253,52 +312,77 @@ const wait = async () => {
|
|
|
wait();
|
|
wait();
|
|
|
|
|
|
|
|
function getValidatorAddressBase64(file: string): string {
|
|
function getValidatorAddressBase64(file: string): string {
|
|
|
- const validator_key_file = fs.readFileSync(file)
|
|
|
|
|
- return Buffer.from(JSON.parse(validator_key_file.toString()).address, "hex").toString("base64")
|
|
|
|
|
|
|
+ const validator_key_file = fs.readFileSync(file);
|
|
|
|
|
+ return Buffer.from(
|
|
|
|
|
+ JSON.parse(validator_key_file.toString()).address,
|
|
|
|
|
+ "hex"
|
|
|
|
|
+ ).toString("base64");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function equal<T>(actual: T, expected: T): boolean {
|
|
function equal<T>(actual: T, expected: T): boolean {
|
|
|
if (Array.isArray(actual) && Array.isArray(expected)) {
|
|
if (Array.isArray(actual) && Array.isArray(expected)) {
|
|
|
- return actual.length === expected.length && actual.every((val, index) => equal(val, expected[index]));
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ actual.length === expected.length &&
|
|
|
|
|
+ actual.every((val, index) => equal(val, expected[index]))
|
|
|
|
|
+ );
|
|
|
} else if (typeof actual === "object" && typeof expected === "object") {
|
|
} else if (typeof actual === "object" && typeof expected === "object") {
|
|
|
- return JSON.stringify(actual) === JSON.stringify(expected)
|
|
|
|
|
|
|
+ return JSON.stringify(actual) === JSON.stringify(expected);
|
|
|
} else {
|
|
} else {
|
|
|
- return actual === expected
|
|
|
|
|
|
|
+ return actual === expected;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function expectEqual<T>(msg: string, actual: T, expected: T): void {
|
|
function expectEqual<T>(msg: string, actual: T, expected: T): void {
|
|
|
if (!equal(actual, expected)) {
|
|
if (!equal(actual, expected)) {
|
|
|
- eject(msg + ":\nExpected: " + green(stringify(expected)) + ", got: " + red(stringify(actual)))
|
|
|
|
|
|
|
+ eject(
|
|
|
|
|
+ msg +
|
|
|
|
|
+ ":\nExpected: " +
|
|
|
|
|
+ green(stringify(expected)) +
|
|
|
|
|
+ ", got: " +
|
|
|
|
|
+ red(stringify(actual))
|
|
|
|
|
+ );
|
|
|
} else {
|
|
} else {
|
|
|
- console.log(msg + ": " + green("PASS"))
|
|
|
|
|
|
|
+ console.log(msg + ": " + green("PASS"));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function expectTxSuccess(msg: string, receipt: DeliverTxResponse): void {
|
|
function expectTxSuccess(msg: string, receipt: DeliverTxResponse): void {
|
|
|
if (receipt.code !== 0) {
|
|
if (receipt.code !== 0) {
|
|
|
- eject("Transaction " + msg + " failed. Transaction hash: " + red(receipt.transactionHash))
|
|
|
|
|
|
|
+ eject(
|
|
|
|
|
+ "Transaction " +
|
|
|
|
|
+ msg +
|
|
|
|
|
+ " failed. Transaction hash: " +
|
|
|
|
|
+ red(receipt.transactionHash)
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- console.log("Transaction " + msg + ": " + green("PASS") + " (" + receipt.transactionHash + ")")
|
|
|
|
|
|
|
+ console.log(
|
|
|
|
|
+ "Transaction " +
|
|
|
|
|
+ msg +
|
|
|
|
|
+ ": " +
|
|
|
|
|
+ green("PASS") +
|
|
|
|
|
+ " (" +
|
|
|
|
|
+ receipt.transactionHash +
|
|
|
|
|
+ ")"
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function stringify<T>(x: T): string {
|
|
function stringify<T>(x: T): string {
|
|
|
if (Array.isArray(x)) {
|
|
if (Array.isArray(x)) {
|
|
|
- return "["+ x.map((x) => stringify(x)) + "]"
|
|
|
|
|
|
|
+ return "[" + x.map((x) => stringify(x)) + "]";
|
|
|
} else if (typeof x === "object") {
|
|
} else if (typeof x === "object") {
|
|
|
- return JSON.stringify(x)
|
|
|
|
|
|
|
+ return JSON.stringify(x);
|
|
|
} else {
|
|
} else {
|
|
|
- return "" + x
|
|
|
|
|
|
|
+ return "" + x;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function red(str: string): string {
|
|
function red(str: string): string {
|
|
|
- return '\x1b[31m' + str + '\x1b[0m'
|
|
|
|
|
|
|
+ return "\x1b[31m" + str + "\x1b[0m";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function green(str: string): string {
|
|
function green(str: string): string {
|
|
|
- return '\x1b[32m' + str + '\x1b[0m'
|
|
|
|
|
|
|
+ return "\x1b[32m" + str + "\x1b[0m";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export default {};
|
|
export default {};
|