Skip to content

Race Condition May Result in Mismatch of Runtime and TrieState (GSR-08) #2402

@danforbes

Description

@danforbes

There is a concurrency issues related to fetching TrieState(nil) and GetRuntime(nil) separately, which may result in different blocks being used for the TrieState and Runtime. The impact is significant as the TrieState stores the execution code for a runtime and thus may result in an invalid bytecode being used by the runtime.

The function HandleSubmittedExtrinsic() is an RPC call that runs in parallel to block importation. It is possible for the block handler routine to import a new block within a single invocation of HandleSubmittedExtrinsic(), which means that the trie state and runtime state used by HandleSubmittedExtrinsic() would be for different blocks.

Consider first fetching the best block hash then passing this hash to each function. See the code snippet below for a potential implementation.

// HandleSubmittedExtrinsic is used to send a Transaction message containing a Extrinsic @ext
func (s *Service) HandleSubmittedExtrinsic(ext types.Extrinsic) error {
	if s.net == nil {
		return nil
	}
	bestBlockHash, err := s.blockState.BestBlockHash()
	if err != nil {
		return err
	}
	ts, err := s.storageState.TrieState(bestBlockHash)
	if err != nil {
		return err
	}
	rt, err := s.blockState.GetRuntime(bestBlockHash)
	if err != nil {
		logger.Critical("failed to get runtime")
		return err
	}
	rt.SetContextStorage(ts)
	// ...
}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions