-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ADR-005: Support multisig chain link (#708)
## Description Closes: #633 This PR implements ADR-005. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://docs.cosmos.network/v0.44/building-modules/intro.html) - [x] included the necessary unit and integration [tests](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#testing) - [x] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
- Loading branch information
Showing
43 changed files
with
3,957 additions
and
346 deletions.
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
.changeset/entries/a492eff6c4ec45c98cb555b14de9f27ba50da5b147ff05b7a4cb1707af73655c.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
type: feat | ||
module: x/profiles | ||
pull_request: 708 | ||
description: Added support for multisig chain links | ||
backward_compatible: false | ||
date: 2022-01-12T03:49:42.2638125Z |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package builder | ||
|
||
import ( | ||
"github.com/desmos-labs/desmos/v2/app/desmos/cmd/chainlink/types" | ||
"github.com/desmos-labs/desmos/v2/x/profiles/client/utils" | ||
) | ||
|
||
// ChainLinkJSONBuilder allows to build a ChainLinkJSON instance | ||
type ChainLinkJSONBuilder interface { | ||
BuildChainLinkJSON(chain types.Chain) (utils.ChainLinkJSON, error) | ||
} | ||
|
||
// ChainLinkJSONBuilderProvider allows to provide the provider ChainLinkJSONBuilder implementation based on whether | ||
// it should create the JSON chain link for single or | ||
type ChainLinkJSONBuilderProvider func(isSingleAccount bool) ChainLinkJSONBuilder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package multi | ||
|
||
import ( | ||
"encoding/hex" | ||
"fmt" | ||
"io/ioutil" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/tx/signing" | ||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
|
||
"github.com/desmos-labs/desmos/v2/app" | ||
"github.com/desmos-labs/desmos/v2/app/desmos/cmd/chainlink/getter" | ||
"github.com/desmos-labs/desmos/v2/app/desmos/cmd/chainlink/types" | ||
"github.com/desmos-labs/desmos/v2/x/profiles/client/utils" | ||
profilestypes "github.com/desmos-labs/desmos/v2/x/profiles/types" | ||
) | ||
|
||
// AccountChainLinkJSONBuilder implements the ChainLinkJSONBuilder for multi signature accounts | ||
type AccountChainLinkJSONBuilder struct { | ||
getter getter.MultiSignatureAccountReferenceGetter | ||
} | ||
|
||
// NewAccountChainLinkJSONBuilder returns a new AccountChainLinkJSONBuilder instance | ||
func NewAccountChainLinkJSONBuilder(getter getter.MultiSignatureAccountReferenceGetter) *AccountChainLinkJSONBuilder { | ||
return &AccountChainLinkJSONBuilder{ | ||
getter: getter, | ||
} | ||
} | ||
|
||
// BuildChainLinkJSON implements ChainLinkJSONBuilder | ||
func (b *AccountChainLinkJSONBuilder) BuildChainLinkJSON(chain types.Chain) (utils.ChainLinkJSON, error) { | ||
txFilePath, err := b.getter.GetMultiSignedTxFilePath() | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
signedChainID, err := b.getter.GetSignedChainID() | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
encodingConfig := app.MakeTestEncodingConfig() | ||
txCfg := encodingConfig.TxConfig | ||
|
||
// Read the transaction file | ||
bytes, err := ioutil.ReadFile(txFilePath) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Parse the transaction | ||
parsedTx, err := txCfg.TxJSONDecoder()(bytes) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Get the sign mode | ||
signMode := signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON | ||
|
||
// Wrap the transaction inside a builder to make it easier to get the signatures | ||
txBuilder, err := txCfg.WrapTxBuilder(parsedTx) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
sigs, err := txBuilder.GetTx().GetSignaturesV2() | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Make sure there is only one signature for the multisig account | ||
if len(sigs) != 1 { | ||
return utils.ChainLinkJSON{}, fmt.Errorf("invalid number of signatures") | ||
} | ||
|
||
// Re-create the bytes that have been signed in order to produce the signature | ||
signingData := authsigning.SignerData{AccountNumber: 0, Sequence: 0, ChainID: signedChainID} | ||
value, err := txCfg.SignModeHandler().GetSignBytes(signMode, signingData, parsedTx) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
addr, err := sdk.Bech32ifyAddressBytes(chain.Prefix, sigs[0].PubKey.Address().Bytes()) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
sigData, err := profilestypes.SignatureDataFromCosmosSignatureData(sigs[0].Data) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
return utils.NewChainLinkJSON( | ||
profilestypes.NewBech32Address(addr, chain.Prefix), | ||
profilestypes.NewProof(sigs[0].PubKey, sigData, hex.EncodeToString(value)), | ||
profilestypes.NewChainConfig(chain.Name), | ||
), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package single | ||
|
||
import ( | ||
"encoding/hex" | ||
|
||
"github.com/cosmos/cosmos-sdk/crypto/hd" | ||
"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/tx/signing" | ||
|
||
"github.com/desmos-labs/desmos/v2/app/desmos/cmd/chainlink/getter" | ||
"github.com/desmos-labs/desmos/v2/app/desmos/cmd/chainlink/types" | ||
"github.com/desmos-labs/desmos/v2/x/profiles/client/utils" | ||
profilestypes "github.com/desmos-labs/desmos/v2/x/profiles/types" | ||
) | ||
|
||
const ( | ||
KeyName = "desmos_chain_link_account" | ||
) | ||
|
||
// AccountChainLinkJSONBuilder implements the ChainLinkJSONBuilder for single signature accounts | ||
type AccountChainLinkJSONBuilder struct { | ||
getter getter.SingleSignatureAccountReferenceGetter | ||
} | ||
|
||
// NewAccountChainLinkJSONBuilder returns a new AccountChainLinkJSONBuilder instance | ||
func NewAccountChainLinkJSONBuilder(getter getter.SingleSignatureAccountReferenceGetter) *AccountChainLinkJSONBuilder { | ||
return &AccountChainLinkJSONBuilder{ | ||
getter: getter, | ||
} | ||
} | ||
|
||
// BuildChainLinkJSON implements ChainLinkJSONBuilder | ||
func (b *AccountChainLinkJSONBuilder) BuildChainLinkJSON(chain types.Chain) (utils.ChainLinkJSON, error) { | ||
mnemonic, err := b.getter.GetMnemonic() | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Create an in-memory keybase for signing | ||
keyBase := keyring.NewInMemory() | ||
_, err = keyBase.NewAccount(KeyName, mnemonic, "", chain.DerivationPath, hd.Secp256k1) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Generate the proof signing it with the key | ||
key, _ := keyBase.Key(KeyName) | ||
addr, _ := sdk.Bech32ifyAddressBytes(chain.Prefix, key.GetAddress()) | ||
value := []byte(addr) | ||
sig, pubkey, err := keyBase.Sign(KeyName, value) | ||
if err != nil { | ||
return utils.ChainLinkJSON{}, err | ||
} | ||
sigData := &profilestypes.SingleSignatureData{ | ||
Mode: signing.SignMode_SIGN_MODE_DIRECT, | ||
Signature: sig, | ||
} | ||
|
||
return utils.NewChainLinkJSON( | ||
profilestypes.NewBech32Address(addr, chain.Prefix), | ||
profilestypes.NewProof(pubkey, sigData, hex.EncodeToString(value)), | ||
profilestypes.NewChainConfig(chain.Name), | ||
), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.