Multi-signature workflow support (#3264)

- New keys add --multisig flag to store multisig keys
  locally.
- New multisign command to generate multisig
  signatures.
- New sign --multisig flag to enable multisig mode.
- Add multisig transactions support in ante handler.
- gaiad add-genesis-account can now take both account
  addresses and key names.

Closes: #3198
This commit is contained in:
Alessio Treglia
2019-01-16 09:30:57 -08:00
committed by Jack Zampolin
parent eff1f7ca10
commit 26cb0a125a
18 changed files with 728 additions and 51 deletions
@@ -3,6 +3,7 @@ package cli
import (
"encoding/hex"
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
+110 -4
View File
@@ -87,15 +87,36 @@ Note that this is the Tendermint signing key, _not_ the operator key you will us
We strongly recommend _NOT_ using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds.
:::
#### Multisig public keys
#### Generate multisig public keys
You can generate and print a multisig public key by typing:
```bash
gaiacli show --multisig-threshold K name1 name2 name3 [...]
gaiacli keys add --multisig=name1,name2,name3[...] --multisig-threshold=K new_key_name
```
`K` is the minimum weight, e.g. minimum number of private keys that must have signed the transactions that carry the generated public key.
`K` is the minimum number of private keys that must have signed the
transactions that carry the public key's address as signer.
The `--multisig` flag must contain the name of public keys that will be combined into a
public key that will be generated and stored as `new_key_name` in the local database.
All names supplied through `--multisig` must already exist in the local database. Unless
the flag `--nosort` is set, the order in which the keys are supplied on the command line
does not matter, i.e. the following commands generate two identical keys:
```bash
gaiacli keys add --multisig=foo,bar,baz --multisig-threshold=2 multisig_address
gaiacli keys add --multisig=baz,foo,bar --multisig-threshold=2 multisig_address
```
Multisig addresses can also be generated on-the-fly and printed through the which command:
```bash
gaiacli keys show --multisig-threshold K name1 name2 name3 [...]
```
For more information regarding how to generate, sign and broadcast transactions with a
multi signature account see [Multisig Transactions](#multisig-transactions).
### Account
@@ -182,7 +203,7 @@ gaiacli tx sign \
unsignedSendTx.json > signedSendTx.json
```
You can validate the transaction's signagures by typing the following:
You can validate the transaction's signatures by typing the following:
```bash
gaiacli tx sign --validate-signatures signedSendTx.json
@@ -576,3 +597,88 @@ gaiacli query gov param voting
gaiacli query gov param tallying
gaiacli query gov param deposit
```
### Multisig transactions
Multisig transactions require signatures of multiple private keys. Thus, generating and signing
a transaction from a multisig account involve cooperation among the parties involved. A multisig
transaction can be initiated by any of the key holders, and at least one of them would need to
import other parties' public keys into their local database and generate a multisig public key
in order to finalize and broadcast the transaction.
For example, given a multisig key comprising the keys `p1`, `p2`, and `p3`, each of which is held
by a distinct party, the user holding `p1` would require to import both `p2` and `p3` in order to
generate the multisig account public key:
```
gaiacli keys add \
--pubkey=cosmospub1addwnpepqtd28uwa0yxtwal5223qqr5aqf5y57tc7kk7z8qd4zplrdlk5ez5kdnlrj4 \
p2
gaiacli keys add \
--pubkey=cosmospub1addwnpepqgj04jpm9wrdml5qnss9kjxkmxzywuklnkj0g3a3f8l5wx9z4ennz84ym5t \
p3
gaiacli keys add \
--multisig-threshold=2
--multisig=p1,p2,p3
p1p2p3
```
A new multisig public key `p1p2p3` has been stored, and its address will be
used as signer of multisig transactions:
```bash
gaiacli keys show --address p1p2p3
```
The first step to create a multisig transaction is to initiate it on behalf
of the multisig address created above:
```bash
gaiacli tx send \
--from=<multisig_address> \
--to=cosmos1570v2fq3twt0f0x02vhxpuzc9jc4yl30q2qned \
--amount=10stake \
--generate-only > unsignedTx.json
```
The file `unsignedTx.json` contains the unsigned transaction encoded in JSON.
`p1` can now sign the transaction with its own private key:
```bash
gaiacli tx sign \
--multisig=<multisig_address> \
--name=p1 \
--output-document=p1signature.json \
unsignedTx.json
```
Once the signature is generated, `p1` transmits both `unsignedTx.json` and
`p1signature.json` to `p2` or `p3`, which in turn will generate their
respective signature:
```bash
gaiacli tx sign \
--multisig=<multisig_address> \
--name=p2 \
--output-document=p2signature.json \
unsignedTx.json
```
`p1p2p3` is a 2-of-3 multisig key, therefore one additional signature
is sufficient. Any the key holders can now generate the multisig
transaction by combining the required signature files:
```bash
gaiacli tx multisign \
unsignedTx.json \
p1p2p3 \
p1signature.json p2signature.json > signedTx.json
```
The transaction can now be sent to the node:
```bash
gaiacli tx broadcast signedTx.json
```