Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add upgrade scripts #84

Merged
merged 2 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
},
"scripts": {
"build": "node scripts/build.js build",
"declareZklink": "node scripts/deploy_zklink.js declareZklink",
"deployZklink": "node scripts/deploy_zklink.js deployZklink",
"upgradeZklink": "node scripts/upgrade_zklink.js upgradeZklink",
"deployFaucetToken": "node scripts/deploy_faucet.js deployFaucetToken",
"addToken": "node scripts/interact.js addToken",
"addBridge": "node scripts/interact.js addBridge"
Expand Down
9 changes: 9 additions & 0 deletions scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@ const FAUCET_TOKEN_SIERRA_PATH = "./target/release/zklink_FaucetToken.sierra.jso
const FAUCET_TOKEN_CASM_PATH = "./target/release/zklink_FaucetToken.casm.json";
const ZKLINK_CONSTANTS_PATH = "./src/utils/constants.cairo";

// upgrade status
const IDLE = "Idle";
const NOTICE_PERIOD = "NoticePeriod";

// command
const COMMAND_BUILD = "scarb --release build";

export var UpgradeStatus = {
IDLE,
NOTICE_PERIOD
}

export var command = {
COMMAND_BUILD
}
Expand Down
119 changes: 12 additions & 107 deletions scripts/deploy_zklink.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@ import { Contract, json, cairo } from "starknet";
import fs from "fs";
import { program } from "commander";
import { logName, contractPath } from "./constants.js"
import { connectStarknet, getDeployLog, buildVerifierConstructorArgs, buildZklinkConstructorArgs, buildGateKeeperConstructorArgs, getClassHashFromError } from "./utils.js";
import { connectStarknet, getDeployLog, buildVerifierConstructorArgs, buildZklinkConstructorArgs, buildGateKeeperConstructorArgs, declare_zklink } from "./utils.js";


program
.command("declareZklink")
.description("Declare zklink and verifier contract")
.action(async () => {
await declare_zklink();
});

program
.command("deployZklink")
.description("Deploy zklink and verifier contract")
Expand All @@ -29,108 +22,20 @@ program
await deploy_zklink(options);
});

async function declare_zklink() {
const { deployLogPath, deployLog } = getDeployLog(logName.DEPLOY_ZKLINK_LOG_PREFIX);
let { provider, deployer, governor, netConfig} = await connectStarknet();

deployLog[logName.DEPLOY_LOG_DEPLOYER] = deployer.address;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));

// declare gatekeeper contract
if (!(logName.DEPLOY_LOG_GATEKEEPER_CLASS_HASH in deployLog)) {
let gatekeeperContractClassHash;
const gatekeeperContractSierra = json.parse(fs.readFileSync(contractPath.GATEKEEPER_SIERRA_PATH).toString("ascii"));
const gatekeeperContractCasm = json.parse(fs.readFileSync(contractPath.GATEKEEPER_CASM_PATH).toString("ascii"));

try {
const gatekeeperDeclareResponse = await deployer.declare({ contract: gatekeeperContractSierra, casm: gatekeeperContractCasm });
await provider.waitForTransaction(gatekeeperDeclareResponse.transaction_hash);
gatekeeperContractClassHash = gatekeeperDeclareResponse.class_hash;
console.log('✅ Gatekeeper Contract declared with classHash = ', gatekeeperContractClassHash);
} catch (error) {
if (error.errorCode !== 'StarknetErrorCode.CLASS_ALREADY_DECLARED') {
throw error;
}

gatekeeperContractClassHash = getClassHashFromError(error);
if (gatekeeperContractClassHash === undefined) {
console.log('❌ Cannot declare gatekeeper contract class hash:', error);
return;
} else {
console.log('✅ Gatekeeper Contract already declared with classHash =', gatekeeperContractClassHash);
}
}
deployLog[logName.DEPLOY_LOG_GATEKEEPER_CLASS_HASH] = gatekeeperContractClassHash;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
} else {
console.log('✅ Gatekeeper Contract already declared with classHash =', deployLog[logName.DEPLOY_LOG_GATEKEEPER_CLASS_HASH]);
}

