Polished docstrings, ran goimports and swapped fmt.Errorf with errors.New where possible

This commit is contained in:
Paul Berg 2018-10-18 09:16:43 +01:00 committed by Martin Holst Swende
parent 3d0e8d37fe
commit d11bc7d913
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 254 additions and 961 deletions

View file

@ -245,21 +245,15 @@ func TestNewAcc(t *testing.T) {
}
}
func signApplicationValidator(t *testing.T) {
func signTextValidator(t *testing.T) {
// TODO
}
func signApplicationClique(t *testing.T) {
// https://etherscan.io/block/1
//header := &types.Header{
// "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
// "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
// "0x05a56e2d52c817161883f50c441c3228cfe54d9f",
//}
// TODO
}
func signDataPlain(t *testing.T) {
func signTextPlain(t *testing.T) {
api, control := setup(t)
//Create two accounts
createAccount(control, api, t)
@ -273,7 +267,7 @@ func signDataPlain(t *testing.T) {
control <- "Y"
control <- "wrongpassword"
h, err := api.SignData(context.Background(), DataPlain.Mime, a, []byte("EHLO world"))
h, err := api.SignData(context.Background(), TextPlain.Mime, a, []byte("EHLO world"))
if h != nil {
t.Errorf("Expected nil-data, got %x", h)
}
@ -281,7 +275,7 @@ func signDataPlain(t *testing.T) {
t.Errorf("Expected ErrLocked! %v", err)
}
control <- "No way"
h, err = api.SignData(context.Background(), DataPlain.Mime, a, []byte("EHLO world"))
h, err = api.SignData(context.Background(), TextPlain.Mime, a, []byte("EHLO world"))
if h != nil {
t.Errorf("Expected nil-data, got %x", h)
}
@ -290,7 +284,7 @@ func signDataPlain(t *testing.T) {
}
control <- "Y"
control <- "a_long_password"
h, err = api.SignData(context.Background(), DataPlain.Mime, a, []byte("EHLO world"))
h, err = api.SignData(context.Background(), TextPlain.Mime, a, []byte("EHLO world"))
if err != nil {
t.Fatal(err)
}
@ -299,22 +293,22 @@ func signDataPlain(t *testing.T) {
}
}
func signDataStructured(t *testing.T) {
func signTypedData(t *testing.T) {
// TODO
}
func TestSignData(t *testing.T) {
// application/validator or `0x00`
signApplicationValidator(t)
signTextValidator(t)
// application/clique or `0x01`
// data/structured `0x01`
signTypedData(t)
// application/clique or `0x02`
signApplicationClique(t)
// data/plain or `0x45`
signDataPlain(t)
// data/structured `0x46`
signDataStructured(t)
// text/plain or `0x45`
signTextPlain(t)
}
func mkTestTx(from common.MixedcaseAddress) SendTxArgs {

View file

@ -1,259 +0,0 @@
package core
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"math/big"
"sort"
"strings"
"unicode"
)
type TypedData struct {
Types EIP712Types `json:"types"`
PrimaryType string `json:"primaryType"`
Domain EIP712Domain `json:"domain"`
Message EIP712Message `json:"message"`
}
type EIP712Types map[string][]map[string]string
type EIP712TypePriority struct {
Type string
Value uint
}
type EIP712Domain struct {
Name string `json:"name"`
Version string `json:"version"`
ChainId *big.Int `json:"chainId"`
VerifyingContract common.Address `json:"verifyingContract"`
Salt hexutil.Bytes `json:"salt"`
}
type EIP712Message map[string]interface{}
// Typed data according to EIP712
//
// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}")
func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, data TypedData) (hexutil.Bytes, error) {
if err := data.Domain.IsValid(); err != nil {
return nil, err
}
if data.PrimaryType == "" {
return nil, fmt.Errorf("primary type undefined")
}
domainTypes := EIP712Types{
"EIP712Domain": data.Types["EIP712Domain"],
}
domainSeparator, err := hashStruct(domainTypes, data.Domain.Values(), "")
if err != nil {
return nil, err
}
delete(data.Types, "EIP712Domain")
typedDataHash, err := hashStruct(data.Types, data.Message, data.PrimaryType)
if err != nil {
return nil, err
}
fmt.Println("domainSeparator", domainSeparator.String())
fmt.Println("typedDataHash", typedDataHash.String())
return common.FromHex("0xdeadbeef"), nil
}
// `encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = "\x19\x01" ‖ domainSeparator ‖ hashStruct(message)`
func hashStruct(types EIP712Types, message EIP712Message, primaryType string) (common.Hash, error) {
if primaryType != "" {
if types[primaryType] == nil {
return common.Hash{}, fmt.Errorf("primaryType specified but undefined")
}
}
typeEncoding, err := encodeType(types, primaryType)
if err != nil {
return common.Hash{}, err
}
typeHash := hex.EncodeToString(crypto.Keccak256([]byte(typeEncoding)))
dataEncoding, err := encodeData(message)
if err != nil {
return common.Hash{}, err
}
dataHash := hex.EncodeToString(crypto.Keccak256([]byte(dataEncoding)))
var buffer bytes.Buffer
buffer.WriteString(typeHash)
buffer.WriteString(dataHash)
hash := common.BytesToHash(crypto.Keccak256(buffer.Bytes()))
return hash, nil
}
// encodeType transforms the given types into an encoding of the form
// `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"`
//
// Each member is written as `type ‖ " " ‖ name` encodings cascade down and are sorted by name
func encodeType(types EIP712Types, primaryType string) (string, error) {
var priorities = make(map[string]uint)
for key := range types {
priorities[key] = 0
}
// Updates the priority for every new custom type discovered
update := func(typeKey string, typeVal string) {
priorities[typeVal]++
// Importantly, we also have to check for parent types to increment them too
for _, typeObj := range types[typeVal] {
_typeVal := typeObj["type"]
firstChar := []rune(_typeVal)[0]
if unicode.IsUpper(firstChar) {
priorities[_typeVal]++
}
}
}
// Checks if referenced type has already been visited to optimise algo
visited := func(arr []string, val string) bool {
for _, elem := range arr {
if elem == val {
return true
}
}
return false
}
for typeKey, typeArr := range types {
var typeValArr []string
for _, typeObj := range typeArr {
typeVal := typeObj["type"]
if typeKey == typeVal {
return "", fmt.Errorf("type %s cannot reference itself", typeVal)
}
firstChar := []rune(typeVal)[0]
if unicode.IsUpper(firstChar) {
if types[typeVal] != nil {
if !visited(typeValArr, typeVal) {
typeValArr = append(typeValArr, typeVal)
update(typeKey, typeVal)
}
} else {
return "", fmt.Errorf("referenced type %s is undefined", typeVal)
}
} else {
if !types.IsStandardType(typeVal) {
if types[typeVal] != nil {
return "", fmt.Errorf("Custom type %s must be capitalized", typeVal)
} else {
return "", fmt.Errorf("Unknown type %s", typeVal)
}
}
}
}
typeValArr = []string{}
}
sortedPriorities := types.SortByPriorityAndName(priorities)
var buffer bytes.Buffer
for _, priority := range sortedPriorities {
typeKey := priority.Type
typeArr := types[typeKey]
buffer.WriteString(typeKey)
buffer.WriteString("(")
for _, typeObj := range typeArr {
buffer.WriteString(typeObj["type"])
buffer.WriteString(" ")
buffer.WriteString(typeObj["name"])
buffer.WriteString(",")
}
buffer.Truncate(buffer.Len() - 1)
buffer.WriteString(")")
}
return buffer.String(), nil
}
func encodeData(values EIP712Message) (string, error) {
return "", nil
}
// Checks if the given type is a standard type accepted by EIP-712
func (types *EIP712Types) IsStandardType(typeStr string) bool {
standardTypes := []string{
"array",
"address",
"boolean",
"bytes",
"string",
"struct",
"uint",
}
for _, val := range standardTypes {
if strings.HasPrefix(typeStr, val) {
return true
}
}
return false
}
// Helper function to sort types by priority and name. Priority is calculated b
// based upon the number of references.
func (types *EIP712Types) SortByPriorityAndName(input map[string]uint) []EIP712TypePriority {
var priorities []EIP712TypePriority
for key, val := range input {
priorities = append(priorities, EIP712TypePriority{key, val})
}
// Alphabetically
sort.Slice(priorities, func(i, j int) bool {
return priorities[i].Type < priorities[j].Type
})
// Priority
sort.Slice(priorities, func(i, j int) bool {
return priorities[i].Value > priorities[j].Value
})
for _, priority := range priorities {
fmt.Printf("%s, Value %d\n", priority.Type, priority.Value)
}
fmt.Printf("\n")
return priorities
}
// Check if the given domain is valid, i.e. contains at least the minimum viable keys and values
func (domain *EIP712Domain) IsValid() error {
if domain.ChainId == big.NewInt(0) {
return fmt.Errorf("chainId must be specified according to EIP-155")
}
if domain.Name == "" && domain.Version == "" && len(domain.VerifyingContract) == 0 && len(domain.Salt) == 0 {
return fmt.Errorf("domain undefined")
}
return nil
}
// Helper function to return the values of a domain in the form of a golang map
func (domain *EIP712Domain) Values() map[string]interface{} {
return map[string]interface{}{
"name": domain.Name,
"version": domain.Version,
"chainId": domain.Name,
"verifyingContract": domain.VerifyingContract,
"salt": domain.Salt,
}
}

File diff suppressed because it is too large Load diff