-
Notifications
You must be signed in to change notification settings - Fork 1
Revamp scripts #10
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
base: chore/update-deps-fix-tests
Are you sure you want to change the base?
Revamp scripts #10
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,43 @@ | ||
| # program-authority-escrow | ||
|
|
||
| A minimalistic, stateless program to safely transfer a solana program from one upgrade authority to another one. | ||
| A stateless Solana program for safe program authority transfers. | ||
|
|
||
| The way it works : | ||
| - The current authority uses Propose to transfer the authority of any program to a PDA of the escrow seeded by (current_authority, new_authority) | ||
| - Once the authority has been transferred two outcomes are possible : | ||
| - If the current authority calls Revert, the PDA will give the authority back to the current authority | ||
| - If the new authority calls Accept, the PDA will give the authority to the new authority | ||
| The current authority calls `propose` to transfer authority to an escrow PDA seeded by `(current_authority, new_authority)`. From there: | ||
| - The current authority can call `revert` to reclaim authority | ||
| - The new authority can call `accept` to complete the transfer | ||
|
|
||
| Basically, this program enforces that the new authority has signed before they accept the authority. | ||
| This makes errors where we mistakenly transfer the authority to a key that we don't own reversible. | ||
| This ensures the new authority has signed before accepting, making accidental transfers to wrong keys reversible. | ||
|
|
||
| Build with `cargo build-sbf` and test with `cargo test-sbf`. | ||
|
|
||
| ## Scripts | ||
|
|
||
| TypeScript scripts are provided to interact with the on-chain program. All scripts support: | ||
| - File-based keypairs or Ledger hardware wallets | ||
| - Squads v3 multisig proposals via `--multisig` | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the transfer and revert scripts don't really support squads. To support squads you need to let currentAuthority be a multisigAuthority |
||
|
|
||
| Install dependencies with `yarn install`. See `scripts/helpers.ts` for documentation on CLI arguments. | ||
|
|
||
| ### Propose | ||
|
|
||
| Transfer program authority to the escrow. The current authority proposes the transfer: | ||
|
|
||
| ## Testing | ||
| To run tests: | ||
| ```shell | ||
| cargo test-sbf | ||
| yarn propose --keypair <path|ledger> --program <program_address> --authority <new_authority> | ||
| ``` | ||
|
|
||
| ## Building | ||
| To build: | ||
| ### Accept | ||
|
|
||
| Accept a proposed authority transfer. The new authority accepts: | ||
|
|
||
| ```shell | ||
| yarn accept --keypair <path|ledger> --program <program_address> --authority <previous_authority> | ||
| ``` | ||
|
|
||
| ### Revert | ||
|
|
||
| Revert a proposed transfer before it's accepted. The current authority reverts: | ||
|
|
||
| ```shell | ||
| cargo build-sbf | ||
| yarn revert --keypair <path|ledger> --program <program_address> --authority <new_authority> | ||
| ``` | ||
| Artifacts will be placed at: `target/deploy/*.so` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,28 @@ | ||
| { | ||
| "scripts": { | ||
| "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", | ||
| "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" | ||
| }, | ||
| "dependencies": { | ||
| "@project-serum/anchor": "^0.26.0" | ||
| }, | ||
| "devDependencies": { | ||
| "chai": "^4.3.4", | ||
| "mocha": "^9.0.3", | ||
| "ts-mocha": "^10.0.0", | ||
| "@types/bn.js": "^5.1.0", | ||
| "@types/chai": "^4.3.0", | ||
| "@types/mocha": "^9.0.0", | ||
| "typescript": "^4.3.5", | ||
| "prettier": "^2.6.2" | ||
| } | ||
| "scripts": { | ||
| "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", | ||
| "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", | ||
| "propose": "ts-node scripts/propose.ts", | ||
| "revert": "ts-node scripts/revert.ts", | ||
| "accept": "ts-node scripts/accept.ts" | ||
| }, | ||
| "dependencies": { | ||
| "@coral-xyz/anchor": "^0.30.0", | ||
| "@ledgerhq/hw-transport": "^6.31.13", | ||
| "@ledgerhq/hw-transport-node-hid": "^6.29.14", | ||
| "@sqds/sdk": "^2.0.4", | ||
| "@types/minimist": "^1.2.5", | ||
| "minimist": "^1.2.8", | ||
| "ts-node": "^10.9.2" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/bn.js": "^5.1.0", | ||
| "@types/chai": "^4.3.0", | ||
| "@types/mocha": "^9.0.0", | ||
| "chai": "^4.3.4", | ||
| "mocha": "^9.0.3", | ||
| "prettier": "^2.6.2", | ||
| "ts-mocha": "^10.0.0", | ||
| "typescript": "^4.3.5" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { PublicKey } from "@solana/web3.js"; | ||
| import { getAuthorityPDA, DEFAULT_MULTISIG_PROGRAM_ID } from "@sqds/sdk"; | ||
| import BN from "bn.js"; | ||
| import { | ||
| parseArgs, | ||
| createWallet, | ||
| initEscrowProgram, | ||
| parseMultisig, | ||
| executeOrPropose, | ||
| } from "./helpers"; | ||
|
|
||
| const BPF_UPGRADABLE_LOADER = new PublicKey( | ||
| "BPFLoaderUpgradeab1e11111111111111111111111" | ||
| ); | ||
|
|
||
| async function main() { | ||
| const args = parseArgs(); | ||
| const wallet = await createWallet(args); | ||
| const { connection, program, programId } = initEscrowProgram(args, wallet); | ||
| const multisigAddress = parseMultisig(args); | ||
|
|
||
| const programToTransfer = new PublicKey(args.program); | ||
| const currentAuthority = new PublicKey(args.authority); | ||
|
|
||
| const programData = PublicKey.findProgramAddressSync( | ||
| [programToTransfer.toBuffer()], | ||
| BPF_UPGRADABLE_LOADER | ||
| )[0]; | ||
|
|
||
| // In multisig mode, the vault becomes the new authority | ||
| let newAuthority: PublicKey; | ||
| if (multisigAddress) { | ||
| [newAuthority] = getAuthorityPDA( | ||
| multisigAddress, | ||
| new BN(1), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're supposed to use the authority index that's specified in the multisig account (you can get it by calling |
||
| DEFAULT_MULTISIG_PROGRAM_ID | ||
| ); | ||
| } else { | ||
| newAuthority = wallet.publicKey; | ||
| } | ||
|
|
||
| const escrowAuthority = PublicKey.findProgramAddressSync( | ||
| [currentAuthority.toBuffer(), newAuthority.toBuffer()], | ||
| programId | ||
| )[0]; | ||
|
|
||
| console.log("Accepting program authority transfer..."); | ||
| console.log(` Wallet: ${wallet.publicKey.toBase58()}`); | ||
| console.log(` Program: ${programToTransfer.toBase58()}`); | ||
| console.log(` Current Authority: ${currentAuthority.toBase58()}`); | ||
| console.log(` New Authority: ${newAuthority.toBase58()}`); | ||
| console.log(` Escrow Authority: ${escrowAuthority.toBase58()}`); | ||
|
|
||
| if (multisigAddress) { | ||
| console.log(` Multisig: ${multisigAddress.toBase58()}`); | ||
| } | ||
|
|
||
| const instruction = await program.methods | ||
| .accept() | ||
| .accounts({ | ||
| currentAuthority: currentAuthority, | ||
| newAuthority: newAuthority, | ||
| programAccount: programToTransfer, | ||
| }) | ||
| .accountsPartial({ | ||
| escrowAuthority: escrowAuthority, | ||
| programData: programData, | ||
| }) | ||
| .instruction(); | ||
|
|
||
| await executeOrPropose(connection, wallet, multisigAddress, instruction); | ||
| } | ||
|
|
||
| main().catch((err) => { | ||
| console.error(err); | ||
| process.exit(1); | ||
| }); | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this section seems emtpy