/
cheque.go
132 lines (114 loc) · 3.52 KB
/
cheque.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2020 The Penguin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package chequebook
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/penguintop/penguin/pkg/property"
"github.com/penguintop/penguin/pkg/xwcfmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/penguintop/penguin/pkg/crypto"
"github.com/penguintop/penguin/pkg/crypto/eip712"
)
// Cheque represents a cheque for a SimpleSwap chequebook
type Cheque struct {
Chequebook common.Address
Beneficiary common.Address
CumulativePayout *big.Int
}
// SignedCheque represents a cheque together with its signature
type SignedCheque struct {
Cheque
Signature []byte
}
// chequebookDomain computes chainId-dependant EIP712 domain
func chequebookDomain(chainID int64) eip712.TypedDataDomain {
return eip712.TypedDataDomain{
Name: "Chequebook",
Version: "1.0",
ChainId: math.NewHexOrDecimal256(chainID),
}
}
// ChequeTypes are the needed type descriptions for cheque signing
var ChequeTypes = eip712.Types{
"EIP712Domain": eip712.EIP712DomainType,
"Cheque": []eip712.Type{
{
Name: "chequebook",
Type: "address",
},
{
Name: "beneficiary",
Type: "address",
},
{
Name: "cumulativePayout",
Type: "uint256",
},
},
}
// ChequeSigner signs cheque
type ChequeSigner interface {
// Sign signs a cheque
Sign(cheque *Cheque) ([]byte, error)
}
type chequeSigner struct {
signer crypto.Signer // the underlying signer used
chainID int64 // the chainID used for EIP712
}
// NewChequeSigner creates a new cheque signer for the given chainID.
func NewChequeSigner(signer crypto.Signer, chainID int64) ChequeSigner {
return &chequeSigner{
signer: signer,
chainID: chainID,
}
}
// eip712DataForCheque converts a cheque into the correct TypedData structure.
func eip712DataForCheque(cheque *Cheque, chainID int64) *eip712.TypedData {
return &eip712.TypedData{
Domain: chequebookDomain(chainID),
Types: ChequeTypes,
Message: eip712.TypedDataMessage{
"chequebook": cheque.Chequebook.Hex(),
"beneficiary": cheque.Beneficiary.Hex(),
"cumulativePayout": cheque.CumulativePayout.String(),
},
PrimaryType: "Cheque",
}
}
// Sign signs a cheque.
func (s *chequeSigner) Sign(cheque *Cheque) ([]byte, error) {
//return s.signer.SignTypedData(eip712DataForCheque(cheque, 0))
domainID := property.Domain()
funcSig := "Cheque(address chequebook,address beneficiary,uint256 cumulativePayout)"
chequebookAddr, _ := xwcfmt.HexAddrToXwcConAddr(hex.EncodeToString(cheque.Chequebook[:]))
beneficiaryAddr, _ := xwcfmt.HexAddrToXwcAddr(hex.EncodeToString(cheque.Beneficiary[:]))
cumulativePayout := cheque.CumulativePayout.String()
dataStr := strings.Join([]string{
domainID, funcSig, chequebookAddr, beneficiaryAddr, cumulativePayout,
}, ",")
return []byte(dataStr), nil
}
func (cheque *Cheque) String() string {
return fmt.Sprintf("Contract: %x Beneficiary: %x CumulativePayout: %v", cheque.Chequebook, cheque.Beneficiary, cheque.CumulativePayout)
}
func (cheque *Cheque) Equal(other *Cheque) bool {
if cheque.Beneficiary != other.Beneficiary {
return false
}
if cheque.CumulativePayout.Cmp(other.CumulativePayout) != 0 {
return false
}
return cheque.Chequebook == other.Chequebook
}
func (cheque *SignedCheque) Equal(other *SignedCheque) bool {
if !bytes.Equal(cheque.Signature, other.Signature) {
return false
}
return cheque.Cheque.Equal(&other.Cheque)
}