Skip to content

Commit 73caa61

Browse files
committed
signer: add SignTypedData; utils add EIP712Hash
1 parent 236f9e6 commit 73caa61

File tree

7 files changed

+72
-214
lines changed

7 files changed

+72
-214
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
prvkey
1+
prvkey
2+
go.sum

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Ethereum Account which can be used to sign messages and transactions.
8282

8383
- [x] SignTx
8484
- [x] SignMsg
85-
- [ ] SignTypedData
85+
- [x] SignTypedData
8686

8787
### Wallet
8888

@@ -111,4 +111,5 @@ Creating Contract Instance for call & execute contract.
111111

112112
- [x] EthToBN
113113
- [x] GweiToBN
114+
- [x] EIP712Hash
114115
- [x] Ecrecover

go.sum

Lines changed: 0 additions & 208 deletions
This file was deleted.

signer.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/ethereum/go-ethereum/common"
1111
"github.com/ethereum/go-ethereum/core/types"
1212
"github.com/ethereum/go-ethereum/crypto"
13+
"github.com/ethereum/go-ethereum/signer/core"
1314
)
1415

1516
type Signer struct {
@@ -62,3 +63,18 @@ func (s Signer) SignMsg(msg []byte) (sig []byte, err error) {
6263
sig[64] += 27
6364
return
6465
}
66+
67+
func (s Signer) SignTypedData(typedData core.TypedData) (sig []byte, err error) {
68+
hash, err := EIP712Hash(typedData)
69+
if err != nil {
70+
return
71+
}
72+
73+
sig, err = crypto.Sign(hash, s.key)
74+
if err != nil {
75+
return
76+
}
77+
78+
sig[64] += 27
79+
return
80+
}

signer_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package goether
22

33
import (
4+
"encoding/json"
45
"math/big"
56
"testing"
67

78
"github.com/ethereum/go-ethereum/common"
89
"github.com/ethereum/go-ethereum/common/hexutil"
10+
"github.com/ethereum/go-ethereum/signer/core"
911
"github.com/stretchr/testify/assert"
1012
)
1113

@@ -25,7 +27,20 @@ func TestSignTx(t *testing.T) {
2527
}
2628

2729
func TestSignMsg(t *testing.T) {
28-
sign, err := TestSigner.SignMsg([]byte("123"))
30+
sig, err := TestSigner.SignMsg([]byte("123"))
2931
assert.NoError(t, err)
30-
assert.Equal(t, "0x409c16579b4fc162f199f897497f5142101992af82cc6a0b9521413cf721151817e52781c0341fa333cdfea6ebe945b9231f8a8b3df7e7040203f9d7df26c2f21c", hexutil.Encode(sign))
32+
assert.Equal(t, "0x409c16579b4fc162f199f897497f5142101992af82cc6a0b9521413cf721151817e52781c0341fa333cdfea6ebe945b9231f8a8b3df7e7040203f9d7df26c2f21c", hexutil.Encode(sig))
33+
}
34+
35+
func TestSignTypedData(t *testing.T) {
36+
typedDataJson := `{"primaryType":"Mail","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"}]},"domain":{"name":"Ether Mail","version":"1","chainId":1,"verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}}`
37+
var typedData core.TypedData
38+
json.Unmarshal([]byte(typedDataJson), &typedData)
39+
sig, err := TestSigner.SignTypedData(typedData)
40+
assert.NoError(t, err)
41+
assert.Equal(t, "0x0a80cc322f7a5e5e0965ff84fd76ea6479fae9d8ce29f7e076c3b9cb8e8097b80052ee91f1fad54d4348c518e42395848431746c8fee40420041f87ea05b5a281c", hexutil.Encode(sig))
42+
43+
hash, err := EIP712Hash(typedData)
44+
addr, err := Ecrecover(hash, sig)
45+
assert.Equal(t, "0xab6c371B6c466BcF14d4003601951e5873dF2AcA", addr.String())
3146
}

utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/ethereum/go-ethereum/common"
88
"github.com/ethereum/go-ethereum/crypto"
9+
"github.com/ethereum/go-ethereum/signer/core"
910
)
1011

