-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Implicit type conversion (like bool <-> int, Bytes32 -> Root, etc) are often considered to be a not really good idea.
However, there are cases with the current beacon chain specs, which demand it.
- Modifying stable specs (like phase0) may be not desirable, e.g. see this discussion
- Implicit conversion of a Python list to SSZ
List/Vectorcan be clumsy and hinder readability
For example, compare
exposed_derived_secrets=[()] * EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS
vs
exposed_derived_secrets=Vector[List[ValidatorIndex, MAX_EARLY_DERIVED_SECRET_REVEALS * SLOTS_PER_EPOCH],
EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS](
[List[ValidatorIndex, MAX_EARLY_DERIVED_SECRET_REVEALS * SLOTS_PER_EPOCH]()] *
EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS
)
Often, a method or a constructor performs implicit conversion, like SSZ constructors or field setters. However, it's not clear how to express the conversion explicitly with type system.
For example, BeaconState has about 29 fields and many of them support implicit conversions, in the sense that if one constructs a BeconState or sets its field with a value of a wrong but compatible type, then the implicit conversion is performed. E.g. python list can be converted to SSZ List or Vector, int can be converted to uint64, bool can be converted to boolean, etc.
That can be in theory modeled with union types, e.g. fieldA: Union[PyList[ElemType],List[ElemType,...]], however, accessing such field will become a problem. Basically, one need to specify a different type signature for getter and setters (and perhaps, for constructors/copy methods of an enclosing object).
So, this looks like a rather ugly solution.
A simpler approach is to specify a list of admissible implicit conversions. For example, there can be rules like:
- if there is an expression
exprofPyList[U]type, but its expected type isList[T,N]. Convert theexprusingList[T,N](expr), provided thatUis a subtype ofTor can be converted toTusing implicit conversion rules. - python
boolcan be converted to SSZbooleanand vice versa, usingboolean(expr)orbool(expr) - exprs of
BytesNtypes can be implicitly converted to correspondingBytesNsubclasses (e.g.Root,BLSPubkey, etc)
Note however, the last kind of implicit conversion can still be dangerous, i.e. hide a potential bug. E.g. Root and Domain are both subclasses of Bytes32, so Domain is a subclass of Bytes32 and given the implicit conversion to Root, one can use Domain object where Root is expected. One thus may need to restrict such conversions to cases, where the lower bound is known, e.g. Bytes32 constant can be implicitly converted to Root or Domain, but not a variable of Bytes32 type,