Closed
Description
Rationale
Why should this feature exist?

As we can see from the cpu profiling. Most cpu time (*TypedData).HashStruct
spent on is about isPrimitiveTypeValid
, which is very slow because it use fmt.Sprintf
to do some simple formatting (see the following code)
This is the copied code from v1.14.6.
// github.com/ethereum/[email protected]/signer/core/apitypes/types.go:845
// Checks if the primitive value is valid
func isPrimitiveTypeValid(primitiveType string) bool {
if primitiveType == "address" ||
primitiveType == "address[]" ||
primitiveType == "bool" ||
primitiveType == "bool[]" ||
primitiveType == "string" ||
primitiveType == "string[]" ||
primitiveType == "bytes" ||
primitiveType == "bytes[]" ||
primitiveType == "int" ||
primitiveType == "int[]" ||
primitiveType == "uint" ||
primitiveType == "uint[]" {
return true
}
// For 'bytesN', 'bytesN[]', we allow N from 1 to 32
for n := 1; n <= 32; n++ {
// e.g. 'bytes28' or 'bytes28[]'
if primitiveType == fmt.Sprintf("bytes%d", n) || primitiveType == fmt.Sprintf("bytes%d[]", n) {
return true
}
}
// For 'intN','intN[]' and 'uintN','uintN[]' we allow N in increments of 8, from 8 up to 256
for n := 8; n <= 256; n += 8 {
if primitiveType == fmt.Sprintf("int%d", n) || primitiveType == fmt.Sprintf("int%d[]", n) {
return true
}
if primitiveType == fmt.Sprintf("uint%d", n) || primitiveType == fmt.Sprintf("uint%d[]", n) {
return true
}
}
return false
}
What are the use-cases?
HashStruct is used to verify EIP712 signature. It would be super nice if it's fast.
Implementation
Do you have ideas regarding the implementation of this feature?
We need to reduce call to fmt.Sprintf
, some ideas:
- precompute all possible value of primitiveType (best performance I guess)
- replace fmt.Sprintf with strconv.Itoa. Example:
fmt.Sprintf("ints%d, n)
=>"ints" + strconv.Itoa(n)
(trivial fix)
Are you willing to implement this feature?
Yes.