// declare verifier contract
if (!(logName.DEPLOY_LOG_VERIFIER_CLASS_HASH in deployLog)) {
let verifierContractClassHash;
const verifierContractSierra = json.parse(fs.readFileSync(contractPath.VERIFIER_SIERRA_PATH).toString("ascii"));
const verifierContractCasm = json.parse(fs.readFileSync(contractPath.VERIFIER_CASM_PATH).toString("ascii"));

try {
const verifierDeclareResponse = await deployer.declare({ contract: verifierContractSierra, casm: verifierContractCasm });
await provider.waitForTransaction(gatekeeperDeclareResponse.transaction_hash);
verifierContractClassHash = verifierDeclareResponse.class_hash;
console.log('✅ Verifier Contract declared with classHash = ', verifierContractClassHash);
} catch (error) {
if (error.errorCode !== 'StarknetErrorCode.CLASS_ALREADY_DECLARED') {
throw error;
}

verifierContractClassHash = getClassHashFromError(error);
if (verifierContractClassHash === undefined) {
console.log('❌ Cannot declare verifier contract class hash:', error);
return;
} else {
console.log('✅ Verifier Contract already declared with classHash =', verifierContractClassHash);
}
}
deployLog[logName.DEPLOY_LOG_VERIFIER_CLASS_HASH] = verifierContractClassHash;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
} else {
console.log('✅ Verifier Contract already declared with classHash =', deployLog[logName.DEPLOY_LOG_VERIFIER_CLASS_HASH]);
}

// declare zklink contract
if (!(logName.DEPLOY_LOG_ZKLINK_CLASS_HASH in deployLog)) {
let zklinkContractClassHash;
const zklinkContractSierra = json.parse(fs.readFileSync(contractPath.ZKLINK_SIERRA_PATH).toString("ascii"));
const zklinkContractCasm = json.parse(fs.readFileSync(contractPath.ZKLINK_CASM_PATH).toString("ascii"));

try {
const zklinkDeclareResponse = await deployer.declare({ contract: zklinkContractSierra, casm: zklinkContractCasm });
await provider.waitForTransaction(zklinkDeclareResponse.transaction_hash);
zklinkContractClassHash = zklinkDeclareResponse.class_hash;
console.log('✅ Zklink Contract declared with classHash = ', zklinkContractClassHash);
} catch (error) {
if (error.errorCode !== 'StarknetErrorCode.CLASS_ALREADY_DECLARED') {
throw error;
}

zklinkContractClassHash = getClassHashFromError(error);
if (zklinkContractClassHash === undefined) {
console.log('❌ Cannot declare zklink contract class hash:', error);
return;
} else {
console.log('✅ Zklink Contract already declared with classHash =', zklinkContractClassHash);
}
}
deployLog[logName.DEPLOY_LOG_ZKLINK_CLASS_HASH] = zklinkContractClassHash;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
} else {
console.log('✅ Zklink Contract already declared with classHash =', deployLog[logName.DEPLOY_LOG_ZKLINK_CLASS_HASH]);
}
}

