mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
Drafted text/validator and and rewritten []byte as hexutil.Bytes
This commit is contained in:
parent
0808627c09
commit
950307bc8a
2 changed files with 79 additions and 46 deletions
|
|
@ -222,3 +222,26 @@ t=2018-10-23T19:51:57+0100 lvl=info msg=Configured api=signer audit log=audit.lo
|
||||||
t=2018-10-23T19:52:05+0100 lvl=info msg=SignTypedData api=signer type=request metadata="{\"remote\":\"127.0.0.1:55568\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66D76e6A80DC7D46d7EC1b79b15Dfa34c3C6eF21 [chksum ok]" data="{Types:map[Person:[map[name:name type:string] map[name:wallet type:address]] Mail:[map[name:from type:Person] map[name:to type:Person] map[name:contents type:string]] EIP712Domain:[map[type:string name:name] map[name:version type:string] map[name:chainId type:uint256] map[name:verifyingContract type:address]]] PrimaryType:Mail Domain:{Name:Ether Mail Version:1 ChainId:+1 VerifyingContract:0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC Salt:0x} Message:map[contents:Hello, Bob! from:map[name:Alice wallet:0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21] to:map[name:Bob wallet:0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB]]}"
|
t=2018-10-23T19:52:05+0100 lvl=info msg=SignTypedData api=signer type=request metadata="{\"remote\":\"127.0.0.1:55568\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66D76e6A80DC7D46d7EC1b79b15Dfa34c3C6eF21 [chksum ok]" data="{Types:map[Person:[map[name:name type:string] map[name:wallet type:address]] Mail:[map[name:from type:Person] map[name:to type:Person] map[name:contents type:string]] EIP712Domain:[map[type:string name:name] map[name:version type:string] map[name:chainId type:uint256] map[name:verifyingContract type:address]]] PrimaryType:Mail Domain:{Name:Ether Mail Version:1 ChainId:+1 VerifyingContract:0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC Salt:0x} Message:map[contents:Hello, Bob! from:map[name:Alice wallet:0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21] to:map[name:Bob wallet:0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB]]}"
|
||||||
t=2018-10-23T20:12:04+0100 lvl=info msg=Configured api=signer audit log=audit.log
|
t=2018-10-23T20:12:04+0100 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
t=2018-10-23T20:12:14+0100 lvl=info msg=SignTypedData api=signer type=request metadata="{\"remote\":\"127.0.0.1:55752\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66D76e6A80DC7D46d7EC1b79b15Dfa34c3C6eF21 [chksum ok]" data="{Types:map[EIP712Domain:[map[name:name type:string] map[name:version type:string] map[name:chainId type:uint256] map[name:verifyingContract type:address]] Person:[map[name:name type:string] map[name:wallet type:address]] Mail:[map[name:from type:Person] map[name:to type:Person] map[type:string name:contents]]] PrimaryType:Mail Domain:{Name:Ether Mail Version:1 ChainId:+1 VerifyingContract:0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC Salt:0x} Message:map[from:map[name:Alice wallet:0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21] to:map[name:Bob wallet:0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB] contents:Hello, Bob!]}"
|
t=2018-10-23T20:12:14+0100 lvl=info msg=SignTypedData api=signer type=request metadata="{\"remote\":\"127.0.0.1:55752\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66D76e6A80DC7D46d7EC1b79b15Dfa34c3C6eF21 [chksum ok]" data="{Types:map[EIP712Domain:[map[name:name type:string] map[name:version type:string] map[name:chainId type:uint256] map[name:verifyingContract type:address]] Person:[map[name:name type:string] map[name:wallet type:address]] Mail:[map[name:from type:Person] map[name:to type:Person] map[type:string name:contents]]] PrimaryType:Mail Domain:{Name:Ether Mail Version:1 ChainId:+1 VerifyingContract:0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC Salt:0x} Message:map[from:map[name:Alice wallet:0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21] to:map[name:Bob wallet:0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB] contents:Hello, Bob!]}"
|
||||||
|
t=2018-10-25T13:47:17+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T13:47:54+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T13:50:09+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:50039\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T13:51:00+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T13:51:07+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:51792\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T13:57:27+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T13:57:30+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:62734\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:01:29+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:01:30+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:53871\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608adeadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:02:00+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:02:10+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:55131\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608adeadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:13:15+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:13:16+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:58361\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:13:53+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:14:04+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:59928\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:14:39+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:14:43+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:61106\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:21:56+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:22:59+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:59342\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=60deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:22:59+0200 lvl=info msg=SignData api=signer type=response data= error="validator address and data undefined"
|
||||||
|
t=2018-10-25T14:23:05+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:59342\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
t=2018-10-25T14:23:31+0200 lvl=info msg=Configured api=signer audit log=audit.log
|
||||||
|
t=2018-10-25T14:23:55+0200 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"127.0.0.1:61180\",\"local\":\"localhost:8550\",\"scheme\":\"HTTP/1.1\",\"User-Agent\":\"PostmanRuntime/7.3.0\",\"Origin\":\"\"}" addr="0x66d76e6a80dc7d46d7ec1b79b15dfa34c3c6ef21 [chksum INVALID]" data=608af3436e40964b9f2c7214953a3f03685f62b8deadbeef content-type=text/validator
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ValidatorData struct {
|
||||||
|
Address common.Address
|
||||||
|
Message hexutil.Bytes
|
||||||
|
}
|
||||||
|
|
||||||
type TypedData struct {
|
type TypedData struct {
|
||||||
Types EIP712Types `json:"types"`
|
Types EIP712Types `json:"types"`
|
||||||
PrimaryType string `json:"primaryType"`
|
PrimaryType string `json:"primaryType"`
|
||||||
|
|
@ -77,7 +82,7 @@ const (
|
||||||
|
|
||||||
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
||||||
// where the V value will be 27 or 28 for legacy reasons.
|
// where the V value will be 27 or 28 for legacy reasons.
|
||||||
func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, req *SignDataRequest) ([]byte, error) {
|
func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, req *SignDataRequest) (hexutil.Bytes, error) {
|
||||||
req.Address = addr
|
req.Address = addr
|
||||||
req.Meta = MetadataFromContext(ctx)
|
req.Meta = MetadataFromContext(ctx)
|
||||||
|
|
||||||
|
|
@ -110,7 +115,7 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, re
|
||||||
//
|
//
|
||||||
// Different types of validation occur.
|
// Different types of validation occur.
|
||||||
func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) {
|
func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) {
|
||||||
var req, err = api.determineSignatureFormat(contentType, data)
|
var req, err = api.determineSignatureFormat(contentType, addr, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +130,11 @@ func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr com
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines which signature method should be used based upon the mime type
|
// Determines which signature method should be used based upon the mime type
|
||||||
func (api *SignerAPI) determineSignatureFormat(contentType string, data hexutil.Bytes) (*SignDataRequest, error) {
|
// In the cases where it matters ensure that the charset is handled. The charset
|
||||||
|
// resides in the 'params' returned as the second returnvalue from mime.ParseMediaType
|
||||||
|
// charset, ok := params["charset"]
|
||||||
|
// As it is now, we accept any charset and just treat it as 'raw'.
|
||||||
|
func (api *SignerAPI) determineSignatureFormat(contentType string, addr common.MixedcaseAddress, data hexutil.Bytes) (*SignDataRequest, error) {
|
||||||
var req *SignDataRequest
|
var req *SignDataRequest
|
||||||
mediaType, _, err := mime.ParseMediaType(contentType)
|
mediaType, _, err := mime.ParseMediaType(contentType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -135,18 +144,19 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, data hexutil.
|
||||||
switch mediaType {
|
switch mediaType {
|
||||||
case TextValidator.Mime:
|
case TextValidator.Mime:
|
||||||
// Data with an intended validator
|
// Data with an intended validator
|
||||||
sighash, msg := signTextWithValidator(data)
|
if len(data) < common.AddressLength {
|
||||||
|
return nil, errors.New("validator address and data undefined")
|
||||||
|
}
|
||||||
|
if len(data) == common.AddressLength {
|
||||||
|
return nil, errors.New("no data to sign")
|
||||||
|
}
|
||||||
|
sighash, msg := SignTextValidator(data)
|
||||||
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
||||||
break
|
break
|
||||||
case TextPlain.Mime:
|
case TextPlain.Mime:
|
||||||
// Sign calculates an Ethereum ECDSA signature for:
|
// Sign calculates an Ethereum ECDSA signature for:
|
||||||
// hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}")
|
// hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}")
|
||||||
|
sighash, msg := SignTextPlain(data)
|
||||||
// In the cases where it matters ensure that the charset is handled. The charset
|
|
||||||
// resides in the 'params' returned as the second returnvalue from mime.ParseMediaType
|
|
||||||
// charset, ok := params["charset"]
|
|
||||||
// As it is now, we accept any charset and just treat it as 'raw'.
|
|
||||||
sighash, msg := signTextPlain(data)
|
|
||||||
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
||||||
break
|
break
|
||||||
case ApplicationClique.Mime:
|
case ApplicationClique.Mime:
|
||||||
|
|
@ -155,11 +165,11 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, data hexutil.
|
||||||
if err := rlp.DecodeBytes(data, header); err != nil {
|
if err := rlp.DecodeBytes(data, header); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sighash, err := signCliqueHeader(header)
|
sighash, err := SignCliqueHeader(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("Clique block %d [0x%x]", header.Number, header.Hash())
|
msg := fmt.Sprintf("clique block %d [0x%x]", header.Number, header.Hash())
|
||||||
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
req = &SignDataRequest{Rawdata: data, Message: msg, Hash: sighash, ContentType: mediaType}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|
@ -169,23 +179,15 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, data hexutil.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// signTextPlain is a helper function that calculates a hash for the given message that can be
|
|
||||||
// safely used to calculate a signature from.
|
|
||||||
//
|
|
||||||
// The hash is calculated as
|
|
||||||
// keccak256("\x19${byteVersion}Ethereum Signed Message:\n"${message length}${message}).
|
|
||||||
//
|
|
||||||
// This gives context to the signed message and prevents signing of transactions.
|
|
||||||
func signTextPlain(data []byte) ([]byte, string) {
|
|
||||||
msg := fmt.Sprintf("\x19\\x%xEthereum Signed Message:\n%d%s", TextPlain.ByteVersion, len(data), data)
|
|
||||||
return crypto.Keccak256([]byte(msg)), msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// signTextWithValidator signs the given message which can be further recovered
|
// signTextWithValidator signs the given message which can be further recovered
|
||||||
// with the given validator.
|
// with the given validator.
|
||||||
func signTextWithValidator(data []byte) ([]byte, string) {
|
//
|
||||||
msg := "TODO"
|
// hash = keccak256("\x19\x00"${address}${data}).
|
||||||
return crypto.Keccak256([]byte(msg)), msg
|
func SignTextValidator(data hexutil.Bytes) (hexutil.Bytes, string) {
|
||||||
|
address := common.BytesToAddress(data[:common.AddressLength])
|
||||||
|
message := data[common.AddressLength:len(data)-1]
|
||||||
|
hash := fmt.Sprintf("\x19\x00:%x%s", address, string(message))
|
||||||
|
return crypto.Keccak256(hexutil.Bytes(hash)), hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// signCliqueHeader returns the hash which is used as input for the proof-of-authority
|
// signCliqueHeader returns the hash which is used as input for the proof-of-authority
|
||||||
|
|
@ -195,7 +197,7 @@ func signTextWithValidator(data []byte) ([]byte, string) {
|
||||||
// The method requires the extra data to be at least 65 bytes -- the original implementation
|
// The method requires the extra data to be at least 65 bytes -- the original implementation
|
||||||
// in clique.go panics if this is the case, thus it's been reimplemented here to avoid the panic
|
// in clique.go panics if this is the case, thus it's been reimplemented here to avoid the panic
|
||||||
// and simply return an error instead
|
// and simply return an error instead
|
||||||
func signCliqueHeader(header *types.Header) (hexutil.Bytes, error) {
|
func SignCliqueHeader(header *types.Header) (hexutil.Bytes, error) {
|
||||||
hash := common.Hash{}
|
hash := common.Hash{}
|
||||||
if len(header.Extra) < 65 {
|
if len(header.Extra) < 65 {
|
||||||
return hash.Bytes(), fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
|
return hash.Bytes(), fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
|
||||||
|
|
@ -222,6 +224,18 @@ func signCliqueHeader(header *types.Header) (hexutil.Bytes, error) {
|
||||||
return hash.Bytes(), nil
|
return hash.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// signTextPlain is a helper function that calculates a hash for the given message that can be
|
||||||
|
// safely used to calculate a signature from. This gives context to the signed message and prevents
|
||||||
|
// signing of transactions.
|
||||||
|
//
|
||||||
|
// hash = keccak256("\x19$Ethereum Signed Message:\n"${message length}${message}).
|
||||||
|
func SignTextPlain(data hexutil.Bytes) (hexutil.Bytes, string) {
|
||||||
|
// The letter `E` is \x45 in hex, retrofitting
|
||||||
|
// https://github.com/ethereum/go-ethereum/pull/2940/commits
|
||||||
|
hash := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data))
|
||||||
|
return crypto.Keccak256(hexutil.Bytes(hash)), hash
|
||||||
|
}
|
||||||
|
|
||||||
// SignTypedData signs EIP-712 conformant typed data
|
// SignTypedData signs EIP-712 conformant typed data
|
||||||
// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}")
|
// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}")
|
||||||
func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) {
|
func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) {
|
||||||
|
|
@ -252,12 +266,11 @@ func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAd
|
||||||
|
|
||||||
// hashStruct generates the following encoding for the given domain and message:
|
// hashStruct generates the following encoding for the given domain and message:
|
||||||
// `encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = "\x19\x01" ‖ domainSeparator ‖ hashStruct(message)`
|
// `encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = "\x19\x01" ‖ domainSeparator ‖ hashStruct(message)`
|
||||||
func (typedData *TypedData) HashStruct(primaryType string, data EIP712Data) []byte {
|
func (typedData *TypedData) HashStruct(primaryType string, data EIP712Data) hexutil.Bytes {
|
||||||
return crypto.Keccak256(typedData.EncodeData(primaryType, data))
|
return crypto.Keccak256(typedData.EncodeData(primaryType, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// dependencies returns an array of custom types ordered by their
|
// dependencies returns an array of custom types ordered by their hierarchical reference tree
|
||||||
// hierarchical reference tree
|
|
||||||
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string {
|
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string {
|
||||||
includes := func(arr []string, str string) bool {
|
includes := func(arr []string, str string) bool {
|
||||||
for _, obj := range arr {
|
for _, obj := range arr {
|
||||||
|
|
@ -289,7 +302,7 @@ func (typedData *TypedData) Dependencies(primaryType string, found []string) []s
|
||||||
// `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"`
|
// `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"`
|
||||||
//
|
//
|
||||||
// each member is written as `type ‖ " " ‖ name` encodings cascade down and are sorted by name
|
// each member is written as `type ‖ " " ‖ name` encodings cascade down and are sorted by name
|
||||||
func (typedData *TypedData) EncodeType(primaryType string) []byte {
|
func (typedData *TypedData) EncodeType(primaryType string) hexutil.Bytes {
|
||||||
// Get dependencies primary first, then alphabetical
|
// Get dependencies primary first, then alphabetical
|
||||||
deps := typedData.Dependencies(primaryType, []string{})
|
deps := typedData.Dependencies(primaryType, []string{})
|
||||||
for i, dep := range deps {
|
for i, dep := range deps {
|
||||||
|
|
@ -317,33 +330,33 @@ func (typedData *TypedData) EncodeType(primaryType string) []byte {
|
||||||
return buffer.Bytes()
|
return buffer.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (typedData *TypedData) TypeHash(primaryType string) []byte {
|
func (typedData *TypedData) TypeHash(primaryType string) hexutil.Bytes {
|
||||||
return crypto.Keccak256(typedData.EncodeType(primaryType))
|
return crypto.Keccak256(typedData.EncodeType(primaryType))
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesValueOf(_interface interface{}) []byte {
|
func bytesValueOf(_interface interface{}) hexutil.Bytes {
|
||||||
bytesVal, ok := _interface.([]byte)
|
bytesVal, ok := _interface.(hexutil.Bytes)
|
||||||
if ok {
|
if ok {
|
||||||
return bytesVal
|
return bytesVal
|
||||||
}
|
}
|
||||||
|
|
||||||
switch reflect.TypeOf(_interface) {
|
switch reflect.TypeOf(_interface) {
|
||||||
case reflect.TypeOf(string("")):
|
case reflect.TypeOf(string("")):
|
||||||
return []byte(_interface.(string))
|
return hexutil.Bytes(_interface.(string))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Errorf("unrecognized interface %v", _interface))
|
panic(fmt.Errorf("unrecognized interface %v", _interface))
|
||||||
return []byte{}
|
return hexutil.Bytes{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeData generates the following encoding:
|
// encodeData generates the following encoding:
|
||||||
// `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)`
|
// `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)`
|
||||||
//
|
//
|
||||||
// each encoded member is 32-byte long
|
// each encoded member is 32-byte long
|
||||||
func (typedData *TypedData) EncodeData(primaryType string, data map[string]interface{}) []byte {
|
func (typedData *TypedData) EncodeData(primaryType string, data map[string]interface{}) hexutil.Bytes {
|
||||||
encTypes := []string{}
|
encTypes := []string{}
|
||||||
encValues := []interface{}{}
|
encValues := []interface{}{}
|
||||||
|
|
||||||
|
|
@ -359,12 +372,10 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
|
||||||
switch encType {
|
switch encType {
|
||||||
case "address":
|
case "address":
|
||||||
primitiveEncType = "uint160"
|
primitiveEncType = "uint160"
|
||||||
bytesValue := []byte{}
|
bytesValue := hexutil.Bytes{}
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
bytesValue = append(bytesValue, 0)
|
bytesValue = append(bytesValue, 0)
|
||||||
}
|
}
|
||||||
//foo := common.BytesToAddress([]byte(encValue.(string)))
|
|
||||||
//fmt.Println(foo)
|
|
||||||
for _, _byte := range encValue.(common.Address) {
|
for _, _byte := range encValue.(common.Address) {
|
||||||
bytesValue = append(bytesValue, _byte)
|
bytesValue = append(bytesValue, _byte)
|
||||||
}
|
}
|
||||||
|
|
@ -387,11 +398,11 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
|
||||||
encTypes = append(encTypes, "bytes32")
|
encTypes = append(encTypes, "bytes32")
|
||||||
sizeStr := strings.TrimPrefix(encType, "bytes")
|
sizeStr := strings.TrimPrefix(encType, "bytes")
|
||||||
size, _ := strconv.Atoi(sizeStr)
|
size, _ := strconv.Atoi(sizeStr)
|
||||||
bytesValue := []byte{}
|
bytesValue := hexutil.Bytes{}
|
||||||
for i := 0; i < 32-size; i++ {
|
for i := 0; i < 32-size; i++ {
|
||||||
bytesValue = append(bytesValue, 0)
|
bytesValue = append(bytesValue, 0)
|
||||||
}
|
}
|
||||||
for _, _byte := range encValue.([]byte) {
|
for _, _byte := range encValue.(hexutil.Bytes) {
|
||||||
bytesValue = append(bytesValue, _byte)
|
bytesValue = append(bytesValue, _byte)
|
||||||
}
|
}
|
||||||
primitiveEncValue = bytesValue
|
primitiveEncValue = bytesValue
|
||||||
|
|
@ -461,7 +472,6 @@ func (api *SignerAPI) EcRecover(ctx context.Context, contentType string, data he
|
||||||
// the V value must be be 27 or 28 for legacy reasons.
|
// the V value must be be 27 or 28 for legacy reasons.
|
||||||
//
|
//
|
||||||
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
|
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
|
||||||
|
|
||||||
if len(sig) != 65 {
|
if len(sig) != 65 {
|
||||||
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
|
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +479,7 @@ func (api *SignerAPI) EcRecover(ctx context.Context, contentType string, data he
|
||||||
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
|
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
|
||||||
}
|
}
|
||||||
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
|
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
|
||||||
hash, _ := signTextPlain(data)
|
hash, _ := SignTextPlain(data)
|
||||||
rpk, err := crypto.SigToPub(hash, sig)
|
rpk, err := crypto.SigToPub(hash, sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
|
|
@ -481,7 +491,7 @@ func (api *SignerAPI) EcRecover(ctx context.Context, contentType string, data he
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON validates the input data
|
// UnmarshalJSON validates the input data
|
||||||
func (typedData *TypedData) UnmarshalJSON(data []byte) error {
|
func (typedData *TypedData) UnmarshalJSON(data hexutil.Bytes) error {
|
||||||
type input struct {
|
type input struct {
|
||||||
Types EIP712Types `json:"types"`
|
Types EIP712Types `json:"types"`
|
||||||
PrimaryType string `json:"primaryType"`
|
PrimaryType string `json:"primaryType"`
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue