core/signer, clef: improve ui-test flow, fix errors in uint handling (#19584)
* core/signer, clef: improve ui-test flow, fix errors in uint handling for eip-712 * core/signer: add fuzzer testcases + crashfixes * signer: address review concerns, check sign in integer parsing
This commit is contained in:
		
				
					committed by
					
						 Guillaume Ballet
						Guillaume Ballet
					
				
			
			
				
	
			
			
			
						parent
						
							7a22da98b9
						
					
				
				
					commit
					17381ecc66
				
			| @@ -33,6 +33,7 @@ import ( | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/accounts" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/keystore" | ||||
| @@ -638,6 +639,10 @@ func testExternalUI(api *core.SignerAPI) { | ||||
| 	errs := make([]string, 0) | ||||
|  | ||||
| 	a := common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef") | ||||
| 	addErr := func(errStr string) { | ||||
| 		log.Info("Test error", "error", errStr) | ||||
| 		errs = append(errs, errStr) | ||||
| 	} | ||||
|  | ||||
| 	queryUser := func(q string) string { | ||||
| 		resp, err := api.UI.OnInputRequired(core.UserInputRequest{ | ||||
| @@ -645,36 +650,39 @@ func testExternalUI(api *core.SignerAPI) { | ||||
| 			Prompt: q, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			errs = append(errs, err.Error()) | ||||
| 			addErr(err.Error()) | ||||
| 		} | ||||
| 		return resp.Text | ||||
| 	} | ||||
| 	expectResponse := func(testcase, question, expect string) { | ||||
| 		if got := queryUser(question); got != expect { | ||||
| 			errs = append(errs, fmt.Sprintf("%s: got %v, expected %v", testcase, got, expect)) | ||||
| 			addErr(fmt.Sprintf("%s: got %v, expected %v", testcase, got, expect)) | ||||
| 		} | ||||
| 	} | ||||
| 	expectApprove := func(testcase string, err error) { | ||||
| 		if err == nil || err == accounts.ErrUnknownAccount { | ||||
| 			return | ||||
| 		} | ||||
| 		errs = append(errs, fmt.Sprintf("%v: expected no error, got %v", testcase, err.Error())) | ||||
| 		addErr(fmt.Sprintf("%v: expected no error, got %v", testcase, err.Error())) | ||||
| 	} | ||||
| 	expectDeny := func(testcase string, err error) { | ||||
| 		if err == nil || err != core.ErrRequestDenied { | ||||
| 			errs = append(errs, fmt.Sprintf("%v: expected ErrRequestDenied, got %v", testcase, err)) | ||||
| 			addErr(fmt.Sprintf("%v: expected ErrRequestDenied, got %v", testcase, err)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var delay = 1 * time.Second | ||||
| 	// Test display of info and error | ||||
| 	{ | ||||
| 		api.UI.ShowInfo("If you see this message, enter 'yes' to next question") | ||||
| 		time.Sleep(delay) | ||||
| 		expectResponse("showinfo", "Did you see the message? [yes/no]", "yes") | ||||
| 		api.UI.ShowError("If you see this message, enter 'yes' to the next question") | ||||
| 		time.Sleep(delay) | ||||
| 		expectResponse("showerror", "Did you see the message? [yes/no]", "yes") | ||||
| 	} | ||||
| 	{ // Sign data test - clique header | ||||
| 		api.UI.ShowInfo("Please approve the next request for signing a clique header") | ||||
| 		time.Sleep(delay) | ||||
| 		cliqueHeader := types.Header{ | ||||
| 			common.HexToHash("0000H45H"), | ||||
| 			common.HexToHash("0000H45H"), | ||||
| @@ -700,14 +708,27 @@ func testExternalUI(api *core.SignerAPI) { | ||||
| 		_, err = api.SignData(ctx, accounts.MimetypeClique, *addr, hexutil.Encode(cliqueRlp)) | ||||
| 		expectApprove("signdata - clique header", err) | ||||
| 	} | ||||
| 	{ // Sign data test - typed data | ||||
| 		api.UI.ShowInfo("Please approve the next request for signing EIP-712 typed data") | ||||
| 		time.Sleep(delay) | ||||
| 		addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") | ||||
| 		data := `{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"test","type":"uint8"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":"1","verifyingContract":"0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","test":"3","wallet":"0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","test":"2"},"contents":"Hello, Bob!"}}` | ||||
| 		//_, err := api.SignData(ctx, accounts.MimetypeTypedData, *addr, hexutil.Encode([]byte(data))) | ||||
| 		var typedData core.TypedData | ||||
| 		err := json.Unmarshal([]byte(data), &typedData) | ||||
| 		_, err = api.SignTypedData(ctx, *addr, typedData) | ||||
| 		expectApprove("sign 712 typed data", err) | ||||
| 	} | ||||
| 	{ // Sign data test - plain text | ||||
| 		api.UI.ShowInfo("Please approve the next request for signing text") | ||||
| 		time.Sleep(delay) | ||||
| 		addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") | ||||
| 		_, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world"))) | ||||
| 		expectApprove("signdata - text", err) | ||||
| 	} | ||||
| 	{ // Sign data test - plain text reject | ||||
| 		api.UI.ShowInfo("Please deny the next request for signing text") | ||||
| 		time.Sleep(delay) | ||||
| 		addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") | ||||
| 		_, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world"))) | ||||
| 		expectDeny("signdata - text", err) | ||||
| @@ -715,6 +736,7 @@ func testExternalUI(api *core.SignerAPI) { | ||||
| 	{ // Sign transaction | ||||
|  | ||||
| 		api.UI.ShowInfo("Please reject next transaction") | ||||
| 		time.Sleep(delay) | ||||
| 		data := hexutil.Bytes([]byte{}) | ||||
| 		to := common.NewMixedcaseAddress(a) | ||||
| 		tx := core.SendTxArgs{ | ||||
| @@ -733,16 +755,19 @@ func testExternalUI(api *core.SignerAPI) { | ||||
| 	} | ||||
| 	{ // Listing | ||||
| 		api.UI.ShowInfo("Please reject listing-request") | ||||
| 		time.Sleep(delay) | ||||
| 		_, err := api.List(ctx) | ||||
| 		expectDeny("list", err) | ||||
| 	} | ||||
| 	{ // Import | ||||
| 		api.UI.ShowInfo("Please reject new account-request") | ||||
| 		time.Sleep(delay) | ||||
| 		_, err := api.New(ctx) | ||||
| 		expectDeny("newaccount", err) | ||||
| 	} | ||||
| 	{ // Metadata | ||||
| 		api.UI.ShowInfo("Please check if you see the Origin in next listing (approve or deny)") | ||||
| 		time.Sleep(delay) | ||||
| 		api.List(context.WithValue(ctx, "Origin", "origin.com")) | ||||
| 		expectResponse("metadata - origin", "Did you see origin (origin.com)? [yes/no] ", "yes") | ||||
| 	} | ||||
|   | ||||
| @@ -42,6 +42,13 @@ const ( | ||||
| // HexOrDecimal256 marshals big.Int as hex or decimal. | ||||
| type HexOrDecimal256 big.Int | ||||
|  | ||||
| // NewHexOrDecimal256 creates a new HexOrDecimal256 | ||||
| func NewHexOrDecimal256(x int64) *HexOrDecimal256 { | ||||
| 	b := big.NewInt(x) | ||||
| 	h := HexOrDecimal256(*b) | ||||
| 	return &h | ||||
| } | ||||
|  | ||||
| // UnmarshalText implements encoding.TextUnmarshaler. | ||||
| func (i *HexOrDecimal256) UnmarshalText(input []byte) error { | ||||
| 	bigint, ok := ParseBig256(string(input)) | ||||
|   | ||||
| @@ -482,7 +482,6 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	req := SignTxRequest{ | ||||
| 		Transaction: args, | ||||
| 		Meta:        MetadataFromContext(ctx), | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"mime" | ||||
| 	"reflect" | ||||
| 	"regexp" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| @@ -95,6 +96,9 @@ func (t *Type) typeName() string { | ||||
| } | ||||
|  | ||||
| func (t *Type) isReferenceType() bool { | ||||
| 	if len(t.Type) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
| 	// Reference types must have a leading uppercase characer | ||||
| 	return unicode.IsUpper([]rune(t.Type)[0]) | ||||
| } | ||||
| @@ -109,11 +113,11 @@ type TypePriority struct { | ||||
| type TypedDataMessage = map[string]interface{} | ||||
|  | ||||
| type TypedDataDomain struct { | ||||
| 	Name              string   `json:"name"` | ||||
| 	Version           string   `json:"version"` | ||||
| 	ChainId           *big.Int `json:"chainId"` | ||||
| 	VerifyingContract string   `json:"verifyingContract"` | ||||
| 	Salt              string   `json:"salt"` | ||||
| 	Name              string                `json:"name"` | ||||
| 	Version           string                `json:"version"` | ||||
| 	ChainId           *math.HexOrDecimal256 `json:"chainId"` | ||||
| 	VerifyingContract string                `json:"verifyingContract"` | ||||
| 	Salt              string                `json:"salt"` | ||||
| } | ||||
|  | ||||
| var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Z](\w*)(\[\])?$`) | ||||
| @@ -323,7 +327,10 @@ func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAd | ||||
| 	} | ||||
| 	rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))) | ||||
| 	sighash := crypto.Keccak256(rawData) | ||||
| 	message := typedData.Format() | ||||
| 	message, err := typedData.Format() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	req := &SignDataRequest{ContentType: DataTyped.Mime, Rawdata: rawData, Message: message, Hash: sighash} | ||||
| 	signature, err := api.sign(addr, req, true) | ||||
| 	if err != nil { | ||||
| @@ -377,9 +384,11 @@ func (typedData *TypedData) Dependencies(primaryType string, found []string) []s | ||||
| func (typedData *TypedData) EncodeType(primaryType string) hexutil.Bytes { | ||||
| 	// Get dependencies primary first, then alphabetical | ||||
| 	deps := typedData.Dependencies(primaryType, []string{}) | ||||
| 	slicedDeps := deps[1:] | ||||
| 	sort.Strings(slicedDeps) | ||||
| 	deps = append([]string{primaryType}, slicedDeps...) | ||||
| 	if len(deps) > 0 { | ||||
| 		slicedDeps := deps[1:] | ||||
| 		sort.Strings(slicedDeps) | ||||
| 		deps = append([]string{primaryType}, slicedDeps...) | ||||
| 	} | ||||
|  | ||||
| 	// Format as a string with fields | ||||
| 	var buffer bytes.Buffer | ||||
| @@ -476,10 +485,60 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter | ||||
| 	return buffer.Bytes(), nil | ||||
| } | ||||
|  | ||||
| func parseInteger(encType string, encValue interface{}) (*big.Int, error) { | ||||
| 	var ( | ||||
| 		length = 0 | ||||
| 		signed = strings.HasPrefix(encType, "int") | ||||
| 		b      *big.Int | ||||
| 	) | ||||
| 	if encType == "int" || encType == "uint" { | ||||
| 		length = 256 | ||||
| 	} else { | ||||
| 		lengthStr := "" | ||||
| 		if strings.HasPrefix(encType, "uint") { | ||||
| 			lengthStr = strings.TrimPrefix(encType, "uint") | ||||
| 		} else { | ||||
| 			lengthStr = strings.TrimPrefix(encType, "int") | ||||
| 		} | ||||
| 		atoiSize, err := strconv.Atoi(lengthStr) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("invalid size on integer: %v", lengthStr) | ||||
| 		} | ||||
| 		length = atoiSize | ||||
| 	} | ||||
| 	switch v := encValue.(type) { | ||||
| 	case *math.HexOrDecimal256: | ||||
| 		b = (*big.Int)(v) | ||||
| 	case string: | ||||
| 		var hexIntValue math.HexOrDecimal256 | ||||
| 		if err := hexIntValue.UnmarshalText([]byte(v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		b = (*big.Int)(&hexIntValue) | ||||
| 	case float64: | ||||
| 		// JSON parses non-strings as float64. Fail if we cannot | ||||
| 		// convert it losslessly | ||||
| 		if float64(int64(v)) == v { | ||||
| 			b = big.NewInt(int64(v)) | ||||
| 		} else { | ||||
| 			return nil, fmt.Errorf("invalid float value %v for type %v", v, encType) | ||||
| 		} | ||||
| 	} | ||||
| 	if b == nil { | ||||
| 		return nil, fmt.Errorf("invalid integer value %v/%v for type %v", encValue, reflect.TypeOf(encValue), encType) | ||||
| 	} | ||||
| 	if b.BitLen() > length { | ||||
| 		return nil, fmt.Errorf("integer larger than '%v'", encType) | ||||
| 	} | ||||
| 	if !signed && b.Sign() == -1 { | ||||
| 		return nil, fmt.Errorf("invalid negative value for unsigned type %v", encType) | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
|  | ||||
| // EncodePrimitiveValue deals with the primitive values found | ||||
| // while searching through the typed data | ||||
| func (typedData *TypedData) EncodePrimitiveValue(encType string, encValue interface{}, depth int) ([]byte, error) { | ||||
|  | ||||
| 	switch encType { | ||||
| 	case "address": | ||||
| 		stringValue, ok := encValue.(string) | ||||
| @@ -527,30 +586,11 @@ func (typedData *TypedData) EncodePrimitiveValue(encType string, encValue interf | ||||
| 		} | ||||
| 	} | ||||
| 	if strings.HasPrefix(encType, "int") || strings.HasPrefix(encType, "uint") { | ||||
| 		length := 0 | ||||
| 		if encType == "int" || encType == "uint" { | ||||
| 			length = 256 | ||||
| 		} else { | ||||
| 			lengthStr := "" | ||||
| 			if strings.HasPrefix(encType, "uint") { | ||||
| 				lengthStr = strings.TrimPrefix(encType, "uint") | ||||
| 			} else { | ||||
| 				lengthStr = strings.TrimPrefix(encType, "int") | ||||
| 			} | ||||
| 			atoiSize, err := strconv.Atoi(lengthStr) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("invalid size on integer: %v", lengthStr) | ||||
| 			} | ||||
| 			length = atoiSize | ||||
| 		b, err := parseInteger(encType, encValue) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		bigIntValue, ok := encValue.(*big.Int) | ||||
| 		if bigIntValue.BitLen() > length { | ||||
| 			return nil, fmt.Errorf("integer larger than '%v'", encType) | ||||
| 		} | ||||
| 		if !ok { | ||||
| 			return nil, dataMismatchError(encType, encValue) | ||||
| 		} | ||||
| 		return abi.U256(bigIntValue), nil | ||||
| 		return abi.U256(b), nil | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("unrecognized type '%s'", encType) | ||||
|  | ||||
| @@ -649,35 +689,32 @@ func (typedData *TypedData) Map() map[string]interface{} { | ||||
| 	return dataMap | ||||
| } | ||||
|  | ||||
| // PrettyPrint generates a nice output to help the users | ||||
| // of clef present data in their apps | ||||
| func (typedData *TypedData) PrettyPrint() string { | ||||
| 	output := bytes.Buffer{} | ||||
| 	formatted := typedData.Format() | ||||
| 	for _, item := range formatted { | ||||
| 		output.WriteString(fmt.Sprintf("%v\n", item.Pprint(0))) | ||||
| 	} | ||||
| 	return output.String() | ||||
| } | ||||
|  | ||||
| // Format returns a representation of typedData, which can be easily displayed by a user-interface | ||||
| // without in-depth knowledge about 712 rules | ||||
| func (typedData *TypedData) Format() []*NameValueType { | ||||
| func (typedData *TypedData) Format() ([]*NameValueType, error) { | ||||
| 	domain, err := typedData.formatData("EIP712Domain", typedData.Domain.Map()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ptype, err := typedData.formatData(typedData.PrimaryType, typedData.Message) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var nvts []*NameValueType | ||||
| 	nvts = append(nvts, &NameValueType{ | ||||
| 		Name:  "EIP712Domain", | ||||
| 		Value: typedData.formatData("EIP712Domain", typedData.Domain.Map()), | ||||
| 		Value: domain, | ||||
| 		Typ:   "domain", | ||||
| 	}) | ||||
| 	nvts = append(nvts, &NameValueType{ | ||||
| 		Name:  typedData.PrimaryType, | ||||
| 		Value: typedData.formatData(typedData.PrimaryType, typedData.Message), | ||||
| 		Value: ptype, | ||||
| 		Typ:   "primary type", | ||||
| 	}) | ||||
| 	return nvts | ||||
| 	return nvts, nil | ||||
| } | ||||
|  | ||||
| func (typedData *TypedData) formatData(primaryType string, data map[string]interface{}) []*NameValueType { | ||||
| func (typedData *TypedData) formatData(primaryType string, data map[string]interface{}) ([]*NameValueType, error) { | ||||
| 	var output []*NameValueType | ||||
|  | ||||
| 	// Add field contents. Structs and arrays have special handlers. | ||||
| @@ -694,44 +731,70 @@ func (typedData *TypedData) formatData(primaryType string, data map[string]inter | ||||
| 			for _, v := range arrayValue { | ||||
| 				if typedData.Types[parsedType] != nil { | ||||
| 					mapValue, _ := v.(map[string]interface{}) | ||||
| 					mapOutput := typedData.formatData(parsedType, mapValue) | ||||
| 					mapOutput, err := typedData.formatData(parsedType, mapValue) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					item.Value = mapOutput | ||||
| 				} else { | ||||
| 					primitiveOutput := formatPrimitiveValue(field.Type, encValue) | ||||
| 					primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					item.Value = primitiveOutput | ||||
| 				} | ||||
| 			} | ||||
| 		} else if typedData.Types[field.Type] != nil { | ||||
| 			mapValue, _ := encValue.(map[string]interface{}) | ||||
| 			mapOutput := typedData.formatData(field.Type, mapValue) | ||||
| 			item.Value = mapOutput | ||||
| 			if mapValue, ok := encValue.(map[string]interface{}); ok { | ||||
| 				mapOutput, err := typedData.formatData(field.Type, mapValue) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 				item.Value = mapOutput | ||||
| 			} else { | ||||
| 				item.Value = "<nil>" | ||||
| 			} | ||||
| 		} else { | ||||
| 			primitiveOutput := formatPrimitiveValue(field.Type, encValue) | ||||
| 			primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			item.Value = primitiveOutput | ||||
| 		} | ||||
| 		output = append(output, item) | ||||
| 	} | ||||
| 	return output | ||||
| 	return output, nil | ||||
| } | ||||
|  | ||||
| func formatPrimitiveValue(encType string, encValue interface{}) string { | ||||
| func formatPrimitiveValue(encType string, encValue interface{}) (string, error) { | ||||
| 	switch encType { | ||||
| 	case "address": | ||||
| 		stringValue, _ := encValue.(string) | ||||
| 		return common.HexToAddress(stringValue).String() | ||||
| 		if stringValue, ok := encValue.(string); !ok { | ||||
| 			return "", fmt.Errorf("could not format value %v as address", encValue) | ||||
| 		} else { | ||||
| 			return common.HexToAddress(stringValue).String(), nil | ||||
| 		} | ||||
| 	case "bool": | ||||
| 		boolValue, _ := encValue.(bool) | ||||
| 		return fmt.Sprintf("%t", boolValue) | ||||
| 		if boolValue, ok := encValue.(bool); !ok { | ||||
| 			return "", fmt.Errorf("could not format value %v as bool", encValue) | ||||
| 		} else { | ||||
| 			return fmt.Sprintf("%t", boolValue), nil | ||||
| 		} | ||||
| 	case "bytes", "string": | ||||
| 		return fmt.Sprintf("%s", encValue) | ||||
| 		return fmt.Sprintf("%s", encValue), nil | ||||
| 	} | ||||
| 	if strings.HasPrefix(encType, "bytes") { | ||||
| 		return fmt.Sprintf("%s", encValue) | ||||
| 	} else if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") { | ||||
| 		bigIntValue, _ := encValue.(*big.Int) | ||||
| 		return fmt.Sprintf("%d (0x%x)", bigIntValue, bigIntValue) | ||||
| 		return fmt.Sprintf("%s", encValue), nil | ||||
|  | ||||
| 	} | ||||
| 	return "NA" | ||||
| 	if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") { | ||||
| 		if b, err := parseInteger(encType, encValue); err != nil { | ||||
| 			return "", err | ||||
| 		} else { | ||||
| 			return fmt.Sprintf("%d (0x%x)", b, b), nil | ||||
| 		} | ||||
| 	} | ||||
| 	return "", fmt.Errorf("unhandled type %v", encType) | ||||
| } | ||||
|  | ||||
| // NameValueType is a very simple struct with Name, Value and Type. It's meant for simple | ||||
| @@ -762,12 +825,21 @@ func (nvt *NameValueType) Pprint(depth int) string { | ||||
| // Validate checks if the types object is conformant to the specs | ||||
| func (t Types) validate() error { | ||||
| 	for typeKey, typeArr := range t { | ||||
| 		for _, typeObj := range typeArr { | ||||
| 		if len(typeKey) == 0 { | ||||
| 			return fmt.Errorf("empty type key") | ||||
| 		} | ||||
| 		for i, typeObj := range typeArr { | ||||
| 			if len(typeObj.Type) == 0 { | ||||
| 				return fmt.Errorf("type %v:%d: empty Type", typeKey, i) | ||||
| 			} | ||||
| 			if len(typeObj.Name) == 0 { | ||||
| 				return fmt.Errorf("type %v:%d: empty Name", typeKey, i) | ||||
| 			} | ||||
| 			if typeKey == typeObj.Type { | ||||
| 				return fmt.Errorf("type '%s' cannot reference itself", typeObj.Type) | ||||
| 			} | ||||
| 			if typeObj.isReferenceType() { | ||||
| 				if _, exist := t[typeObj.Type]; !exist { | ||||
| 				if _, exist := t[typeObj.typeName()]; !exist { | ||||
| 					return fmt.Errorf("reference type '%s' is undefined", typeObj.Type) | ||||
| 				} | ||||
| 				if !typedDataReferenceTypeRegexp.MatchString(typeObj.Type) { | ||||
| @@ -895,7 +967,7 @@ func isPrimitiveTypeValid(primitiveType string) bool { | ||||
| // validate checks if the given domain is valid, i.e. contains at least | ||||
| // the minimum viable keys and values | ||||
| func (domain *TypedDataDomain) validate() error { | ||||
| 	if domain.ChainId == big.NewInt(0) { | ||||
| 	if domain.ChainId == nil { | ||||
| 		return errors.New("chainId must be specified according to EIP-155") | ||||
| 	} | ||||
|  | ||||
|   | ||||
							
								
								
									
										51
									
								
								signer/core/signed_data_internal_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								signer/core/signed_data_internal_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| // Copyright 2019 The go-ethereum Authors | ||||
| // This file is part of go-ethereum. | ||||
| // | ||||
| // go-ethereum is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // (at your option) any later version. | ||||
| // | ||||
| // go-ethereum is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | ||||
| // | ||||
| package core | ||||
|  | ||||
| import ( | ||||
| 	"math/big" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestParseInteger(t *testing.T) { | ||||
| 	for i, tt := range []struct { | ||||
| 		t   string | ||||
| 		v   interface{} | ||||
| 		exp *big.Int | ||||
| 	}{ | ||||
| 		{"uint32", "-123", nil}, | ||||
| 		{"int32", "-123", big.NewInt(-123)}, | ||||
| 		{"uint32", "0xff", big.NewInt(0xff)}, | ||||
| 		{"int8", "0xffff", nil}, | ||||
| 	} { | ||||
| 		res, err := parseInteger(tt.t, tt.v) | ||||
| 		if tt.exp == nil && res == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		if tt.exp == nil && res != nil { | ||||
| 			t.Errorf("test %d, got %v, expected nil", i, res) | ||||
| 			continue | ||||
| 		} | ||||
| 		if tt.exp != nil && res == nil { | ||||
| 			t.Errorf("test %d, got '%v', expected %v", i, err, tt.exp) | ||||
| 			continue | ||||
| 		} | ||||
| 		if tt.exp.Cmp(res) != 0 { | ||||
| 			t.Errorf("test %d, got %v expected %v", i, res, tt.exp) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -20,12 +20,16 @@ import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"io/ioutil" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/accounts/keystore" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||
| 	"github.com/ethereum/go-ethereum/common/math" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/signer/core" | ||||
| ) | ||||
|  | ||||
| @@ -128,7 +132,7 @@ var jsonTypedData = ` | ||||
|       "domain": { | ||||
|         "name": "Ether Mail", | ||||
|         "version": "1", | ||||
|         "chainId": 1, | ||||
|         "chainId": "1", | ||||
|         "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|       }, | ||||
|       "message": { | ||||
| @@ -151,7 +155,7 @@ const primaryType = "Mail" | ||||
| var domainStandard = core.TypedDataDomain{ | ||||
| 	"Ether Mail", | ||||
| 	"1", | ||||
| 	big.NewInt(1), | ||||
| 	math.NewHexOrDecimal256(1), | ||||
| 	"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", | ||||
| 	"", | ||||
| } | ||||
| @@ -241,7 +245,6 @@ func TestDomainChainId(t *testing.T) { | ||||
| 	if _, ok := withoutChainID.Domain.Map()["chainId"]; ok { | ||||
| 		t.Errorf("Expected the chainId key to not be present in the domain map") | ||||
| 	} | ||||
|  | ||||
| 	withChainID := core.TypedData{ | ||||
| 		Types: core.Types{ | ||||
| 			"EIP712Domain": []core.Type{ | ||||
| @@ -251,7 +254,7 @@ func TestDomainChainId(t *testing.T) { | ||||
| 		}, | ||||
| 		Domain: core.TypedDataDomain{ | ||||
| 			Name:    "test", | ||||
| 			ChainId: big.NewInt(1), | ||||
| 			ChainId: math.NewHexOrDecimal256(1), | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| @@ -310,495 +313,13 @@ func TestEncodeData(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestMalformedDomainkeys(t *testing.T) { | ||||
| 	// Verifies that malformed domain keys are properly caught: | ||||
| 	//{ | ||||
| 	//	"name": "Ether Mail", | ||||
| 	//	"version": "1", | ||||
| 	//	"chainId": 1, | ||||
| 	//	"vxerifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
| 	//} | ||||
| 	jsonTypedData := ` | ||||
|     { | ||||
|       "types": { | ||||
|         "EIP712Domain": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "version", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "chainId", | ||||
|             "type": "uint256" | ||||
|           }, | ||||
|           { | ||||
|             "name": "verifyingContract", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Person": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "wallet", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Mail": [ | ||||
|           { | ||||
|             "name": "from", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "to", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "contents", | ||||
|             "type": "string" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "primaryType": "Mail", | ||||
|       "domain": { | ||||
|         "name": "Ether Mail", | ||||
|         "version": "1", | ||||
|         "chainId": 1, | ||||
|         "vxerifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|       }, | ||||
|       "message": { | ||||
|         "from": { | ||||
|           "name": "Cow", | ||||
|           "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|         }, | ||||
|         "to": { | ||||
|           "name": "Bob", | ||||
|           "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|         }, | ||||
|         "contents": "Hello, Bob!" | ||||
|       } | ||||
|     } | ||||
| ` | ||||
| 	var malformedDomainTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &malformedDomainTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	_, err = malformedDomainTypedData.HashStruct("EIP712Domain", malformedDomainTypedData.Domain.Map()) | ||||
| 	if err == nil || err.Error() != "provided data '<nil>' doesn't match type 'address'" { | ||||
| 		t.Errorf("Expected `provided data '<nil>' doesn't match type 'address'`, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestMalformedTypesAndExtradata(t *testing.T) { | ||||
| 	// Verifies several quirks | ||||
| 	// 1. Using dynamic types and only validating the prefix: | ||||
| 	//{ | ||||
| 	//	"name": "chainId", | ||||
| 	//	"type": "uint256 ... and now for something completely different" | ||||
| 	//} | ||||
| 	// 2. Extra data in message: | ||||
| 	//{ | ||||
| 	//  "blahonga": "zonk bonk" | ||||
| 	//} | ||||
| 	jsonTypedData := ` | ||||
|     { | ||||
|       "types": { | ||||
|         "EIP712Domain": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "version", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "chainId", | ||||
|             "type": "uint256 ... and now for something completely different" | ||||
|           }, | ||||
|           { | ||||
|             "name": "verifyingContract", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Person": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "wallet", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Mail": [ | ||||
|           { | ||||
|             "name": "from", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "to", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "contents", | ||||
|             "type": "string" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "primaryType": "Mail", | ||||
|       "domain": { | ||||
|         "name": "Ether Mail", | ||||
|         "version": "1", | ||||
|         "chainId": 1, | ||||
|         "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|       }, | ||||
|       "message": { | ||||
|         "from": { | ||||
|           "name": "Cow", | ||||
|           "wallet": "0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|         }, | ||||
|         "to": { | ||||
|           "name": "Bob", | ||||
|           "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|         }, | ||||
|         "contents": "Hello, Bob!" | ||||
|       } | ||||
|     } | ||||
| ` | ||||
| 	var malformedTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &malformedTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	malformedTypedData.Types["EIP712Domain"][2].Type = "uint256" | ||||
| 	malformedTypedData.Message["blahonga"] = "zonk bonk" | ||||
| 	_, err = malformedTypedData.HashStruct(malformedTypedData.PrimaryType, malformedTypedData.Message) | ||||
| 	if err == nil || err.Error() != "there is extra data provided in the message" { | ||||
| 		t.Errorf("Expected `there is extra data provided in the message`, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestTypeMismatch(t *testing.T) { | ||||
| 	// Verifies that: | ||||
| 	// 1. Mismatches between the given type and data, i.e. `Person` and | ||||
| 	// 		the data item is a string, are properly caught: | ||||
| 	//{ | ||||
| 	//	"name": "contents", | ||||
| 	//	"type": "Person" | ||||
| 	//}, | ||||
| 	//{ | ||||
| 	//	"contents": "Hello, Bob!" <-- string not "Person" | ||||
| 	//} | ||||
| 	// 2. Nonexistent types are properly caught: | ||||
| 	//{ | ||||
| 	//	"name": "contents", | ||||
| 	//	"type": "Blahonga" | ||||
| 	//} | ||||
| 	jsonTypedData := ` | ||||
|     { | ||||
|       "types": { | ||||
|         "EIP712Domain": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "version", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "chainId", | ||||
|             "type": "uint256" | ||||
|           }, | ||||
|           { | ||||
|             "name": "verifyingContract", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Person": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "wallet", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Mail": [ | ||||
|           { | ||||
|             "name": "from", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "to", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
|             "name": "contents", | ||||
|             "type": "Person" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "primaryType": "Mail", | ||||
|       "domain": { | ||||
|         "name": "Ether Mail", | ||||
|         "version": "1", | ||||
|         "chainId": 1, | ||||
|         "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|       }, | ||||
|       "message": { | ||||
|         "from": { | ||||
|           "name": "Cow", | ||||
|           "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|         }, | ||||
|         "to": { | ||||
|           "name": "Bob", | ||||
|           "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|         }, | ||||
|         "contents": "Hello, Bob!" | ||||
|       } | ||||
|     } | ||||
| ` | ||||
| 	var mismatchTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &mismatchTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	_, err = mismatchTypedData.HashStruct(mismatchTypedData.PrimaryType, mismatchTypedData.Message) | ||||
| 	if err.Error() != "provided data 'Hello, Bob!' doesn't match type 'Person'" { | ||||
| 		t.Errorf("Expected `provided data 'Hello, Bob!' doesn't match type 'Person'`, got '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	mismatchTypedData.Types["Mail"][2].Type = "Blahonga" | ||||
| 	_, err = mismatchTypedData.HashStruct(mismatchTypedData.PrimaryType, mismatchTypedData.Message) | ||||
| 	if err == nil || err.Error() != "reference type 'Blahonga' is undefined" { | ||||
| 		t.Fatalf("Expected `reference type 'Blahonga' is undefined`, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestTypeOverflow(t *testing.T) { | ||||
| 	// Verifies data that doesn't fit into it: | ||||
| 	//{ | ||||
| 	//	"test": 65536 <-- test defined as uint8 | ||||
| 	//} | ||||
| 	var overflowTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &overflowTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	// Set test to something outside uint8 | ||||
| 	(overflowTypedData.Message["from"]).(map[string]interface{})["test"] = big.NewInt(65536) | ||||
|  | ||||
| 	_, err = overflowTypedData.HashStruct(overflowTypedData.PrimaryType, overflowTypedData.Message) | ||||
| 	if err == nil || err.Error() != "integer larger than 'uint8'" { | ||||
| 		t.Fatalf("Expected `integer larger than 'uint8'`, got '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	(overflowTypedData.Message["from"]).(map[string]interface{})["test"] = big.NewInt(3) | ||||
| 	(overflowTypedData.Message["to"]).(map[string]interface{})["test"] = big.NewInt(4) | ||||
|  | ||||
| 	_, err = overflowTypedData.HashStruct(overflowTypedData.PrimaryType, overflowTypedData.Message) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Expected no err, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestArray(t *testing.T) { | ||||
| 	// Makes sure that arrays work fine | ||||
| 	//{ | ||||
| 	//	"type": "address[]" | ||||
| 	//}, | ||||
| 	//{ | ||||
| 	//	"type": "string[]" | ||||
| 	//}, | ||||
| 	//{ | ||||
| 	//	"type": "uint16[]", | ||||
| 	//} | ||||
|  | ||||
| 	jsonTypedData := ` | ||||
| 		{ | ||||
| 	      "types": { | ||||
| 	        "EIP712Domain": [ | ||||
| 	          { | ||||
| 	            "name": "name", | ||||
| 	            "type": "string" | ||||
| 	          }, | ||||
| 	          { | ||||
| 	            "name": "version", | ||||
| 	            "type": "string" | ||||
| 	          }, | ||||
| 	          { | ||||
| 	            "name": "chainId", | ||||
| 	            "type": "uint256" | ||||
| 	          }, | ||||
| 	          { | ||||
| 	            "name": "verifyingContract", | ||||
| 	            "type": "address" | ||||
| 	          } | ||||
| 	        ], | ||||
| 	        "Foo": [ | ||||
| 	          { | ||||
| 	            "name": "bar", | ||||
| 	            "type": "address[]" | ||||
| 	          } | ||||
| 	        ] | ||||
| 	      }, | ||||
| 	      "primaryType": "Foo", | ||||
| 	      "domain": { | ||||
| 	        "name": "Lorem", | ||||
| 	        "version": "1", | ||||
| 	        "chainId": 1, | ||||
| 	        "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
| 	      }, | ||||
| 	      "message": { | ||||
| 	        "bar": [ | ||||
| 	        	"0x0000000000000000000000000000000000000001", | ||||
| 	        	"0x0000000000000000000000000000000000000002", | ||||
| 	        	"0x0000000000000000000000000000000000000003" | ||||
|         	] | ||||
| 	      } | ||||
| 	    } | ||||
| 	` | ||||
| 	var arrayTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &arrayTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	_, err = arrayTypedData.HashStruct(arrayTypedData.PrimaryType, arrayTypedData.Message) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Expected no err, got '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	// Change array to string | ||||
| 	arrayTypedData.Types["Foo"][0].Type = "string[]" | ||||
| 	arrayTypedData.Message["bar"] = []interface{}{ | ||||
| 		"lorem", | ||||
| 		"ipsum", | ||||
| 		"dolores", | ||||
| 	} | ||||
| 	_, err = arrayTypedData.HashStruct(arrayTypedData.PrimaryType, arrayTypedData.Message) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Expected no err, got '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	// Change array to uint | ||||
| 	arrayTypedData.Types["Foo"][0].Type = "uint[]" | ||||
| 	arrayTypedData.Message["bar"] = []interface{}{ | ||||
| 		big.NewInt(1955), | ||||
| 		big.NewInt(108), | ||||
| 		big.NewInt(44010), | ||||
| 	} | ||||
| 	_, err = arrayTypedData.HashStruct(arrayTypedData.PrimaryType, arrayTypedData.Message) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Expected no err, got '%v'", err) | ||||
| 	} | ||||
|  | ||||
| 	// Should not work with fixed-size arrays | ||||
| 	arrayTypedData.Types["Foo"][0].Type = "uint[3]" | ||||
| 	_, err = arrayTypedData.HashStruct(arrayTypedData.PrimaryType, arrayTypedData.Message) | ||||
| 	if err == nil || err.Error() != "unknown type 'uint[3]'" { | ||||
| 		t.Fatalf("Expected `unknown type 'uint[3]'`, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestCustomTypeAsArray(t *testing.T) { | ||||
| 	var jsonTypedData = ` | ||||
|     { | ||||
|       "types": { | ||||
|         "EIP712Domain": [ | ||||
|           { | ||||
|             "name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
| 			"name": "version", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "chainId", | ||||
|             "type": "uint256" | ||||
|           }, | ||||
|           { | ||||
| 			"name": "verifyingContract", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Person": [ | ||||
|           { | ||||
| 			"name": "name", | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
| 			"name": "wallet", | ||||
|             "type": "address" | ||||
|           } | ||||
|         ], | ||||
|         "Person[]": [ | ||||
|           { | ||||
| 			"name": "baz", | ||||
|             "type": "string" | ||||
|           } | ||||
| 		], | ||||
|         "Mail": [ | ||||
|           { | ||||
| 			"name": "from", | ||||
|             "type": "Person" | ||||
|           }, | ||||
|           { | ||||
| 			"name": "to", | ||||
|             "type": "Person[]" | ||||
|           }, | ||||
|           { | ||||
| 			"name": "contents", | ||||
|             "type": "string" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "primaryType": "Mail", | ||||
|       "domain": { | ||||
| 		"name": "Ether Mail", | ||||
|         "version": "1", | ||||
|         "chainId": 1, | ||||
|         "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|       }, | ||||
|       "message": { | ||||
|         "from": { | ||||
| 			"name": "Cow", | ||||
| 			"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|         }, | ||||
|         "to": {"baz": "foo"}, | ||||
|         "contents": "Hello, Bob!" | ||||
|       } | ||||
|     } | ||||
|  | ||||
| ` | ||||
| 	var malformedTypedData core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &malformedTypedData) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	_, err = malformedTypedData.HashStruct("EIP712Domain", malformedTypedData.Domain.Map()) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Expected no error, got '%v'", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestFormatter(t *testing.T) { | ||||
| 	var d core.TypedData | ||||
| 	err := json.Unmarshal([]byte(jsonTypedData), &d) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unmarshalling failed '%v'", err) | ||||
| 	} | ||||
| 	formatted := d.Format() | ||||
| 	formatted, _ := d.Format() | ||||
| 	for _, item := range formatted { | ||||
| 		fmt.Printf("'%v'\n", item.Pprint(0)) | ||||
| 	} | ||||
| @@ -806,3 +327,82 @@ func TestFormatter(t *testing.T) { | ||||
| 	j, _ := json.Marshal(formatted) | ||||
| 	fmt.Printf("'%v'\n", string(j)) | ||||
| } | ||||
|  | ||||
| func sign(typedData core.TypedData) ([]byte, []byte, error) { | ||||
| 	domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))) | ||||
| 	sighash := crypto.Keccak256(rawData) | ||||
| 	return typedDataHash, sighash, nil | ||||
| } | ||||
|  | ||||
| func TestJsonFiles(t *testing.T) { | ||||
| 	testfiles, err := ioutil.ReadDir("testdata/") | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed reading files: %v", err) | ||||
| 	} | ||||
| 	for i, fInfo := range testfiles { | ||||
| 		if !strings.HasSuffix(fInfo.Name(), "json") { | ||||
| 			continue | ||||
| 		} | ||||
| 		expectedFailure := strings.HasPrefix(fInfo.Name(), "expfail") | ||||
| 		data, err := ioutil.ReadFile(path.Join("testdata", fInfo.Name())) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("Failed to read file %v: %v", fInfo.Name(), err) | ||||
| 			continue | ||||
| 		} | ||||
| 		var typedData core.TypedData | ||||
| 		err = json.Unmarshal([]byte(data), &typedData) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("Test %d, file %v, json unmarshalling failed: %v", i, fInfo.Name(), err) | ||||
| 			continue | ||||
| 		} | ||||
| 		_, _, err = sign(typedData) | ||||
| 		fmt.Printf("Error %v\n", err) | ||||
| 		if err != nil && !expectedFailure { | ||||
| 			t.Errorf("Test %d failed, file %v: %v", i, fInfo.Name(), err) | ||||
| 		} | ||||
| 		if expectedFailure && err == nil { | ||||
| 			t.Errorf("Test %d succeeded (expected failure), file %v: %v", i, fInfo.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TestFuzzerFiles tests some files that have been found by fuzzing to cause | ||||
| // crashes or hangs. | ||||
| func TestFuzzerFiles(t *testing.T) { | ||||
| 	corpusdir := path.Join("testdata", "fuzzing") | ||||
| 	testfiles, err := ioutil.ReadDir(corpusdir) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed reading files: %v", err) | ||||
| 	} | ||||
| 	verbose := false | ||||
| 	for i, fInfo := range testfiles { | ||||
| 		data, err := ioutil.ReadFile(path.Join(corpusdir, fInfo.Name())) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("Failed to read file %v: %v", fInfo.Name(), err) | ||||
| 			continue | ||||
| 		} | ||||
| 		var typedData core.TypedData | ||||
| 		err = json.Unmarshal([]byte(data), &typedData) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("Test %d, file %v, json unmarshalling failed: %v", i, fInfo.Name(), err) | ||||
| 			continue | ||||
| 		} | ||||
| 		_, err = typedData.EncodeData("EIP712Domain", typedData.Domain.Map(), 1) | ||||
| 		if verbose && err != nil { | ||||
| 			fmt.Printf("%d, EncodeData[1] err: %v\n", i, err) | ||||
| 		} | ||||
| 		_, err = typedData.EncodeData(typedData.PrimaryType, typedData.Message, 1) | ||||
| 		if verbose && err != nil { | ||||
| 			fmt.Printf("%d, EncodeData[2] err: %v\n", i, err) | ||||
| 		} | ||||
| 		typedData.Format() | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										5
									
								
								signer/core/testdata/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								signer/core/testdata/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| ### EIP 712 tests | ||||
|  | ||||
| These tests are json files which are converted into eip-712 typed data.  | ||||
| All files are expected to be proper json, and tests will fail if they are not.  | ||||
| Files that begin with `expfail' are expected to not pass the hashstruct construction.  | ||||
							
								
								
									
										60
									
								
								signer/core/testdata/arrays-1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								signer/core/testdata/arrays-1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Foo": [ | ||||
|       { | ||||
|         "name": "addys", | ||||
|         "type": "address[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "stringies", | ||||
|         "type": "string[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "inties", | ||||
|         "type": "uint[]" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Foo", | ||||
|   "domain": { | ||||
|     "name": "Lorem", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "addys": [ | ||||
|       "0x0000000000000000000000000000000000000001", | ||||
|       "0x0000000000000000000000000000000000000002", | ||||
|       "0x0000000000000000000000000000000000000003" | ||||
|     ], | ||||
|     "stringies": [ | ||||
|       "lorem", | ||||
|       "ipsum", | ||||
|       "dolores" | ||||
|     ], | ||||
|     "inties": [ | ||||
|       "0x0000000000000000000000000000000000000001", | ||||
|       "3", | ||||
|       4.0 | ||||
|     ] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										54
									
								
								signer/core/testdata/custom_arraytype.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								signer/core/testdata/custom_arraytype.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { "name": "Cow"}, | ||||
|     "to": [{ "name": "Moose"},{ "name": "Goose"}], | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										76
									
								
								signer/core/testdata/eip712.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								signer/core/testdata/eip712.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test2", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "test": "3", | ||||
|       "test2": 5.0, | ||||
|       "wallet": "0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "test": "0", | ||||
|       "test2": 5, | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										67
									
								
								signer/core/testdata/expfail_arraytype_overload.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								signer/core/testdata/expfail_arraytype_overload.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person[]": [ | ||||
|       { | ||||
|         "name": "baz", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": {"baz": "foo"}, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										64
									
								
								signer/core/testdata/expfail_datamismatch_1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								signer/core/testdata/expfail_datamismatch_1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "Person" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										76
									
								
								signer/core/testdata/expfail_extradata-1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								signer/core/testdata/expfail_extradata-1.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256 ... and now for something completely different" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test2", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "test": "3", | ||||
|       "test2": 5.0, | ||||
|       "wallet": "0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "test": "0", | ||||
|       "test2": 5, | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										77
									
								
								signer/core/testdata/expfail_extradata-2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								signer/core/testdata/expfail_extradata-2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "test2", | ||||
|         "type": "uint8" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "blahonga": "zonk bonk", | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "test": "3", | ||||
|       "test2": 5.0, | ||||
|       "wallet": "0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "test": "0", | ||||
|       "test2": 5, | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										64
									
								
								signer/core/testdata/expfail_malformeddomainkeys.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								signer/core/testdata/expfail_malformeddomainkeys.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "string" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "vFAILFAILerifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										64
									
								
								signer/core/testdata/expfail_nonexistant_type.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								signer/core/testdata/expfail_nonexistant_type.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "contents", | ||||
|         "type": "Blahonga" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "Cow", | ||||
|       "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "Bob", | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "contents": "Hello, Bob!" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/expfail_toolargeuint.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/expfail_toolargeuint.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test":"257" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/expfail_toolargeuint2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/expfail_toolargeuint2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test":257 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/expfail_unconvertiblefloat.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/expfail_unconvertiblefloat.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test":"255.3" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/expfail_unconvertiblefloat2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/expfail_unconvertiblefloat2.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test": 255.3 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test":"255.3" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										60
									
								
								signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Foo": [ | ||||
|       { | ||||
|         "name": "addys", | ||||
|         "type": "address[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "stringies", | ||||
|         "type": "string[]" | ||||
|       }, | ||||
|       { | ||||
|         "name": "inties", | ||||
|         "type": "uint[]" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Foo", | ||||
|   "domain": { | ||||
|     "name": "Lorem", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "addys": [ | ||||
|       "0x0000000000000000000000000000000000000001", | ||||
|       "0x0000000000000000000000000000000000000002", | ||||
|       "0x0000000000000000000000000000000000000003" | ||||
|     ], | ||||
|     "stringies": [ | ||||
|       "lorem", | ||||
|       "ipsum", | ||||
|       "dolores" | ||||
|     ], | ||||
|     "inties": [ | ||||
|       "0x0000000000000000000000000000000000000001", | ||||
|       "3", | ||||
|       4.0 | ||||
|     ] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "uint256" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "test", | ||||
|         "type": "uint8" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "Ether Mail", | ||||
|     "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "test":257 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"domain":{"version":"0","chainId":""}} | ||||
							
								
								
									
										54
									
								
								signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| {  "types": {  "":[   { | ||||
|        "name": "name", | ||||
|    "type":"string"    }, | ||||
|    { | ||||
|     "name":"version", | ||||
|       "type": "string"    },     { | ||||
|      "name": "chaiI", | ||||
|     "type":"uint256 . ad nowretig omeedifere"     },     { | ||||
|      "ae": "eifinC", | ||||
|     "ty":"dess" | ||||
|     } | ||||
|  ], | ||||
|   "Person":[ | ||||
|      { | ||||
|     "name":"name", | ||||
|       "type": "string" | ||||
|  },  { | ||||
|      "name":"tes",    "type":"it8" | ||||
|     }, | ||||
|       {    "name":"t",      "tye":"uit8" | ||||
|     }, | ||||
|     { | ||||
|        "a":"ale", | ||||
|     "type": "ress" | ||||
|      } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|    { | ||||
|        "name":"from",    "type":"Person"     }, | ||||
|    { | ||||
|      "name": "to",        "type": "Person" | ||||
|     }, | ||||
|    { | ||||
|      "name": "contents", | ||||
|      "type": "string" | ||||
|     } | ||||
|    ] | ||||
|  }, "primaryType": "Mail", | ||||
|  "domain": { | ||||
| "name":"theMail",    "version": "1", | ||||
|     "chainId": "1", | ||||
|     "verifyingntract": "0xCcccCCCcCCCCCCCcCCcCCCcCcccccC" | ||||
|   }, | ||||
|   "message": {   "from": { | ||||
|     "name": "Cow", | ||||
|      "test": "3", | ||||
|       "est2":5.0, | ||||
|       "llt": "0xcD2a3938E13D947E0bE734DfDD86"   },   "to": {     "name": "Bob", | ||||
|     "ts":"", | ||||
|      "tet2": 5, | ||||
|      "allet": "0bBBBBbbBBbbbbBbbBbbbbBBBbB" | ||||
|   }, | ||||
|     "contents": "Hello, Bob!"  } | ||||
| } | ||||
							
								
								
									
										64
									
								
								signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| { | ||||
|   "types": { | ||||
|     "EIP712Domain": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "version", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "chainId", | ||||
|         "type": "int" | ||||
|       }, | ||||
|       { | ||||
|         "name": "verifyingContract", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Person": [ | ||||
|       { | ||||
|         "name": "name", | ||||
|         "type": "string" | ||||
|       }, | ||||
|       { | ||||
|         "name": "wallet", | ||||
|         "type": "address" | ||||
|       } | ||||
|     ], | ||||
|     "Mail": [ | ||||
|       { | ||||
|         "name": "from", | ||||
|         "type": "Person" | ||||
|       }, | ||||
|       { | ||||
|         "name": "to", | ||||
|         "type": "Mail" | ||||
|       }, | ||||
|       { | ||||
|         "name": "s", | ||||
|         "type": "Person" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "primaryType": "Mail", | ||||
|   "domain": { | ||||
|     "name": "l", | ||||
|     "version": "1", | ||||
|     "chainId": "", | ||||
|     "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | ||||
|   }, | ||||
|   "message": { | ||||
|     "from": { | ||||
|       "name": "", | ||||
|       "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||||
|     }, | ||||
|     "to": { | ||||
|       "name": "", | ||||
|       "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||||
|     }, | ||||
|     "": "" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"types":{"0":[{}]}} | ||||
		Reference in New Issue
	
	Block a user