async function deploy_zklink(options) {
const { deployLogPath, deployLog } = getDeployLog(logName.DEPLOY_ZKLINK_LOG_PREFIX);
const log = getDeployLog(logName.DEPLOY_ZKLINK_LOG_PREFIX);
const { deployLogPath, deployLog } = log;
let { provider, deployer, governor, netConfig } = await connectStarknet();

// declare contracts
const declare_options = {
declareGatekeeper: true,
declareVerifier: true,
declareZklink: true,
upgrade: false
};
await declare_zklink(provider, deployer, log, declare_options);

if (options.governor === undefined) {
options.governor = netConfig.network.accounts.governor.address;
}
Expand Down
107 changes: 107 additions & 0 deletions scripts/upgrade_zklink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { Contract, json, cairo, CairoCustomEnum } from "starknet";
import fs from "fs";
import { program } from "commander";
import { logName, contractPath, UpgradeStatus } from "./constants.js"
import { connectStarknet, getDeployLog, declare_zklink } from "./utils.js"

program
.command("upgradeZklink")
.description("Upgrade the Zklink contract")
.option("--upgrade-verifier <upgradeVerifier>", "Upgrade the verifier", false)
.option("--upgrade-zklink <upgradeZklink>", "Upgrade the zklink", false)
.option("--skip-verify <skipVerify>", "Skip the verification", false)
.action(async (options) => {
await upgrade_zklink(options);
});

program.parse();

async function upgrade_zklink(options) {
const log = getDeployLog(logName.DEPLOY_ZKLINK_LOG_PREFIX);
const { deployLog, deployLogPath } = log;
let { provider, deployer, governor, netConfig} = await connectStarknet();

const upgradeVerifier = options.upgradeVerifier;
const upgradeZklink = options.upgradeZklink;
const skipVerify = options.skipVerify;
console.log("deployer: ", deployer.address);
console.log("governor: ", governor.address);
console.log("upgrade verifier: ", upgradeVerifier);
console.log("upgrade zklink: ", upgradeZklink);
console.log("skip verify: ", skipVerify);

if (!upgradeVerifier && !upgradeZklink) {
console.log("Nothing to upgrade");
return;
}

const gateKeeperAddress = deployLog[logName.DEPLOY_LOG_GATEKEEPER];
if (gateKeeperAddress === undefined) {
console.log("Gatekeeper address is not found");
return;
}

const gatekeeperContractSierra = json.parse(fs.readFileSync(contractPath.GATEKEEPER_SIERRA_PATH).toString("ascii"));
const gatekeeper = new Contract(gatekeeperContractSierra.abi, deployLog[logName.DEPLOY_LOG_GATEKEEPER], provider);

gatekeeper.connect(deployer);
let upgradeStatus = await gatekeeper.upgradeStatus();
let verifierClassHash = deployLog[logName.DEPLOY_LOG_VERIFIER_CLASS_HASH];
let zklinkClassHash = deployLog[logName.DEPLOY_LOG_ZKLINK_CLASS_HASH];
// if upgrade status is Idle, then declare contract
if (upgradeStatus.activeVariant() === UpgradeStatus.IDLE) {
const declare_options = {
declareGatekeeper: false,
declareVerifier: upgradeVerifier,
declareZklink: upgradeZklink,
upgrade: true
};
await declare_zklink(provider, deployer, log, declare_options);

if (upgradeVerifier) {
verifierClassHash = deployLog[logName.DEPLOY_LOG_VERIFIER_CLASS_HASH];
if (verifierClassHash === undefined) {
console.log("Zklink class hash is not found");
return;
}
}

if (upgradeZklink) {
zklinkClassHash = deployLog[logName.DEPLOY_LOG_ZKLINK_CLASS_HASH]
if (zklinkClassHash === undefined) {
console.log("Zklink class hash is not found");
return;
}
}
}

// check if upgrade at testnet
const zklinkContractSierra = json.parse(fs.readFileSync(contractPath.ZKLINK_SIERRA_PATH).toString("ascii"));
const zklink = new Contract(zklinkContractSierra.abi, deployLog[logName.DEPLOY_LOG_ZKLINK], provider);
zklink.connect(deployer);
const noticePeriod = await zklink.getNoticePeriod();
if (noticePeriod > 0) {
console.log("Notice period is not zero, can not exec this task");
return;
}

// start upgrade
if (upgradeStatus.activeVariant() === UpgradeStatus.IDLE) {
gatekeeper.connect(governor);
const call = gatekeeper.populate("startUpgrade", [[verifierClassHash, zklinkClassHash]]);
const tx = await gatekeeper.startUpgrade(call.calldata);
await provider.waitForTransaction(tx.transaction_hash);
console.log("Upgrade started at tx", tx.transaction_hash);
gatekeeper.connect(deployer);
upgradeStatus = await gatekeeper.upgradeStatus();
}


if (upgradeStatus.activeVariant() == UpgradeStatus.NOTICE_PERIOD) {
gatekeeper.connect(governor);
const call = gatekeeper.populate("finishUpgrade");
const tx = await gatekeeper.finishUpgrade(call.calldata);
await provider.waitForTransaction(tx.transaction_hash);
console.log("Upgrade finished at tx", tx.transaction_hash);
}
}
Loading