github.com/phillinzzz/newBsc@v1.1.6/signer/core/signed_data.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "fmt" 24 "math/big" 25 "mime" 26 "reflect" 27 "regexp" 28 "sort" 29 "strconv" 30 "strings" 31 "unicode" 32 33 "github.com/phillinzzz/newBsc/accounts" 34 "github.com/phillinzzz/newBsc/common" 35 "github.com/phillinzzz/newBsc/common/hexutil" 36 "github.com/phillinzzz/newBsc/common/math" 37 "github.com/phillinzzz/newBsc/consensus/clique" 38 "github.com/phillinzzz/newBsc/consensus/parlia" 39 "github.com/phillinzzz/newBsc/core/types" 40 "github.com/phillinzzz/newBsc/crypto" 41 "github.com/phillinzzz/newBsc/rlp" 42 ) 43 44 type SigFormat struct { 45 Mime string 46 ByteVersion byte 47 } 48 49 var ( 50 IntendedValidator = SigFormat{ 51 accounts.MimetypeDataWithValidator, 52 0x00, 53 } 54 DataTyped = SigFormat{ 55 accounts.MimetypeTypedData, 56 0x01, 57 } 58 ApplicationClique = SigFormat{ 59 accounts.MimetypeClique, 60 0x02, 61 } 62 ApplicationParlia = SigFormat{ 63 accounts.MimetypeParlia, 64 0x03, 65 } 66 TextPlain = SigFormat{ 67 accounts.MimetypeTextPlain, 68 0x45, 69 } 70 ) 71 72 type ValidatorData struct { 73 Address common.Address 74 Message hexutil.Bytes 75 } 76 77 type TypedData struct { 78 Types Types `json:"types"` 79 PrimaryType string `json:"primaryType"` 80 Domain TypedDataDomain `json:"domain"` 81 Message TypedDataMessage `json:"message"` 82 } 83 84 type Type struct { 85 Name string `json:"name"` 86 Type string `json:"type"` 87 } 88 89 func (t *Type) isArray() bool { 90 return strings.HasSuffix(t.Type, "[]") 91 } 92 93 // typeName returns the canonical name of the type. If the type is 'Person[]', then 94 // this method returns 'Person' 95 func (t *Type) typeName() string { 96 if strings.HasSuffix(t.Type, "[]") { 97 return strings.TrimSuffix(t.Type, "[]") 98 } 99 return t.Type 100 } 101 102 func (t *Type) isReferenceType() bool { 103 if len(t.Type) == 0 { 104 return false 105 } 106 // Reference types must have a leading uppercase character 107 return unicode.IsUpper([]rune(t.Type)[0]) 108 } 109 110 type Types map[string][]Type 111 112 type TypePriority struct { 113 Type string 114 Value uint 115 } 116 117 type TypedDataMessage = map[string]interface{} 118 119 type TypedDataDomain struct { 120 Name string `json:"name"` 121 Version string `json:"version"` 122 ChainId *math.HexOrDecimal256 `json:"chainId"` 123 VerifyingContract string `json:"verifyingContract"` 124 Salt string `json:"salt"` 125 } 126 127 var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Z](\w*)(\[\])?$`) 128 129 // sign receives a request and produces a signature 130 // 131 // Note, the produced signature conforms to the secp256k1 curve R, S and V values, 132 // where the V value will be 27 or 28 for legacy reasons, if legacyV==true. 133 func (api *SignerAPI) sign(req *SignDataRequest, legacyV bool) (hexutil.Bytes, error) { 134 // We make the request prior to looking up if we actually have the account, to prevent 135 // account-enumeration via the API 136 res, err := api.UI.ApproveSignData(req) 137 if err != nil { 138 return nil, err 139 } 140 if !res.Approved { 141 return nil, ErrRequestDenied 142 } 143 // Look up the wallet containing the requested signer 144 account := accounts.Account{Address: req.Address.Address()} 145 wallet, err := api.am.Find(account) 146 if err != nil { 147 return nil, err 148 } 149 pw, err := api.lookupOrQueryPassword(account.Address, 150 "Password for signing", 151 fmt.Sprintf("Please enter password for signing data with account %s", account.Address.Hex())) 152 if err != nil { 153 return nil, err 154 } 155 // Sign the data with the wallet 156 signature, err := wallet.SignDataWithPassphrase(account, pw, req.ContentType, req.Rawdata) 157 if err != nil { 158 return nil, err 159 } 160 if legacyV { 161 signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper 162 } 163 return signature, nil 164 } 165 166 // SignData signs the hash of the provided data, but does so differently 167 // depending on the content-type specified. 168 // 169 // Different types of validation occur. 170 func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) { 171 var req, transformV, err = api.determineSignatureFormat(ctx, contentType, addr, data) 172 if err != nil { 173 return nil, err 174 } 175 signature, err := api.sign(req, transformV) 176 if err != nil { 177 api.UI.ShowError(err.Error()) 178 return nil, err 179 } 180 return signature, nil 181 } 182 183 // determineSignatureFormat determines which signature method should be used based upon the mime type 184 // In the cases where it matters ensure that the charset is handled. The charset 185 // resides in the 'params' returned as the second returnvalue from mime.ParseMediaType 186 // charset, ok := params["charset"] 187 // As it is now, we accept any charset and just treat it as 'raw'. 188 // This method returns the mimetype for signing along with the request 189 func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (*SignDataRequest, bool, error) { 190 var ( 191 req *SignDataRequest 192 useEthereumV = true // Default to use V = 27 or 28, the legacy Ethereum format 193 ) 194 mediaType, _, err := mime.ParseMediaType(contentType) 195 if err != nil { 196 return nil, useEthereumV, err 197 } 198 199 switch mediaType { 200 case IntendedValidator.Mime: 201 // Data with an intended validator 202 validatorData, err := UnmarshalValidatorData(data) 203 if err != nil { 204 return nil, useEthereumV, err 205 } 206 sighash, msg := SignTextValidator(validatorData) 207 messages := []*NameValueType{ 208 { 209 Name: "This is a request to sign data intended for a particular validator (see EIP 191 version 0)", 210 Typ: "description", 211 Value: "", 212 }, 213 { 214 Name: "Intended validator address", 215 Typ: "address", 216 Value: validatorData.Address.String(), 217 }, 218 { 219 Name: "Application-specific data", 220 Typ: "hexdata", 221 Value: validatorData.Message, 222 }, 223 { 224 Name: "Full message for signing", 225 Typ: "hexdata", 226 Value: fmt.Sprintf("0x%x", msg), 227 }, 228 } 229 req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Messages: messages, Hash: sighash} 230 case ApplicationClique.Mime: 231 // Clique is the Ethereum PoA standard 232 stringData, ok := data.(string) 233 if !ok { 234 return nil, useEthereumV, fmt.Errorf("input for %v must be an hex-encoded string", ApplicationClique.Mime) 235 } 236 cliqueData, err := hexutil.Decode(stringData) 237 if err != nil { 238 return nil, useEthereumV, err 239 } 240 header := &types.Header{} 241 if err := rlp.DecodeBytes(cliqueData, header); err != nil { 242 return nil, useEthereumV, err 243 } 244 // The incoming clique header is already truncated, sent to us with a extradata already shortened 245 if len(header.Extra) < 65 { 246 // Need to add it back, to get a suitable length for hashing 247 newExtra := make([]byte, len(header.Extra)+65) 248 copy(newExtra, header.Extra) 249 header.Extra = newExtra 250 } 251 // Get back the rlp data, encoded by us 252 sighash, cliqueRlp, err := cliqueHeaderHashAndRlp(header) 253 if err != nil { 254 return nil, useEthereumV, err 255 } 256 messages := []*NameValueType{ 257 { 258 Name: "Clique header", 259 Typ: "clique", 260 Value: fmt.Sprintf("clique header %d [0x%x]", header.Number, header.Hash()), 261 }, 262 } 263 // Clique uses V on the form 0 or 1 264 useEthereumV = false 265 req = &SignDataRequest{ContentType: mediaType, Rawdata: cliqueRlp, Messages: messages, Hash: sighash} 266 case ApplicationParlia.Mime: 267 stringData, ok := data.(string) 268 if !ok { 269 return nil, useEthereumV, fmt.Errorf("input for %v must be an hex-encoded string", ApplicationParlia.Mime) 270 } 271 parliaData, err := hexutil.Decode(stringData) 272 if err != nil { 273 return nil, useEthereumV, err 274 } 275 header := &types.Header{} 276 if err := rlp.DecodeBytes(parliaData, header); err != nil { 277 return nil, useEthereumV, err 278 } 279 // The incoming parlia header is already truncated, sent to us with a extradata already shortened 280 if len(header.Extra) < 65 { 281 // Need to add it back, to get a suitable length for hashing 282 newExtra := make([]byte, len(header.Extra)+65) 283 copy(newExtra, header.Extra) 284 header.Extra = newExtra 285 } 286 // Get back the rlp data, encoded by us 287 sighash, parliaRlp, err := parliaHeaderHashAndRlp(header, api.chainID) 288 if err != nil { 289 return nil, useEthereumV, err 290 } 291 messages := []*NameValueType{ 292 { 293 Name: "Parlia header", 294 Typ: "parlia", 295 Value: fmt.Sprintf("parlia header %d [0x%x]", header.Number, header.Hash()), 296 }, 297 } 298 // Parlia uses V on the form 0 or 1 299 useEthereumV = false 300 req = &SignDataRequest{ContentType: mediaType, Rawdata: parliaRlp, Messages: messages, Hash: sighash} 301 default: // also case TextPlain.Mime: 302 // Calculates an Ethereum ECDSA signature for: 303 // hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}") 304 // We expect it to be a string 305 if stringData, ok := data.(string); !ok { 306 return nil, useEthereumV, fmt.Errorf("input for text/plain must be an hex-encoded string") 307 } else { 308 if textData, err := hexutil.Decode(stringData); err != nil { 309 return nil, useEthereumV, err 310 } else { 311 sighash, msg := accounts.TextAndHash(textData) 312 messages := []*NameValueType{ 313 { 314 Name: "message", 315 Typ: accounts.MimetypeTextPlain, 316 Value: msg, 317 }, 318 } 319 req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Messages: messages, Hash: sighash} 320 } 321 } 322 } 323 req.Address = addr 324 req.Meta = MetadataFromContext(ctx) 325 return req, useEthereumV, nil 326 } 327 328 // SignTextWithValidator signs the given message which can be further recovered 329 // with the given validator. 330 // hash = keccak256("\x19\x00"${address}${data}). 331 func SignTextValidator(validatorData ValidatorData) (hexutil.Bytes, string) { 332 msg := fmt.Sprintf("\x19\x00%s%s", string(validatorData.Address.Bytes()), string(validatorData.Message)) 333 return crypto.Keccak256([]byte(msg)), msg 334 } 335 336 // cliqueHeaderHashAndRlp returns the hash which is used as input for the proof-of-authority 337 // signing. It is the hash of the entire header apart from the 65 byte signature 338 // contained at the end of the extra data. 339 // 340 // The method requires the extra data to be at least 65 bytes -- the original implementation 341 // in clique.go panics if this is the case, thus it's been reimplemented here to avoid the panic 342 // and simply return an error instead 343 func cliqueHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error) { 344 if len(header.Extra) < 65 { 345 err = fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra)) 346 return 347 } 348 rlp = clique.CliqueRLP(header) 349 hash = clique.SealHash(header).Bytes() 350 return hash, rlp, err 351 } 352 353 func parliaHeaderHashAndRlp(header *types.Header, chainId *big.Int) (hash, rlp []byte, err error) { 354 if len(header.Extra) < 65 { 355 err = fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra)) 356 return 357 } 358 rlp = parlia.ParliaRLP(header, chainId) 359 hash = parlia.SealHash(header, chainId).Bytes() 360 return hash, rlp, err 361 } 362 363 // SignTypedData signs EIP-712 conformant typed data 364 // hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}") 365 // It returns 366 // - the signature, 367 // - and/or any error 368 func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) { 369 signature, _, err := api.signTypedData(ctx, addr, typedData, nil) 370 return signature, err 371 } 372 373 // signTypedData is identical to the capitalized version, except that it also returns the hash (preimage) 374 // - the signature preimage (hash) 375 func (api *SignerAPI) signTypedData(ctx context.Context, addr common.MixedcaseAddress, 376 typedData TypedData, validationMessages *ValidationMessages) (hexutil.Bytes, hexutil.Bytes, error) { 377 domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) 378 if err != nil { 379 return nil, nil, err 380 } 381 typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) 382 if err != nil { 383 return nil, nil, err 384 } 385 rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))) 386 sighash := crypto.Keccak256(rawData) 387 messages, err := typedData.Format() 388 if err != nil { 389 return nil, nil, err 390 } 391 req := &SignDataRequest{ 392 ContentType: DataTyped.Mime, 393 Rawdata: rawData, 394 Messages: messages, 395 Hash: sighash, 396 Address: addr} 397 if validationMessages != nil { 398 req.Callinfo = validationMessages.Messages 399 } 400 signature, err := api.sign(req, true) 401 if err != nil { 402 api.UI.ShowError(err.Error()) 403 return nil, nil, err 404 } 405 return signature, sighash, nil 406 } 407 408 // HashStruct generates a keccak256 hash of the encoding of the provided data 409 func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage) (hexutil.Bytes, error) { 410 encodedData, err := typedData.EncodeData(primaryType, data, 1) 411 if err != nil { 412 return nil, err 413 } 414 return crypto.Keccak256(encodedData), nil 415 } 416 417 // Dependencies returns an array of custom types ordered by their hierarchical reference tree 418 func (typedData *TypedData) Dependencies(primaryType string, found []string) []string { 419 includes := func(arr []string, str string) bool { 420 for _, obj := range arr { 421 if obj == str { 422 return true 423 } 424 } 425 return false 426 } 427 428 if includes(found, primaryType) { 429 return found 430 } 431 if typedData.Types[primaryType] == nil { 432 return found 433 } 434 found = append(found, primaryType) 435 for _, field := range typedData.Types[primaryType] { 436 for _, dep := range typedData.Dependencies(field.Type, found) { 437 if !includes(found, dep) { 438 found = append(found, dep) 439 } 440 } 441 } 442 return found 443 } 444 445 // EncodeType generates the following encoding: 446 // `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"` 447 // 448 // each member is written as `type ‖ " " ‖ name` encodings cascade down and are sorted by name 449 func (typedData *TypedData) EncodeType(primaryType string) hexutil.Bytes { 450 // Get dependencies primary first, then alphabetical 451 deps := typedData.Dependencies(primaryType, []string{}) 452 if len(deps) > 0 { 453 slicedDeps := deps[1:] 454 sort.Strings(slicedDeps) 455 deps = append([]string{primaryType}, slicedDeps...) 456 } 457 458 // Format as a string with fields 459 var buffer bytes.Buffer 460 for _, dep := range deps { 461 buffer.WriteString(dep) 462 buffer.WriteString("(") 463 for _, obj := range typedData.Types[dep] { 464 buffer.WriteString(obj.Type) 465 buffer.WriteString(" ") 466 buffer.WriteString(obj.Name) 467 buffer.WriteString(",") 468 } 469 buffer.Truncate(buffer.Len() - 1) 470 buffer.WriteString(")") 471 } 472 return buffer.Bytes() 473 } 474 475 // TypeHash creates the keccak256 hash of the data 476 func (typedData *TypedData) TypeHash(primaryType string) hexutil.Bytes { 477 return crypto.Keccak256(typedData.EncodeType(primaryType)) 478 } 479 480 // EncodeData generates the following encoding: 481 // `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)` 482 // 483 // each encoded member is 32-byte long 484 func (typedData *TypedData) EncodeData(primaryType string, data map[string]interface{}, depth int) (hexutil.Bytes, error) { 485 if err := typedData.validate(); err != nil { 486 return nil, err 487 } 488 489 buffer := bytes.Buffer{} 490 491 // Verify extra data 492 if exp, got := len(typedData.Types[primaryType]), len(data); exp < got { 493 return nil, fmt.Errorf("there is extra data provided in the message (%d < %d)", exp, got) 494 } 495 496 // Add typehash 497 buffer.Write(typedData.TypeHash(primaryType)) 498 499 // Add field contents. Structs and arrays have special handlers. 500 for _, field := range typedData.Types[primaryType] { 501 encType := field.Type 502 encValue := data[field.Name] 503 if encType[len(encType)-1:] == "]" { 504 arrayValue, ok := encValue.([]interface{}) 505 if !ok { 506 return nil, dataMismatchError(encType, encValue) 507 } 508 509 arrayBuffer := bytes.Buffer{} 510 parsedType := strings.Split(encType, "[")[0] 511 for _, item := range arrayValue { 512 if typedData.Types[parsedType] != nil { 513 mapValue, ok := item.(map[string]interface{}) 514 if !ok { 515 return nil, dataMismatchError(parsedType, item) 516 } 517 encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) 518 if err != nil { 519 return nil, err 520 } 521 arrayBuffer.Write(encodedData) 522 } else { 523 bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) 524 if err != nil { 525 return nil, err 526 } 527 arrayBuffer.Write(bytesValue) 528 } 529 } 530 531 buffer.Write(crypto.Keccak256(arrayBuffer.Bytes())) 532 } else if typedData.Types[field.Type] != nil { 533 mapValue, ok := encValue.(map[string]interface{}) 534 if !ok { 535 return nil, dataMismatchError(encType, encValue) 536 } 537 encodedData, err := typedData.EncodeData(field.Type, mapValue, depth+1) 538 if err != nil { 539 return nil, err 540 } 541 buffer.Write(crypto.Keccak256(encodedData)) 542 } else { 543 byteValue, err := typedData.EncodePrimitiveValue(encType, encValue, depth) 544 if err != nil { 545 return nil, err 546 } 547 buffer.Write(byteValue) 548 } 549 } 550 return buffer.Bytes(), nil 551 } 552 553 // Attempt to parse bytes in different formats: byte array, hex string, hexutil.Bytes. 554 func parseBytes(encType interface{}) ([]byte, bool) { 555 switch v := encType.(type) { 556 case []byte: 557 return v, true 558 case hexutil.Bytes: 559 return v, true 560 case string: 561 bytes, err := hexutil.Decode(v) 562 if err != nil { 563 return nil, false 564 } 565 return bytes, true 566 default: 567 return nil, false 568 } 569 } 570 571 func parseInteger(encType string, encValue interface{}) (*big.Int, error) { 572 var ( 573 length int 574 signed = strings.HasPrefix(encType, "int") 575 b *big.Int 576 ) 577 if encType == "int" || encType == "uint" { 578 length = 256 579 } else { 580 lengthStr := "" 581 if strings.HasPrefix(encType, "uint") { 582 lengthStr = strings.TrimPrefix(encType, "uint") 583 } else { 584 lengthStr = strings.TrimPrefix(encType, "int") 585 } 586 atoiSize, err := strconv.Atoi(lengthStr) 587 if err != nil { 588 return nil, fmt.Errorf("invalid size on integer: %v", lengthStr) 589 } 590 length = atoiSize 591 } 592 switch v := encValue.(type) { 593 case *math.HexOrDecimal256: 594 b = (*big.Int)(v) 595 case string: 596 var hexIntValue math.HexOrDecimal256 597 if err := hexIntValue.UnmarshalText([]byte(v)); err != nil { 598 return nil, err 599 } 600 b = (*big.Int)(&hexIntValue) 601 case float64: 602 // JSON parses non-strings as float64. Fail if we cannot 603 // convert it losslessly 604 if float64(int64(v)) == v { 605 b = big.NewInt(int64(v)) 606 } else { 607 return nil, fmt.Errorf("invalid float value %v for type %v", v, encType) 608 } 609 } 610 if b == nil { 611 return nil, fmt.Errorf("invalid integer value %v/%v for type %v", encValue, reflect.TypeOf(encValue), encType) 612 } 613 if b.BitLen() > length { 614 return nil, fmt.Errorf("integer larger than '%v'", encType) 615 } 616 if !signed && b.Sign() == -1 { 617 return nil, fmt.Errorf("invalid negative value for unsigned type %v", encType) 618 } 619 return b, nil 620 } 621 622 // EncodePrimitiveValue deals with the primitive values found 623 // while searching through the typed data 624 func (typedData *TypedData) EncodePrimitiveValue(encType string, encValue interface{}, depth int) ([]byte, error) { 625 switch encType { 626 case "address": 627 stringValue, ok := encValue.(string) 628 if !ok || !common.IsHexAddress(stringValue) { 629 return nil, dataMismatchError(encType, encValue) 630 } 631 retval := make([]byte, 32) 632 copy(retval[12:], common.HexToAddress(stringValue).Bytes()) 633 return retval, nil 634 case "bool": 635 boolValue, ok := encValue.(bool) 636 if !ok { 637 return nil, dataMismatchError(encType, encValue) 638 } 639 if boolValue { 640 return math.PaddedBigBytes(common.Big1, 32), nil 641 } 642 return math.PaddedBigBytes(common.Big0, 32), nil 643 case "string": 644 strVal, ok := encValue.(string) 645 if !ok { 646 return nil, dataMismatchError(encType, encValue) 647 } 648 return crypto.Keccak256([]byte(strVal)), nil 649 case "bytes": 650 bytesValue, ok := parseBytes(encValue) 651 if !ok { 652 return nil, dataMismatchError(encType, encValue) 653 } 654 return crypto.Keccak256(bytesValue), nil 655 } 656 if strings.HasPrefix(encType, "bytes") { 657 lengthStr := strings.TrimPrefix(encType, "bytes") 658 length, err := strconv.Atoi(lengthStr) 659 if err != nil { 660 return nil, fmt.Errorf("invalid size on bytes: %v", lengthStr) 661 } 662 if length < 0 || length > 32 { 663 return nil, fmt.Errorf("invalid size on bytes: %d", length) 664 } 665 if byteValue, ok := parseBytes(encValue); !ok || len(byteValue) != length { 666 return nil, dataMismatchError(encType, encValue) 667 } else { 668 // Right-pad the bits 669 dst := make([]byte, 32) 670 copy(dst, byteValue) 671 return dst, nil 672 } 673 } 674 if strings.HasPrefix(encType, "int") || strings.HasPrefix(encType, "uint") { 675 b, err := parseInteger(encType, encValue) 676 if err != nil { 677 return nil, err 678 } 679 return math.U256Bytes(b), nil 680 } 681 return nil, fmt.Errorf("unrecognized type '%s'", encType) 682 683 } 684 685 // dataMismatchError generates an error for a mismatch between 686 // the provided type and data 687 func dataMismatchError(encType string, encValue interface{}) error { 688 return fmt.Errorf("provided data '%v' doesn't match type '%s'", encValue, encType) 689 } 690 691 // EcRecover recovers the address associated with the given sig. 692 // Only compatible with `text/plain` 693 func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { 694 // Returns the address for the Account that was used to create the signature. 695 // 696 // Note, this function is compatible with eth_sign and personal_sign. As such it recovers 697 // the address of: 698 // hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}") 699 // addr = ecrecover(hash, signature) 700 // 701 // Note, the signature must conform to the secp256k1 curve R, S and V values, where 702 // the V value must be be 27 or 28 for legacy reasons. 703 // 704 // https://github.com/phillinzzz/newBsc/wiki/Management-APIs#personal_ecRecover 705 if len(sig) != 65 { 706 return common.Address{}, fmt.Errorf("signature must be 65 bytes long") 707 } 708 if sig[64] != 27 && sig[64] != 28 { 709 return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") 710 } 711 sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 712 hash := accounts.TextHash(data) 713 rpk, err := crypto.SigToPub(hash, sig) 714 if err != nil { 715 return common.Address{}, err 716 } 717 return crypto.PubkeyToAddress(*rpk), nil 718 } 719 720 // UnmarshalValidatorData converts the bytes input to typed data 721 func UnmarshalValidatorData(data interface{}) (ValidatorData, error) { 722 raw, ok := data.(map[string]interface{}) 723 if !ok { 724 return ValidatorData{}, errors.New("validator input is not a map[string]interface{}") 725 } 726 addr, ok := raw["address"].(string) 727 if !ok { 728 return ValidatorData{}, errors.New("validator address is not sent as a string") 729 } 730 addrBytes, err := hexutil.Decode(addr) 731 if err != nil { 732 return ValidatorData{}, err 733 } 734 if !ok || len(addrBytes) == 0 { 735 return ValidatorData{}, errors.New("validator address is undefined") 736 } 737 738 message, ok := raw["message"].(string) 739 if !ok { 740 return ValidatorData{}, errors.New("message is not sent as a string") 741 } 742 messageBytes, err := hexutil.Decode(message) 743 if err != nil { 744 return ValidatorData{}, err 745 } 746 if !ok || len(messageBytes) == 0 { 747 return ValidatorData{}, errors.New("message is undefined") 748 } 749 750 return ValidatorData{ 751 Address: common.BytesToAddress(addrBytes), 752 Message: messageBytes, 753 }, nil 754 } 755 756 // validate makes sure the types are sound 757 func (typedData *TypedData) validate() error { 758 if err := typedData.Types.validate(); err != nil { 759 return err 760 } 761 if err := typedData.Domain.validate(); err != nil { 762 return err 763 } 764 return nil 765 } 766 767 // Map generates a map version of the typed data 768 func (typedData *TypedData) Map() map[string]interface{} { 769 dataMap := map[string]interface{}{ 770 "types": typedData.Types, 771 "domain": typedData.Domain.Map(), 772 "primaryType": typedData.PrimaryType, 773 "message": typedData.Message, 774 } 775 return dataMap 776 } 777 778 // Format returns a representation of typedData, which can be easily displayed by a user-interface 779 // without in-depth knowledge about 712 rules 780 func (typedData *TypedData) Format() ([]*NameValueType, error) { 781 domain, err := typedData.formatData("EIP712Domain", typedData.Domain.Map()) 782 if err != nil { 783 return nil, err 784 } 785 ptype, err := typedData.formatData(typedData.PrimaryType, typedData.Message) 786 if err != nil { 787 return nil, err 788 } 789 var nvts []*NameValueType 790 nvts = append(nvts, &NameValueType{ 791 Name: "EIP712Domain", 792 Value: domain, 793 Typ: "domain", 794 }) 795 nvts = append(nvts, &NameValueType{ 796 Name: typedData.PrimaryType, 797 Value: ptype, 798 Typ: "primary type", 799 }) 800 return nvts, nil 801 } 802 803 func (typedData *TypedData) formatData(primaryType string, data map[string]interface{}) ([]*NameValueType, error) { 804 var output []*NameValueType 805 806 // Add field contents. Structs and arrays have special handlers. 807 for _, field := range typedData.Types[primaryType] { 808 encName := field.Name 809 encValue := data[encName] 810 item := &NameValueType{ 811 Name: encName, 812 Typ: field.Type, 813 } 814 if field.isArray() { 815 arrayValue, _ := encValue.([]interface{}) 816 parsedType := field.typeName() 817 for _, v := range arrayValue { 818 if typedData.Types[parsedType] != nil { 819 mapValue, _ := v.(map[string]interface{}) 820 mapOutput, err := typedData.formatData(parsedType, mapValue) 821 if err != nil { 822 return nil, err 823 } 824 item.Value = mapOutput 825 } else { 826 primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) 827 if err != nil { 828 return nil, err 829 } 830 item.Value = primitiveOutput 831 } 832 } 833 } else if typedData.Types[field.Type] != nil { 834 if mapValue, ok := encValue.(map[string]interface{}); ok { 835 mapOutput, err := typedData.formatData(field.Type, mapValue) 836 if err != nil { 837 return nil, err 838 } 839 item.Value = mapOutput 840 } else { 841 item.Value = "<nil>" 842 } 843 } else { 844 primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) 845 if err != nil { 846 return nil, err 847 } 848 item.Value = primitiveOutput 849 } 850 output = append(output, item) 851 } 852 return output, nil 853 } 854 855 func formatPrimitiveValue(encType string, encValue interface{}) (string, error) { 856 switch encType { 857 case "address": 858 if stringValue, ok := encValue.(string); !ok { 859 return "", fmt.Errorf("could not format value %v as address", encValue) 860 } else { 861 return common.HexToAddress(stringValue).String(), nil 862 } 863 case "bool": 864 if boolValue, ok := encValue.(bool); !ok { 865 return "", fmt.Errorf("could not format value %v as bool", encValue) 866 } else { 867 return fmt.Sprintf("%t", boolValue), nil 868 } 869 case "bytes", "string": 870 return fmt.Sprintf("%s", encValue), nil 871 } 872 if strings.HasPrefix(encType, "bytes") { 873 return fmt.Sprintf("%s", encValue), nil 874 875 } 876 if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") { 877 if b, err := parseInteger(encType, encValue); err != nil { 878 return "", err 879 } else { 880 return fmt.Sprintf("%d (0x%x)", b, b), nil 881 } 882 } 883 return "", fmt.Errorf("unhandled type %v", encType) 884 } 885 886 // NameValueType is a very simple struct with Name, Value and Type. It's meant for simple 887 // json structures used to communicate signing-info about typed data with the UI 888 type NameValueType struct { 889 Name string `json:"name"` 890 Value interface{} `json:"value"` 891 Typ string `json:"type"` 892 } 893 894 // Pprint returns a pretty-printed version of nvt 895 func (nvt *NameValueType) Pprint(depth int) string { 896 output := bytes.Buffer{} 897 output.WriteString(strings.Repeat("\u00a0", depth*2)) 898 output.WriteString(fmt.Sprintf("%s [%s]: ", nvt.Name, nvt.Typ)) 899 if nvts, ok := nvt.Value.([]*NameValueType); ok { 900 output.WriteString("\n") 901 for _, next := range nvts { 902 sublevel := next.Pprint(depth + 1) 903 output.WriteString(sublevel) 904 } 905 } else { 906 if nvt.Value != nil { 907 output.WriteString(fmt.Sprintf("%q\n", nvt.Value)) 908 } else { 909 output.WriteString("\n") 910 } 911 } 912 return output.String() 913 } 914 915 // Validate checks if the types object is conformant to the specs 916 func (t Types) validate() error { 917 for typeKey, typeArr := range t { 918 if len(typeKey) == 0 { 919 return fmt.Errorf("empty type key") 920 } 921 for i, typeObj := range typeArr { 922 if len(typeObj.Type) == 0 { 923 return fmt.Errorf("type %q:%d: empty Type", typeKey, i) 924 } 925 if len(typeObj.Name) == 0 { 926 return fmt.Errorf("type %q:%d: empty Name", typeKey, i) 927 } 928 if typeKey == typeObj.Type { 929 return fmt.Errorf("type %q cannot reference itself", typeObj.Type) 930 } 931 if typeObj.isReferenceType() { 932 if _, exist := t[typeObj.typeName()]; !exist { 933 return fmt.Errorf("reference type %q is undefined", typeObj.Type) 934 } 935 if !typedDataReferenceTypeRegexp.MatchString(typeObj.Type) { 936 return fmt.Errorf("unknown reference type %q", typeObj.Type) 937 } 938 } else if !isPrimitiveTypeValid(typeObj.Type) { 939 return fmt.Errorf("unknown type %q", typeObj.Type) 940 } 941 } 942 } 943 return nil 944 } 945 946 // Checks if the primitive value is valid 947 func isPrimitiveTypeValid(primitiveType string) bool { 948 if primitiveType == "address" || 949 primitiveType == "address[]" || 950 primitiveType == "bool" || 951 primitiveType == "bool[]" || 952 primitiveType == "string" || 953 primitiveType == "string[]" { 954 return true 955 } 956 if primitiveType == "bytes" || 957 primitiveType == "bytes[]" || 958 primitiveType == "bytes1" || 959 primitiveType == "bytes1[]" || 960 primitiveType == "bytes2" || 961 primitiveType == "bytes2[]" || 962 primitiveType == "bytes3" || 963 primitiveType == "bytes3[]" || 964 primitiveType == "bytes4" || 965 primitiveType == "bytes4[]" || 966 primitiveType == "bytes5" || 967 primitiveType == "bytes5[]" || 968 primitiveType == "bytes6" || 969 primitiveType == "bytes6[]" || 970 primitiveType == "bytes7" || 971 primitiveType == "bytes7[]" || 972 primitiveType == "bytes8" || 973 primitiveType == "bytes8[]" || 974 primitiveType == "bytes9" || 975 primitiveType == "bytes9[]" || 976 primitiveType == "bytes10" || 977 primitiveType == "bytes10[]" || 978 primitiveType == "bytes11" || 979 primitiveType == "bytes11[]" || 980 primitiveType == "bytes12" || 981 primitiveType == "bytes12[]" || 982 primitiveType == "bytes13" || 983 primitiveType == "bytes13[]" || 984 primitiveType == "bytes14" || 985 primitiveType == "bytes14[]" || 986 primitiveType == "bytes15" || 987 primitiveType == "bytes15[]" || 988 primitiveType == "bytes16" || 989 primitiveType == "bytes16[]" || 990 primitiveType == "bytes17" || 991 primitiveType == "bytes17[]" || 992 primitiveType == "bytes18" || 993 primitiveType == "bytes18[]" || 994 primitiveType == "bytes19" || 995 primitiveType == "bytes19[]" || 996 primitiveType == "bytes20" || 997 primitiveType == "bytes20[]" || 998 primitiveType == "bytes21" || 999 primitiveType == "bytes21[]" || 1000 primitiveType == "bytes22" || 1001 primitiveType == "bytes22[]" || 1002 primitiveType == "bytes23" || 1003 primitiveType == "bytes23[]" || 1004 primitiveType == "bytes24" || 1005 primitiveType == "bytes24[]" || 1006 primitiveType == "bytes25" || 1007 primitiveType == "bytes25[]" || 1008 primitiveType == "bytes26" || 1009 primitiveType == "bytes26[]" || 1010 primitiveType == "bytes27" || 1011 primitiveType == "bytes27[]" || 1012 primitiveType == "bytes28" || 1013 primitiveType == "bytes28[]" || 1014 primitiveType == "bytes29" || 1015 primitiveType == "bytes29[]" || 1016 primitiveType == "bytes30" || 1017 primitiveType == "bytes30[]" || 1018 primitiveType == "bytes31" || 1019 primitiveType == "bytes31[]" || 1020 primitiveType == "bytes32" || 1021 primitiveType == "bytes32[]" { 1022 return true 1023 } 1024 if primitiveType == "int" || 1025 primitiveType == "int[]" || 1026 primitiveType == "int8" || 1027 primitiveType == "int8[]" || 1028 primitiveType == "int16" || 1029 primitiveType == "int16[]" || 1030 primitiveType == "int32" || 1031 primitiveType == "int32[]" || 1032 primitiveType == "int64" || 1033 primitiveType == "int64[]" || 1034 primitiveType == "int128" || 1035 primitiveType == "int128[]" || 1036 primitiveType == "int256" || 1037 primitiveType == "int256[]" { 1038 return true 1039 } 1040 if primitiveType == "uint" || 1041 primitiveType == "uint[]" || 1042 primitiveType == "uint8" || 1043 primitiveType == "uint8[]" || 1044 primitiveType == "uint16" || 1045 primitiveType == "uint16[]" || 1046 primitiveType == "uint32" || 1047 primitiveType == "uint32[]" || 1048 primitiveType == "uint64" || 1049 primitiveType == "uint64[]" || 1050 primitiveType == "uint128" || 1051 primitiveType == "uint128[]" || 1052 primitiveType == "uint256" || 1053 primitiveType == "uint256[]" { 1054 return true 1055 } 1056 return false 1057 } 1058 1059 // validate checks if the given domain is valid, i.e. contains at least 1060 // the minimum viable keys and values 1061 func (domain *TypedDataDomain) validate() error { 1062 if domain.ChainId == nil && len(domain.Name) == 0 && len(domain.Version) == 0 && len(domain.VerifyingContract) == 0 && len(domain.Salt) == 0 { 1063 return errors.New("domain is undefined") 1064 } 1065 1066 return nil 1067 } 1068 1069 // Map is a helper function to generate a map version of the domain 1070 func (domain *TypedDataDomain) Map() map[string]interface{} { 1071 dataMap := map[string]interface{}{} 1072 1073 if domain.ChainId != nil { 1074 dataMap["chainId"] = domain.ChainId 1075 } 1076 1077 if len(domain.Name) > 0 { 1078 dataMap["name"] = domain.Name 1079 } 1080 1081 if len(domain.Version) > 0 { 1082 dataMap["version"] = domain.Version 1083 } 1084 1085 if len(domain.VerifyingContract) > 0 { 1086 dataMap["verifyingContract"] = domain.VerifyingContract 1087 } 1088 1089 if len(domain.Salt) > 0 { 1090 dataMap["salt"] = domain.Salt 1091 } 1092 return dataMap 1093 }