Script to generate change registration governance (#1508)
* Script to generate change registration governance Change-Id: If99e78b031dcd4049a9ee40b09914eeb93e7518a * Rework from code review Change-Id: I93cf3166c1ab961add2c524084de1981a44b194e * Change chain_id to chain-id Change-Id: Iae6f9854a64d8559d03c56949d03043a94dbf7f6
This commit is contained in:
parent
8dc459b550
commit
b357ad7061
|
@ -10,6 +10,9 @@ import {
|
|||
CONTRACTS,
|
||||
setDefaultWasm,
|
||||
hexToUint8Array,
|
||||
getEmitterAddressSolana,
|
||||
getEmitterAddressTerra,
|
||||
getEmitterAddressEth,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { execute_solana } from "./solana";
|
||||
import {
|
||||
|
@ -254,11 +257,17 @@ yargs(hideBin(process.argv))
|
|||
describe: "Module to query",
|
||||
type: "string",
|
||||
choices: ["Core", "NFTBridge", "TokenBridge"],
|
||||
})
|
||||
.option("emitter", {
|
||||
alias: "e",
|
||||
describe: "Print in emitter address format",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
required: false,
|
||||
});
|
||||
},
|
||||
async (argv) => {
|
||||
assertChain(argv["chain"]);
|
||||
assertEVMChain(argv["chain"]);
|
||||
const network = argv.network.toUpperCase();
|
||||
if (
|
||||
network !== "MAINNET" &&
|
||||
|
@ -267,20 +276,58 @@ yargs(hideBin(process.argv))
|
|||
) {
|
||||
throw Error(`Unknown network: ${network}`);
|
||||
}
|
||||
let chain = argv["chain"]
|
||||
let module = argv["module"] as "Core" | "NFTBridge" | "TokenBridge";
|
||||
let addr = ""
|
||||
switch (module) {
|
||||
case "Core":
|
||||
console.log(CONTRACTS[network][argv["chain"]]["core"]);
|
||||
addr = CONTRACTS[network][chain]["core"];
|
||||
break;
|
||||
case "NFTBridge":
|
||||
console.log(CONTRACTS[network][argv["chain"]]["nft_bridge"]);
|
||||
addr = CONTRACTS[network][chain]["nft_bridge"];
|
||||
break;
|
||||
case "TokenBridge":
|
||||
console.log(CONTRACTS[network][argv["chain"]]["token_bridge"]);
|
||||
addr = CONTRACTS[network][chain]["token_bridge"];
|
||||
break;
|
||||
default:
|
||||
impossible(module);
|
||||
}
|
||||
if (argv["emitter"]) {
|
||||
if (chain === "solana" || chain === "pythnet") { // TODO: Create an isSolanaChain()
|
||||
addr = await getEmitterAddressSolana(addr);
|
||||
} else if (isTerraChain(chain)) {
|
||||
addr = await getEmitterAddressTerra(addr);
|
||||
} else if (chain === "algorand") {
|
||||
if (network !== "MAINNET") {
|
||||
throw Error(`unable to look up algorand emitter address for ${network}`);
|
||||
}
|
||||
addr = "25e716e0618d9f38b603a97cc42db659069c0f5185230e5e61679fa876191ec4";
|
||||
} else if (chain === "near") {
|
||||
if (network !== "MAINNET") {
|
||||
throw Error(`unable to look up near emitter address for ${network}`);
|
||||
}
|
||||
addr = "148410499d3fcda4dcfd68a1ebfcdddda16ab28326448d4aae4d2f0465cdfcb7";
|
||||
} else {
|
||||
addr = getEmitterAddressEth(addr);
|
||||
}
|
||||
}
|
||||
console.log(addr);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"chain-id <chain>",
|
||||
"Print the wormhole chain ID integer associated with the specified chain name",
|
||||
(yargs) => {
|
||||
return yargs
|
||||
.positional("chain", {
|
||||
describe: "Chain to query",
|
||||
type: "string",
|
||||
choices: Object.keys(CHAINS),
|
||||
});
|
||||
},
|
||||
async (argv) => {
|
||||
assertChain(argv["chain"]);
|
||||
console.log(toChainId(argv["chain"]));
|
||||
}
|
||||
)
|
||||
.command(
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"google.golang.org/protobuf/encoding/prototext"
|
||||
|
||||
nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
|
||||
"github.com/status-im/keycard-go/hexutils"
|
||||
)
|
||||
|
||||
var AdminClientGovernanceVAAVerifyCmd = &cobra.Command{
|
||||
|
@ -59,7 +60,7 @@ func runGovernanceVAAVerify(cmd *cobra.Command, args []string) {
|
|||
log.Fatalf("invalid update: %v", err)
|
||||
}
|
||||
|
||||
digest := v.SigningMsg()
|
||||
digest := v.SigningMsg().Bytes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -71,6 +72,6 @@ func runGovernanceVAAVerify(cmd *cobra.Command, args []string) {
|
|||
|
||||
log.Printf("Serialized: %v", hex.EncodeToString(b))
|
||||
|
||||
log.Printf("VAA with digest %s: %+v", digest.Hex(), spew.Sdump(v))
|
||||
log.Printf("VAA with digest %s: %+v", hexutils.BytesToHex(digest), spew.Sdump(v))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
rm -rf my_proposal
|
||||
|
||||
./register-chain-governance.sh -m TokenBridge -c solana -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c ethereum -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c terra -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c bsc -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c polygon -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c avalanche -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c oasis -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c fantom -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m TokenBridge -c aurora -o my_proposal > governance.md
|
||||
|
||||
# These are already on the current guardian set.
|
||||
# ./register-chain-governance.sh -m TokenBridge -c karura -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c klaytn -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c celo -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c acala -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c terra2 -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c algorand -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c near -o my_proposal > governance.md
|
||||
|
||||
./register-chain-governance.sh -m NFTBridge -c solana -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c ethereum -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c bsc -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c polygon -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c avalanche -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c oasis -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c fantom -o my_proposal > governance.md
|
||||
./register-chain-governance.sh -m NFTBridge -c aurora -o my_proposal > governance.md
|
||||
|
||||
# These are already on the current guardian set.
|
||||
# ./register-chain-governance.sh -m NFTBridge -c karura -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m NFTBridge -c klaytn -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m NFTBridge -c celo -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m NFTBridge -c acala -o my_proposal > governance.md
|
|
@ -0,0 +1,178 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This tool automates the process of writing bridge registration governance
|
||||
# proposals in markdown format.
|
||||
#
|
||||
# There are two ways to run this script: either in "one-shot" mode, where a
|
||||
# single governance VAA is generated:
|
||||
#
|
||||
# ./register-chain-governance.sh -m TokenBridge -c solana > governance.md
|
||||
#
|
||||
# or in "multi" mode, where multiple VAAs are created in the same proposal:
|
||||
#
|
||||
# ./register-chain-governance.sh -m TokenBridge -c solana -o my_proposal > governance.md
|
||||
# ./register-chain-governance.sh -m TokenBridge -c avalanche -o my_proposal > governance.md
|
||||
# ... -o my_proposal > governance.md
|
||||
#
|
||||
# In multi mode, there's an additional "-o" flag, which takes a directory name,
|
||||
# where intermediate progress is saved between runs. If the directory doesn't
|
||||
# exist, the tool will create it.
|
||||
#
|
||||
# In both one-shot and multi modes, the script outputs the markdown-formatted
|
||||
# proposal to STDOUT, so it's a good idea to pipe it into a file (as in the above examples).
|
||||
#
|
||||
# In multi-mode, it always outputs the most recent version, so it's safe to
|
||||
# override the previous files.
|
||||
#
|
||||
# Once a multi-mode run is completed, the directory specified with the -o flag can be deleted.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function usage() {
|
||||
cat <<EOF >&2
|
||||
Usage:
|
||||
|
||||
$(basename "$0") [-h] [-m s] [-c s] [-o d] -- Generate bridge registration governance proposal for a given module
|
||||
|
||||
where:
|
||||
-h show this help text
|
||||
-m module (TokenBridge, NFTBridge)
|
||||
-c chain name
|
||||
-o multi-mode output directory
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if guardiand and worm commands exist. They needed for generating the protoxt and
|
||||
# computing the digest.
|
||||
if ! command -v guardiand >/dev/null 2>&1; then
|
||||
echo "ERROR: guardiand binary not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v worm >/dev/null 2>&1; then
|
||||
echo "ERROR: worm binary not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Parse command line options
|
||||
address=""
|
||||
module=""
|
||||
chain_name=""
|
||||
multi_mode=false
|
||||
out_dir=""
|
||||
while getopts ':hm:c:a:o:' option; do
|
||||
case "$option" in
|
||||
h) usage
|
||||
;;
|
||||
m) module=$OPTARG
|
||||
;;
|
||||
c) chain_name=$OPTARG
|
||||
;;
|
||||
o) multi_mode=true
|
||||
out_dir=$OPTARG
|
||||
;;
|
||||
:) printf "missing argument for -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
\?) printf "illegal option: -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
[ -z "$chain_name" ] && usage
|
||||
[ -z "$module" ] && usage
|
||||
|
||||
# Use the worm client to get the emitter address and wormhole chain ID.
|
||||
address=`worm contract --emitter mainnet $chain_name $module`
|
||||
[ -z "$address" ] && usage
|
||||
|
||||
chain=`worm chain-id $chain_name`
|
||||
[ -z "$chain" ] && usage
|
||||
|
||||
### The script constructs the governance proposal in two different steps. First,
|
||||
### the governance prototxt (for VAA injection by the guardiand tool), then the voting/verification instructions.
|
||||
gov_msg_file=""
|
||||
instructions_file=""
|
||||
if [ "$multi_mode" = true ]; then
|
||||
mkdir -p "$out_dir"
|
||||
gov_msg_file="$out_dir/governance.prototxt"
|
||||
instructions_file="$out_dir/instructions.md"
|
||||
else
|
||||
gov_msg_file=$(mktemp)
|
||||
instructions_file=$(mktemp)
|
||||
fi
|
||||
|
||||
# Generate the command to create the governance prototxt
|
||||
function create_governance() {
|
||||
case "$module" in
|
||||
TokenBridge)
|
||||
echo "\
|
||||
guardiand template token-bridge-register-chain \\
|
||||
--chain-id $chain --module \"TokenBridge\" \\
|
||||
--new-address $address"
|
||||
;;
|
||||
NFTBridge)
|
||||
echo "\
|
||||
guardiand template token-bridge-register-chain \\
|
||||
--chain-id $chain --module \"NFTBridge\" \\
|
||||
--new-address $address"
|
||||
;;
|
||||
*) echo "unknown module $module" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Construct the governance proto
|
||||
|
||||
echo "# Registration $chain_name $module" >> "$gov_msg_file"
|
||||
# Append the new governance message to the gov file
|
||||
eval "$(create_governance)" >> "$gov_msg_file"
|
||||
|
||||
# Multiple messages will include multiple 'current_set_index' fields, but the
|
||||
# proto format only takes one. This next part cleans up the file so there's only
|
||||
# a single 'current_set_index' field.
|
||||
# 1. we grab the first one and save it
|
||||
current_set_index=$(grep "current_set_index" "$gov_msg_file" | head -n 1)
|
||||
# 2. remove all 'current_set_index' fields
|
||||
rest=$(grep -v "current_set_index" "$gov_msg_file")
|
||||
# 3. write the set index
|
||||
echo "$current_set_index" > "$gov_msg_file"
|
||||
# 4. then the rest of the file
|
||||
echo "$rest" >> "$gov_msg_file"
|
||||
|
||||
################################################################################
|
||||
# Compute expected digests
|
||||
|
||||
# just use the 'guardiand' command, which spits out a bunch of text to
|
||||
# stderr. We grab that output and pick out the VAA hashes
|
||||
verify=$(guardiand admin governance-vaa-verify "$gov_msg_file" 2>&1)
|
||||
digest=$(echo "$verify" | grep "VAA with digest" | cut -d' ' -f6 | sed 's/://g')
|
||||
|
||||
################################################################################
|
||||
# Print vote command and expected digests
|
||||
|
||||
# This we only print to stdout, because in multi mode, it gets recomputed each
|
||||
# time. The rest of the output gets printed into the instructions file
|
||||
cat <<-EOD
|
||||
# Governance
|
||||
Shell command for voting:
|
||||
|
||||
\`\`\`shell
|
||||
cat << EOF > governance.prototxt
|
||||
$(cat "$gov_msg_file")
|
||||
|
||||
EOF
|
||||
|
||||
guardiand admin governance-vaa-inject --socket /path/to/admin.sock governance.prototxt
|
||||
\`\`\`
|
||||
|
||||
Expected digest(s):
|
||||
\`\`\`
|
||||
$digest
|
||||
\`\`\`
|
||||
EOD
|
Loading…
Reference in New Issue