-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
(cherry picked from commit d4d27e1) closes: #8776 Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: Alessio Treglia <alessio@tendermint.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Anil Kumar Kammari <anil@vitwit.com>
- Loading branch information
1 parent
e23c0ce
commit 1e17860
Showing
5 changed files
with
170 additions
and
3 deletions.
There are no files selected for viewing
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,88 @@ | ||
package multisig | ||
|
||
import ( | ||
types "github.com/cosmos/cosmos-sdk/codec/types" | ||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
) | ||
|
||
// tmMultisig implements a K of N threshold multisig. It is used for | ||
// Amino JSON marshaling of LegacyAminoPubKey (see below for details). | ||
// | ||
// This struct is copy-pasted from: | ||
// https://github.com/tendermint/tendermint/blob/v0.33.9/crypto/multisig/threshold_pubkey.go | ||
// | ||
// This struct was used in the SDK <=0.39. In 0.40 and the switch to protobuf, | ||
// it has been converted to LegacyAminoPubKey. However, there's one difference: | ||
// the threshold field was an `uint` before, and an `uint32` after. This caused | ||
// amino marshaling to be breaking: amino marshals `uint32` as a JSON number, | ||
// and `uint` as a JSON string. | ||
// | ||
// In this file, we're overriding LegacyAminoPubKey's default JSON Amino | ||
// marshaling by using this struct. Please note that we are NOT overriding the | ||
// Amino binary marshaling, as that _might_ introduce breaking changes in the | ||
// keyring, where multisigs are amino-binary-encoded. | ||
// | ||
// ref: https://github.com/cosmos/cosmos-sdk/issues/8776 | ||
type tmMultisig struct { | ||
K uint `json:"threshold"` | ||
PubKeys []cryptotypes.PubKey `json:"pubkeys"` | ||
} | ||
|
||
// protoToTm converts a LegacyAminoPubKey into a tmMultisig. | ||
func protoToTm(protoPk *LegacyAminoPubKey) (tmMultisig, error) { | ||
var ok bool | ||
pks := make([]cryptotypes.PubKey, len(protoPk.PubKeys)) | ||
for i, pk := range protoPk.PubKeys { | ||
pks[i], ok = pk.GetCachedValue().(cryptotypes.PubKey) | ||
if !ok { | ||
return tmMultisig{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", (cryptotypes.PubKey)(nil), pk.GetCachedValue()) | ||
} | ||
} | ||
|
||
return tmMultisig{ | ||
K: uint(protoPk.Threshold), | ||
PubKeys: pks, | ||
}, nil | ||
} | ||
|
||
// tmToProto converts a tmMultisig into a LegacyAminoPubKey. | ||
func tmToProto(tmPk tmMultisig) (*LegacyAminoPubKey, error) { | ||
var err error | ||
pks := make([]*types.Any, len(tmPk.PubKeys)) | ||
for i, pk := range tmPk.PubKeys { | ||
pks[i], err = types.NewAnyWithValue(pk) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
return &LegacyAminoPubKey{ | ||
Threshold: uint32(tmPk.K), | ||
PubKeys: pks, | ||
}, nil | ||
} | ||
|
||
// MarshalAminoJSON overrides amino JSON unmarshaling. | ||
func (m LegacyAminoPubKey) MarshalAminoJSON() (tmMultisig, error) { //nolint:golint | ||
return protoToTm(&m) | ||
} | ||
|
||
// UnmarshalAminoJSON overrides amino JSON unmarshaling. | ||
func (m *LegacyAminoPubKey) UnmarshalAminoJSON(tmPk tmMultisig) error { | ||
protoPk, err := tmToProto(tmPk) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Instead of just doing `*m = *protoPk`, we prefer to modify in-place the | ||
// existing Anys inside `m` (instead of allocating new Anys), as so not to | ||
// break the `.compat` fields in the existing Anys. | ||
for i := range m.PubKeys { | ||
m.PubKeys[i].TypeUrl = protoPk.PubKeys[i].TypeUrl | ||
m.PubKeys[i].Value = protoPk.PubKeys[i].Value | ||
} | ||
m.Threshold = protoPk.Threshold | ||
|
||
return 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
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
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