fix(x/tx): concurrent map writes when calling GetSigners (#21073)
This commit is contained in:
parent
6b7e9f8935
commit
de0708b401
@ -214,6 +214,10 @@ func NewSimApp(
|
||||
signingCtx := interfaceRegistry.SigningContext()
|
||||
txConfig := authtx.NewTxConfig(appCodec, signingCtx.AddressCodec(), signingCtx.ValidatorAddressCodec(), authtx.DefaultSignModes)
|
||||
|
||||
if err := signingCtx.Validate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
std.RegisterLegacyAminoCodec(legacyAmino)
|
||||
std.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
|
||||
@ -33,6 +33,10 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos-
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Improvements
|
||||
|
||||
* [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also call Validate when creating the Context.
|
||||
|
||||
## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22
|
||||
|
||||
### Improvements
|
||||
|
||||
@ -3,6 +3,7 @@ package signing
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
cosmos_proto "github.com/cosmos/cosmos-proto"
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
@ -29,7 +30,7 @@ type Context struct {
|
||||
typeResolver protoregistry.MessageTypeResolver
|
||||
addressCodec address.Codec
|
||||
validatorAddressCodec address.Codec
|
||||
getSignersFuncs map[protoreflect.FullName]GetSignersFunc
|
||||
getSignersFuncs sync.Map
|
||||
customGetSignerFuncs map[protoreflect.FullName]GetSignersFunc
|
||||
maxRecursionDepth int
|
||||
}
|
||||
@ -110,7 +111,7 @@ func NewContext(options Options) (*Context, error) {
|
||||
typeResolver: protoTypes,
|
||||
addressCodec: options.AddressCodec,
|
||||
validatorAddressCodec: options.ValidatorAddressCodec,
|
||||
getSignersFuncs: map[protoreflect.FullName]GetSignersFunc{},
|
||||
getSignersFuncs: sync.Map{},
|
||||
customGetSignerFuncs: customGetSignerFuncs,
|
||||
maxRecursionDepth: options.MaxRecursionDepth,
|
||||
}
|
||||
@ -334,14 +335,17 @@ func (c *Context) getGetSignersFn(messageDescriptor protoreflect.MessageDescript
|
||||
if ok {
|
||||
return f, nil
|
||||
}
|
||||
f, ok = c.getSignersFuncs[messageDescriptor.FullName()]
|
||||
|
||||
loadedFn, ok := c.getSignersFuncs.Load(messageDescriptor.FullName())
|
||||
if !ok {
|
||||
var err error
|
||||
f, err = c.makeGetSignersFunc(messageDescriptor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.getSignersFuncs[messageDescriptor.FullName()] = f
|
||||
c.getSignersFuncs.Store(messageDescriptor.FullName(), f)
|
||||
} else {
|
||||
f = loadedFn.(GetSignersFunc)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
|
||||
@ -51,6 +51,21 @@ var deeplyNestedRepeatedSigner = &testpb.DeeplyNestedRepeatedSigner{
|
||||
},
|
||||
}
|
||||
|
||||
func TestGetGetSignersFnConcurrent(t *testing.T) {
|
||||
ctx, err := NewContext(Options{
|
||||
AddressCodec: dummyAddressCodec{},
|
||||
ValidatorAddressCodec: dummyValidatorAddressCodec{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
desc := (&testpb.RepeatedSigner{}).ProtoReflect().Descriptor()
|
||||
for i := 0; i < 50; i++ {
|
||||
go func() {
|
||||
_, _ = ctx.getGetSignersFn(desc)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSigners(t *testing.T) {
|
||||
ctx, err := NewContext(Options{
|
||||
AddressCodec: dummyAddressCodec{},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user