From 4f4a25d79f75fd30652922d5a4307cfc8c0cee7b Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 20 Jan 2023 05:01:33 -0500 Subject: [PATCH] signer/core: don't require capital lettered reference types (#26462) --- signer/core/apitypes/types.go | 31 +++---- signer/core/signed_data_test.go | 150 ++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 21 deletions(-) diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index 3e099feaab..c72cad5939 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -27,8 +27,6 @@ import ( "sort" "strconv" "strings" - "unicode" - "unicode/utf8" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" @@ -38,7 +36,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Z](\w*)(\[\])?$`) +var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Za-z](\w*)(\[\])?$`) type ValidationInfo struct { Typ string `json:"type"` @@ -224,15 +222,6 @@ func (t *Type) typeName() string { return t.Type } -func (t *Type) isReferenceType() bool { - if len(t.Type) == 0 { - return false - } - // Reference types must have a leading uppercase character - r, _ := utf8.DecodeRuneInString(t.Type) - return unicode.IsUpper(r) -} - type Types map[string][]Type type TypePriority struct { @@ -731,15 +720,15 @@ func (t Types) validate() error { if typeKey == typeObj.Type { return fmt.Errorf("type %q cannot reference itself", typeObj.Type) } - if typeObj.isReferenceType() { - if _, exist := t[typeObj.typeName()]; !exist { - return fmt.Errorf("reference type %q is undefined", typeObj.Type) - } - if !typedDataReferenceTypeRegexp.MatchString(typeObj.Type) { - return fmt.Errorf("unknown reference type %q", typeObj.Type) - } - } else if !isPrimitiveTypeValid(typeObj.Type) { - return fmt.Errorf("unknown type %q", typeObj.Type) + if isPrimitiveTypeValid(typeObj.Type) { + continue + } + // Must be reference type + if _, exist := t[typeObj.typeName()]; !exist { + return fmt.Errorf("reference type %q is undefined", typeObj.Type) + } + if !typedDataReferenceTypeRegexp.MatchString(typeObj.Type) { + return fmt.Errorf("unknown reference type %q", typeObj.Type) } } } diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go index 608b2adebe..3e3837cae2 100644 --- a/signer/core/signed_data_test.go +++ b/signer/core/signed_data_test.go @@ -848,3 +848,153 @@ func TestGnosisSafe(t *testing.T) { t.Fatal("expected equality") } } + +var complexTypedDataLCRefType = ` +{ + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "version", + "type": "string" + } + ], + "Action": [ + { + "name": "action", + "type": "string" + }, + { + "name": "params", + "type": "string" + } + ], + "cCell": [ + { + "name": "capacity", + "type": "string" + }, + { + "name": "lock", + "type": "string" + }, + { + "name": "type", + "type": "string" + }, + { + "name": "data", + "type": "string" + }, + { + "name": "extraData", + "type": "string" + } + ], + "Transaction": [ + { + "name": "DAS_MESSAGE", + "type": "string" + }, + { + "name": "inputsCapacity", + "type": "string" + }, + { + "name": "outputsCapacity", + "type": "string" + }, + { + "name": "fee", + "type": "string" + }, + { + "name": "action", + "type": "Action" + }, + { + "name": "inputs", + "type": "cCell[]" + }, + { + "name": "outputs", + "type": "cCell[]" + }, + { + "name": "digest", + "type": "bytes32" + } + ] + }, + "primaryType": "Transaction", + "domain": { + "chainId": "56", + "name": "da.systems", + "verifyingContract": "0x0000000000000000000000000000000020210722", + "version": "1" + }, + "message": { + "DAS_MESSAGE": "SELL mobcion.bit FOR 100000 CKB", + "inputsCapacity": "1216.9999 CKB", + "outputsCapacity": "1216.9998 CKB", + "fee": "0.0001 CKB", + "digest": "0x53a6c0f19ec281604607f5d6817e442082ad1882bef0df64d84d3810dae561eb", + "action": { + "action": "start_account_sale", + "params": "0x00" + }, + "inputs": [ + { + "capacity": "218 CKB", + "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...", + "type": "account-cell-type,0x01,0x", + "data": "{ account: mobcion.bit, expired_at: 1670913958 }", + "extraData": "{ status: 0, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }" + } + ], + "outputs": [ + { + "capacity": "218 CKB", + "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...", + "type": "account-cell-type,0x01,0x", + "data": "{ account: mobcion.bit, expired_at: 1670913958 }", + "extraData": "{ status: 1, records_hash: 0x55478d76900611eb079b22088081124ed6c8bae21a05dd1a0d197efcc7c114ce }" + }, + { + "capacity": "201 CKB", + "lock": "das-lock,0x01,0x051c152f77f8efa9c7c6d181cc97ee67c165c506...", + "type": "account-sale-cell-type,0x01,0x", + "data": "0x1209460ef3cb5f1c68ed2c43a3e020eec2d9de6e...", + "extraData": "" + } + ] + } +} +` + +func TestComplexTypedDataWithLowercaseReftype(t *testing.T) { + var td apitypes.TypedData + err := json.Unmarshal([]byte(complexTypedDataLCRefType), &td) + if err != nil { + t.Fatalf("unmarshalling failed '%v'", err) + } + _, sighash, err := sign(td) + if err != nil { + t.Fatal(err) + } + expSigHash := common.FromHex("0x49191f910874f0148597204d9076af128d4694a7c4b714f1ccff330b87207bff") + if !bytes.Equal(expSigHash, sighash) { + t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash) + } +}