Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(codec)!: update codec to x/tx v0.6.0 #15873

Merged
merged 50 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
0331b97
fix for 32 bit platforms
kocubinski Apr 14, 2023
3310120
use interface for protoregistry.Files struct
kocubinski Apr 17, 2023
78247ad
Add default mode
kocubinski Apr 18, 2023
2d9bc1b
refactor(codec)!: update codec to x/tx v0.6.0
aaronc Apr 18, 2023
e997676
fix tests, add signing.Context.Validate
aaronc Apr 18, 2023
1bd5544
update go.mod
aaronc Apr 18, 2023
a7cc17a
CHANGELOG.md
aaronc Apr 18, 2023
0b531ed
add validation check
aaronc Apr 18, 2023
0dc96b8
go mod tidy
aaronc Apr 18, 2023
68273ac
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 19, 2023
93475ea
fix decode tests
kocubinski Apr 19, 2023
059e1ac
simpler
kocubinski Apr 19, 2023
a8628b8
try to fix validate
aaronc Apr 19, 2023
97aaef5
more hacky address codec fix
kocubinski Apr 20, 2023
7d83030
fix validate another way
aaronc Apr 20, 2023
2de4eed
Merge remote-tracking branch 'origin/aaronc/11275-update-codec' into …
aaronc Apr 20, 2023
a4ad892
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
aaronc Apr 20, 2023
ed17c8c
merge
aaronc Apr 20, 2023
bd2b706
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 20, 2023
c0f4eda
remove unused code
kocubinski Apr 20, 2023
e0a3553
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocubinski/x…
kocubinski Apr 20, 2023
2128b1a
Merge branch 'kocubinski/x-tx-0.5.x' into aaronc/11275-update-codec
kocubinski Apr 20, 2023
c9c34ed
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 25, 2023
f899dcf
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 25, 2023
5bd54fe
use x/tx v0.6.1
kocubinski Apr 25, 2023
4c34673
go mod tidy
kocubinski Apr 25, 2023
1e5b778
Squashed commit of the following:
kocubinski Apr 25, 2023
0439089
fix some errors
kocubinski Apr 25, 2023
b45e0bb
sensible refactor and cleanup for NewTxConfig
kocubinski Apr 26, 2023
f88ca77
delete unused code
kocubinski Apr 26, 2023
d568178
lint fix and rosetta go mod tidy
kocubinski Apr 26, 2023
8a00f65
Merge branch 'main' into aaronc/11275-update-codec
kocubinski Apr 26, 2023
9c76023
add comments
kocubinski Apr 26, 2023
409ed10
linting fixes
kocubinski Apr 26, 2023
76f5774
fix rosetta tests
kocubinski Apr 26, 2023
2dc5a5a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 26, 2023
c8c4893
gofumpt
kocubinski Apr 26, 2023
49541c4
clean up tx.ConfigOptions a bit
kocubinski Apr 26, 2023
e623044
fix usage
kocubinski Apr 26, 2023
2c71536
nit
kocubinski Apr 26, 2023
bf0830d
move variadic arg to options struct
kocubinski Apr 26, 2023
fe9f831
fix usage
kocubinski Apr 26, 2023
cae22dd
go mod tidy
kocubinski Apr 26, 2023
23398ce
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 26, 2023
1711502
fix failing simapp_v1 test
kocubinski Apr 26, 2023
ea46ef4
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
kocubinski Apr 26, 2023
f92230d
rosetta go.mod fix after merge
kocubinski Apr 26, 2023
5dae4ed
address review comments
aaronc Apr 27, 2023
8211a3a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11275…
aaronc Apr 27, 2023
506ecf9
remove unused import
kocubinski Apr 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (crypto) [#15070](https://github.com/cosmos/cosmos-sdk/pull/15070) `GenerateFromPassword` and `Cost` from `bcrypt.go` now take a `uint32` instead of a `int` type.
* (x/capability) [#15344](https://github.com/cosmos/cosmos-sdk/pull/15344) Capability module was removed and is now housed in [IBC-GO](https://github.com/cosmos/ibc-go).
* [#15299](https://github.com/cosmos/cosmos-sdk/pull/15299) remove `StdTx` transaction and signing APIs. No SDK version has actually supported `StdTx` since before Stargate.
* (codec) [#15600](https://github.com/cosmos/cosmos-sdk/pull/15600) add support for getting signers to `codec.Codec` and protoregistry support to `InterfaceRegistry`:
* `Codec` is now a private interface and has the methods `InterfaceRegistry`, `GetMsgAnySigners`, `GetMsgV1Signers`, and `GetMsgV2Signers` which will fail when using `AminoCodec`.
All implementations of `Codec` by other users must now embed an official implementation from the `codec` package.
* `InterfaceRegistry` is now a private interface and implements `protodesc.Resolver` plus the `RangeFiles` method
All implementations of `InterfaceRegistry` by other users must now embed the official implementation.
* `AminoCodec` is marked as deprecated.
* (codec) [#15600](https://github.com/cosmos/cosmos-sdk/pull/15600) [#15873](https://github.com/cosmos/cosmos-sdk/pull/15873) add support for getting signers to `codec.Codec` and `InterfaceRegistry`:
* `Codec` has new methods `InterfaceRegistry`, `GetMsgAnySigners`, `GetMsgV1Signers`, and `GetMsgV2Signers` as well as unexported methods. All implementations of `Codec` by other users must now embed an official implementation from the `codec` package.
* `InterfaceRegistry` is has unexported methods and implements `protodesc.Resolver` plus the `RangeFiles` and `SigningContext` methods. All implementations of `InterfaceRegistry` by other users must now embed the official implementation.
* `AminoCodec` is marked as deprecated and no longer implements `Codec.
* (x/crisis) [#15852](https://github.com/cosmos/cosmos-sdk/pull/15852) Crisis keeper now takes a instance of the address codec to be able to decode user addresses
* (x/slashing) [#15875](https://github.com/cosmos/cosmos-sdk/pull/15875) `x/slashing.NewAppModule` now requires an `InterfaceRegistry` parameter.
* (client) [#15822](https://github.com/cosmos/cosmos-sdk/pull/15822) The return type of the interface method `TxConfig.SignModeHandler` has been changed to `x/tx/signing.HandlerMap`.
Expand Down
28 changes: 4 additions & 24 deletions codec/amino_codec.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package codec

import (
"fmt"

"github.com/cosmos/gogoproto/proto"
protov2 "google.golang.org/protobuf/proto"

"github.com/cosmos/cosmos-sdk/codec/types"
)

// Deprecated: AminoCodec defines a codec that utilizes Codec for both binary and JSON
Expand All @@ -16,7 +11,10 @@ type AminoCodec struct {
*LegacyAmino
}

var _ Codec = &AminoCodec{}
var (
_ BinaryCodec = &AminoCodec{}
_ JSONCodec = &AminoCodec{}
)

// Deprecated: NewAminoCodec returns a reference to a new AminoCodec.
// Use NewLegacyAmino instead.
Expand Down Expand Up @@ -131,21 +129,3 @@ func (ac *AminoCodec) MarshalInterfaceJSON(i proto.Message) ([]byte, error) {
func (ac *AminoCodec) UnmarshalInterfaceJSON(bz []byte, ptr interface{}) error {
return ac.LegacyAmino.UnmarshalJSON(bz, ptr)
}

func (ac *AminoCodec) GetMsgAnySigners(*types.Any) ([]string, protov2.Message, error) {
return nil, nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) GetMsgV1Signers(proto.Message) ([]string, protov2.Message, error) {
return nil, nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) GetMsgV2Signers(protov2.Message) ([]string, error) {
return nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) InterfaceRegistry() types.InterfaceRegistry {
panic("amino codec does not support interface registry")
}

func (ac *AminoCodec) mustEmbedCodec() {}
6 changes: 3 additions & 3 deletions codec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ type (
// GetMsgAnySigners returns the signers of the given message encoded in a protobuf Any
// as well as the decoded google.golang.org/protobuf/proto.Message that was used to
// extract the signers so that this can be used in other contexts.
GetMsgAnySigners(msg *types.Any) ([]string, protov2.Message, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does changing this interface contract require a mention in the CHANGELOG?

Copy link
Member Author

@aaronc aaronc Apr 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's new anyway and there are CHANGELOG entries already for this addition

GetMsgAnySigners(msg *types.Any) ([][]byte, protov2.Message, error)

// GetMsgV2Signers returns the signers of the given message.
GetMsgV2Signers(msg protov2.Message) ([]string, error)
GetMsgV2Signers(msg protov2.Message) ([][]byte, error)

// GetMsgV1Signers returns the signers of the given message plus the
// decoded google.golang.org/protobuf/proto.Message that was used to extract the
// signers so that this can be used in other contexts.
GetMsgV1Signers(msg proto.Message) ([]string, protov2.Message, error)
GetMsgV1Signers(msg proto.Message) ([][]byte, protov2.Message, error)

// mustEmbedCodec requires that all implementations of Codec embed an official implementation from the codec
// package. This allows new methods to be added to the Codec interface without breaking backwards compatibility.
Expand Down
6 changes: 5 additions & 1 deletion codec/codec_common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ func testMarshalingTestCase(require *require.Assertions, tc testCase, m mustMars
}
}

func testMarshaling(t *testing.T, cdc codec.Codec) {
func testMarshaling(t *testing.T, cdc interface {
codec.BinaryCodec
codec.JSONCodec
},
) {
any, err := types.NewAnyWithValue(&testdata.Dog{Name: "rufus"})
require.NoError(t, err)

Expand Down
23 changes: 6 additions & 17 deletions codec/proto_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"

"cosmossdk.io/x/tx/signing"

"github.com/cosmos/cosmos-sdk/codec/types"
)

Expand All @@ -29,7 +27,6 @@ type ProtoCodecMarshaler interface {
// encoding.
type ProtoCodec struct {
interfaceRegistry types.InterfaceRegistry
getSignersCtx *signing.GetSignersContext
}

var (
Expand All @@ -39,16 +36,8 @@ var (

// NewProtoCodec returns a reference to a new ProtoCodec
func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
getSignersCtx, err := signing.NewGetSignersContext(
signing.GetSignersOptions{
ProtoFiles: interfaceRegistry,
})
if err != nil {
panic(err)
}
return &ProtoCodec{
interfaceRegistry: interfaceRegistry,
getSignersCtx: getSignersCtx,
}
}

Expand Down Expand Up @@ -277,7 +266,7 @@ func (pc *ProtoCodec) InterfaceRegistry() types.InterfaceRegistry {
return pc.interfaceRegistry
}

func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([]string, proto.Message, error) {
func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([][]byte, proto.Message, error) {
msgv2, err := anyutil.Unpack(&anypb.Any{
TypeUrl: msg.TypeUrl,
Value: msg.Value,
Expand All @@ -286,17 +275,17 @@ func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([]string, proto.Message,
return nil, nil, err
}

signers, err := pc.getSignersCtx.GetSigners(msgv2)
signers, err := pc.interfaceRegistry.SigningContext().GetSigners(msgv2)
return signers, msgv2, err
}

func (pc *ProtoCodec) GetMsgV2Signers(msg proto.Message) ([]string, error) {
return pc.getSignersCtx.GetSigners(msg)
func (pc *ProtoCodec) GetMsgV2Signers(msg proto.Message) ([][]byte, error) {
return pc.interfaceRegistry.SigningContext().GetSigners(msg)
}

func (pc *ProtoCodec) GetMsgV1Signers(msg gogoproto.Message) ([]string, proto.Message, error) {
func (pc *ProtoCodec) GetMsgV1Signers(msg gogoproto.Message) ([][]byte, proto.Message, error) {
if msgV2, ok := msg.(proto.Message); ok {
signers, err := pc.getSignersCtx.GetSigners(msgV2)
signers, err := pc.interfaceRegistry.SigningContext().GetSigners(msgV2)
return signers, msgV2, err
}
a, err := types.NewAnyWithValue(msg)
Expand Down
28 changes: 22 additions & 6 deletions codec/proto_codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/status"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoregistry"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
Expand Down Expand Up @@ -174,11 +175,16 @@ func BenchmarkProtoCodecMarshalLengthPrefixed(b *testing.B) {
}

func TestGetSigners(t *testing.T) {
interfaceRegistry := types.NewInterfaceRegistry()
interfaceRegistry, err := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
AddressCodec: testAddressCodec{},
ValidatorAddressCodec: testAddressCodec{},
ProtoFiles: protoregistry.GlobalFiles,
})
require.NoError(t, err)
cdc := codec.NewProtoCodec(interfaceRegistry)
testAddr := sdk.AccAddress([]byte("test"))
testAddr := sdk.AccAddress("test")
testAddrStr := testAddr.String()
testAddr2 := sdk.AccAddress([]byte("test2"))
testAddr2 := sdk.AccAddress("test2")
testAddrStr2 := testAddr2.String()

msgSendV1 := banktypes.NewMsgSend(testAddr, testAddr2, sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1))))
Expand All @@ -190,17 +196,27 @@ func TestGetSigners(t *testing.T) {

signers, msgSendV2Copy, err := cdc.GetMsgV1Signers(msgSendV1)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)
require.True(t, protov2.Equal(msgSendV2, msgSendV2Copy))

signers, err = cdc.GetMsgV2Signers(msgSendV2)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)

msgSendAny, err := types.NewAnyWithValue(msgSendV1)
require.NoError(t, err)
signers, msgSendV2Copy, err = cdc.GetMsgAnySigners(msgSendAny)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)
require.True(t, protov2.Equal(msgSendV2, msgSendV2Copy))
}

type testAddressCodec struct{}

func (t testAddressCodec) StringToBytes(text string) ([]byte, error) {
return sdk.AccAddressFromBech32(text)
}

func (t testAddressCodec) BytesToString(bz []byte) (string, error) {
return sdk.AccAddress(bz).String(), nil
}
64 changes: 58 additions & 6 deletions codec/types/interface_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"

"cosmossdk.io/core/address"

"cosmossdk.io/x/tx/signing"
)

// AnyUnpacker is an interface which allows safely unpacking types packed
Expand Down Expand Up @@ -65,6 +69,8 @@ type InterfaceRegistry interface {
// the entire FileDescriptorSet.
RangeFiles(f func(protoreflect.FileDescriptor) bool)

SigningContext() *signing.Context

// mustEmbedInterfaceRegistry requires that all implementations of InterfaceRegistry embed an official implementation
// from this package. This allows new methods to be added to the InterfaceRegistry interface without breaking
// backwards compatibility.
Expand Down Expand Up @@ -101,28 +107,60 @@ type interfaceRegistry struct {
interfaceImpls map[reflect.Type]interfaceMap
implInterfaces map[reflect.Type]reflect.Type
typeURLMap map[string]reflect.Type
signingCtx *signing.Context
}

type interfaceMap = map[string]reflect.Type

// NewInterfaceRegistry returns a new InterfaceRegistry
func NewInterfaceRegistry() InterfaceRegistry {
protoFiles, err := proto.MergedRegistry()
registry, err := NewInterfaceRegistryWithOptions(InterfaceRegistryOptions{
ProtoFiles: protoregistry.GlobalFiles,
AddressCodec: failingAddressCodec{},
ValidatorAddressCodec: failingAddressCodec{},
})
if err != nil {
panic(err)
}
return NewInterfaceRegistryWithProtoFiles(protoFiles)
return registry
}

// InterfaceRegistryOptions are options for creating a new InterfaceRegistry.
type InterfaceRegistryOptions struct {
// ProtoFiles is the set of files to use for the registry. It is required.
ProtoFiles *protoregistry.Files

// AddressCodec is the address codec to use for the registry. It is required.
AddressCodec address.Codec

// ValidatorAddressCodec is the validator address codec to use for the registry. It is required.
ValidatorAddressCodec address.Codec
}

// NewInterfaceRegistryWithProtoFiles returns a new InterfaceRegistry with the specified *protoregistry.Files instance.
func NewInterfaceRegistryWithProtoFiles(files *protoregistry.Files) InterfaceRegistry {
// NewInterfaceRegistryWithOptions returns a new InterfaceRegistry with the given options.
func NewInterfaceRegistryWithOptions(options InterfaceRegistryOptions) (InterfaceRegistry, error) {
if options.ProtoFiles == nil {
return nil, fmt.Errorf("proto files must be provided")
}

signingCtx, err := signing.NewContext(signing.Options{
FileResolver: options.ProtoFiles,
TypeResolver: nil,
AddressCodec: options.AddressCodec,
ValidatorAddressCodec: options.ValidatorAddressCodec,
})
if err != nil {
return nil, err
}

return &interfaceRegistry{
interfaceNames: map[string]reflect.Type{},
interfaceImpls: map[reflect.Type]interfaceMap{},
implInterfaces: map[reflect.Type]reflect.Type{},
typeURLMap: map[string]reflect.Type{},
Files: files,
}
Files: options.ProtoFiles,
signingCtx: signingCtx,
}, nil
}

func (registry *interfaceRegistry) RegisterInterface(protoName string, iface interface{}, impls ...proto.Message) {
Expand Down Expand Up @@ -314,6 +352,10 @@ func (registry *interfaceRegistry) Resolve(typeURL string) (proto.Message, error
return msg, nil
}

func (registry *interfaceRegistry) SigningContext() *signing.Context {
return registry.signingCtx
}

func (registry *interfaceRegistry) mustEmbedInterfaceRegistry() {}

// UnpackInterfaces is a convenience function that calls UnpackInterfaces
Expand All @@ -324,3 +366,13 @@ func UnpackInterfaces(x interface{}, unpacker AnyUnpacker) error {
}
return nil
}

type failingAddressCodec struct{}

func (f failingAddressCodec) StringToBytes(string) ([]byte, error) {
return nil, fmt.Errorf("InterfaceRegistry requires a proper address codec implementation to do address conversion")
}

func (f failingAddressCodec) BytesToString([]byte) (string, error) {
return "", fmt.Errorf("InterfaceRegistry requires a proper address codec implementation to do address conversion")
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
cosmossdk.io/log v1.0.0
cosmossdk.io/math v1.0.0
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc
cosmossdk.io/x/tx v0.5.5
cosmossdk.io/x/tx v0.6.1
github.com/99designs/keyring v1.2.1
github.com/armon/go-metrics v0.4.1
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816
Expand Down Expand Up @@ -162,6 +162,8 @@ require (

// Below are the long-lived replace of the Cosmos SDK
replace (
// TODO: remove after release 0.6.2
cosmossdk.io/x/tx => ./x/tx
// use cosmos fork of keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc h1:9piuA+NYmhe+SyMPtMoboLw/djgDbrI3dD5TG020Tnk=
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc/go.mod h1:UFF5rmjN7WYVfxo6ArdY/l1+yyWMURBWOmSJypGqFHQ=
cosmossdk.io/x/tx v0.5.5 h1:9XG3KOrqObt7Rw7KhT7fiqRd6EepUfmA9ERa8CHj1WM=
cosmossdk.io/x/tx v0.5.5/go.mod h1:Oh3Kh+IPOfMEILNxVd2e8SLqRrIjYHpdGBfDg4ghU/k=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
Expand Down
Loading