1112
func EthToBN(amount float64) (bn *big.Int) {
@@ -20,6 +21,20 @@ func GweiToBN(amount float64) (bn *big.Int) {
2021
return bn
2122
}
2223

24+
func EIP712Hash(typedData core.TypedData) (hash []byte, err error) {
25+
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
26+
if err != nil {
27+
return
28+
}
29+
typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
30+
if err != nil {
31+
return
32+
}
33+
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
34+
hash = crypto.Keccak256(rawData)
35+
return
36+
}
37+
2338
func Ecrecover(hash, sig []byte) (addr common.Address, err error) {
2439
if len(sig) != 65 {
2540
err = fmt.Errorf("invalid length of signture: %d", len(sig))

utils_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package goether
22

33
import (
4+
"encoding/json"
45
"math/big"
56
"testing"
67

78
"github.com/ethereum/go-ethereum/accounts"
89
"github.com/ethereum/go-ethereum/common/hexutil"
10+
"github.com/ethereum/go-ethereum/signer/core"
911
"github.com/stretchr/testify/assert"
1012
)
1113

@@ -17,11 +19,27 @@ func TestGweiToBN(t *testing.T) {
1719
assert.Equal(t, big.NewInt(1100000000), GweiToBN(1.1))
1820
}
1921

22+
func TestEIP712(t *testing.T) {
23+
raw := `{"types": {"EIP712Domain": [{"name": "name","type": "string"},{"name": "version","type": "string"},{"name": "chainId","type": "uint256"}],"Order": [{"name": "action","type": "string"},{"name": "orderHashes","type": "string[]"},{"name": "makerAddress","type": "address"}]},"primaryType": "Order","domain": {"name": "ZooDex","version": "1","chainId": "42"},"message": {"action": "cancelOrder","orderHashes": ["0x123", "0x456", "0x789"],"makerAddress": "0xf9593A9d7F735814B87D08e8D8aD624f58d53B10"}}
24+
`
25+
typedData := core.TypedData{}
26+
err := json.Unmarshal([]byte(raw), &typedData)
27+
assert.NoError(t, err)
28+
29+
hash, err := EIP712Hash(typedData)
30+
assert.NoError(t, err)
31+
assert.Equal(t, "0xcf3985dd9eb11ce656eafc2dddd08ce3058ad00c74669b3d171f31e9a0472d8e", hexutil.Encode(hash))
32+
33+
addr, err := Ecrecover(hash, hexutil.MustDecode("0xa9a3e5f72b48651b735d0908f1f240b06eafe7166dbe6b4fc8b57d8b8515ef555fe4b124c2b50d6907423426ec46bc12c5956942dcfd01e02d70912c87a389c41b"))
34+
assert.NoError(t, err)
35+
assert.Equal(t, "0xf9593A9d7F735814B87D08e8D8aD624f58d53B10", addr.String())
36+
}
37+
2038
func TestEcrecover(t *testing.T) {
2139
hash := accounts.TextHash([]byte("123"))
22-
sign, _ := hexutil.Decode("0x409c16579b4fc162f199f897497f5142101992af82cc6a0b9521413cf721151817e52781c0341fa333cdfea6ebe945b9231f8a8b3df7e7040203f9d7df26c2f21c")
40+
sig, _ := hexutil.Decode("0x409c16579b4fc162f199f897497f5142101992af82cc6a0b9521413cf721151817e52781c0341fa333cdfea6ebe945b9231f8a8b3df7e7040203f9d7df26c2f21c")
2341

24-
addr, err := Ecrecover(hash, sign)
42+
addr, err := Ecrecover(hash, sig)
2543
assert.NoError(t, err)
2644
assert.Equal(t, "0xab6c371B6c466BcF14d4003601951e5873dF2AcA", addr.String())
2745
}

0 commit comments

Comments
 (0)