Skip to content

Commit

Permalink
Remove write lock option from the platformvm API (#2157)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph authored Oct 11, 2023
1 parent 9725095 commit 2eb6e84
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 35 deletions.
116 changes: 108 additions & 8 deletions vms/platformvm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ func (s *Service) GetHeight(r *http.Request, _ *struct{}, response *api.GetHeigh
zap.String("method", "getHeight"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

ctx := r.Context()
height, err := s.vm.GetCurrentHeight(ctx)
response.Height = json.Uint64(height)
Expand Down Expand Up @@ -137,6 +140,9 @@ func (s *Service) ExportKey(_ *http.Request, args *ExportKeyArgs, reply *ExportK
return fmt.Errorf("couldn't parse %s to address: %w", args.Address, err)
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -176,6 +182,9 @@ func (s *Service) ImportKey(_ *http.Request, args *ImportKeyArgs, reply *api.JSO
return fmt.Errorf("problem formatting address: %w", err)
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -221,12 +230,14 @@ func (s *Service) GetBalance(_ *http.Request, args *GetBalanceRequest, response
logging.UserStrings("addresses", args.Addresses),
)

// Parse to address
addrs, err := avax.ParseServiceAddresses(s.addrManager, args.Addresses)
if err != nil {
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

utxos, err := avax.GetAllUTXOs(s.vm.state, addrs)
if err != nil {
return fmt.Errorf("couldn't get UTXO set of %v: %w", args.Addresses, err)
Expand Down Expand Up @@ -341,6 +352,9 @@ func (s *Service) CreateAddress(_ *http.Request, args *api.UserPass, response *a
logging.UserString("username", args.Username),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand All @@ -367,6 +381,9 @@ func (s *Service) ListAddresses(_ *http.Request, args *api.UserPass, response *a
logging.UserString("username", args.Username),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -446,6 +463,10 @@ func (s *Service) GetUTXOs(_ *http.Request, args *api.GetUTXOsArgs, response *ap
if limit <= 0 || builder.MaxPageSize < limit {
limit = builder.MaxPageSize
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

if sourceChain == s.vm.ctx.ChainID {
utxos, endAddr, endUTXOID, err = avax.GetPaginatedUTXOs(
s.vm.state,
Expand Down Expand Up @@ -531,6 +552,9 @@ func (s *Service) GetSubnets(_ *http.Request, args *GetSubnetsArgs, response *Ge
zap.String("method", "getSubnets"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

getAll := len(args.IDs) == 0
if getAll {
subnets, err := s.vm.state.GetSubnets() // all subnets
Expand Down Expand Up @@ -656,6 +680,9 @@ func (s *Service) GetStakingAssetID(_ *http.Request, args *GetStakingAssetIDArgs
return nil
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

transformSubnetIntf, err := s.vm.state.GetSubnetTransformation(args.SubnetID)
if err != nil {
return fmt.Errorf(
Expand Down Expand Up @@ -757,8 +784,10 @@ func (s *Service) GetCurrentValidators(_ *http.Request, args *GetCurrentValidato
vdrToDelegators := map[ids.NodeID][]platformapi.PrimaryDelegator{}

// Create set of nodeIDs
nodeIDs := set.Set[ids.NodeID]{}
nodeIDs.Add(args.NodeIDs...)
nodeIDs := set.Of(args.NodeIDs...)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

numNodeIDs := nodeIDs.Len()
targetStakers := make([]*state.Staker, 0, numNodeIDs)
Expand Down Expand Up @@ -972,8 +1001,10 @@ func (s *Service) GetPendingValidators(_ *http.Request, args *GetPendingValidato
reply.Delegators = []interface{}{}

// Create set of nodeIDs
nodeIDs := set.Set[ids.NodeID]{}
nodeIDs.Add(args.NodeIDs...)
nodeIDs := set.Of(args.NodeIDs...)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

numNodeIDs := nodeIDs.Len()
targetStakers := make([]*state.Staker, 0, numNodeIDs)
Expand Down Expand Up @@ -1081,6 +1112,9 @@ func (s *Service) GetCurrentSupply(r *http.Request, args *GetCurrentSupplyArgs,
zap.String("method", "getCurrentSupply"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

supply, err := s.vm.state.GetCurrentSupply(args.SubnetID)
if err != nil {
return fmt.Errorf("fetching current supply failed: %w", err)
Expand Down Expand Up @@ -1207,6 +1241,9 @@ func (s *Service) AddValidator(_ *http.Request, args *AddValidatorArgs, reply *a
return fmt.Errorf("problem while parsing reward address: %w", err)
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1317,6 +1354,9 @@ func (s *Service) AddDelegator(_ *http.Request, args *AddDelegatorArgs, reply *a
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1423,6 +1463,9 @@ func (s *Service) AddSubnetValidator(_ *http.Request, args *AddSubnetValidatorAr
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1505,6 +1548,9 @@ func (s *Service) CreateSubnet(_ *http.Request, args *CreateSubnetArgs, response
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1599,6 +1645,9 @@ func (s *Service) ExportAVAX(_ *http.Request, args *ExportAVAXArgs, response *ap
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1685,6 +1734,9 @@ func (s *Service) ImportAVAX(_ *http.Request, args *ImportAVAXArgs, response *ap
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1789,8 +1841,7 @@ func (s *Service) CreateBlockchain(_ *http.Request, args *CreateBlockchainArgs,
}
// If creating AVM instance, use secp256k1fx
// TODO: Document FXs and have user specify them in API call
fxIDsSet := set.Set[ids.ID]{}
fxIDsSet.Add(fxIDs...)
fxIDsSet := set.Of(fxIDs...)
if vmID == constants.AVMID && !fxIDsSet.Contains(secp256k1fx.ID) {
fxIDs = append(fxIDs, secp256k1fx.ID)
}
Expand All @@ -1805,6 +1856,9 @@ func (s *Service) CreateBlockchain(_ *http.Request, args *CreateBlockchainArgs,
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

user, err := keystore.NewUserFromKeystore(s.vm.ctx.Keystore, args.Username, args.Password)
if err != nil {
return err
Expand Down Expand Up @@ -1878,6 +1932,9 @@ func (s *Service) GetBlockchainStatus(r *http.Request, args *GetBlockchainStatus
return errMissingBlockchainID
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

// if its aliased then vm created this chain.
if aliasedID, err := s.vm.Chains.Lookup(args.BlockchainID); err == nil {
if s.nodeValidates(aliasedID) {
Expand Down Expand Up @@ -1987,6 +2044,9 @@ func (s *Service) ValidatedBy(r *http.Request, args *ValidatedByArgs, response *
zap.String("method", "validatedBy"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

var err error
ctx := r.Context()
response.SubnetID, err = s.vm.GetSubnetID(ctx, args.BlockchainID)
Expand All @@ -2010,6 +2070,9 @@ func (s *Service) Validates(_ *http.Request, args *ValidatesArgs, response *Vali
zap.String("method", "validates"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

if args.SubnetID != constants.PrimaryNetworkID {
subnetTx, _, err := s.vm.state.GetTx(args.SubnetID)
if err != nil {
Expand Down Expand Up @@ -2066,6 +2129,9 @@ func (s *Service) GetBlockchains(_ *http.Request, _ *struct{}, response *GetBloc
zap.String("method", "getBlockchains"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

subnets, err := s.vm.state.GetSubnets()
if err != nil {
return fmt.Errorf("couldn't retrieve subnets: %w", err)
Expand Down Expand Up @@ -2119,7 +2185,6 @@ func (s *Service) GetBlockchains(_ *http.Request, _ *struct{}, response *GetBloc
return nil
}

// IssueTx issues a tx
func (s *Service) IssueTx(_ *http.Request, args *api.FormattedTx, response *api.JSONTxID) error {
s.vm.ctx.Log.Debug("API called",
zap.String("service", "platform"),
Expand All @@ -2134,6 +2199,10 @@ func (s *Service) IssueTx(_ *http.Request, args *api.FormattedTx, response *api.
if err != nil {
return fmt.Errorf("couldn't parse tx: %w", err)
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

if err := s.vm.Builder.AddUnverifiedTx(tx); err != nil {
return fmt.Errorf("couldn't issue tx: %w", err)
}
Expand All @@ -2148,6 +2217,9 @@ func (s *Service) GetTx(_ *http.Request, args *api.GetTxArgs, response *api.GetT
zap.String("method", "getTx"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

tx, _, err := s.vm.state.GetTx(args.TxID)
if err != nil {
return fmt.Errorf("couldn't get tx: %w", err)
Expand Down Expand Up @@ -2187,6 +2259,9 @@ func (s *Service) GetTxStatus(_ *http.Request, args *GetTxStatusArgs, response *
zap.String("method", "getTxStatus"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

_, txStatus, err := s.vm.state.GetTx(args.TxID)
if err == nil { // Found the status. Report it.
response.Status = txStatus
Expand Down Expand Up @@ -2280,6 +2355,9 @@ func (s *Service) GetStake(_ *http.Request, args *GetStakeArgs, response *GetSta
return err
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

currentStakerIterator, err := s.vm.state.GetCurrentStakerIterator()
if err != nil {
return err
Expand Down Expand Up @@ -2370,6 +2448,9 @@ func (s *Service) GetMinStake(_ *http.Request, args *GetMinStakeArgs, reply *Get
return nil
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

transformSubnetIntf, err := s.vm.state.GetSubnetTransformation(args.SubnetID)
if err != nil {
return fmt.Errorf(
Expand Down Expand Up @@ -2451,6 +2532,10 @@ func (s *Service) GetMaxStakeAmount(_ *http.Request, args *GetMaxStakeAmountArgs
if startTime.After(endTime) {
return errStartAfterEndTime
}

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

now := s.vm.state.GetTimestamp()
if startTime.Before(now) {
return errStartTimeInThePast
Expand Down Expand Up @@ -2494,6 +2579,9 @@ func (s *Service) GetRewardUTXOs(_ *http.Request, args *api.GetTxArgs, reply *Ge
zap.String("method", "getRewardUTXOs"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

utxos, err := s.vm.state.GetRewardUTXOs(args.TxID)
if err != nil {
return fmt.Errorf("couldn't get reward UTXOs: %w", err)
Expand Down Expand Up @@ -2530,6 +2618,9 @@ func (s *Service) GetTimestamp(_ *http.Request, _ *struct{}, reply *GetTimestamp
zap.String("method", "getTimestamp"),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

reply.Timestamp = s.vm.state.GetTimestamp()
return nil
}
Expand Down Expand Up @@ -2615,6 +2706,9 @@ func (s *Service) GetValidatorsAt(r *http.Request, args *GetValidatorsAtArgs, re
zap.Stringer("subnetID", args.SubnetID),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

ctx := r.Context()
var err error
reply.Validators, err = s.vm.GetValidatorSet(ctx, height, args.SubnetID)
Expand All @@ -2632,6 +2726,9 @@ func (s *Service) GetBlock(_ *http.Request, args *api.GetBlockArgs, response *ap
zap.Stringer("encoding", args.Encoding),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

block, err := s.vm.manager.GetStatelessBlock(args.BlockID)
if err != nil {
return fmt.Errorf("couldn't get block with id %s: %w", args.BlockID, err)
Expand Down Expand Up @@ -2662,6 +2759,9 @@ func (s *Service) GetBlockByHeight(_ *http.Request, args *api.GetBlockByHeightAr
zap.Stringer("encoding", args.Encoding),
)

s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

blockID, err := s.vm.state.GetBlockIDAtHeight(uint64(args.Height))
if err != nil {
return fmt.Errorf("couldn't get block at height %d: %w", args.Height, err)
Expand Down
Loading

0 comments on commit 2eb6e84

Please sign in to comment.