{"id":13573299,"url":"https://github.com/informalsystems/multisig","last_synced_at":"2025-12-30T01:31:39.518Z","repository":{"id":37496238,"uuid":"432583851","full_name":"informalsystems/multisig","owner":"informalsystems","description":"Painless multisig for many keys across many cosmos-sdk chains","archived":false,"fork":false,"pushed_at":"2024-04-16T18:21:03.000Z","size":338,"stargazers_count":35,"open_issues_count":17,"forks_count":10,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-21T17:20:47.616Z","etag":null,"topics":["cosmos","cosmos-sdk","cryptocurrency","multisig"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/informalsystems.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-28T00:19:58.000Z","updated_at":"2024-05-20T04:28:50.185Z","dependencies_parsed_at":"2023-10-17T05:01:05.680Z","dependency_job_id":"def25e4e-3387-4fe9-aca7-24c482f22b6d","html_url":"https://github.com/informalsystems/multisig","commit_stats":{"total_commits":120,"total_committers":9,"mean_commits":"13.333333333333334","dds":0.5666666666666667,"last_synced_commit":"8c7ee5d33325818c33e76a349e39ea1be07fee53"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/informalsystems%2Fmultisig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/informalsystems%2Fmultisig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/informalsystems%2Fmultisig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/informalsystems%2Fmultisig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/informalsystems","download_url":"https://codeload.github.com/informalsystems/multisig/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247179333,"owners_count":20897017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cosmos","cosmos-sdk","cryptocurrency","multisig"],"created_at":"2024-08-01T15:00:32.947Z","updated_at":"2025-12-30T01:31:39.477Z","avatar_url":"https://github.com/informalsystems.png","language":"Go","funding_links":[],"categories":["Tools"],"sub_categories":["CLI"],"readme":"# Multisig\n\n---\n\nDisclaimer: Use at your risk, responsibility for damages (if any) to anyone\nresulting from the use of this software rest entirely with the user. The author\nis not responsible for any damage that its use could cause.\n\nNote: use a released version. The `main` branch is an active development branch.\nThe tool is still a bit rough around the edges, so its best to use from a clean directory and with a clean S3 bucket.\n\n---\n\nThis is a tool for managing multisig txs with Cosmos-SDK based binaries and an\nAWS S3 bucket.\n\nSee the [github issue #5661 on the\nCosmos-SDK](https://github.com/cosmos/cosmos-sdk/issues/5661) for discussion\nabout multisig handling. This tool is a multi-chain/multi-key solution to that problem using S3\nbuckets.\n\nSee the [TODO](#todo) list at the bottom of this document for work that needs to be done (please open an issue if you intend to work on something!) :)\n\n## How it Works\n\nQuick summary, with much more below:\n\n- Configure an S3 bucket, some keys, and some chains in a TOML file.\n- Create a directory in the bucket for each chain and key, like `/\u003cchain name\u003e/\u003ckey name\u003e/`\n- All signers have access to the entire s3 bucket, and can read/write at will, so assumption is they are all\n  trusted\n- `multisig tx push` takes an unsigned tx file and pushes it to the s3 directory along with data needed for signing (eg. account number, sequence number, chain id)\n- `multisig tx vote` generate a vote tx and push it to s3 directory\n- `multisig tx authz` generate an authz grant tx (delegate, withdraw, commission, vote, unbond, redelegate) or revoke an authz authorization\n- `multisig sign` fetches the unsigned tx and signing data for a given chain and key, signs it using the correct binary (eg. `gaiad tx sign unsigned.json ...`), and pushes the signature back to the directory\n- `multisig list` lists the files in a directory so you can see who has signed\n- `multisig broadcast` fetches all the data from a directory, compiles the signed tx (eg. `gaiad tx multisign unsigned.json ...`), broadcasts it using the configured node, and deletes all the files from the directory so signing can start fresh for a new tx\n- `multisig delete` deletes txs from the S3 directory\n\nEverything generally tries to clean up after itself, but files are created and\nremoved from the present working directory, so you may want to be somewhere\nclean. You can also use the `multisig raw` commands to clean-up the s3 bucket individual files \nor the `multisig delete` to clean-up multiple files at once.\n\nNote that s3 doesn't actually have directories, everything is just a file in the\nbucket, but files can be prefixed with what looks like directory paths. So the\nappearance of a \"directory\" is just an empty object with a name ending in a `/`.\n\n## Install\n\n```\ngit clone https://github.com/informalsystems/multisig\ncd multisig\ngo install\n```\n\nMake sure your `$HOME/go/bin` or your `$GOPATH/bin` is on your `$PATH`.\n\nThen \n\n```\nmultisig help\n```\n\nfor the list of commands and options.\n\n## Configure\n\n`multisig` uses a simple `config.toml` file. \nPath to config file may be specified via `--config` flag. \nIf the config path isn't specified explicitly, multisig will look for it in the current working directory.\nIf config file is not present in the current working directory, multisig will look for it in `~/.mulitisig/config.toml`.\nA documented example file is provided in `data/config.toml`. Copy this example\nfile to your current directory or to `~/.multisig/` and modify it as necessary.\n\nYou will need to:\n\n- Configure your AWS Bucket\n- Configure your Keys\n- Configure your Chains\n\n### Configure your AWS Bucket\n\nEach user will need an AWS Access Key ID and Secret Access Key that gives them\nread/write access to the bucket.\n\nIn the `[aws]` section of the multisig config, each user must set the  `bucket`, \n`bucketregion`, `pub`, and `priv` fields \nwith the bucket name, AWS region of the bucket, Access Key ID, and Secret Access Key.\n\n```\n# aws credentials\n\n[aws]\nbucket = \"\u003cbucketName\u003e\"         # s3 bucket name\nbucketregion = \"\u003cbucketRegion\u003e\" # aws bucket region\npub = \"\u003caccess key id\u003e\"         # Access Key ID\npriv = \"\u003csecret access key\u003e\"    # Secret Access Key\n```\n\nIf you are setting up the bucket for the first time, you can create an AWS IAM Policy that restricts access to a single bucket and attach\nit to a User or Group:\n\n```\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"ListObjectsInBucket\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\"s3:ListBucket\"],\n            \"Resource\": [\"arn:aws:s3:::bucket-name\"]\n        },\n        {\n            \"Sid\": \"AllObjectActions\",\n            \"Effect\": \"Allow\",\n            \"Action\": \"s3:*Object\",\n            \"Resource\": [\"arn:aws:s3:::bucket-name/*\"]\n        }\n    ]\n}\n```\n\nSee [Source](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_rw-bucket.html).\n\n### Configure you Keys\n\nYou can specify multiple keys. Each key gets its own `[[keys]]` table. \nEach key must have a `name` used by all signers. The `name` is a high level name for this key\nthat is independent of any chain or any name in a keystore.\nThe key must also specify its multisig `address`.\nThe address can be specified using any bech32 prefix, it doesn't matter if its\n`cosmos1` or `osmo1` or whatever. The key itself is chain agnostic.\n\nEach user may also specify a `localname` for the multisig key if they refer to it with a different name in their \nlocal keystore than the shared `name`. If `localname` is not specified, it defaults to `name`.\n\nNote this means that each key is expected to have the same local name in each binary's keystore (ie.\nif its called `mycorp-multisig` in `gaiad`, call it `mycorp-multisig` in `osmod`)!\n\nAs an example:\n\n```\n[[keys]]\nname = \"mycorp-main\"            # name of this multisig key - same for everyone\naddress = \"cosmos1...\"          # bech32 address of the key - same for everyone\nlocalname = \"mycorp-multisig\"   # name of this key in a signer's local keystore - can be different for everyone\n```\n\n### Configure gas\n\nIf you specify a default value for `gas` in the configuration file those will be used instead of the hard-coded \nvalues coded in the tool.\n\nFor example, to set a default gas of `300000` add this to the config file:\n```\ndefaultGas = 300000\n```\n\n\u003e Note: multisig also supports flags that you can specify gas and fees for transaction commands.\n\n### Configure your Chains\n\nYou can specify multiple chains. Each chain gets its own `[[chains]]` table.\nIt should include:\n\n- a `name` for the chain\n- the `binary` used to generate, sign, and broadcast txs\n- the bech32 `prefix` for addresses\n- the chain `id` for signing\n- the `denom` for a particular chain (e.g. `uatom`)\n- an optional `node` to interact with (for commands that can use/require nodes)\n\n```\n[[chains]]\nname = \"cosmos\"                 # name of the chain\nbinary = \"gaiad\"                # name of binary\nprefix = \"cosmos\"               # bech32 prefix\nid = \"cosmoshub-4\"              # chain-id\ndenom = \"uatom\"                 # native denom\nnode = \"http://localhost:26657\" # a synced node - only needed for `tx` and `broadcast` commands\n```\n\n## Run\n\nCommands:\n\n| Command                                                            | Command Line         |\n|--------------------------------------------------------------------|----------------------|\n| Broadcast a transaction to the blockchain                          | `multisig broadcast` |\n| Delete transaction files from S3                                   | `multisig delete`    |\n| Help information                                                   | `multisig help`      |\n| List transaction files on S3                                       | `multisig list`      |\n| Raw operations commands on S3 and utilities (e.g. convert address) | `multisig raw`       |\n| Sign a transaction locally and upload the signature to S3          | `multisig sign`      |\n| Create transaction files and upload to S3                          | `multisig tx`        |\n\n## Tx\n\nThe multisig tx command allows you to push transactions to S3. You can push `unsigned.json` transactions that are manually generated\nor you can use commands to generate the transactions and push it automatically to S3.\n\n### tx push\n```\nmultisig tx push \u003cunsigned tx file\u003e \u003cchain name\u003e \u003ckey name\u003e\n```\n\nThis will push the unsigned tx file (`e.g unsigned.json`) to the directory in the s3 bucket for the specified chain and key (ie. `/\u003cchain name\u003e/\u003ckey name\u003e/0`). \n\nIt will also fetch the account number and sequence number from the given `--node \u003cnode address\u003e`,\nand push a file to the bucket called `signdata.json` containing the account number, sequence number, and chain ID.\nThe sequence and account number can be overwriten or specified without a node\nusing the `--sequence` and `--account` flags\n\n\u003e Note: if you use `--node` its shelling out to the `\u003cbinary\u003e query account \u003caddress\u003e`\ncommand and parsing the response. \n\nThis assumes that the `\u003cbinary\u003e` (e.g gaiad) is properly installed on the machine and accessible (can be executed from a command prompt e.g. `$\u003e gaiad`) . The `\u003cbinary\u003e` name is retrieved from the config.toml file.\n\nTo push multiple txs for the same chain and key, use the `--additional` flag.\nEach additional tx will increment the path suffix and the sequence number. For\nexample, after pushing two txs for the same chain/key pair, you'd have:\n\n```\ncosmos/\ncosmos/my-key/\ncosmos/my-key/0/signdata.json\ncosmos/my-key/0/unsigned.json\ncosmos/\ncosmos/my-key/\ncosmos/my-key/1/signdata.json\ncosmos/my-key/1/unsigned.json\n```\n\nTo overwrite the first tx, use `--force`.\n\n### tx vote\n\n```\nmultisig tx vote \u003cchain name\u003e \u003ckey name\u003e \u003cproposal number\u003e \u003cvote option\u003e [flags]\n```\n\nThis will generate a tx for a governance proposal vote and it will push it to s3 directly. You will need to specify the proposal number and the vote (e.g. yes, no).\n\n### tx withdraw\n\n```\nmultisig tx withdraw \u003cchain name\u003e \u003ckey name\u003e\n```\n\nThis will generate a tx for withdraw all rewards for the account, and it will push it to s3 directly.\n\n### tx claim-validator\n\n```\nmultisig tx claim-validator \u003cchain name\u003e \u003ckey name\u003e \u003cvalidator_address\u003e\n```\n\nThis will generate a tx to claim the rewards and commission from a validator account, and it will push it to s3 directly.\n\n### tx authz grant\n\n```\nmultisig tx authz grant \u003cchain name\u003e \u003ckey name\u003e \u003cgrantee address\u003e \u003cdelegate|withdraw|commission|vote|unbond|redelegate\u003e \u003cexpiration in days\u003e\n```\n\nThis will generate a tx to grant authz permissions to a particular account (grantee). You will also need to specify the message-type that \nyou want to grant permission. Currently, only withdraw, commission, delegate, vote are supported. You also need to specify the expiration for\nthis grant, for example to grant permissions for 30 days please specify '30' as the '\u003cexpiration\u003e parameter.'\n\n### tx authz revoke\n\n```\nmultisig tx authz revoke \u003cchain name\u003e \u003ckey name\u003e \u003cgrantee address\u003e \u003cdelegate|withdraw|commission|vote|unbond|redelegate\u003e [flags]\n```\n\nThis will generate a tx to revoke a previously granted authz permission\n\n## List\n\nTo see the files in the directory of a chain and key:\n\n```\nmultisig list \u003cchain name\u003e \u003ckey name\u003e \n```\n\nTo list all the files in the bucket:\n\n```\nmultisig list --all\n```\n\nExample output:k\n\n```\n$ multisig list --all\ncosmos/\ncosmos/mycorp-main/\ncosmos/mycorp-validator/\njuno/\njuno/mycorp-main/\nosmosis/\nosmosis/mycorp-main/\nosmosis/mycorp-main/0/eb.json\nosmosis/mycorp-main/0/signdata.json\nosmosis/mycorp-main/0/unsigned.json\n```\n\nThis shows all the chain/key pairs that have been setup. All of them are empty\nexcept `osmosis/mycorp-main` which has one signature (`eb.json`).\n\n## Delete\n\nTo delete multiple files from S3 for a particular chain/key pair:\n\n```\n multisig delete \u003cchain name\u003e \u003ckey name\u003e [flags]\n```\n\n## Sign\n\nTo sign a tx:\n\n```\nmultisig sign \u003cchain name\u003e \u003ckey name\u003e --from \u003clocal signing key\u003e  --index \u003ctx\nindex\u003e\n```\n\nWhere `--from` is the name of the key in your local keystore, the same as you would provide to `--from` in `gaiad` or other Cosmos-SDK binaries, and `--index` is the tx index to sign for (default 0).\n\n## Broadcast\n\nTo assemble the signed tx and broadcast it, run:\n\n```\nmultisig broadcast \u003cchain name\u003e \u003ckey name\u003e\n```\n\nThe `--index` flag can be used to sign a transaction under that index (default 0). Note that transactions must be\nbroadcast in the index sequential order (e.g. 0, 1, 2).\n\nThe `--node` flag can be used to overwrite what's in the config file.\n\nThe `--key` flag can be used to specify the local multisig key name.\n\n## Raw\n\nThere are a set of `raw` subcommands for direct manipulation of bucket objects.\nThis is mostly for debugging purposes and generally should not need to be used.\nSee `multisig raw --help` and the help menu for each subcommand for more info.\n\n## Running the tests\n\nThe tests are made in an integrational manner to test the things on the real chain.\nTo bootstrap the tests a local container is launched with an instance of gaia, minio, and multisig tool.\nEnsure you have docker installed and running before launching the tests.\nTo run the tests use the following command in project's directory:\n\n```\n./run_tests.sh\n```\n\nThe command will pull the necessary images and will build the gaia from scratch so the first run can be time-consuming.\n\n## TODO\n\n### High Priority\n\n- add denoms to chains and have `tx push` validate txs are using correct denoms\n- tx push should check fees and gas are high enough\n- `broadcast` should log the tx once its complete (maybe a log file\n  in each top level chain directory?) - should include the key, tx id, and the description \n- need a way to assign local key names (`--from`) to keys (possibly on a per-chain basis)\n- use `--broadcast-mode block` ?\n- new command to show unclaimed rewards for all addresses on all networks\n\n### Mid Priority\n\n- simulate tx to estimate gas\n- add a command for porting a multisig from one binary's keystore to another\n  (ie. decoding the bech32 for each key and running `keys add` on the new\n  binary)\n- proper error handling - sometimes we just print a message and return no error,\n  but then the exit code is still 0\n- make tx and query response parsing more robust (currently shelling out to CLI\n  commands - should we be using the REST server ? maybe 26657 nodes are more\n  available than rest ? )\n\n### Lower Priority\n\n- Use the https://github.com/cosmos/chain-registry for configuring chains instead of the\n  config.toml ?\n- other features to better manage multisigs and keystores across binaries ?!\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finformalsystems%2Fmultisig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finformalsystems%2Fmultisig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finformalsystems%2Fmultisig/lists"}